Skip to content

Instantly share code, notes, and snippets.

@Sergeydigl3
Last active November 11, 2025 23:21
Show Gist options
  • Select an option

  • Save Sergeydigl3/7efa11fa11b7fa97f54b1eb69fa1a53f to your computer and use it in GitHub Desktop.

Select an option

Save Sergeydigl3/7efa11fa11b7fa97f54b1eb69fa1a53f to your computer and use it in GitHub Desktop.
Traefik Best wildcard setup
CF_API_TOKEN=token_same
CF_DNS_API_TOKEN=token_same # Idk which token name is valid
CF_EMAIL=[email protected]
DOMAIN_1=ex1.ru
DOMAIN_2=ex2.ru
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
env_file:
- .env
command:
- "--configFile=/etc/traefik/traefik.yml"
# Domains from environment variables
- "--entrypoints.websecure.http.tls.domains[0].main=${DOMAIN_1}"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.${DOMAIN_1}"
- "--entrypoints.websecure.http.tls.domains[1].main=${DOMAIN_2}"
- "--entrypoints.websecure.http.tls.domains[1].sans=*.${DOMAIN_2}"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
- ./dynamic.yml:/etc/traefik/dynamic.yml:ro
- traefik_letsencrypt:/letsencrypt
networks:
- caddy
- nextcloud-aio
volumes:
traefik_letsencrypt:
networks:
caddy:
external: true
nextcloud-aio:
external: true
http:
routers:
dashboard:
rule: Host(`traefik.{{ env "DOMAIN_1" }}`)
entryPoints:
- websecure
middlewares:
- dashboard-auth
service: api@internal
devloop-respond:
rule: Host(`{{ env "DOMAIN_1" }}`)
service: noop@internal
middlewares:
- devloop-msg
akitari-respond:
rule: Host(`{{ env "DOMAIN_2" }}`)
service: noop@internal
middlewares:
- akitari-msg
nextcloud:
rule: Host(`nc.{{ env "DOMAIN_1" }}`)
service: nextcloud-service
aio-nextcloud:
rule: Host(`aionc.{{ env "DOMAIN_1" }}`)
service: aionc-service
services:
nextcloud-service: { loadBalancer: { servers: [ { url: "http://nextcloud-aio-apache:11000" } ] } }
aionc-service: { loadBalancer: { servers: [ { url: "https://nextcloud-aio-mastercontainer:8080" } ] } }
middlewares:
dashboard-auth:
basicAuth:
users:
- "dingo3:$apr1$4LKL1amA$vj.8e5l.vMidL360oW0Tw1"
devloop-msg:
plugin:
staticresponse:
Body: Hello mister fish...
StatusCode: "200"
akitari-msg:
plugin:
staticresponse:
Body: Hello mister crabs...
StatusCode: "200"
entryPoints:
web:
address: ":80"
asDefault: false
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: false
websecure:
asDefault: true
address: ":443"
http:
tls:
certResolver: cf_prod
# domains:
# - main: "dn1.ru"
# sans:
# - "*.dn1.ru"
# - main: "dn2.ru"
# sans:
# - "*.dn2.ru"
certificatesResolvers:
cf_test:
acme:
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
storage: "/letsencrypt/acme-test"
dnsChallenge: &dnsChallenge
provider: cloudflare
#disablePropagationCheck: true # uncomment this if you have issues pulling certificates through cloudflare, By setting this flag to true disables the need to wait for the propagation of the TXT record to all authoritative name servers.
delayBeforeCheck: 60s # uncomment along with disablePropagationCheck if needed to ensure the TXT record is ready before verification is attempted
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
- "8.8.8.8:53"
cf_prod:
acme:
storage: "/letsencrypt/acme-prod"
dnsChallenge: *dnsChallenge
providers:
docker:
exposedByDefault: false
file:
filename: /etc/traefik/dynamic.yml
watch: true
serversTransport:
insecureSkipVerify: true
experimental:
plugins:
staticresponse:
moduleName: "github.com/jdel/staticresponse"
version: "v0.0.1"
api:
dashboard: true
log:
level: INFO
services:
whoami:
image: traefik/whoami:latest
container_name: whoami
labels:
- traefik.enable=true
- traefik.http.routers.whoami.rule=Host(`whoami.dn1.ru`)
# Optional. Not always needed
# - traefik.http.services.whoami.loadbalancer.server.port=12345
# But also you can just add expose section
# expose:
# - "12345"
networks:
- caddy
networks:
caddy:
external: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment