wg-easy Docker 安裝教學:WireGuard 網頁管理介面
透過 Docker Compose 部署 wg-easy,快速建立 WireGuard VPN。本文說明 v15 版本後的設定變更、NET_ADMIN 權限需求,以及如何透過 QR code 實現手機一鍵連線。
您即將建置的內容
wg-easy 是一個具備網頁介面的 WireGuard,以單一 Docker 容器形式執行。它會為您管理 WireGuard 介面,並提供瀏覽器 UI 以建立用戶端。您建立的每個用戶端都會獲得設定檔與 QR code,因此手機只需透過相機掃描螢幕即可加入 VPN。
通道本身即為標準的 WireGuard。封包由核心模組處理,因此傳輸效能與手動設定無異。您獲得的優勢在於用戶端生命週期管理:無需透過 SSH 編輯設定檔即可新增、停用與刪除節點。您放棄的則是對該設定檔的直接控制權,這部分內容請參閱 手動在 VPS 上設定 WireGuard。
您需要一台具備公開 IPv4 位址的 KVM VPS、安裝 Docker Engine 與 Compose 外掛程式,並擁有 root 存取權。共享主機核心的容器虛擬化技術(如 OpenVZ 或 LXC)通常無法載入 WireGuard 模組,這會導致容器無法啟動介面。
第 15 版將設定移出環境變數
您找到的大多數指南都是針對 wg-easy 14 編寫的,當時您需將 WG_HOST 設定為伺服器位址,並將 PASSWORD_HASH 設定為管理員密碼的 bcrypt雜湊值,兩者皆透過環境變數設定。第 15 版經過重新編寫。官方遷移說明明確指出,v15 不再使用與 v14 相同的環境變數,且大多數設定已移至網頁介面的管理面板中。
因此,WG_HOST 與 PASSWORD_HASH 已不再生效。如果您複製舊的 compose 檔案,容器啟動後會忽略這些行,並要求您在瀏覽器中建立管理員帳號。這並非錯誤,而是新的設定流程。
截至 2026 年 7 月,建議鎖定的主要標籤為 15。請鎖定主要版本而非使用 latest,因為主要版本升級會變更磁碟上的設定格式,且無法順利還原。
Compose 檔案
為此堆疊建立目錄,並將官方的 compose 檔案寫入其中。這是上游提供的原始檔案,未經任何修改。
sudo mkdir -p /etc/docker/containers/wg-easy
sudo curl -o /etc/docker/containers/wg-easy/docker-compose.yml \
https://raw.githubusercontent.com/wg-easy/wg-easy/master/docker-compose.yml檔案內容如下:
volumes:
etc_wireguard:
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
networks:
wg:
ipv4_address: 10.42.42.42
ipv6_address: fdcc:ad94:bacf:61a3::2a
volumes:
- etc_wireguard:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.all.forwarding=1
- net.ipv6.conf.default.forwarding=1
networks:
wg:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 10.42.42.0/24
- subnet: fdcc:ad94:bacf:61a3::/64etc_wireguard 是一個具名儲存卷(named volume),用於存放伺服器金鑰以及您建立的每個客戶端。請務必備份該儲存卷,否則重建容器時將會遺失所有節點資訊。若您偏好將這些檔案存放在主機檔案系統中,可將其替換為綁定掛載(bind mount)。在執行此操作前,請先閱讀 綁定掛載與具名儲存卷的差異,因為兩者的權限行為有所不同。
為何需要 NET_ADMIN、SYS_MODULE 與 sysctl 設定
預設情況下,容器不允許存取網路堆疊,而以下每一項設定皆是為了移除特定的限制。
NET_ADMIN 允許容器建立 wg0 介面、指派位址並寫入路由。若缺少此權限,容器啟動後會在嘗試啟用介面時終止,因為 ip link add wg0 type wireguard 會回傳 Operation not permitted。
SYS_MODULE 加上唯讀的 /lib/modules 掛載,讓容器能在宿主機尚未載入 WireGuard 核心模組時自行載入。該模組位於宿主機核心而非映像檔內,因此必須掛載宿主機目錄。在現代核心中,該模組通常已內建,您可在宿主機上執行 sudo modprobe wireguard && echo ok 進行確認。
net.ipv4.ip_forward=1 會讓核心轉發非目的地為本機的封包。若缺少此設定,客戶端雖能連線並完成握手,但所有發往網際網路的封包都會被丟棄,導致 ping 1.1.1.1 超時,儘管 VPN 看起來處於連線狀態。
net.ipv4.conf.all.src_valid_mark=1 是最容易讓人困惑的設定。WireGuard 會標記其輸出的封包,以避免它們被路由回隧道中。嚴格的反向路徑過濾(reverse path filtering)會偵測到來源位址與預期路由不符的封包並將其丟棄。此 sysctl 設定會告知核心接受這些已標記的封包,這是維持全隧道(full tunnel)運作而不中斷的關鍵。
啟動服務並建立管理員帳號
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -f請使用 docker compose up 與 docker compose down,不要使用 start 與 stop。上游開發者警告,若在不同設定下建立容器並執行 start,會導致網路狀態不一致。若您希望在重啟後自動恢復堆疊,restart: unless-stopped 已涵蓋此功能,而 compose 服務的開機行為 說明了該政策的具體承諾範圍。
網頁介面監聽 TCP 51821 埠。首次存取時會顯示設定頁面,請在此建立管理員帳號,並確認用戶端連線至伺服器時所使用的 Host 位址。該 Host 位址會寫入每個用戶端設定檔的 Endpoint 行,因此必須填入 VPS 的公開 IP 或 DNS 名稱。若設定錯誤,提供給手機的 QR code 將指向無法連線的位置,導致握手失敗。
關於該埠的額外說明:除非設定 INSECURE=true,否則 wg-easy 15 會拒絕純 HTTP 連線。透過不受信任的憑證以 HTTPS 存取,或在前端透過反向代理進行 TLS termination 皆可正常運作。若使用預設設定透過 http:// 存取則無法連線。
請勿將 UI 連接埠暴露至網際網路
該 compose 檔案將 51821 埠發佈至所有介面上。這是一個能路由您網路流量的設備登入頁面,不應對外開放。在 Docker 中發佈連接埠會將規則寫入 DOCKER 鏈,其評估優先順序高於 ufw,因此 ufw 的拒絕規則無法將其關閉。此陷阱值得深入了解,為何 Docker 發佈的連接埠會忽略 ufw 一文對此有完整說明。
最簡單的修正方式是將 UI 綁定至 loopback 介面,並透過 SSH tunnel 進行存取:
ports:
- "51820:51820/udp"
- "127.0.0.1:51821:51821/tcp"
environment:
- INSECURE=true接著在您的筆記型電腦上執行:
ssh -L 51821:127.0.0.1:51821 youruser@your.server.address在筆記型電腦的瀏覽器中開啟 http://127.0.0.1:51821。流量會經由 SSH 加密,該連接埠不會回應其他來源,且 INSECURE=true 在此處是安全的,因為明文 HTTP 的傳輸路徑從未離開過 loopback 介面。
開啟 UDP 51820 埠,並檢查兩層防火牆
WireGuard 本身需要從網際網路存取 UDP 51820 埠。雖然 Docker 會發布該埠,但許多服務供應商會在 VPS 前端設置獨立的網路防火牆,而 Docker 無法感知其存在。請務必在兩處同時開啟該埠。若您使用 ufw 管理主機防火牆,參考 VPS 的基本 ufw 規則 會比手動編寫 nftables 更為簡便。
請檢查容器是否確實正在監聽:
sudo ss -ulnp | grep 51820您應能看到一個監聽中的 UDP socket。若該行未顯示任何內容,代表容器未能成功啟動介面,此時 sudo docker compose logs wg-easy 將會顯示失敗原因。
建立客戶端並使用手機掃描
在 UI 中建立一個客戶端,並為其命名以便日後辨識,例如使用該裝置的名稱。wg-easy 會自動分配下一個可用的通道位址並產生金鑰對。每個客戶端列都提供一個 QR Code 以及可供下載的 .conf 檔案。
在手機上安裝官方的 WireGuard 應用程式,選擇從 QR Code 新增通道,並將相機對準螢幕上的代碼。通道會以您輸入的名稱顯示。將其開啟後,UI 中的客戶端列便會開始顯示傳輸計數器與最近的交握時間。一旦手機連上通道,即可存取未公開至網際網路的服務;這正是手機如何隨時隨地將相片上傳至 自架相片伺服器 的方式,且該伺服器無需對外開放任何連接埠。同樣的技巧也適用於媒體服務,例如將 Jellyfin 媒體庫重建成 90 年代影音出租店,讓您在飯店房間瀏覽時,依然享有與區域網路內相同的隱私。警報通知則可透過同一通道反向運作,例如 自架的 ntfy 伺服器 可以在備份作業失敗時,立即將訊息推送到手機,且無需回應來自公用網際網路的任何請求。
若客戶端啟用後未顯示交握資訊,代表其完全無法連線至伺服器。這通常指向 UDP 51820 埠的問題,可能是供應商防火牆阻擋,或是設定檔中寫入的端點位址錯誤。若客戶端顯示已交握但無法連上網際網路,則問題通常在於轉發設定或 DNS。
在桌機上,請下載 .conf 檔案並匯入至 WireGuard 客戶端,避免手動輸入。該檔案中的私鑰僅會產生並顯示一次。請務必將此檔案視同 SSH 私鑰妥善保管。
何時該捨棄 UI
當您的對等節點僅為個人與手機時,wg-easy 是合適的工具。UI 的操作速度優於編輯設定檔,且撤銷遺失的手機存取權僅需點擊一次即可完成。
當您需要 UI 未提供的功能時,就會觸及它的極限。站對站(site-to-site)路由通常是第一個門檻,此時對等節點的 AllowedIPs 需要涵蓋整個遠端子網,而非單一 IP 位址。接下來則是針對個別對等節點設定路由規則的分割通道(split tunnels),或是由您的佈建工具所產生的設定檔。到了這個階段,手動設定並不會比較困難,只是方式不同;WireGuard 基礎指南展示了如何從 wg0.conf 建立相同的通道。如果您希望完全停止運作控制平面,WireGuard 與 Tailscale 的比較涵蓋了託管方案的選項。這是否為公平的交易,取決於協調伺服器實際能存取的範圍,在將網路交給它之前,建議先閱讀 Tailscale 的信任模型。成本通常是下一個考量點,Tailscale 免費方案的實際涵蓋範圍對於家庭或小型團隊而言通常已足夠,無需支付任何費用。超過此規模後,計費方式將改為按使用者人數而非裝置數量計算,這與您現有的 VPS 固定費用結構不同,因此在遷移團隊前,請先確認 Tailscale 超出免費方案後的費用。您剛建立的完整通道在該平台有直接的對應功能,透過 將 VPS 宣告為 Tailscale 出口節點,即可獲得相同的伺服器對外路由,且是在管理控制台中核准,而非寫入每個用戶端的設定檔中。子網限制也有對應解法,因為 從 VPS 宣告整個私有網路,即可將該網路提供給 tailnet 中的所有裝置,無需再進行導致您放棄 UI 的個別對等節點 AllowedIPs 編輯。如果您想要儀表板與自動化網狀路由,但不想使用他人的協調伺服器,在 VPS 上執行您自己的 NetBird 伺服器 可將控制平面保留在您擁有的硬體上,代價則是需要自行處理 wg-easy 不會要求您的 DNS 與 TLS 設定。
如果上述的 compose 語法對您來說比 WireGuard 本身更陌生,VPS 上的 Docker Compose 基礎說明了檔案格式與日常指令。
FAQ
為什麼 wg-easy 忽略了我的 WG_HOST 和 PASSWORD_HASH?
這些變數屬於 wg-easy 14 版本。15 版本經過重寫,上游開發者已將幾乎所有設定移至網頁介面的管理面板中。該容器不會讀取這兩個變數,因此它會正常啟動,並在您首次存取時要求建立管理員帳號。請改在該設定頁面中指定客戶端連線用的主機位址。
如果我的核心已經內建 WireGuard,還需要 SYS_MODULE 嗎?
不需要。SYS_MODULE 和 /lib/modules 掛載的存在是為了讓容器在宿主機未載入模組時能自行載入。若宿主機執行 sudo modprobe wireguard 已能成功,則該權限即無用處。移除它是合理的加固步驟,且無論如何 NET_ADMIN 仍然是必要的。
客戶端已連線但無法存取網際網路,問題出在哪裡?
若握手成功但沒有流量,通常是轉發(forwarding)設定的問題。請確認 net.ipv4.ip_forward=1 和 net.ipv4.conf.all.src_valid_mark=1 是否仍存在於 compose 檔案中,手動編輯的副本經常會遺失這些設定。若轉發已開啟,請檢查客戶端接收到的 DNS 伺服器。如果隧道將所有流量導向 VPN,但指向的 DNS 伺服器無法連線,瀏覽器看起來就會像連線中斷一樣。
如何備份我的客戶端設定?
所有資料都存放在 etc_wireguard 命名卷中的 wg0.json 檔案內。使用者介面也提供備份按鈕,可匯出相同的資料。在進行任何升級前,請將該檔案複製到伺服器以外的地方。還原時,只需在全新容器的設定步驟中上傳該檔案即可。
我可以將 wg-easy 放在反向代理後方嗎?
可以。將代理伺服器置於 TCP 51821 埠前方並處理 TLS 終止,同時在容器上設定 INSECURE=true,使其能接受來自代理的純 HTTP 請求。請務必直接對外開放 UDP 51820 埠,因為 VPN 流量屬於 UDP,無法通過 HTTP 代理。