From c2f9a0c21c77ce42556855abc25cfae92cd2f31d Mon Sep 17 00:00:00 2001 From: jack Date: Sun, 22 Mar 2026 04:47:46 +0700 Subject: [PATCH] feat: wildcard TLS via Cloudflare DNS-01 + real-IP forwarding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Switch Traefik ACME to dnsChallenge (provider: cloudflare) - Add *.csrx.ru wildcard cert via tls.stores.default.defaultGeneratedCert - Pass CLOUDFLARE_DNS_API_TOKEN to Traefik via env_file: .env - Add Cloudflare IP ranges to forwardedHeaders.trustedIPs (real visitor IPs) - Fix UFW: allow 172.16.0.0/12 on 80/443 so act_runner can reach Forgejo - Add A records: auth.csrx.ru, status.csrx.ru, csrx.ru root → 87.249.49.32 Result: one *.csrx.ru cert covers all subdomains, auto-renewed by Traefik. Co-Authored-By: Claude Sonnet 4.6 --- roles/services/templates/docker-compose.yml.j2 | 4 ++-- .../templates/traefik/dynamic/routes.yml.j2 | 13 +++++++++++-- roles/services/templates/traefik/traefik.yml.j2 | 9 ++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/roles/services/templates/docker-compose.yml.j2 b/roles/services/templates/docker-compose.yml.j2 index 967c355..6fe9feb 100644 --- a/roles/services/templates/docker-compose.yml.j2 +++ b/roles/services/templates/docker-compose.yml.j2 @@ -69,8 +69,8 @@ services: - {{ services_root }}/traefik/dynamic:/etc/traefik/dynamic:ro - {{ services_root }}/traefik/acme.json:/acme/acme.json - {{ services_root }}/traefik/logs:/var/log/traefik - environment: - - CLOUDFLARE_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN} + # env_file passes CLOUDFLARE_DNS_API_TOKEN (and all secrets) to Traefik + env_file: .env logging: driver: json-file options: diff --git a/roles/services/templates/traefik/dynamic/routes.yml.j2 b/roles/services/templates/traefik/dynamic/routes.yml.j2 index e90a531..bc4e491 100644 --- a/roles/services/templates/traefik/dynamic/routes.yml.j2 +++ b/roles/services/templates/traefik/dynamic/routes.yml.j2 @@ -1,8 +1,17 @@ # Traefik dynamic routing config — generated by Ansible # Do not edit manually; re-run ansible-playbook deploy.yml -# NOTE: wildcard cert (*.csrx.ru) будет включён после переноса NS на Cloudflare. -# Тогда переключим ACME на dnsChallenge и добавим tls.stores.default.defaultGeneratedCert +# ── Wildcard TLS certificate via Cloudflare DNS-01 ──────────────────────────── +# One *.csrx.ru cert covers all subdomains. New services = zero cert wait. +tls: + stores: + default: + defaultGeneratedCert: + resolver: letsencrypt + domain: + main: "*.{{ domain_base }}" + sans: + - "{{ domain_base }}" http: routers: diff --git a/roles/services/templates/traefik/traefik.yml.j2 b/roles/services/templates/traefik/traefik.yml.j2 index 9511cdf..8053173 100644 --- a/roles/services/templates/traefik/traefik.yml.j2 +++ b/roles/services/templates/traefik/traefik.yml.j2 @@ -93,9 +93,12 @@ certificatesResolvers: acme: email: "{{ acme_email }}" storage: /acme/acme.json - # TODO: switch to dnsChallenge after Cloudflare NS propagation - httpChallenge: - entryPoint: web + dnsChallenge: + provider: cloudflare + # Use Cloudflare's own resolvers to avoid propagation delays + resolvers: + - "1.1.1.1:53" + - "1.0.0.1:53" providers: file: