do traefik for ansible

This commit is contained in:
Kyattsukuro 2026-09-10 23:15:35 +02:00
parent 21ef8778af
commit 852e36d8bc
9 changed files with 140 additions and 37 deletions

1
README.md Normal file
View File

@ -0,0 +1 @@
# traefik

17
defaults/main.yml Normal file
View File

@ -0,0 +1,17 @@
path: /srv/{{ role_name }}
traefik_override: {}
traefik_defaults:
expose_additional_ports: [] # 22 and 2022 will activate ssh
include_external_services:
config.yml.j2:
main_domain: ""
arpa_top_level: ""
http_port: ""
https_port: ""
hetzner_api_token: ""
duckdns_api_token: ""
basic_auth_password: ""

9
handlers/main.yml Normal file
View File

@ -0,0 +1,9 @@
- name: restart container
community.docker.docker_compose_v2:
project_src: "{{ path }}"
project_name: "{{ role_name }}"
recreate: "always"
services: ["traefik"]
state: "restarted"
when: not _traefik_already_restarted

17
meta/main.yml Normal file
View File

@ -0,0 +1,17 @@
---
galaxy_info:
author: "Niklas Freese <niklas@urmel.de>"
description: traefik
company: "Urmel Services"
license: AGPL-3.0-or-later
min_ansible_version: 2.1
# If this a Container Enabled role, provide the minimum Ansible Container version.
# min_ansible_container_version:
galaxy_tags: []
# List tags for your role here, one per line. A tag is a keyword that describes
# and categorizes the role. Users find roles by searching for tags. Be sure to
# remove the '[]' above, if you add tags to this list.
#
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
# Maximum 20 tags per role.

47
tasks/main.yml Normal file
View File

@ -0,0 +1,47 @@
---
- name: "set local variables from overrides and defaults"
set_fact:
traefik: "{{ (traefik_defaults | combine(traefik_override, recursive=True)) if traefik_override else traefik_defaults }}"
- name: "Set arpa domain"
set_fact:
arpa_top_level: "{{ traefik.arpa_top_level | default(traefik.main_domain.split('.')[-2:] | join('.'), true) }}"
- name: ensure that path exists
file:
path: "{{ path }}/config/file_provider"
state: directory
- name: ensure that data exists
file:
path: "{{ path }}/data"
state: directory
- name: template docker-compose
template:
src: compose.yml.j2
dest: "{{ path }}/compose.yml"
- name: template traefik.yml
template:
src: traefik.yml.j2
dest: "{{ path }}/config/traefik.yml"
- name: Populate templates
template:
src: "configs/{{ item.path }}"
dest: "{{ path }}/config/file_provider/{{ item.path | regex_replace('\\.j2$', '') }}"
with_filetree: "{{ role_path }}/templates/configs"
when:
- item.state == "file"
- item.path | regex_replace('\\.yml\\.j2$', '') | basename in traefik.include_external_services.keys()
- name: ensure container is running
community.docker.docker_compose_v2:
project_src: "{{ path }}"
project_name: "{{ role_name }}"
state: "present"
pull: "always"
wait: true
services: ["traefik"]
register: _compose_result

View File

@ -1,5 +1,3 @@
version: '3'
services: services:
traefik: traefik:
image: traefik:v3.6.7 image: traefik:v3.6.7
@ -10,33 +8,36 @@ services:
networks: networks:
- exposed - exposed
ports: ports:
- 80:80 - {{ traefik.http_port }}:{{ traefik.http_port }}
- 443:443
- 2022:2022 - {{ traefik.https_port }}:{{ traefik.https_port }}
{% for port in traefik.expose_additional_ports %}
- "{{ port }}"
{% endfor %}
environment: environment:
- HETZNER_API_TOKEN=${HETZNER_API_TOKEN} - HETZNER_API_TOKEN={{ traefik.hetzner_api_token }}
- DUCKDNS_TOKEN=${DUCKDNS_TOKEN} {% if traefik.duckdns_api_token %}
- AUTH_STRING=${AUTH_STRING} - DUCKDNS_TOKEN={{ traefik.duckdns_api_token }}
{%- endif -%}
- AUTH_STRING={{ traefik.basic_auth_password }}
- DUCKDNS_POLLING_INTERVAL=5 - DUCKDNS_POLLING_INTERVAL=5
- DUCKDNS_PROPAGATION_TIMEOUT=120 - DUCKDNS_PROPAGATION_TIMEOUT=120
volumes: volumes:
- /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- ${PROJECT_PATH-$PWD}/traefik.yml:/traefik.yml:ro - ./config/traefik.yml:/traefik.yml:ro
- ${PROJECT_PATH-$PWD}/config:/config:ro - ./config/file_provider:/config:ro
- traefik-certs:/certs - ./data/certs:/certs
labels: labels:
traefik.enable: true traefik.enable: true
traefik.http.routers.traefik-dashboard.entrypoints: https traefik.http.routers.traefik-dashboard.entrypoints: https
traefik.http.routers.traefik-dashboard.rule: Host(`traefik.arpa.urmel.de`) traefik.http.routers.traefik-dashboard.rule: Host(`traefik.arpa.{{ arpa_top_level }}`)
traefik.http.routers.traefik-dashboard.tls: "true" traefik.http.routers.traefik-dashboard.tls: "true"
traefik.http.routers.traefik-dashboard.tls.certresolver: hetzner traefik.http.routers.traefik-dashboard.tls.certresolver: hetzner
traefik.http.routers.traefik-dashboard.service: api@internal traefik.http.routers.traefik-dashboard.service: api@internal
traefik.http.routers.traefik-dashboard.middlewares: local-only@file, traefik-auth@file traefik.http.routers.traefik-dashboard.middlewares: local-only@file
volumes:
traefik-certs:
networks: networks:
exposed: exposed:

