安裝¶
ShadowDNS 可從原始碼編譯、在 Debian/Ubuntu 上安裝 .deb 套件,或使用發布於 GHCR 的官方 linux/amd64 container image。
從原始碼編譯¶
前置條件:Go 1.27+。
Binary 產出於 bin/shadowdns-<GOOS>-<GOARCH>。如需在 macOS 上交叉編譯 linux/amd64 的部署用 binary:
.deb 套件安裝¶
建置套件¶
安裝¶
套件安裝內容¶
| 路徑 | 內容 |
|---|---|
/usr/bin/shadowdns |
主程式 |
/lib/systemd/system/shadowdns.service |
systemd service unit |
/etc/logrotate.d/shadowdns |
logrotate 設定(每日輪替 /var/log/shadowdns/*.log,postrotate 送 SIGUSR1 讓 daemon 重開 log 檔) |
/etc/shadowdns/named.conf.example |
named.conf 範例 |
/etc/shadowdns/shadowdns.yaml.example |
shadowdns.yaml 範例 |
/usr/share/bash-completion/completions/shadowdns |
bash completion |
/usr/share/zsh/vendor-completions/_shadowdns |
zsh completion |
/usr/share/fish/vendor_completions.d/shadowdns.fish |
fish completion |
安裝時的 postinstall script 會自動:
- 建立
shadowdns系統使用者與群組(如不存在) - 建立
/var/log/shadowdnslog 目錄(ownershadowdns:shadowdns,mode 0750) - 執行
systemctl daemon-reload
systemd 服務¶
套件附帶的 service unit 以下列參數啟動:
/usr/bin/shadowdns \
--named-conf /etc/shadowdns/named.conf \
--config /etc/shadowdns/shadowdns.yaml \
--log-file /var/log/shadowdns/shadowdns.log
因此啟用服務前,請先把設定檔放到 /etc/shadowdns/(可從同目錄的 .example 檔案複製修改):
sudo cp /etc/shadowdns/named.conf.example /etc/shadowdns/named.conf
sudo cp /etc/shadowdns/shadowdns.yaml.example /etc/shadowdns/shadowdns.yaml
# 編輯兩個檔案以符合你的環境後:
sudo systemctl enable --now shadowdns
Service unit 的安全強化重點:
- 以非特權使用者
shadowdns執行,透過AmbientCapabilities=CAP_NET_BIND_SERVICE綁定 53 port ProtectSystem=strict沙箱,僅/var/log/shadowdns可寫RuntimeDirectory=shadowdns於每次啟動建立/run/shadowdns,供預設的pid-file "/var/run/shadowdns/pid"使用ExecReload對應 SIGHUP,因此systemctl reload shadowdns即可熱重載設定
驗證安裝¶
應用層 log 位於 /var/log/shadowdns/shadowdns.log。
Container Image¶
官方 image 僅支援 linux/amd64。正式部署應使用精確版本 tag(或 digest);latest 會指向最新 release。
Image 使用 Distroless nonroot runtime,並以 UID/GID 65532 執行;其中沒有 shell、package manager、診斷 client、內嵌設定或 Docker HEALTHCHECK。預設參數為:
--named-conf /etc/shadowdns/named.conf
--config /etc/shadowdns/shadowdns.yaml
--listen 0.0.0.0:5353
--no-color
明確 listener 僅支援 IPv4,並覆寫 mounted BIND 設定中的宿主專用 listen-on 與 listen-on-v6 位址;此 image 預設不提供 first-class dual-stack container listening。
請先準備完整的 /etc/shadowdns 目錄樹,包含 named.conf、shadowdns.yaml、所有 include 檔案、zone files 與 GeoIP databases。Include paths 會相對於 include 所在檔案解析,但相對的 options { directory "zones"; }; 是從 container working directory 解析,不會自動相對於 /etc/shadowdns;請改用 /etc/shadowdns/zones 等 container 內 absolute path。設定中其他 absolute paths 同樣必須以相同路徑額外掛載,或改寫至 /etc/shadowdns 之下;只掛載 /etc/shadowdns 不會自動 remap /srv/zones。請將下方 OWNER 與 vX.Y.Z 替換成 package owner及GHCR中確實存在的tag,再執行:
docker run --rm --name shadowdns \
-p 53:5353/udp \
-p 53:5353/tcp \
-p 9153:9153/tcp \
--mount type=bind,src=/srv/shadowdns/config,dst=/etc/shadowdns,readonly \
ghcr.io/OWNER/shadowdns:vX.Y.Z
Operational logs 預設寫到 stderr,應交由 container runtime 收集。要重新載入 mounted 設定,請直接向 container 傳送 SIGHUP;SIGTERM 會執行 graceful shutdown:
Health probes 由部署端設定,因為 image 不含 HEALTHCHECK。Readiness 可用外部 DNS client 查詢 authoritative zones 中已知存在的 record;liveness 可視需要探測 http://<container-address>:9153/metrics。
可寫狀態與選用 Listeners¶
設定 mount 可保持唯讀。若啟用 DoH ACME,請將 /var/lib/shadowdns 掛載到 persistent storage,並確保 UID 65532 可寫;如此 ACME account key 才能跨 container replacement 重用。File-backed main log 或 query log同樣必須使用明確掛載、由 UID 65532 擁有的可寫路徑;image 絕不 fallback 為 root。
DoH HTTPS、ACME HTTP-01 與 ephemeral API 必須使用大於 1023 的 container ports,再將外部 443 與 80 port map 或 route 至這些非特權 listeners。
首次發布 GHCR Package¶
第一次 release workflow 推送 package 後,package owner 必須在 GitHub package settings:
- 將 visibility 改為 Public。
- 確認 package 已連結 source repository。
- 從未登入的環境驗證 anonymous pull。
- 確認精確 release tag 與
latest指向相同 image digest。
GitHub Packages API 與 gh CLI 目前沒有可修改 package visibility 的受支援操作,因此這是一次性的 UI 步驟;後續 release 會保留既有 public visibility。