NAS 自架之旅:告別自簽憑證,使用 Traefik 架設完美內網
在內網架設服務時,常見的做法是使用類似 https://192.168.1.100
的方式。不過,當服務數量多時,不僅網址難記,自簽憑證還會帶來煩人的警告提示。這次我們就來看看如何利用 Traefik 為每個服務自動簽發合法憑證,讓內網管理更方便。
需要具備合法網域
如果要取得合法簽章,必須擁有自己的網域。除非你要把自己的憑證裝進你的每台設備中。
Traefik 設定
Traefik 是由 Golang 開發的反向代理工具,不僅能取代 Nginx,還能與 Docker 無縫結合。以下是我的 Traefik 的設定檔範例:
api:
dashboard: true
insecure: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
permanent: true
websecure:
address: ":443"
http:
tls:
certResolver: letsencrypt
domains:
- main: lab.yourdomain.com
sans:
- '*.lab.yourdomain.com'
providers:
file:
watch: true
filename: /etc/traefik/provider.yml
docker:
watch: true
endpoint: "unix:///var/run/docker.sock"
defaultRule: "Host(`{{ lower ( trimPrefix `/` .Name ) }}.lab.yourdomain.com`)"
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: youremail@yourdomain.com
storage: /etc/traefik/acme.json
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
serversTransport:
insecureSkipVerify: true
設定檔中可以看到兩個 provider,分別是 file 和 docker。docker provider 會透過 docker api 去讀取 docker label 屬性,所以我們可以把每個服務的 Traefik 設定直接寫在 docker compose 的設定檔中。而 file provider 則適合用來配置非 Docker 容器的服務,例如 NAS 本身的 Web UI。
整體的邏輯是透過 dns rewrite 將 *.lab.yourdomain.com
指向 Traefik 內網的 ip,然後利用 Traefik 進行反向代理與憑證管理。憑證的部分我比較懶惰是直接簽一張 *.lab.yourdomain.com
的萬用憑證,但也可以為每個服務單獨簽發憑證。
DNS 的部分我是用 Adguard Home 作為內網的 dns server,除了用來 dns rewrite 外,還可以順便擋廣告。但如果不介意隱私的話,也可以直接在公開網域的 dns 直接把 *.lab.yourdomain.com
指向內網的 ip,這樣就不用多一台內網的 dns server。
docker compose 設定
Traefik
Traefik 的 docker compose 設定檔如下
services:
traefik:
image: traefik:v3.2
container_name: traefik
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "/array/appdata/traefik:/etc/traefik"
environment:
- CF_DNS_API_TOKEN=...
networks:
- homelab
labels:
traefik.enable: true
traefik.http.services.traefik.loadbalancer.server.port: 8080
traefik.http.routers.traefik.rule: "Host(`traefik.lab.yourdomain.com`)"
traefik.http.routers.traefik.entrypoints: websecure
traefik.http.routers.traefik.service: traefik
networks:
homelab:
external: true
因為我的 dns 使用 cloudflare 管理,所以在這邊會需要 Cloudflare 的 API token。Traefik 本身的 Web UI 介面預設開在 8080,這裡透過 docker labels 去單獨設定這個服務,讓我們可以透過 https://traefik.lab.yourdomain.com
反向代理存取 traefik container 的 8080 port。我這裡建立了一個 docker network 叫做 homelab
,讓 Traefik 和其他需要反向代理的服務在同一個網段中,而不用在內網搶 port。
Adguard Home
底下提供另一個例子是 Adguard Home 的 docker compose 設定檔
services:
adguardhome:
image: adguard/adguardhome:latest
container_name: adguardhome
restart: unless-stopped
ports:
- 192.168.1.100:53:53/tcp
- 192.168.1.100:53:53/udp
volumes:
- /array/appdata/adguardhome/work:/opt/adguardhome/work
- /array/appdata/adguardhome/conf:/opt/adguardhome/conf
networks:
- homelab
labels:
traefik.enable: true
traefik.http.services.adguardhome.loadbalancer.server.port: 3000
traefik.http.routers.adguardhome.rule: "Host(`adguard.lab.yourdomain.com`)"
traefik.http.routers.adguardhome.entrypoints: websecure
traefik.http.routers.adguardhome.service: adguardhome
networks:
homelab:
external: true
我一樣把 Adguard Home 加到同一個 docker network 中,並設定 docker labels,這樣就可以透過 https://adguard.lab.yourdomain.com
反向代理存取 adguardhome container 的 3000 port。
Adguard Home 這裡有個小坑是需要把 ports bind 在內網的 ip 上,而不是 127.0.0.1
,不然其他 docker 會沒辦法 resolve。1
總結
過去我們需要透過像 https://192.168.1.100:9005
的方式存取內網服務,不僅會有自簽憑證的煩人警告,網址又難記,不同的服務的 port 還會打架。如今設定好 Traefik 之後,我們就可以直接用 https://nextcloud.lab.yourdomain.com
正常有合法簽章的網域來存取內網服務,十分舒服。