version: "3.8" services: traefik: image: traefik:v3 container_name: traefik restart: unless-stopped command: - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--providers.docker.network=dns-net" - "--providers.file.directory=/etc/traefik/dynamic" - "--providers.file.watch=true" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" - "--entrypoints.websecure.http3" - "--entrypoints.dot.address=:853" - "--entrypoints.doq.address=:853/udp" - "--entrypoints.cluster.address=:53443" - "--certificatesresolvers.myresolver.acme.dnschallenge=true" - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=cloudflare" - "--certificatesresolvers.myresolver.acme.dnschallenge.resolvers=1.1.1.1:53,8.8.8.8:53" - "--certificatesresolvers.myresolver.acme.dnschallenge.delaybeforecheck=60s" - "--certificatesresolvers.myresolver.acme.email=admin@shnt.top" - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json" environment: - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} ports: - target: 80 published: 80 protocol: tcp mode: host - target: 443 published: 443 protocol: tcp mode: host - target: 443 published: 443 protocol: udp mode: host - target: 853 published: 853 protocol: tcp mode: host - target: 853 published: 853 protocol: udp mode: host - target: 53443 published: 53443 protocol: tcp mode: host volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt - ./traefik/dynamic:/etc/traefik/dynamic:ro networks: - dns-net technitium-smart: image: technitium/dns-server:latest container_name: technitium-smart restart: unless-stopped networks: - dns-net cap_add: - NET_ADMIN - NET_RAW - NET_BIND_SERVICE environment: - DNS_SERVER_ADMIN_PASSWORD=${DNS_SERVER_ADMIN_PASSWORD} - DNS_SERVER_ENABLE_DNS_OVER_HTTP=true - DNS_SERVER_ENABLE_DNS_OVER_TLS=false - DNS_SERVER_WEB_SERVICE_ENABLE_HTTPS=true - DNS_SERVER_WEB_SERVICE_HTTPS_PORT=53443 - DNS_SERVER_WEB_SERVICE_USE_SELF_SIGNED_CERT=true # Новая консоль: папку со статикой отдаёт том technitium-console (нужен Technitium 15.5+) - DNS_SERVER_WEB_SERVICE_WWW_FOLDER_PATH=/opt/technitium-console - TZ=Asia/Novosibirsk - ASPNETCORE_FORWARDEDHEADERS_ENABLED=true - DOTNET_SYSTEM_NET_SOCKETS_INLINE_RECEIVE=1 volumes: - technitium-data:/etc/dns - technitium-console:/opt/technitium-console:ro # AXFR зоны кластера (TLSA). Если 53 уже слушает не этот контейнер, удалите блок. # Файрволом пускайте TCP/53 только с IP соседних нод. # ports: # - target: 53 # published: 53 # protocol: tcp # mode: host # - target: 53 # published: 53 # protocol: udp # mode: host labels: - "traefik.enable=true" - "traefik.docker.network=dns-net" - "traefik.http.middlewares.old-panel-headers.headers.customrequestheaders.X-Forwarded-Proto=https" - "traefik.http.middlewares.old-panel-headers.headers.customrequestheaders.X-Forwarded-Host=old.dns.shnt.top" # DoH - "traefik.http.routers.doh.rule=(Host(`dns.shnt.top`) || HostRegexp(`^[a-z0-9-]+\\.dns\\.shnt\\.top$`) || Host(`ndns.shnt.top`) || HostRegexp(`^[a-z0-9-]+\\.ndns\\.shnt\\.top$`)) && PathPrefix(`/dns-query`)" - "traefik.http.routers.doh.entrypoints=websecure" - "traefik.http.routers.doh.tls.certresolver=myresolver" - "traefik.http.routers.doh.tls.domains[0].main=dns.shnt.top" - "traefik.http.routers.doh.tls.domains[0].sans=*.dns.shnt.top" - "traefik.http.routers.doh.tls.domains[1].main=ndns.shnt.top" - "traefik.http.routers.doh.tls.domains[1].sans=*.ndns.shnt.top" - "traefik.http.routers.doh.priority=1000" - "traefik.http.routers.doh.service=doh-svc" - "traefik.http.services.doh-svc.loadbalancer.server.port=8080" - "traefik.http.services.doh-svc.loadbalancer.server.scheme=http" # Панель - "traefik.http.routers.panel-old.rule=Host(`dns.shnt.top`) || Host(`old.dns.shnt.top`) || Host(`ndns.shnt.top`) || HostRegexp(`^[a-z0-9-]+\\.ndns\\.shnt\\.top$`)" - "traefik.http.routers.panel-old.entrypoints=websecure" - "traefik.http.routers.panel-old.tls.certresolver=myresolver" - "traefik.http.routers.panel-old.tls.domains[0].main=dns.shnt.top" - "traefik.http.routers.panel-old.tls.domains[0].sans=*.dns.shnt.top" - "traefik.http.routers.panel-old.tls.domains[1].main=ndns.shnt.top" - "traefik.http.routers.panel-old.tls.domains[1].sans=*.ndns.shnt.top" - "traefik.http.routers.panel-old.priority=10" - "traefik.http.routers.panel-old.middlewares=old-panel-headers" - "traefik.http.routers.panel-old.service=panel-old-svc" - "traefik.http.services.panel-old-svc.loadbalancer.server.port=5380" # DoT - "traefik.tcp.routers.dot.rule=HostSNI(`dns.shnt.top`) || HostSNIRegexp(`^.+\\.dns\\.shnt\\.top$`) || HostSNI(`ndns.shnt.top`) || HostSNIRegexp(`^.+\\.ndns\\.shnt\\.top$`)" - "traefik.tcp.routers.dot.entrypoints=dot" - "traefik.tcp.routers.dot.tls=true" - "traefik.tcp.routers.dot.tls.certresolver=myresolver" - "traefik.tcp.routers.dot.tls.domains[0].main=dns.shnt.top" - "traefik.tcp.routers.dot.tls.domains[0].sans=*.dns.shnt.top" - "traefik.tcp.routers.dot.tls.domains[1].main=ndns.shnt.top" - "traefik.tcp.routers.dot.tls.domains[1].sans=*.ndns.shnt.top" - "traefik.tcp.routers.dot.tls.options=dot@file" - "traefik.tcp.routers.dot.service=dot-svc" - "traefik.tcp.services.dot-svc.loadbalancer.server.port=538" - "traefik.tcp.services.dot-svc.loadbalancer.proxyprotocol.version=2" # DoQ - "traefik.udp.routers.doq.entrypoints=doq" - "traefik.udp.routers.doq.service=doq-svc" - "traefik.udp.services.doq-svc.loadbalancer.server.port=8530" # Кластер: TLS passthrough на Technitium :53443 (без certresolver и Proxy Protocol) - "traefik.tcp.routers.cluster.rule=HostSNI(`ndns.shnt.top`) || HostSNIRegexp(`^.+\\.ndns\\.shnt\\.top$`) || HostSNI(`dns.shnt.top`) || HostSNIRegexp(`^.+\\.dns\\.shnt\\.top$`)" - "traefik.tcp.routers.cluster.entrypoints=cluster" - "traefik.tcp.routers.cluster.tls.passthrough=true" - "traefik.tcp.routers.cluster.service=cluster-svc" - "traefik.tcp.services.cluster-svc.loadbalancer.server.port=53443" # Копирует новую консоль в том technitium-console и завершается. # Без labels Traefik: наружу этот контейнер ничего не отдаёт. # Обновление: docker compose pull technitium-console && docker compose up -d technitium-console technitium-console: image: git.shx.one/denozord/technitium-console:latest container_name: technitium-console restart: "no" volumes: - technitium-console:/target networks: - dns-net # Хаб: одна консоль со статистикой обоих серверов на https://dnss.shnt.top # (docs/hub-deploy.md). Только чтение. Токены и вход хаба берутся из .env: # MDNS_TOKEN, NDNS_TOKEN (пользователь hub-reader на каждом сервере), HUB_USER, HUB_PASSWORD. # Обновление: docker compose pull technitium-hub && docker compose up -d technitium-hub technitium-hub: image: git.shx.one/denozord/technitium-hub:latest container_name: technitium-hub restart: unless-stopped networks: - dns-net volumes: - technitium-hub-data:/data environment: # id=адрес по порядку; токен каждого из _TOKEN. Сервер на ЭТОМ же хосте можно # указать изнутри сети, мимо Traefik: ndns=http://technitium-smart:5380 - HUB_SERVERS=mdns=https://mdns.shnt.top,ndns=https://ndns.shnt.top - MDNS_TOKEN=${MDNS_TOKEN} - NDNS_TOKEN=${NDNS_TOKEN} # Токены hub-admin: без них хаб только читает. Нужны для установки и обновления приложений - MDNS_ADMIN_TOKEN=${MDNS_ADMIN_TOKEN} - NDNS_ADMIN_TOKEN=${NDNS_ADMIN_TOKEN} # Только пока нет /data/users.json; потом пользователи создаются через users-cli (docs/hub-deploy.md) - HUB_USER=${HUB_USER} - HUB_PASSWORD=${HUB_PASSWORD} - HUB_DATA=/data # За Traefik: брать адрес клиента из X-Forwarded-For (для ограничения попыток входа и журнала) - HUB_TRUST_PROXY=1 # Как часто проверять, что конфиги серверов не разошлись с эталоном (минуты, 0 выключает) # - HUB_DRIFT_MINUTES=15 - HUB_DOMAIN=dnss.shnt.top - TZ=Asia/Novosibirsk labels: - "traefik.enable=true" - "traefik.docker.network=dns-net" - "traefik.http.routers.hub.rule=Host(`dnss.shnt.top`)" - "traefik.http.routers.hub.entrypoints=websecure" - "traefik.http.routers.hub.tls.certresolver=myresolver" - "traefik.http.routers.hub.service=hub-svc" - "traefik.http.services.hub-svc.loadbalancer.server.port=8080" networks: dns-net: driver: bridge name: dns-net volumes: technitium-data: technitium-console: technitium-hub-data: