feat: wildcard TLS via Cloudflare DNS-01 + real-IP forwarding
Some checks failed
CI/CD / syntax-check (push) Successful in 44s
CI/CD / deploy (push) Failing after 46s

- 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 <noreply@anthropic.com>
This commit is contained in:
jack 2026-03-22 04:47:46 +07:00
parent f183fe485f
commit c2f9a0c21c
3 changed files with 19 additions and 7 deletions

View file

@ -69,8 +69,8 @@ services:
- {{ services_root }}/traefik/dynamic:/etc/traefik/dynamic:ro - {{ services_root }}/traefik/dynamic:/etc/traefik/dynamic:ro
- {{ services_root }}/traefik/acme.json:/acme/acme.json - {{ services_root }}/traefik/acme.json:/acme/acme.json
- {{ services_root }}/traefik/logs:/var/log/traefik - {{ services_root }}/traefik/logs:/var/log/traefik
environment: # env_file passes CLOUDFLARE_DNS_API_TOKEN (and all secrets) to Traefik
- CLOUDFLARE_DNS_API_TOKEN=${CLOUDFLARE_DNS_API_TOKEN} env_file: .env
logging: logging:
driver: json-file driver: json-file
options: options:

View file

@ -1,8 +1,17 @@
# Traefik dynamic routing config — generated by Ansible # Traefik dynamic routing config — generated by Ansible
# Do not edit manually; re-run ansible-playbook deploy.yml # Do not edit manually; re-run ansible-playbook deploy.yml
# NOTE: wildcard cert (*.csrx.ru) будет включён после переноса NS на Cloudflare. # ── Wildcard TLS certificate via Cloudflare DNS-01 ────────────────────────────
# Тогда переключим ACME на dnsChallenge и добавим tls.stores.default.defaultGeneratedCert # 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: http:
routers: routers:

View file

@ -93,9 +93,12 @@ certificatesResolvers:
acme: acme:
email: "{{ acme_email }}" email: "{{ acme_email }}"
storage: /acme/acme.json storage: /acme/acme.json
# TODO: switch to dnsChallenge after Cloudflare NS propagation dnsChallenge:
httpChallenge: provider: cloudflare
entryPoint: web # Use Cloudflare's own resolvers to avoid propagation delays
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
providers: providers:
file: file: