|
version: '3.7' |
|
|
|
services: |
|
reverse-proxy: |
|
image: traefik:v2.10 |
|
command: |
|
- "--log" |
|
- "--log.level=${LOG_LEVEL:-INFO}" |
|
- "--log.format=json" |
|
- "--api.insecure=true" |
|
- "--providers.docker" |
|
- "--providers.docker.swarmMode=true" |
|
- "--providers.docker.exposedbydefault=false" |
|
- "--providers.file.directory=/config" |
|
- "--providers.file.watch=true" |
|
- "--serversTransport.insecureSkipVerify=true" # Allow self-signed certificates for target hosts - https://doc.traefik.io/traefik/routing/overview/#insecureskipverify |
|
- "--metrics" |
|
- "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0" |
|
- "--entrypoints.web.address=:80" |
|
- "--entrypoints.web.http.redirections.entrypoint.to=websecure" |
|
- "--entrypoints.web.http.redirections.entrypoint.scheme=https" |
|
- "--entrypoints.websecure.address=:443" |
|
- "--entrypoints.websecure.http.tls=true" |
|
- "--entrypoints.websecure.http.tls.certresolver=letsencrypt" |
|
- "--entrypoints.webinternal.address=:82" |
|
- "--certificatesresolvers.letsencrypt.acme.email=<YOUR EMAIL>" |
|
- "--certificatesresolvers.letsencrypt.acme.storage=/etc/traefik/acme/letsencrypt.json" |
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare" |
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.delaybeforecheck=300" |
|
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.resolvers=8.8.8.8:53" |
|
secrets: |
|
- cf_token |
|
environment: |
|
- CLOUDFLARE_DNS_API_TOKEN_FILE=/run/secrets/cf_token |
|
- CLOUDFLARE_HTTP_TIMEOUT=${HTTP_TIMEOUT} |
|
- CLOUDFLARE_POLLING_INTERVAL=${POLLING_INTERVAL} |
|
- CLOUDFLARE_PROPAGATION_TIMEOUT=${PROPAGATION_TIMEOUT} |
|
- CLOUDFLARE_TTL=${TTL} |
|
deploy: |
|
restart_policy: |
|
condition: any |
|
delay: 5s |
|
max_attempts: 3 |
|
window: 120s |
|
update_config: # Start new instance before stopping existing one |
|
delay: 10s |
|
order: start-first |
|
parallelism: 1 |
|
rollback_config: |
|
parallelism: 0 |
|
order: stop-first |
|
placement: |
|
constraints: |
|
- node.role == manager |
|
labels: |
|
- traefik.enable=true |
|
|
|
- traefik.http.routers.api.rule=Host(`traefik.${ROOT_DOMAIN}`) |
|
- traefik.http.routers.api.service=api@internal |
|
- traefik.http.routers.api.entrypoints=websecure |
|
- traefik.http.routers.api.tls=true |
|
|
|
- traefik.http.services.api.loadbalancer.server.port=8080 |
|
ports: |
|
# HTTP |
|
- target: 80 |
|
published: 80 |
|
|
|
# HTTPS |
|
- target: 443 |
|
published: 443 |
|
|
|
# Web UI (enabled by --api.insecure=true) |
|
- target: 8080 |
|
published: 8080 |
|
networks: |
|
- traefik |
|
- internal |
|
volumes: |
|
# So that Traefik can listen to the Docker events |
|
- /var/run/docker.sock:/var/run/docker.sock |
|
- acme:/etc/traefik/acme |
|
- traefik:/config |
|
- cloudflare:/cloudflare |
|
|
|
traefik-forward-auth: |
|
image: thomseddon/traefik-forward-auth:2.1.0 |
|
networks: |
|
- traefik |
|
environment: |
|
- PROVIDERS_GOOGLE_CLIENT_ID=${PROVIDERS_GOOGLE_CLIENT_ID} |
|
- PROVIDERS_GOOGLE_CLIENT_SECRET=${PROVIDERS_GOOGLE_CLIENT_SECRET} |
|
- SECRET=${SECRET} |
|
- AUTH_HOST=auth.${ROOT_DOMAIN} |
|
- COOKIE_DOMAIN=${ROOT_DOMAIN} |
|
- WHITELIST=${WHITELIST} |
|
deploy: |
|
labels: |
|
- traefik.enable=true |
|
- traefik.docker.network=traefik |
|
|
|
- traefik.http.routers.auth.rule=Host(`auth.${ROOT_DOMAIN}`) |
|
- traefik.http.routers.auth.entrypoints=websecure |
|
- traefik.http.routers.auth.tls=true |
|
- traefik.http.routers.auth.tls.domains[0].main=${ROOT_DOMAIN} |
|
- traefik.http.routers.auth.tls.domains[0].sans=*.${ROOT_DOMAIN} |
|
- traefik.http.routers.auth.tls.certresolver=letsencrypt |
|
- traefik.http.routers.auth.service=auth@docker |
|
|
|
- traefik.http.services.auth.loadbalancer.server.port=4181 |
|
|
|
- traefik.http.middlewares.forward-auth.forwardauth.address=http://traefik-forward-auth:4181 |
|
- traefik.http.middlewares.forward-auth.forwardauth.trustForwardHeader=true |
|
- traefik.http.middlewares.forward-auth.forwardauth.authResponseHeaders=X-Forwarded-User |
|
|
|
- traefik.http.routers.auth.middlewares=forward-auth |
|
|
|
- traefik.constraint=proxy-public |
|
|
|
tunnel: |
|
container_name: cloudflared-tunnel |
|
image: cloudflare/cloudflared |
|
restart: unless-stopped |
|
command: tunnel run |
|
deploy: |
|
mode: replicated |
|
replicas: 3 |
|
update_config: |
|
delay: 30s |
|
order: start-first |
|
monitor: 20s |
|
networks: |
|
- traefik |
|
environment: |
|
- TUNNEL_TOKEN=${TUNNEL_TOKEN} |
|
|
|
error-pages: |
|
image: tarampampam/error-pages:2.26.0 |
|
environment: |
|
TEMPLATE_NAME: l7-dark |
|
networks: |
|
- traefik |
|
deploy: |
|
mode: replicated |
|
replicas: 2 |
|
update_config: |
|
delay: 20s |
|
order: start-first |
|
monitor: 10s |
|
labels: |
|
- traefik.enable=true |
|
- traefik.docker.network=traefik |
|
|
|
# use as "fallback" for any non-registered services (with priority below normal) |
|
- traefik.http.routers.error-pages.rule=HostRegexp(`{host:.+}`) |
|
- traefik.http.routers.error-pages.priority=10 |
|
|
|
# should say that all of your services work on https |
|
- traefik.http.routers.error-pages.tls='true' |
|
- traefik.http.routers.error-pages.entrypoints=websecure |
|
- traefik.http.routers.error-pages.middlewares=error-pages |
|
- traefik.http.services.error-pages.loadbalancer.server.port=8080 |
|
|
|
# "errors" middleware settings |
|
- traefik.http.middlewares.error-pages.errors.status=400-599 |
|
- traefik.http.middlewares.error-pages.errors.service=error-pages |
|
- traefik.http.middlewares.error-pages.errors.query=/{status}.html |
|
|
|
cloudflare-companion: |
|
image: ghcr.io/tiredofit/docker-traefik-cloudflare-companion:latest |
|
volumes: |
|
- /var/run/docker.sock:/var/run/docker.sock |
|
deploy: |
|
placement: |
|
constraints: |
|
- node.role == manager |
|
environment: |
|
- TIMEZONE=Europe/London |
|
|
|
- LOG_TYPE=CONSOLE |
|
- LOG_LEVEL=INFO |
|
|
|
- TRAEFIK_VERSION=2 |
|
- RC_TYPE=CNAME |
|
|
|
- TARGET_DOMAIN=${ROOT_DOMAIN} |
|
- REFRESH_ENTRIES=TRUE |
|
|
|
- DOCKER_SWARM_MODE=TRUE |
|
|
|
- ENABLE_TRAEFIK_POLL=TRUE |
|
- TRAEFIK_POLL_URL=https://traefik.${ROOT_DOMAIN}/api |
|
- TRAEFIK_FILTER_LABEL=traefik.constraint |
|
- TRAEFIK_FILTER=proxy-public |
|
|
|
- DOMAIN1=${ROOT_DOMAIN} |
|
- DOMAIN1_ZONE_ID=${ZONE_ID} |
|
- DOMAIN1_PROXIED=TRUE |
|
restart: always |
|
networks: |
|
- internal |
|
secrets: |
|
- cf_token |
|
|
|
networks: |
|
traefik: |
|
external: true |
|
internal: |
|
|
|
volumes: |
|
acme: |
|
traefik: |
|
cloudflare: |
|
|
|
secrets: |
|
cf_token: |
|
external: true |
Hi @mattdy,
An additional information, it seems that it's not created because the cloudflare-companion does not reach the traefik
It's required to create the traefik.mydomain DNS record before? If so, which record type and what's the destination.
Thanks in advance