View File

@ -2,19 +2,20 @@ http:
routers: routers:
traefik-secure: traefik-secure:
service: noop@internal service: noop@internal
rule: Host(`urmel.de`) rule: Host(`{{ traefik.main_domain }}`)
entryPoints: entryPoints:
- https - https
- http - http
tls: tls:
certResolver: hetzner certResolver: hetzner
domains: domains:
- main: "arpa.urmel.de" - main: "arpa.{{ arpa_top_level }}"
sans: sans:
- "*.arpa.urmel.de" - "*.arpa.{{ arpa_top_level }}"
- main: "urmel.de" - main: "{{ traefik.main_domain }}"
sans: sans:
- "*.urmel.de" - "*.{{ traefik.main_domain }}"
{% if traefik.duckdns_api_token -%}
forward-duckdns: forward-duckdns:
service: noop@internal service: noop@internal
rule: HostRegexp(`(.+\.)?urmel\.duckdns\.org`) rule: HostRegexp(`(.+\.)?urmel\.duckdns\.org`)
@ -29,21 +30,27 @@ http:
entryPoints: entryPoints:
- https - https
- http - http
{%- endif %}
middlewares: middlewares:
traefik-auth: traefik-auth:
basicauth: basicauth:
users: '{{ env "AUTH_STRING" }}' users: '{% raw %}{{ env "AUTH_STRING" }}{% endraw %}'
{% if traefik.duckdns_api_token %}
redirect-duckdns: redirect-duckdns:
redirectRegex: redirectRegex:
regex: "^http(s?)://(.+\\.)?urmel\\.duckdns\\.org(:[0-9]+)?(/.*$|$)" regex: "^http(s?)://(.+\\.)?urmel\\.duckdns\\.org(:[0-9]+)?(/.*$|$)"
replacement: "http${1}://${2}urmel.de${3}${4}" replacement: "http${1}://${2}urmel.de${3}${4}"
{% endif %}
local-only: local-only:
ipAllowList: ipAllowList:
sourceRange: sourceRange:
- "10.0.0.0/8" - "10.0.0.0/8"
- "172.16.0.0/12" - "172.16.0.0/12"
- "168.168.0.0/16" - "192.168.0.0/16"
secure-only: secure-only:
ipAllowList: ipAllowList:
sourceRange: sourceRange:

View File

@ -2,7 +2,7 @@ http:
routers: routers:
homeassistant: homeassistant:
service: homeassistant service: homeassistant
rule: Host(`home.urmel.de`) rule: Host(`home.{{ traefik.main_domain }}`)
priority: 10 priority: 10
entryPoints: entryPoints:
- https - https
@ -15,11 +15,11 @@ http:
homeassistant: homeassistant:
loadbalancer: loadbalancer:
servers: servers:
- url: "http://172.24.2.4:8123" - url: "http://{{ traefik.include_external_services.homeassistant.url }}:8123"
passHostHeader: true passHostHeader: true
middlewares: middlewares:
homeassistant-headers: homeassistant-headers:
headers: headers:
customResponseHeaders: customResponseHeaders:
X-Frame-Options: "ALLOW-FROM *.urmel.de" X-Frame-Options: "ALLOW-FROM *.{{ traefik.main_domain }}"
Content-Security-Policy: "frame-ancestors *.urmel.de" Content-Security-Policy: "frame-ancestors *.{{ traefik.main_domain }}"

View File

@ -4,7 +4,7 @@ api:
entryPoints: entryPoints:
http: http:
asDefault: true asDefault: true
address: ":80" address: ":{{ traefik.http_port }}"
http: http:
redirections: redirections:
entryPoint: entryPoint:
@ -12,9 +12,11 @@ entryPoints:
scheme: https scheme: https
https: https:
asDefault: true asDefault: true
address: ":443" address: ":{{ traefik.https_port }}"
{% if 2022 in traefik.expose_additional_ports -%}
public_ssh: public_ssh:
address: ":2022" address: ":2022"
{% endif -%}
serversTransport: serversTransport:
insecureSkipVerify: true insecureSkipVerify: true
providers: providers:
@ -35,6 +37,7 @@ certificatesResolvers:
provider: "hetzner" provider: "hetzner"
resolvers: resolvers:
- "hydrogen.ns.hetzner.com" - "hydrogen.ns.hetzner.com"
{% if traefik.duckdns_api_token -%}
duckdns: duckdns:
acme: acme:
email: nikl.free44@gmail.com email: nikl.free44@gmail.com
@ -49,3 +52,4 @@ certificatesResolvers:
resolvers: resolvers:
- "8.8.8.8:53" - "8.8.8.8:53"
- "1.1.1.1:53" - "1.1.1.1:53"
{%- endif %}