traefik 역방향프록시 어떻게 설정해야하나여.
traefik 구글 다 디졌는데도 설치방법뿐이 안나오네요. 친해지긴 힘들다 생각듭니다.
navystack님 블로그 및 서버포럼 작성글 참고 하였습니다.
헤놀: dva3221 7.2-u4
cloudfire= dns전용
잘돌아가긴 하는데 와일드카드 인증서 만들어지는거 맞는지 확인부탁합니다. 사이트마다 다 제각각이라 접근이 너무 어렵네요.
1.질문: domain.com, drive.domain.com, cam.domain.com 등을 역방향프록시 설정하려면 문장을 어디에다가 넣어야 하는건지요?
2.질문: http 자동 리다이렉션이 적용된건지도 궁금합니다.
version: "3.9" services: healthcheck: volumes: networks: ports: networks: volumes: |
좋은답변을 받기위해서는 좋은 질문이 필요합니다.
유의할점⚠️
- 예의를 지켜주세요. 답변자는 답변을 할 의무는 없습니다.
- 질문에 대한 대부분의 답은 검색으로 찾아보실 수 있습니다.
- 답변자가 답변을 하면서 대개 많은 경우는 다시 질문을 하는 경우가 많이 있습니다.
- (질문의 대한 정보가 부족합니다. ~일 경우 결과물이 어떻게 됩니까? 등등)
질문방법🙏
자신의 상황을 최대한 자세히 설명해주세요.
상황이 정확하고 많을 수록 답변의 정확도가 올라갑니다.
ex) ex) 헤놀로지라면 메인보드 모델 칩셋정보, CPU, 사용한 DSM 버전, 모델, 부수적인 추가 컨트롤러 나 랜카드 등과 어떠한 로더의 이미지를 사용했는지.(arpl-i18n, mshell), 어떤 버전을 사용했는지, 문제가있다면 어떠한것인지 스크린샷을 동반하고 에러의 경우 에러로그를 출력해서 주시면 좋습니다.
*가능하면 최신버전 OS/SW를 이용해주세요
답변에대한 피드백을 주세요.
정보가 질문에 모두 담겨있지않다면 대부분의 답변이 다른정보를 요구합니다.
이러한 답변에 대해 명확한 피드백을 주시면 도움이 됩니다.
저 같은 경우는
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"
- '--entryPoints.web.http.redirections.entryPoint.to=websecure'
- '--entrypoints.web.http.redirections.entryPoint.scheme=https'
- '--entrypoints.web.http.redirections.entrypoint.permanent=true'
- "--providers.docker=true"
- '--providers.docker.watch=true'
- '--providers.docker.network=proxynet'
- "--providers.docker.endpoint=tcp://dockersocket:2375"
- "--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.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"
- '--metrics.prometheus.addServicesLabels=true'
- '--metrics.prometheus.addrouterslabels=true'
- '--metrics.prometheus.addEntryPointsLabels=true'
- "--global.checkNewVersion=true"
- "--global.sendAnonymousUsage=false"
- "--experimental.http3=true" # QUIC 활성화
- "--entrypoints.websecure.http3" # QUIC 활성화
- "--entrypoints.websecure.http3.advertisedport=443" # QUIC 활성화
- "--experimental.plugins.geoblock.modulename=github.com/PascalMinder/geoblock" #geoblock 플러그인
- "--experimental.plugins.geoblock.version=v0.2.7" #geoblock 플러그인
- "--experimental.plugins.crowdsec-bouncer-traefik-plugin.modulename=github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin" #crowdsec 플러그인
- "--experimental.plugins.crowdsec-bouncer-traefik-plugin.version=v1.2.0" #crowdsec 플러그인
environment:
- CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN}
- TZ=Asia/Seoul
network_mode: "proxynet"
volumes:
- /mnt/cache/appdata/Reverse_Proxy/traefik/acme:/etc/traefik/acme
- /mnt/cache/appdata/Reverse_Proxy/traefik:/etc/traefik
- /mnt/cache/appdata/Reverse_Proxy/traefik/rule:/etc/traefik/rule
- /mnt/cache/appdata/Reverse_Proxy/traefik/log:/etc/traefik/log
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"
restart: unless-stopped
logging:
options:
max-size: "20m"
이렇게 설정하고, 대쉬보드는 도메인 할당이 필요없을 것 같아서 아예 라벨에서 제외했습니다.
그리고, 별도의 treafik.toml 파일에
[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 = "tcp://dockersocket:2375"
exposedByDefault = false
network = "proxynet"
watch = true
[certificatesResolvers.cloudflare.acme]
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
지정하였고(지금 잘 기억은 안나는데 이 부분에서 http를 https로, 그리고 http3로 연결하게 하던 걸로 기억하는..), 아, 위에 compose 파일에도 entrypoints가 있긴 하네요. 중복으로 들어간 듯한..?
dynamic.toml 파일에
[http]
[http.middlewares.security-headers.headers] #보안미들웨어
browserXssFilter = true # 브라우저의 내장 XSS(크로스 사이트 스크립팅) 필터를 활성화
contentTypeNosniff = true #브라우저가 응답의 MIME 유형을 추측하지 못하게 하여, MIME 유형 변조 공격을 방지
forceSTSHeader = true # HTTP Strict Transport Security(HSTS)를 구성
stsPreload = true # HTTP Strict Transport Security(HSTS)를 구성
stsSeconds = 31536000 # HTTP Strict Transport Security(HSTS)를 구성
stsincludesubdomains = false # HTTP Strict Transport Security(HSTS)를 구성
isdevelopment = false #개발 모드를 비활성화
referrerPolicy = "strict-origin-when-cross-origin"
customRequestHeaders.X-Forwarded-Proto = "https, wss" #이 헤드를 헤더를 "https, wss"로 설정, 프록시된 요청이 HTTPS/WSS(WebSocket Secure)로 이루어짐으로 나타냄
[http.middlewares.security-nextcloud.headers] #넥스트클라우드 커스텀. referrerPolicy 추가.
browserXssFilter = true
contentTypeNosniff = true
forceSTSHeader = true
stsPreload = true
stsSeconds = 31536000
stsincludesubdomains = false
isdevelopment = false
referrerPolicy = "no-referrer" #브라우저는 Referer 헤더를 전혀 보내지 않음, __Host-Prefix 용
customRequestHeaders.X-Forwarded-Proto = "https, wss"
[http.middlewares.www-to-Root.redirectRegex] #정규 표현식을 사용하여 요청을 다른 위치로 리다이렉트
regex = "^https?://www\\.(.+)" #“www” 서브도메인에서 루트 도메인으로의 리다이렉트를 설정
replacement = "https://${1}"
permanent = true
[http.middlewares.normal-compress.compress] #압축미들웨어(기본)
minResponseBodyBytes = 1024
[http.middlewares.large-compress.compress] # 압축미들웨어(라지, 넥클같은 고용량 클라우드 용?)
minResponseBodyBytes = 8192
[http.middlewares.ratelimit-normal.ratelimit] # rate limiting을 설정
average = 100 #특정 시간 동안 허용되는 평균 요청 수를 지정, 이 설정은 초당 100
burst = 50 #일시적인 요청의 폭증을 처리하기 위한 버퍼를 지정
[http.middlewares.ratelimit-large.ratelimit] # 대용량 파일, 동시 여러 미디어 스트리밍 등.
average = 1000
burst = 500
[http.middlewares.retry.retry] #재시도(retry) 미들웨어, 서비스 일시 불능 or 응답X 때 요청을 자동 재시도
attempts = 3 #3회 재시도도
[http.routers] #Traefik에서 HTTP 요청을 처리하는 라우터를 정의
[http.routers.nextcloud] #넥스트클라우드 이름의 라우터 정의
rule = "Host(`도메인`)" # 라우터가 어떤 요청을 처리할지를 결정하는 규칙을 정의, ''안의 도메인으로 들어오는 모든 요청 처리
service = "nextcloud-aio" # 라우터가 요청을 전달할 서비스를 지정
entrypoints = ["websecure"] #라우터가 수신할 네트워크 진입점을 지정
middlewares = ["crowdsec", "my-geoblock2", "security-nextcloud", "www-to-Root", "large-compress", "ratelimit-large", "retry"] #사용할 미들웨어
[http.routers.nextcloud.tls] # 라우터가 TLS(Transport Layer Security)를 사용하여 요청을 처리하도록 설정
certresolver = "cloudflare" # TLS 인증서를 해석하는데 사용할 CertResolver를 지정
domains = [ { main = "*.도메인" } ] #인증서를 발급받을 도메인을 지정
[http.services] #Traefik에서 사용할 서비스를 정의, 서비스는 라우터로부터 요청을 받아 처리
[http.services.nextcloud-aio.loadBalancer] #로드 밸런서 서비스를 정의, 로드 밸런서는 여러 서버 간에 요청을 분산
[[http.services.nextcloud-aio.loadBalancer.servers]] #서비스가 요청을 전달할 서버의 URL을 지정
url = "http://도커 내부 ip:포트번호"
[tls.options] # Traefik에서 사용할 TLS 옵션을 정의
[tls.options.default]
minVersion = "VersionTLS12"
[tls.options.mintls13]
minVersion = "VersionTLS13"
여러 미들웨어를 만들고, 라우터를 정의하고, 라우터에 미들웨어를 연결하고, 라우터가 사용할 와일드카드 도메인을 만들고 했습니다.
또 서비스에 연결할 도커 내부 ip 주소를 설정하고요.
저도 뭐, navystack님 도움 많이 받고 한 거라, 자세히 알지는 못합니다만... 조금이나마 도움이 되었으면 하네요/
만일 compose 라벨에 미들웨어나 구성할 예정이라면
# - "traefik.http.routers.dashboard.rule=Host(`${DASHBOARD_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.middlewares=authtraefik, security"
# - "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"
TRF_DOMAIN = 와일드카드 인증서용 도메인이나 도메인
뭐, 이런식으로 구성하시면 될 것 같습니다.
[http.services] #Traefik에서 사용할 서비스를 정의, 서비스는 라우터로부터 요청을 받아 처리
[http.services.nextcloud-aio.loadBalancer] #로드 밸런서 서비스를 정의, 로드 밸런서는 여러 서버 간에 요청을 분산
[[http.services.nextcloud-aio.loadBalancer.servers]] #서비스가 요청을 전달할 서버의 URL을 지정
url = "http://도커 내부 ip:포트번호"
이것만 복사 붙혀넣기하면 될까요?
서브도메인 여러개사용중입니다.
저 같은 경우에는 entrypoint를 websecure라 정의했기에
[http.routers]
[http.routers.nextcloud]
rule = "Host(`도메인`)"
service = "nextcloud-aio"
entrypoints = ["websecure"]
middlewares = ["crowdsec", "my-geoblock2", "security-nextcloud", "www-to-Root", "large-compress", "ratelimit-large", "retry"]
[http.routers.nextcloud.tls]
certresolver = "cloudflare"
domains = [ { main = "*.도메인" } ]
에서 entrypoint = [websecure]이 된 것입니다.
마찬가지로 routers도 제가 nextcloud라 정의해한 것이며
service도 제가 nextcloud-aio로 정의한 것이기에 원하는 명으로 변경해주시면 될 것 같습니다.
미들웨어도 필요없으시다면... 빼셔도 무방하지 않을까.. 나중에 원하는 부분만 추가하면 되는 부분이니깐요.
미들웨어 이름도 제가 저렇게 정의한 것이니 원하는 이름으로 정의해서 원하는 부분만 사용하시면 될 것 같아요.
도메인은 이 라우터에 사용할 도메인을 기입하시면 될 듯 합니다. 그럼 이에 맞춰 인증서가 발급될 것입니다.
[http.services]
[http.services.nextcloud-aio.loadBalancer]
[[http.services.nextcloud-aio.loadBalancer.servers]]
url = "http://도커 내부 ip:포트번호"
[tls.options]
[tls.options.default]
minVersion = "VersionTLS12"
[tls.options.mintls13]
minVersion = "VersionTLS13"
또 위에서 services를 nextcloud-aio로 정의했기에 로드벨런서도 nextcloud-aio로 지정했다(?)고 보시면 편하지 않을까 싶네요.
저 tls 옵션도 tls 최소 버전 기본 버전 이렇게 한 것으로 알고 있는데 필요없는지까지는.. ㅎㅎ
지금 모바일로 작성하고 있고, 저도 treafik을 제대로 이해한 것은 아니기에 조금 두서 없는 글이 되었습니다만.. 양해 부탁드리겠습니다 ㅎㅎ
1. 보통 각 컨테이너에서 설정해 주죠. traefik 컨테이너에 dash.domain.com을 설정해 준 것 처럼요.
nginx 컨테이너에서 블로그를 운영중이면 nginx 컨테이너의 label에 blog.domain.com의 rule을 설정하는 식으로요.
꼭 compose의 label에 적어줄 필요는 없고 yaml이나 toml 파일로 설정해 줘도 되긴 합니다.
2. http 자동 리다이렉션은 middleware로 정의해서 rule마다 선택적으로 적용하는 방법이 있고 아예 entryPoint에 설정해서 포트 전체에 적용하는 방법이 있습니다.
포트 전체에 일괄 적용하려면 아래처럼 하면 됩니다.
그런데 compose 설정을 보니까 entryPoints가 정의되어 있지 않은 것 같네요.
entryPoints: web: address: :80 http: redirections: entryPoint: to: websecure scheme: https websecure: address: :443
compose로 작성하려면...
command: - "--entrypoints.web.address=:80" - "--entrypoints.web.http.redirections.entryPoint.to=websecure" - "--entrypoints.web.http.redirections.entryPoint.scheme=https" - "--entrypoints.websecure.address=:443"
traefik은 라우팅 rule의 도메인을 검사해서 적용 가능한 인증서가 없으면 발급받는 식이라서요.
본문대로라면 dash.domain.com 인증서만 발급됩니다.
와일드카드 인증서를 만들고 싶으시면 이렇게 해 보세요.
전 compose에는 service만 설정하고 나머지는 파일에 설정하는 걸 선호해서 dynamic.yaml을 예시로 들어볼게요.
tls: stores: default: defaultGeneratedCert: resolver: letsencrypt # 본인이 정의한 resolver 이름 domain: main: '*.domain.com' sans: - domain.com http: routers: dashboard: # 본인이 정의한 라우터 이름 rule: Host(`dash.domain.com`) service: api@internal tls: {}
이렇게 설정하고 라우팅 룰에 tls: {} 만 입력하면 기본 와일드카드 인증서를 사용합니다.
기본 인증서로 지정하지 않고 아래처럼 라우팅 정의할 때 넣어도 되고요.
http: routers: dashboard: # 본인이 정의한 라우터 이름 rule: Host(`dash.domain.com`) service: api@internal tls: certResolver: letsencrypt domains: - main: '*.domain.com' sans: - domain.com
기본 인증서든 라우팅에 정의된 인증서이든 한번만 인증서 발급을 정의해 두면 traefik이 알아서 발급/갱신/재사용합니다.
각 라우팅 규칙마다 certResolver 등을 지정해 줄 필요가 없는 거죠.
본문의 내용을 제 나름 정리해 보면 이렇습니다.
docker-compose.yml
version: "3.9" services: traefik: image: traefik:v2.11.0 restart: unless-stopped logging: options: max-size: "10m" healthcheck: test: ["CMD", "wget", "http://localhost:8082/ping", "--spider"] interval: 10s timeout: 2s retries: 3 start_period: 5s environment: - CLOUDFLARE_EMAIL=test@nate.com - CLOUDFLARE_DNS_API_TOKEN=-123456789123456789 labels: - traefik.enable=true volumes: - /var/run/docker.sock:/var/run/docker.sock - ./etc/traefik.toml:/etc/traefik/traefik.yml - ./etc/dynamic.toml:/etc/traefik/dynamic.yml - ./traefik-certificates:/etc/traefik/acme networks: - traefik-network ports: - target: 80 published: 9080 mode: host - target: 443 published: 9443 mode: host protocol: tcp - target: 443 published: 9443 mode: host protocol: udp # traefik api는 굳이 8080 매핑할 필요 없이 80 이나 443의 라우팅으로 접근하세요. #- target: 8080 # published: 9085 # mode: host # protocol: tcp networks: traefik-network: external: true volumes: traefik-certificates: driver: local driver_opts: o: bind type: none device: ./etc/traefik/ssl/
log: level: WARN accessLog: {} providers: docker: network: traefik-network #defaultRule: '' # 자동으로 라우팅 룰 만들어지는 걸 원치 않을 경우 entryPoints: web: address: :80 http: redirections: entryPoint: to: websecure scheme: https websecure: address: :443 certificatesresolvers: letsencrypt: acme: email: test@nate.com httpChallenge: entryPoint: web dnsChallenge: provider: cloudflare delayBeforeCheck: 30s resolvers: - 1.1.1.1:53 - 8.8.8.8:53
dynamic.yaml - 동적 설정이라 수정시 바로 적용
tls: stores: default: defaultGeneratedCert: resolver: letsencrypt domain: main: '*.domain.com' sans: - domain.com http: services: # 자동으로 등록되는 도커의 서비스 외에 추가로 정의 my_drive: loadBalancer: servers: - url: http://1.2.3.4.5:8080 - url: http://my.drive.com:12345 routers: dashboard: rule: Host(`dash.domain.com`) service: api@internal tls: {} blog: rule: Host(`blog.domain.com`) service: blog@docker # 자동으로 등록되는 도커의 이름은 대시보드에서 확인 # tls: {} # tls 옵션이 없을 경우 인증서 적용 안됨 drive: rule: Host(`drive.domain.com`) service: my_drive@file # 위의 services에서 정의한 서비스 tls: {} entryPoints: # entryPoints를 정의하지 않으면 모든 entryPoints 적용 - web cam: rule: Host(`cam.second-domain.com`) service: cam@docker tls:
certResolver: letsencrypt
domains:
- main: '*.second-domain.com'
sans:
- second-domain.com
Nginx Proxy Manager vs Traefik
Nginx Proxy Manager와 Traefik은 둘 다 리버스 프록시와 로드 밸런서를 구성하는 데 사용되는 도구입니다. 각각의 특징과 장단점을 살펴보겠습니다.
Nginx Proxy Manager:
Nginx를 기반으로 하는 웹 인터페이스를 제공하여 사용자가 쉽게 프록시와 인증을 구성할 수 있습니다.
사용자 친화적인 GUI를 통해 SSL 인증서 관리 및 HTTPS 설정을 용이하게 합니다.
단일 호스트 또는 도메인에 대한 단순한 프록시와 리디렉션 작업을 수행하는 데 뛰어납니다.
그러나 고급 기능이나 복잡한 환경에서는 한계가 있을 수 있습니다.
Traefik:
Docker와 Kubernetes와 같은 컨테이너 환경에서 특히 잘 작동합니다.
동적으로 컨테이너를 관리하고 프록시 서버를 자동으로 갱신합니다.
동적 라우팅 및 로드 밸런싱 기능을 강화하며, 클라우드 네이티브 환경에 적합합니다.
그러나 처음에는 설정이 다소 복잡할 수 있으며, 특히 더 많은 기능을 활용하려는 경우 추가적인 학습이 필요할 수 있습니다.
결론적으로, Nginx Proxy Manager는 간단하고 사용하기 쉬운 인터페이스를 제공하여 단순한 웹 서버 및 프록시 설정에 적합하며, Traefik은 동적인 컨테이너 환경에서 더 유연하고 확장 가능한 솔루션으로 사용됩니다. 선택은 환경 및 요구 사항에 따라 다를 수 있습니다.
cmt alert