Initial IPv6 delployment #2
1
.idea/alpina.iml
generated
1
.idea/alpina.iml
generated
@ -28,6 +28,7 @@
|
|||||||
<option value="$MODULE_DIR$/roles/nextcloud/templates" />
|
<option value="$MODULE_DIR$/roles/nextcloud/templates" />
|
||||||
<option value="$MODULE_DIR$/roles/arrstack/templates" />
|
<option value="$MODULE_DIR$/roles/arrstack/templates" />
|
||||||
<option value="$MODULE_DIR$/roles/jellyfin/templates" />
|
<option value="$MODULE_DIR$/roles/jellyfin/templates" />
|
||||||
|
<option value="$MODULE_DIR$/roles/docker_host/templates" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
23
.idea/jsonSchemas.xml
generated
23
.idea/jsonSchemas.xml
generated
@ -3,6 +3,24 @@
|
|||||||
<component name="JsonSchemaMappingsProjectConfiguration">
|
<component name="JsonSchemaMappingsProjectConfiguration">
|
||||||
<state>
|
<state>
|
||||||
<map>
|
<map>
|
||||||
|
<entry key="Ansible Tasks File">
|
||||||
|
<value>
|
||||||
|
<SchemaInfo>
|
||||||
|
<option name="name" value="Ansible Tasks File" />
|
||||||
|
<option name="relativePathToSchema" value="https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/ansible.json#/$defs/tasks" />
|
||||||
|
<option name="applicationDefined" value="true" />
|
||||||
|
<option name="patterns">
|
||||||
|
<list>
|
||||||
|
<Item>
|
||||||
|
<option name="pattern" value="true" />
|
||||||
|
<option name="path" value="*/tasks/*.yml" />
|
||||||
|
<option name="mappingKind" value="Pattern" />
|
||||||
|
</Item>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
</SchemaInfo>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="Traefik v2">
|
<entry key="Traefik v2">
|
||||||
<value>
|
<value>
|
||||||
<SchemaInfo>
|
<SchemaInfo>
|
||||||
@ -45,6 +63,11 @@
|
|||||||
<option name="applicationDefined" value="true" />
|
<option name="applicationDefined" value="true" />
|
||||||
<option name="patterns">
|
<option name="patterns">
|
||||||
<list>
|
<list>
|
||||||
|
<Item>
|
||||||
|
<option name="pattern" value="true" />
|
||||||
|
<option name="path" value="*/docker-compose.yml" />
|
||||||
|
<option name="mappingKind" value="Pattern" />
|
||||||
|
</Item>
|
||||||
<Item>
|
<Item>
|
||||||
<option name="pattern" value="true" />
|
<option name="pattern" value="true" />
|
||||||
<option name="path" value="*/docker-compose.yml.j2" />
|
<option name="path" value="*/docker-compose.yml.j2" />
|
||||||
|
2
Makefile
2
Makefile
@ -1,4 +1,6 @@
|
|||||||
.POSIX:
|
.POSIX:
|
||||||
|
.PHONY: *
|
||||||
|
.EXPORT_ALL_VARIABLES:
|
||||||
|
|
||||||
env ?= staging
|
env ?= staging
|
||||||
vault_id ?= alpina@contrib/rbw-client.sh
|
vault_id ?= alpina@contrib/rbw-client.sh
|
||||||
|
14
README.md
14
README.md
@ -2,3 +2,17 @@
|
|||||||
|
|
||||||
A home for configuring all of my homelab containers on a Debian Linux machine.
|
A home for configuring all of my homelab containers on a Debian Linux machine.
|
||||||
This assumes a Debian Linux machine with Docker and Docker Compose installed.
|
This assumes a Debian Linux machine with Docker and Docker Compose installed.
|
||||||
|
|
||||||
|
# Notes
|
||||||
|
|
||||||
|
## IPv6
|
||||||
|
The current configuration is designed to work with IPv6.
|
||||||
|
However, because of how (not properly) I'm doing the subnetting
|
||||||
|
from the host's network, NDP doesn't work.
|
||||||
|
This means that container IPs are not accessible from other hosts on the local network.
|
||||||
|
I simply have a static route on my router to the container subnet,
|
||||||
|
that uses the IP of this host as the gateway.
|
||||||
|
|
||||||
|
This is a limitation of my current ISP, I only have a single /64 subnet for my lab network.
|
||||||
|
I'd like to get a /56 or /48, perhaps using Hurricane Electric's tunnel broker.
|
||||||
|
*Sigh* ISPs being stingy with the 2^48 prefixes they're afraid of running out of.
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
{% macro default_network(subnet_index) %}
|
||||||
|
default:
|
||||||
|
enable_ipv6: true
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: {{ docker_ipv6_subnet | ansible.utils.ipsubnet(80, subnet_index) }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro traefik_labels(host, service="", port="", auth=false) %}
|
{% macro traefik_labels(host, service="", port="", auth=false) %}
|
||||||
traefik.enable=true
|
traefik.enable=true
|
||||||
- traefik.http.routers.{{ host }}.rule=Host(`{{ host }}.{{ domain }}`)
|
- traefik.http.routers.{{ host }}.rule=Host(`{{ host }}.{{ domain }}`)
|
||||||
|
@ -28,8 +28,12 @@
|
|||||||
when: item.state == "file"
|
when: item.state == "file"
|
||||||
|
|
||||||
- name: Deploy docker-compose for {{ current_svc_name }}
|
- name: Deploy docker-compose for {{ current_svc_name }}
|
||||||
community.docker.docker_compose:
|
command: docker compose -f "{{ current_svc_path }}/docker-compose.yml" up -d --pull --remove-orphans
|
||||||
project_src: "{{ current_svc_path }}"
|
register: docker_compose_output
|
||||||
state: present
|
# Not perfect idempotency, but the built-in docker_compose module doesn't support docker-compose v2
|
||||||
pull: true
|
# And of course there's an IPv6 bug in docker-compose v1, smh
|
||||||
remove_orphans: true
|
# https://github.com/docker/compose/issues/7670
|
||||||
|
changed_when: "'created' in docker_compose_output.stderr.lower()"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: docker_compose_output
|
||||||
|
1
inventories/prod/group_vars/docker_hosts.yml
Normal file
1
inventories/prod/group_vars/docker_hosts.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
docker_ipv6_index: 255
|
1
inventories/staging/group_vars/docker_hosts.yml
Normal file
1
inventories/staging/group_vars/docker_hosts.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
docker_ipv6_index: 254
|
14
poetry.lock
generated
14
poetry.lock
generated
@ -254,6 +254,18 @@ files = [
|
|||||||
{file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
|
{file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "netaddr"
|
||||||
|
version = "0.8.0"
|
||||||
|
description = "A network address manipulation library for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "netaddr-0.8.0-py2.py3-none-any.whl", hash = "sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac"},
|
||||||
|
{file = "netaddr-0.8.0.tar.gz", hash = "sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "23.0"
|
version = "23.0"
|
||||||
@ -366,4 +378,4 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.10"
|
python-versions = "^3.10"
|
||||||
content-hash = "4c3656f66006d184debf3777b8df073898df0eb1f53611cdd47ec4c543071595"
|
content-hash = "e5cad99dc808b0751037fa8d524f2a4c4eac8f6ae5710c6ed5f32def518746b9"
|
||||||
|
@ -9,6 +9,7 @@ readme = "README.md"
|
|||||||
python = "^3.10"
|
python = "^3.10"
|
||||||
ansible = "^7.3.0"
|
ansible = "^7.3.0"
|
||||||
ansible-vault = "^2.1.0"
|
ansible-vault = "^2.1.0"
|
||||||
|
netaddr = "^0.8.0"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
set -x
|
||||||
apk add --no-cache wireguard-tools-wg
|
|
||||||
|
|
||||||
local_gateway=$(ip route | grep default | awk '{print $3}')
|
local_gateway=$(ip route | grep default | awk '{print $3}')
|
||||||
# This used as the gateway address for NAT-PMP to work properly
|
# This used as the gateway address for NAT-PMP to work properly
|
||||||
@ -19,5 +18,9 @@ ip route add default via "$wg_gateway"
|
|||||||
# Note that the DNS isn't changed, so there's actually a leak there
|
# Note that the DNS isn't changed, so there's actually a leak there
|
||||||
# That's on purpose, just in case I want to access local jackett from qbit
|
# That's on purpose, just in case I want to access local jackett from qbit
|
||||||
|
|
||||||
|
# Still need to figure out how to make this work with IPv6
|
||||||
|
# Prevent IPv6 leaks
|
||||||
|
# ip -6 route del default
|
||||||
|
|
||||||
# Finally, optionally allow access to the home network
|
# Finally, optionally allow access to the home network
|
||||||
# ip route add "\{\{ home_network }}" via "$local_gateway"
|
# ip route add "\{\{ home_network }}" via "$local_gateway"
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
|
{% import 'contrib/compose_helpers.j2' as helpers with context %}
|
||||||
{##}
|
{##}
|
||||||
version: "3.7"
|
version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
{# {{ helpers.default_network(249) | indent(2) }}#}
|
||||||
|
# TODO: Figure out IPv6 leaks
|
||||||
|
ipv4_only:
|
||||||
traefik_traefik:
|
traefik_traefik:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
@ -14,10 +16,13 @@ services:
|
|||||||
cap_add:
|
cap_add:
|
||||||
- NET_ADMIN
|
- NET_ADMIN
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("qbit", port="8080", auth=true) | indent(6) }}
|
- {{ helpers.traefik_labels('qbit', port='8080', auth=true) | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- DOCKER_MODS=linuxserver/mods:universal-package-install
|
||||||
|
- INSTALL_PACKAGES=wireguard-tools-wg
|
||||||
networks:
|
networks:
|
||||||
- default
|
- ipv4_only
|
||||||
- traefik_traefik
|
- traefik_traefik
|
||||||
volumes:
|
volumes:
|
||||||
- ./wireguard:/etc/wireguard:ro
|
- ./wireguard:/etc/wireguard:ro
|
||||||
@ -31,12 +36,12 @@ services:
|
|||||||
image: linuxserver/prowlarr:latest
|
image: linuxserver/prowlarr:latest
|
||||||
container_name: prowlarr
|
container_name: prowlarr
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("prowlarr", port="9696", auth=true) | indent(6) }}
|
- {{ helpers.traefik_labels('prowlarr', port='9696', auth=true) | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
- qbittorrent
|
- qbittorrent
|
||||||
networks:
|
networks:
|
||||||
- default
|
- ipv4_only
|
||||||
- traefik_traefik
|
- traefik_traefik
|
||||||
volumes:
|
volumes:
|
||||||
- {{ base_volume_path }}/arrstack/config/prowlarr:/config
|
- {{ base_volume_path }}/arrstack/config/prowlarr:/config
|
||||||
@ -45,12 +50,12 @@ services:
|
|||||||
image: linuxserver/sonarr:latest
|
image: linuxserver/sonarr:latest
|
||||||
container_name: sonarr
|
container_name: sonarr
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("sonarr", port="8989", auth=true) | indent(6) }}
|
- {{ helpers.traefik_labels('sonarr', port='8989', auth=true) | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
- qbittorrent
|
- qbittorrent
|
||||||
networks:
|
networks:
|
||||||
- default
|
- ipv4_only
|
||||||
- traefik_traefik
|
- traefik_traefik
|
||||||
volumes:
|
volumes:
|
||||||
- {{ base_volume_path }}/arrstack/config/sonarr:/config
|
- {{ base_volume_path }}/arrstack/config/sonarr:/config
|
||||||
@ -61,12 +66,12 @@ services:
|
|||||||
image: linuxserver/radarr:latest
|
image: linuxserver/radarr:latest
|
||||||
container_name: radarr
|
container_name: radarr
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("radarr", port="7878", auth=true) | indent(6) }}
|
- {{ helpers.traefik_labels('radarr', port='7878', auth=true) | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
- qbittorrent
|
- qbittorrent
|
||||||
networks:
|
networks:
|
||||||
- default
|
- ipv4_only
|
||||||
- traefik_traefik
|
- traefik_traefik
|
||||||
volumes:
|
volumes:
|
||||||
- {{ base_volume_path }}/arrstack/config/radarr:/config
|
- {{ base_volume_path }}/arrstack/config/radarr:/config
|
||||||
|
@ -7,5 +7,5 @@ PrivateKey = {{ wg_privkey }}
|
|||||||
|
|
||||||
[Peer]
|
[Peer]
|
||||||
PublicKey = {{ wg_peer_pubkey }}
|
PublicKey = {{ wg_peer_pubkey }}
|
||||||
AllowedIPs = 0.0.0.0/0
|
AllowedIPs = 0.0.0.0/0,::0/0
|
||||||
Endpoint = {{ wg_peer_endpoint }}
|
Endpoint = {{ wg_peer_endpoint }}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
|
{% import 'contrib/compose_helpers.j2' as helpers with context %}
|
||||||
{##}
|
{##}
|
||||||
version: "3.7"
|
version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
{{ helpers.default_network(253) | indent(2) }}
|
||||||
traefik_traefik:
|
traefik_traefik:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
@ -12,11 +12,14 @@ services:
|
|||||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}
|
image: ghcr.io/goauthentik/server:${AUTHENTIK_VERSION}
|
||||||
container_name: authentik_server
|
container_name: authentik_server
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("auth", port="9000") | indent(6) }}
|
- {{ helpers.traefik_labels('auth', port='9000') | indent(6) }}
|
||||||
- traefik.http.middlewares.authentik.forwardauth.address=http://authentik_server:9000/outpost.goauthentik.io/auth/traefik
|
- traefik.http.middlewares.authentik.forwardauth.address=http://localhost:9000/outpost.goauthentik.io/auth/traefik
|
||||||
- traefik.http.middlewares.authentik.forwardauth.trustForwardHeader=true
|
- traefik.http.middlewares.authentik.forwardauth.trustForwardHeader=true
|
||||||
- traefik.http.middlewares.authentik.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
|
- traefik.http.middlewares.authentik.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
# Port forward is needed because traefik can't resolve the container name from the host network
|
||||||
|
ports:
|
||||||
|
- "9000:9000"
|
||||||
command: server
|
command: server
|
||||||
env_file:
|
env_file:
|
||||||
- .env.authentik
|
- .env.authentik
|
||||||
@ -61,3 +64,5 @@ services:
|
|||||||
interval: 30s
|
interval: 30s
|
||||||
retries: 5
|
retries: 5
|
||||||
timeout: 3s
|
timeout: 3s
|
||||||
|
volumes:
|
||||||
|
- {{ base_volume_path }}/authentik/redis:/data
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
- name: Install Debian packages
|
||||||
|
become: yes
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-compose-plugin
|
||||||
|
- firewalld
|
||||||
|
state: latest
|
||||||
|
|
||||||
- name: Upgrade Debian packages
|
- name: Upgrade Debian packages
|
||||||
become: yes
|
become: yes
|
||||||
ansible.builtin.apt:
|
ansible.builtin.apt:
|
||||||
@ -8,6 +17,44 @@
|
|||||||
state: latest
|
state: latest
|
||||||
register: apt_upgrades
|
register: apt_upgrades
|
||||||
|
|
||||||
|
- name: Allow SSH
|
||||||
|
become: yes
|
||||||
|
firewalld:
|
||||||
|
service: ssh
|
||||||
|
permanent: yes
|
||||||
|
state: enabled
|
||||||
|
immediate: yes
|
||||||
|
|
||||||
|
- name: Allow Web
|
||||||
|
become: yes
|
||||||
|
firewalld:
|
||||||
|
service: http
|
||||||
|
permanent: yes
|
||||||
|
state: disabled
|
||||||
|
immediate: yes
|
||||||
|
|
||||||
|
- name: Allow Web Secure
|
||||||
|
become: yes
|
||||||
|
firewalld:
|
||||||
|
service: https
|
||||||
|
permanent: yes
|
||||||
|
state: enabled
|
||||||
|
immediate: yes
|
||||||
|
|
||||||
|
- name: Allow 443 udp for http3
|
||||||
|
become: yes
|
||||||
|
firewalld:
|
||||||
|
port: 443/udp
|
||||||
|
permanent: yes
|
||||||
|
state: enabled
|
||||||
|
immediate: yes
|
||||||
|
|
||||||
|
- name: Enable Firewall
|
||||||
|
become: yes
|
||||||
|
firewalld:
|
||||||
|
state: enabled
|
||||||
|
immediate: yes
|
||||||
|
|
||||||
- name: Reboot if needed
|
- name: Reboot if needed
|
||||||
become: yes
|
become: yes
|
||||||
ansible.builtin.reboot:
|
ansible.builtin.reboot:
|
||||||
|
@ -3,3 +3,41 @@
|
|||||||
state: directory
|
state: directory
|
||||||
path: "{{ my_svc_path }}"
|
path: "{{ my_svc_path }}"
|
||||||
mode: "700"
|
mode: "700"
|
||||||
|
|
||||||
|
- name: Get IPv6 subnet for Docker
|
||||||
|
set_fact:
|
||||||
|
docker_ipv6_subnet: "{{ \
|
||||||
|
ansible_default_ipv6.address \
|
||||||
|
| ansible.utils.ipsubnet(64) \
|
||||||
|
| ansible.utils.ipsubnet(72, docker_ipv6_index) \
|
||||||
|
}}"
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
var: docker_ipv6_subnet
|
||||||
|
|
||||||
|
- name: Configure Docker daemon
|
||||||
|
become: yes
|
||||||
|
template:
|
||||||
|
src: "daemon.json.j2"
|
||||||
|
dest: "/etc/docker/daemon.json"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
register: docker_daemon_config
|
||||||
|
|
||||||
|
- name: Remove docker0 from firewalld trusted zone
|
||||||
|
become: yes
|
||||||
|
firewalld:
|
||||||
|
zone: trusted
|
||||||
|
interface: docker0
|
||||||
|
permanent: yes
|
||||||
|
immediate: yes
|
||||||
|
state: disabled
|
||||||
|
register: docker0_firewalld
|
||||||
|
|
||||||
|
- name: Restart Docker daemon
|
||||||
|
become: yes
|
||||||
|
service:
|
||||||
|
name: docker
|
||||||
|
state: restarted
|
||||||
|
when: docker_daemon_config.changed or docker0_firewalld.changed
|
||||||
|
4
roles/docker_host/templates/daemon.json.j2
Normal file
4
roles/docker_host/templates/daemon.json.j2
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"ipv6": true,
|
||||||
|
"fixed-cidr-v6": "{{ docker_ipv6_subnet | ansible.utils.ipsubnet(80, 0) }}"
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
|
{% import 'contrib/compose_helpers.j2' as helpers with context %}
|
||||||
{##}
|
{##}
|
||||||
version: "3.7"
|
version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
{{ helpers.default_network(252) | indent(2) }}
|
||||||
traefik_traefik:
|
traefik_traefik:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ services:
|
|||||||
image: gitea/gitea:1.18
|
image: gitea/gitea:1.18
|
||||||
container_name: gitea_server
|
container_name: gitea_server
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("gitea", port="3000") | indent(6) }}
|
- {{ helpers.traefik_labels('gitea', port='3000') | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- .env.gitea
|
- .env.gitea
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
|
{% import 'contrib/compose_helpers.j2' as helpers with context %}
|
||||||
{##}
|
{##}
|
||||||
version: "3.7"
|
version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
{{ helpers.default_network(250) | indent(2) }}
|
||||||
traefik_traefik:
|
traefik_traefik:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ services:
|
|||||||
image: jellyfin/jellyfin:10.8.6
|
image: jellyfin/jellyfin:10.8.6
|
||||||
container_name: jellyfin_jellyfin
|
container_name: jellyfin_jellyfin
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("jellyfin", port="8096") | indent(6) }}
|
- {{ helpers.traefik_labels('jellyfin', port='8096') | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file:
|
env_file:
|
||||||
- .env.jellyfin
|
- .env.jellyfin
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
|
{% import 'contrib/compose_helpers.j2' as helpers with context %}
|
||||||
{##}
|
{##}
|
||||||
version: "3.7"
|
version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
{{ helpers.default_network(251) | indent(2) }}
|
||||||
traefik_traefik:
|
traefik_traefik:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ services:
|
|||||||
image: nginx:1.23-alpine
|
image: nginx:1.23-alpine
|
||||||
container_name: nextcloud_web
|
container_name: nextcloud_web
|
||||||
labels:
|
labels:
|
||||||
- {{ traefik_labels("nc") | indent(6) }}
|
- {{ helpers.traefik_labels('nc') | indent(6) }}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
links:
|
links:
|
||||||
- app
|
- app
|
||||||
|
@ -1,35 +1,37 @@
|
|||||||
{% from "contrib/compose_helpers.j2" import traefik_labels with context %}
|
{% import 'contrib/compose_helpers.j2' as helpers with context %}
|
||||||
{##}
|
{##}
|
||||||
version: "3.7"
|
version: "3.9"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
|
||||||
traefik:
|
traefik:
|
||||||
internal: true
|
internal: true
|
||||||
|
enable_ipv6: true
|
||||||
ipam:
|
ipam:
|
||||||
config:
|
config:
|
||||||
- subnet: {{ traefik_ip }}/24
|
- subnet: {{ traefik_ip }}/24
|
||||||
|
- subnet: {{ docker_ipv6_subnet | ansible.utils.ipsubnet(80, 255) }}
|
||||||
|
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:v2.9
|
image: traefik:v2.9
|
||||||
container_name: traefik
|
container_name: traefik
|
||||||
labels:
|
|
||||||
- {{ traefik_labels("traefik", service="api@internal") | indent(6) }}
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
- "8080:8080"
|
|
||||||
env_file:
|
env_file:
|
||||||
- .env.traefik
|
- .env.traefik
|
||||||
networks:
|
network_mode: host
|
||||||
default:
|
|
||||||
traefik:
|
|
||||||
ipv4_address: {{ traefik_ip }}
|
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
||||||
- ./traefik.yml:/etc/traefik/traefik.yml:ro
|
- ./traefik.yml:/etc/traefik/traefik.yml:ro
|
||||||
- {{ base_volume_path }}/traefik/rules:/rules:ro
|
- ./rules:/rules:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- {{ base_volume_path }}/traefik/rules:/rules/extra:ro
|
||||||
- {{ base_volume_path }}/traefik/logs:/logs
|
- {{ base_volume_path }}/traefik/logs:/logs
|
||||||
- {{ base_volume_path }}/traefik/acme:/acme
|
- {{ base_volume_path }}/traefik/acme:/acme
|
||||||
|
|
||||||
|
# This is mostly just so that the traefik network gets created
|
||||||
|
whoami:
|
||||||
|
image: containous/whoami
|
||||||
|
container_name: whoami
|
||||||
|
labels:
|
||||||
|
- {{ helpers.traefik_labels('whoami', port=80) | indent(6) }}
|
||||||
|
networks:
|
||||||
|
- traefik
|
||||||
|
25
roles/traefik/templates/rules/traefik-dash.yml.j2
Normal file
25
roles/traefik/templates/rules/traefik-dash.yml.j2
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
http:
|
||||||
|
routers:
|
||||||
|
traefik-dash:
|
||||||
|
rule: "Host(`traefik.{{ domain }}`)"
|
||||||
|
entryPoints:
|
||||||
|
- web
|
||||||
|
service: traefik-dash
|
||||||
|
|
||||||
|
traefik-dash-tls:
|
||||||
|
rule: "Host(`traefik.{{ domain }}`)"
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
service: traefik-dash
|
||||||
|
tls:
|
||||||
|
certResolver: letsencrypt
|
||||||
|
domains:
|
||||||
|
- main: "{{ domain }}"
|
||||||
|
sans:
|
||||||
|
- "*.{{ domain }}"
|
||||||
|
|
||||||
|
services:
|
||||||
|
traefik-dash:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
- url: "http://localhost:8080"
|
@ -8,14 +8,16 @@ accessLog:
|
|||||||
filePath: /logs/access.log
|
filePath: /logs/access.log
|
||||||
bufferingSize: 100
|
bufferingSize: 100
|
||||||
|
|
||||||
|
experimental:
|
||||||
|
http3: true
|
||||||
|
|
||||||
entryPoints:
|
entryPoints:
|
||||||
web:
|
web:
|
||||||
address: ":80"
|
address: ":80"
|
||||||
forwardedHeaders:
|
|
||||||
trustedIPs:
|
|
||||||
- "172.16.0.0/12"
|
|
||||||
websecure:
|
websecure:
|
||||||
address: ":443"
|
address: ":443"
|
||||||
|
http3:
|
||||||
|
advertisedPort: 443
|
||||||
|
|
||||||
certificatesResolvers:
|
certificatesResolvers:
|
||||||
letsencrypt:
|
letsencrypt:
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
- docker_host
|
- docker_host
|
||||||
- traefik
|
- traefik
|
||||||
- authentik
|
- authentik
|
||||||
|
- gitea
|
||||||
- nextcloud
|
- nextcloud
|
||||||
- jellyfin
|
- jellyfin
|
||||||
- gitea
|
|
||||||
- arrstack
|
- arrstack
|
||||||
post_tasks:
|
post_tasks:
|
||||||
- name: Docker prune objects
|
- name: Docker prune objects
|
||||||
|
Loading…
x
Reference in New Issue
Block a user