traefik compose에 질문이 있습니다.
리버스 프록시 용으로 현재 Traefik에 도전하고 있습니다. 기존에 대부분 도커들을 unraid 커뮤니티 앱에 의존하고 있었는데 traefik은 아무래도 그러면 매우 불편할 것 같아 처음으로 compose에 도전하고 있습니다.
현재 최종 목표는 우선 nextcloud 리버스프록시이지만, 그 전에 클라우드 플레어를 통한 와일드카드 인증서 발급 및, 대쉬보드 실행이 목표입니다.
NavyStack님의 깃허브와 블로그를 토대로 나름대로의 구문들을 만들어 보았지만 compose up까지만 되고, 대쉬보드 실행이 전혀 되지 않아 이렇게 질문을 드리게 되었습니다.
https://github.com/NavyStack/nextcloud-onlyoffice-traefik/blob/b62f7beedc82057afba37d63913cf1d58563d6a2/docker-compose.yml
함께 와일드카드 인증서가 만들어져야 할(?) acme.json 파일도 전혀 반응이 없으며, log 파일도 log가 생기지 않습니다. 아마 제대로 compose가 되지 않은게 아닐까 싶습니다.
제 compose.yml 파일은 다음과 같습니다.
version: "3.9"
services:
traefik:
image: ${TRAEFIK_IMAGE_TAG}
command:
- "--log.level=${TRAEFIK_LOG_LEVEL}"
- "--log.filePath=/mnt/user/appdata/traefik/log/traefik.log"
- "--accesslog=true"
- "--api.dashboard=true"
- "--api.insecure=true"
- "--ping=true"
- "--ping.entrypoint=ping"
- "--entryPoints.ping.address=:8082"
- "--entryPoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--providers.docker=true"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedByDefault=false"
- "--providers.file.filename=/mnt/user/appdata/traefik/traefik.toml"
- "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
- "--certificatesresolvers.cloudflare.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.cloudflare.acme.email=${CLOUDFLARE_EMAIL}"
- "--certificatesresolvers.cloudflare.acme.KeyType=EC256"
- "--certificatesresolvers.cloudflare.acme.storage=/mnt/user/appdata/traefik/acme/acme.json"
- "--metrics.prometheus=true"
- "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
- "--global.checkNewVersion=true"
- "--global.sendAnonymousUsage=false"
- "--experimental.http3=true" # QUIC 활성화
- "--entrypoints.websecure.http3" # QUIC 활성화
- "--entrypoints.websecure.http3.advertisedport=443" # QUIC 활성화
environment:
- CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
- CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /mnt/user/appdata/traefik/acme:/etc/traefik/acme
- /mnt/user/appdata/traefik/traefik.toml:/etc/traefik/traefik.toml
- /mnt/user/appdata/traefik/rule/dynamic.toml:/etc/traefik/dynamic.toml
- /mnt/user/appdata/traefik/log:/mnt/user/appdata/traefik/log
networks:
- proxynet
ports:
- "80:80"
- "443:443/tcp"
- "443:443/udp" # QUIC 활성화
- "8080:8080/tcp"
healthcheck:
test: ["CMD", "wget", "http://localhost:8082/ping","--spider"]
interval: 10s
timeout: 5s
retries: 3
start_period: 5s
labels:
- "traefik.enable=true"
- "traefik.http.services.dashboard.loadbalancer.server.port=8080"
- "traefik.http.services.dashboard.loadbalancer.passhostheader=true"
- "traefik.http.routers.dashboard.rule=Host(${TRF_DOMAIN})"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=cloudflare"
- "traefik.http.routers.dashboard.tls.domains[0].main=${TRF_DOMAIN}"
- "traefik.http.routers.dashboard.tls.domains[0].sans=*.${TRF_DOMAIN}"
- "traefik.http.routers.dashboard.middlewares=authtraefik"
- "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.authtraefik.basicauth.users=${TRAEFIK_BASIC_AUTH}"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
restart: unless-stopped
logging:
options:
max-size: "20m"
networks:
proxynet:
external: true
함께 .env 파일 내용은 다음과 같습니다.
# Traefik Variables
TRAEFIK_IMAGE_TAG=traefik:latest
TRAEFIK_LOG_LEVEL=WARN
CLOUDFLARE_EMAIL=클라우드플레어 이메일
CLOUDFLARE_API_KEY=클라우드플레어 Global API Key
TRAEFIK_BASIC_AUTH=온라인htpasswd 생성기로 생성한 사용자 이름과 비밀번호(MD5)
TRF_DOMAIN=클라우드플레어에 연결된 개인 도메인
혹시 여기서 추가하거나 수정해야 할 구문이 뭐가 있는지 알려 주신다면 정말 감사하겠습니다.
원래 클라우드플레어에 등록된 example.com이 아니라 traefik.example.com로 대쉬보드를 연결하고 싶었지만..
거기 까지는 잘 모르겠네요.
어서 도커 리버스프록시에도 도전해 보고 싶은데 실력이 너무 부족합니다.
많은 가르침 부탁드리겠습니다 :)
acme.json 파일은 만들어야 합니다.
권한도 600으로 잡아야합니다 (보안)
그래서 git clone으로 하시는게 제일 편하구요. :)
이미 만들어서 올려놓았거든요
혹시 root로 하시나요?
재현 한번 해보겠습니다.
로그를 다시 확인하니
command traefik error: no configuration found in file: /etc/traefik/traefik.toml
에러가 발생하더라고요.
- "--providers.file.filename=/mnt/user/appdata/traefik/traefik.toml"
- /mnt/user/appdata/traefik/traefik.toml:/etc/traefik/traefik.toml
- /mnt/user/appdata/traefik/rule/dynamic.toml:/etc/traefik/dynamic.toml
를 # 처리 하니 대쉬보드 진입이 됩니다.
혹시 이 부분을 어떻게 해결해야 할까요?
반만 해결된 거네요.
도메인으로 진입 시, 대쉬보드가 404 page not found를....
traefik이 에러 찾기 쉽다고 하신 말씀을 얼추 이해할 것 같습니다.
대쉬보드 보니, host에 에러 사유가 나오네요.
error while parsing rule Host(shishamo.kr): shishamo.kr is not defined
invalid rule Host(shishamo.kr), error: shishamo.kr is not defined
라고요.
으어.. 되는 건 좋은데, 하나가 해결되니 다른 문제가 또..ㅋㅋㅋ
PC로 보니까 선생님의 docker-compose 파일에 마운트가 덜되었네요.
- "--certificatesresolvers.cloudflare.acme.storage=/mnt/user/appdata/traefik/acme/acme.json"
여기에서 =(또는 :)는 기준으로 오른쪽은 컨테이너 내부의 경로여야합니다.
경로 지정이 안되어있습니다 오른쪽은 컨테이너 내부에 마운트 되어야합니다.
마찬가지로
- "--log.filePath=/mnt/user/appdata/traefik/log/traefik.log"
- "--providers.file.filename=/mnt/user/appdata/traefik/traefik.toml"
이부분도 수정하셔야 할듯합니다. :)
https://github.com/NavyStack/traefik/blob/9e5ecacfbd09bc0c0e8680a76e3c5fd0d66cf7d8/etc/traefik.toml#L45
(이런식으로 컨테이너 안의 경로임)
지금 어디까지 하신 상황인가요?
지금보니까 제가 github에는 초보자분들 배려해서 복잡해 보일 수 있는거 안쪽으로 치워놓았는데,
혹시 중복으로 선언된거 없는지 확인하셔야 할듯 합니다 :)
저는 약간 걱정되는게, 어제 스테이징 인증서로 하라 말씀드렸는데,
혹시 인증서 제한 초과했으면 구글 트러스트 서비스 인증서로 도와드릴게요.
저는 LE는 제한 사항 때문에 불편해서 못쓰겠더라구요
아. 이제 어느정도 이해를 한 것 같습니다.
log랑 .toml은 해결이 된 것 같습니다.
경로 지정을 이상하게 하고 있었군요.
이제 host 에러를 수정해 봐야겠습니다.
아.. 저 구문에서 크게 발전한 것은 없지만.. 그래도 어느정도 오류 수정은 되었습니다.
NavyStack님이 언급하신 경로 문제는 수정되었습니다.
version: "3.9"
services:
traefik:
container_name: traefik
image: ${TRAEFIK_IMAGE_TAG}
command:
- "--log.level=${TRAEFIK_LOG_LEVEL}"
- "--log.filePath=/etc/traefik/log/traefik.log"
- "--accesslog=true"
- "--api.dashboard=true"
- "--api.insecure=true"
- "--ping=true"
- "--ping.entrypoint=ping"
- "--entryPoints.ping.address=:8082"
- "--entryPoints.web.address=:80"
- "--entryPoints.websecure.address=:443"
- "--providers.docker=true"
- "--providers.docker.endpoint=unix:///var/run/docker.sock"
- "--providers.docker.exposedByDefault=false"
- "--providers.file.filename=/etc/traefik/rule/traefik.toml"
- "--providers.file.filename=/etc/traefik/rule/dynamic.toml"
- "--certificatesresolvers.cloudflare.acme.dnschallenge=true"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.cloudflare.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
- "--certificatesresolvers.cloudflare.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.cloudflare.acme.email=${CLOUDFLARE_EMAIL}"
- "--certificatesresolvers.cloudflare.acme.KeyType=EC256"
- "--certificatesresolvers.cloudflare.acme.storage=/etc/traefik/acme/acme.json"
- "--metrics.prometheus=true"
- "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
- "--global.checkNewVersion=true"
- "--global.sendAnonymousUsage=false"
- "--experimental.http3=true" # QUIC 활성화
- "--entrypoints.websecure.http3" # QUIC 활성화
- "--entrypoints.websecure.http3.advertisedport=443" # QUIC 활성화
environment:
- CLOUDFLARE_EMAIL=${CLOUDFLARE_EMAIL}
- CLOUDFLARE_API_KEY=${CLOUDFLARE_API_KEY}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /mnt/cache/appdata/traefik/acme:/etc/traefik/acme
- /mnt/cache/appdata/traefik:/etc/traefik
- /mnt/cache/appdata/traefik/rule:/etc/traefik/rule
- /mnt/cache/appdata/traefik/log:/etc/traefik/log
networks:
- proxynet
ports:
- "80:80"
- "443:443/tcp"
- "443:443/udp" # QUIC 활성화
- "8080:8080/tcp"
healthcheck:
test: ["CMD", "wget", "http://localhost:8082/ping","--spider"]
interval: 20s
timeout: 5s
retries: 3
start_period: 5s
labels:
- "traefik.enable=true"
- "traefik.http.services.dashboard.loadbalancer.server.port=8080"
- "traefik.http.services.dashboard.loadbalancer.passhostheader=true"
- "traefik.http.routers.dashboard.rule=Host(${TRF_DOMAIN})"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls=true"
- "traefik.http.routers.dashboard.tls.certresolver=cloudflare"
- "traefik.http.routers.dashboard.tls.domains[0].main=${TRF_DOMAIN}"
- "traefik.http.routers.dashboard.tls.domains[0].sans=*.${TRF_DOMAIN}"
- "traefik.http.routers.dashboard.middlewares=authtraefik"
- "traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.authtraefik.basicauth.users=${TRAEFIK_BASIC_AUTH}"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
restart: unless-stopped
logging:
options:
max-size: "20m"
networks:
proxynet:
external: true
이후 traefik.toml과 dynamic.toml도 지정했습니다.
[http]
[http.middlewares]
[http.middlewares.security-headers.headers]
browserXssFilter = true
contentTypeNosniff = true
forceSTSHeader = true
stsPreload = true
sslRedirect = true
stsSeconds = 31536000
[http.middlewares.websocket.headers.customRequestHeaders]
X-Forwarded-Proto = "https, wss"
[http.middlewares.www-to-Root.redirectRegex]
regex = "^https?://www\\.(.+)"
replacement = "https://${1}"
permanent = true
[http.middlewares.compress-1024.compress]
minResponseBodyBytes = 1024
[tls.options]
[tls.options.default]
minVersion = "VersionTLS12"
[tls.options.mintls13]
minVersion = "VersionTLS13"
[global]
sendAnonymousUsage = false
checkNewVersion = true
[api]
dashboard = true
insecure = true
debug = true
[log]
level = "ERROR"
filePath = "/etc/traefik/log/traefik.log"
[accessLog]
filePath = "/etc/traefik/log/access.log"
[ping]
entryPoint = "ping"
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.redirections]
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
permanent = true
[entryPoints.websecure]
address = ":443"
[entryPoints.websecure.http3]
advertisedPort = 443
[entryPoints.ping]
address = ":8082"
[providers]
[providers.file]
watch = true
filename = "/etc/traefik/dynamic.toml"
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
exposedByDefault = false
network = "proxynet"
watch = true
[certificatesResolvers.cloudflare.acme]
email = "${CLOUDFLARE_EMAIL}"
storage = "/etc/traefik/acme/acme.json"
[certificatesResolvers.cloudflare.acme.dnsChallenge]
provider = "cloudflare"
resolvers = ["1.1.1.1:53", "1.0.0.1:53"]
[metrics]
[metrics.prometheus]
buckets = [0.1,0.3,1.2,5.0]
addEntryPointsLabels = true
addRoutersLabels = true
addServicesLabels = true
[experimental]
http3 = true
이제 해결할 부분은 입니다.
아직 클라우드플레어와 제대로 연결이 되지 않았나 봅니다.
404 페이지가 뜨더라고요.
time="2024-02-04T03:36:44Z" level=error msg="error while parsing rule Host(도메인): 도메인 is not defined" routerName=dashboard@docker entryPointName=websecure
time="2024-02-04T03:36:44Z" level=error msg="invalid rule Host(도메인), error: 도메인 is not defined" routerName=dashboard@docker entryPointName=websecure
스테이징 열겠습니다.
대쉬보드 도메인을 canme으로 서브도메인 지정하고, 넣으니
이렇게 뜹니다. 이러면 대쉬보드는 제대로 지정된 것이 맞지요????!!!!
그런데 지정된 TRAEFIK_BASIC_AUTH가 먹질 않네요. 이건 조금 더 찾아보겠습니다.
아예 제 API키 넣어서 깃허브에 올려드릴게요. 그거 확인해보세요. IP로 제한해서 어차피 다른사람은 못써써 ㅎㅎ
여기에 올렸습니다.
.env는 개인적으로 컨테이너 올라가는 것 보고 해도 늦지 않다고 생각하지만 사람마다 다를 수 있는거니까요 :)
처음 하시는데 너무 복잡하면 어질어질하니, 최대한 우겨넣었습니다.
선생님맞게 네트워크 이름도 변경하였구 선생님이 지정하신 인증서 리졸버 이름도 수정했습니다.
그나저나 api키를 잘못 입력했다니... Global API Key를 입력하는게 아니었던가요? ㅠㅠㅠ
진짜.. 이렇게까지 도움을 주시니 너무 감사합니다.
가능하면 토큰으로 권한을 엄격하게 해서 진행하세요. :)
정말 감사합니다.
올려주신 페이지 확인해서 수정하겠습니다.
다 하구 하셔요.. ㅠㅠ
Traefik 컨테이너만 먼저 올리고
https://github.com/NavyStack/focalboard-ns/blob/main/docker-compose-traefik.yml
이런식으로 간편하게 입력만 하면 나머지는 알아서 해줍니다.
다만, 현재 선생님은
cmt alert