Docker में wg-easy के साथ WireGuard कैसे सेटअप करें
Docker Compose का उपयोग करके wg-easy इंस्टॉल करें। NET_ADMIN और sysctls सेटिंग्स के साथ VPN कॉन्फ़िगर करें। फोन पर QR कोड से कनेक्ट करने का आसान तरीका यहाँ जानें।
आप क्या बना रहे हैं
wg-easy एक वेब इंटरफेस के साथ WireGuard है, जो एक Docker container के रूप में चलता है। यह आपके लिए WireGuard इंटरफेस को मैनेज करता है और क्लाइंट बनाने के लिए एक ब्राउज़र UI जोड़ता है। आपके द्वारा बनाए गए प्रत्येक क्लाइंट को एक config फाइल और एक QR कोड मिलता है, इसलिए फोन स्क्रीन पर कैमरा पॉइंट करके VPN से जुड़ जाता है।
टनल स्वयं सामान्य WireGuard है। kernel module पैकेट को मूव करता है, इसलिए थ्रूपुट हाथ से लिखे गए सेटअप के समान ही होता है। आप जो हासिल करते हैं वह क्लाइंट लाइफसाइकिल है: SSH पर config फाइल को एडिट किए बिना पीयर्स को जोड़ना, डिसेबल करना और डिलीट करना। आप जो छोड़ते हैं वह उस config का सीधा नियंत्रण है, जो VPS पर मैन्युअल WireGuard सेटअप का विषय है।
आपको एक सार्वजनिक IPv4 एड्रेस वाला KVM VPS, Compose प्लगइन के साथ Docker Engine और root एक्सेस की आवश्यकता है। कंटेनर वर्चुअलाइजेशन जो होस्ट kernel को साझा करता है, जैसे कि OpenVZ या LXC, आमतौर पर WireGuard मॉड्यूल को लोड नहीं कर सकता है, और कंटेनर इंटरफेस को चालू करने में विफल रहेगा।
Version 15 में सेटिंग्स को environment से हटा दिया गया है
आपको मिलने वाली अधिकांश गाइड wg-easy 14 के लिए लिखी गई थीं, जहाँ आप WG_HOST को अपने सर्वर एड्रेस पर और PASSWORD_HASH को एडमिन पासवर्ड के bcrypt हैश पर सेट करते थे, ये दोनों environment variables के रूप में होते थे। Version 15 एक पूर्ण पुनर्लेखन (rewrite) है। आधिकारिक माइग्रेशन नोट्स स्पष्ट रूप से कहते हैं कि v15, v14 वाले environment variables का उपयोग नहीं करता है, और उनमें से अधिकांश को वेब UI के एडमिन पैनल में स्थानांतरित कर दिया गया है।
इसलिए WG_HOST और PASSWORD_HASH अब कोई कार्य नहीं करते हैं। यदि आप पुरानी compose फाइल कॉपी करते हैं, तो कंटेनर स्टार्ट तो हो जाता है, लेकिन उन लाइनों को अनदेखा कर देता है और फिर आपसे ब्राउज़र में एक एडमिन अकाउंट बनाने के लिए कहता है। यह कोई बग नहीं है। यह नया सेटअप फ्लो है।
जुलाई 2026 तक, पिन करने के लिए प्रमुख टैग 15 है। latest का उपयोग करने के बजाय प्रमुख वर्ज़न को पिन करें, क्योंकि एक प्रमुख अपग्रेड ऑन-डिस्क कॉन्फ़िगरेशन फॉर्मेट को बदल देता है और इसे आसानी से रोल बैक नहीं किया जा सकेगा।
Compose file
Stack के लिए एक directory बनाएँ और उसमें official compose file लिखें। यह upstream file है, जिसे बदला नहीं गया है।
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 है जिसमें server key और आपके द्वारा बनाए गए सभी clients सुरक्षित रहते हैं। इस volume का backup लें, अन्यथा rebuild करने पर आपके सभी peers हट जाएंगे। यदि आप उन files को host filesystem पर देखना चाहते हैं, तो इसे bind mount से बदलें। ऐसा करने से पहले bind mounts और named volumes के बीच का अंतर पढ़ें, क्योंकि permissions का व्यवहार अलग होता है।
NET_ADMIN, SYS_MODULE और sysctls की आवश्यकता क्यों है
डिफ़ॉल्ट रूप से किसी container को network stack में बदलाव करने की अनुमति नहीं होती है, और इनमें से प्रत्येक लाइन एक विशिष्ट प्रतिबंध को हटाती है।
NET_ADMIN container को wg0 interface बनाने, उसे एक address असाइन करने और routes लिखने की अनुमति देता है। इसके बिना container start तो होता है, लेकिन interface को up करते समय बंद हो जाता है, क्योंकि ip link add wg0 type wireguard, Operation not permitted return करता है।
SYS_MODULE और read-only /lib/modules mount container को WireGuard kernel module लोड करने की अनुमति देते हैं, यदि host ने इसे पहले से लोड नहीं किया है। Module host kernel पर स्थित होता है, न कि image के अंदर, इसीलिए host directory का दिखाई देना आवश्यक है। आधुनिक kernel पर module आमतौर पर पहले से ही built-in होता है, जिसे आप host पर sudo modprobe wireguard && echo ok के साथ confirm कर सकते हैं।
net.ipv4.ip_forward=1 kernel को उन packets को forward करने के लिए कहता है जो स्वयं उस box के लिए नहीं हैं। इसके बिना client connect होता है, handshake सफल होता है, लेकिन internet के लिए भेजा गया हर packet drop हो जाता है, जिससे VPN connected दिखने के बावजूद ping 1.1.1.1 time out हो जाता है।
net.ipv4.conf.all.src_valid_mark=1 वह सेटिंग है जो लोगों को हैरान करती है। WireGuard अपने outgoing packets को mark करता है ताकि उन्हें वापस tunnel में route न किया जाए। Strict reverse path filtering ऐसे packet को देखती है जिसका source address अपेक्षित route से मेल नहीं खाता और उसे drop कर देती है। यह sysctl kernel को marked packets को स्वीकार करने का निर्देश देता है, जो एक full tunnel को स्वयं को तोड़ने से रोकता है।
इसे start करें और admin account बनाएँ
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -fdocker compose up और docker compose down का उपयोग करें, न कि start और stop का। Upstream चेतावनी देता है कि अलग settings के तहत बनाए गए container पर start का उपयोग करने से network असंगत (inconsistent) स्थिति में रह जाता है। यदि आप reboot के बाद stack को वापस चाहते हैं, तो restart: unless-stopped इसे पहले ही कवर कर लेता है, और compose services के boot व्यवहार में यह समझाया गया है कि वह policy क्या करती है और क्या नहीं।
Web UI TCP 51821 पर listen करता है। पहली बार visit करने पर यह एक setup page दिखाता है जहाँ आप admin account बनाते हैं और उस host address की पुष्टि करते हैं जिसका उपयोग clients सर्वर तक पहुँचने के लिए करेंगे। वह host address हर client config की Endpoint line में चला जाता है, इसलिए यह VPS का public IP या DNS name होना चाहिए। यदि यह गलत है, तो आपके द्वारा phone को दिया गया QR code किसी ऐसी जगह point करेगा जहाँ तक पहुँचा नहीं जा सकता और handshake कभी पूरा नहीं होगा।
उस port के बारे में एक और बात: wg-easy 15 plain HTTP को तब तक स्वीकार नहीं करता जब तक आप INSECURE=true set न करें। इसे untrusted certificate के साथ HTTPS पर access करना, या इसके सामने reverse proxy पर TLS terminate करना, दोनों ही ठीक हैं। default settings के साथ इसे http:// पर access करना सही नहीं है।
UI port को इंटरनेट पर पब्लिश न करें
Compose file 51821 port को हर interface पर पब्लिश कर देती है। यह एक ऐसे बॉक्स का लॉगिन पेज है जो आपके traffic को रूट कर सकता है, इसलिए इसे दुनिया के लिए खुला नहीं होना चाहिए। Docker में port पब्लिश करने से DOCKER chain में नियम लिख दिए जाते हैं, जिन्हें ufw से पहले evaluate किया जाता है, इसलिए ufw का deny नियम इसे बंद नहीं कर पाता। यह एक ऐसी समस्या है जिसे समझना जरूरी है, और why Docker published ports ignore ufw में इसका पूरा विवरण दिया गया है।
इसका सरल समाधान यह है कि UI को loopback पर bind करें और इसे 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 खोलें। Traffic SSH द्वारा एन्क्रिप्टेड रहता है, यह port किसी और को जवाब नहीं देता, और INSECURE=true यहाँ सुरक्षित है क्योंकि plain HTTP hop कभी भी loopback interface से बाहर नहीं जाता है।
UDP 51820 को खोलें और दोनों firewalls की जाँच करें
WireGuard को इंटरनेट से UDP 51820 तक पहुँच की आवश्यकता होती है। Docker इसे publish तो करता है, लेकिन कई providers VPS के सामने एक अलग network firewall रखते हैं जिसके बारे में Docker को जानकारी नहीं होती। दोनों स्थानों पर port खोलें। यदि आप ufw के साथ host firewall manage करते हैं, तो VPS के लिए बुनियादी ufw नियम हाथ से nftables लिखने की तुलना में आसान विकल्प है।
जाँचें कि container वास्तव में listening स्थिति में है या नहीं:
sudo ss -ulnp | grep 51820आपको एक listening UDP socket दिखाई देना चाहिए। उस line पर कुछ भी न दिखने का अर्थ है कि container ने interface को start नहीं किया है, और sudo docker compose logs wg-easy में इसका कारण लिखा होगा।
एक क्लाइंट बनाएँ और उसे फोन पर स्कैन करें
UI में, एक क्लाइंट बनाएँ और उसे ऐसा नाम दें जिसे आप बाद में पहचान सकें, जैसे कि वह डिवाइस जिससे वह संबंधित है। wg-easy अगला खाली tunnel पता आवंटित करता है और आपके लिए key pair जनरेट करता है। प्रत्येक क्लाइंट पंक्ति एक QR कोड और एक डाउनलोड करने योग्य .conf फ़ाइल प्रदान करती है।
फोन पर आधिकारिक WireGuard ऐप इंस्टॉल करें, QR कोड से tunnel जोड़ने का विकल्प चुनें, और कैमरे को अपनी स्क्रीन पर मौजूद कोड की ओर करें। tunnel आपके द्वारा टाइप किए गए नाम के साथ दिखाई देता है। इसे चालू करें, और UI में क्लाइंट पंक्ति transfer counters और हालिया handshake समय दिखाना शुरू कर देती है। एक बार जब फोन tunnel पर आ जाता है, तो वह उन सेवाओं तक पहुँच सकता है जिन्हें आपने कभी इंटरनेट पर पब्लिश नहीं किया था। इसी तरह एक फोन कहीं से भी self-hosted photo server पर फोटो अपलोड करता रहता है, बिना उस सर्वर का एक भी port दुनिया के लिए खोले। यही तरीका मीडिया पर भी लागू होता है, और 90 के दशक के वीडियो स्टोर के रूप में फिर से बनाई गई Jellyfin library को होटल के कमरे से ब्राउज़ करना एक सुखद अनुभव है, जबकि यह उतना ही निजी रहता है जितना कि आपके LAN पर था। अलर्ट उसी tunnel पर विपरीत दिशा में काम करते हैं, क्योंकि self-hosted ntfy server उस फोन पर संदेश भेज सकता है जैसे ही कोई बैकअप जॉब विफल होती है, बिना सार्वजनिक इंटरनेट से किसी अनुरोध का उत्तर दिए।
यदि कोई क्लाइंट उसे सक्षम करने के बाद handshake नहीं दिखाता है, तो वह सर्वर तक नहीं पहुँच पा रहा है। यह UDP 51820 की ओर इशारा करता है, जो या तो provider firewall पर है या कॉन्फ़िगरेशन में डाले गए endpoint पते पर है। यदि कोई क्लाइंट handshake दिखाता है लेकिन इंटरनेट काम नहीं कर रहा है, तो यह forwarding या DNS की समस्या है।
डेस्कटॉप पर, .conf फ़ाइल डाउनलोड करें और इसे फिर से टाइप करने के बजाय WireGuard क्लाइंट में import करें। उस फ़ाइल में मौजूद private key एक बार जनरेट होती है और एक बार दिखाई जाती है। इस फ़ाइल के साथ वैसा ही व्यवहार करें जैसा आप SSH private key के साथ करते हैं।
UI से आगे कब बढ़ें
जब आपके peers केवल लोग और उनके phones हों, तब wg-easy एक सही tool है। config files को edit करने की तुलना में UI अधिक तेज़ है, और खोए हुए phone का access एक click में revoke किया जा सकता है।
जब आप कुछ ऐसा करना चाहेंगे जिसे UI support नहीं करता, तब आप इसकी सीमाओं तक पहुँच जाएंगे। Site-to-site routing, जहाँ किसी peer का AllowedIPs एक single address के बजाय पूरे remote subnet को cover करता है, आमतौर पर पहली बाधा होती है। इसके बाद per-peer routing rules के साथ split tunnels, या आपके provisioning tool द्वारा generate की गई config आती है। उस स्थिति में, manually setup करना कठिन नहीं होता, बस तरीका अलग होता है, और the plain WireGuard guide वही tunnel दिखाती है जिसे wg0.conf से बनाया गया है। यदि आप control plane को चलाना पूरी तरह बंद करना चाहते हैं, तो WireGuard compared with Tailscale managed option के बारे में जानकारी देता है। क्या यह एक उचित सौदा है, यह इस बात पर निर्भर करता है कि coordination server वास्तव में कहाँ तक पहुँच सकता है, और अपना network सौंपने से पहले Tailscale's trust model को पढ़ना उचित है। लागत आमतौर पर अगला सवाल होता है, और what the Tailscale free plan actually covers इतना पर्याप्त है कि एक घर या छोटी टीम को इसके लिए कुछ भी भुगतान नहीं करना पड़ता। उस सीमा के बाद, billing devices के बजाय users की संख्या पर आधारित होती है, जो उस VPS से अलग तरह का बिल है जिसके लिए आप पहले से भुगतान कर रहे हैं, इसलिए टीम को migrate करने से पहले what Tailscale costs once you outgrow the free plan वह संख्या है जिसे आपको देखना चाहिए। आपने जो full tunnel अभी बनाया है, उसका वहाँ सीधा विकल्प मौजूद है, क्योंकि advertising the VPS as a Tailscale exit node आपको सर्वर के माध्यम से वही route प्रदान करता है, जिसे प्रत्येक client config में लिखने के बजाय admin console में approve किया जाता है। subnet की बाधा का भी एक विकल्प है, क्योंकि advertising a whole private network from the VPS उस network को tailnet के प्रत्येक device तक पहुँचा देता है, बिना उस per-peer AllowedIPs editing के जिसने आपको UI छोड़ने पर मजबूर किया था। यदि आप वह dashboard और automatic mesh routing चाहते हैं, लेकिन किसी और का coordination server नहीं, तो running your own NetBird server on a VPS control plane को आपके अपने hardware पर रखता है, जिसकी कीमत DNS और TLS setup है, जिसे wg-easy ने कभी नहीं माँगा था।
यदि ऊपर दिया गया compose syntax, WireGuard के बजाय आपके लिए अपरिचित हिस्सा था, तो Docker Compose basics on a VPS file format और रोज़मर्रा के commands को समझाता है।
FAQ
wg-easy मेरे WG_HOST और PASSWORD_HASH को अनदेखा क्यों कर रहा है?
ये variables wg-easy 14 के लिए थे। वर्ज़न 15 एक पूर्ण पुनर्लेखन (rewrite) है, और upstream ने लगभग सभी कॉन्फ़िगरेशन को वेब UI के एडमिन पैनल में स्थानांतरित कर दिया है। कंटेनर इन variables को नहीं पढ़ता है, इसलिए यह सामान्य रूप से शुरू होता है और पहली बार खोलने पर आपसे एडमिन अकाउंट बनाने के लिए कहता है। उस सेटअप पेज पर ही client-facing host address सेट करें।
यदि मेरे kernel में पहले से ही WireGuard है, तो क्या मुझे SYS_MODULE की आवश्यकता है?
नहीं। SYS_MODULE और /lib/modules माउंट इसलिए मौजूद हैं ताकि यदि होस्ट में मॉड्यूल न हो, तो कंटेनर उसे लोड कर सके। जिस होस्ट पर sudo modprobe wireguard पहले से ही सफल है, वहां इस क्षमता (capability) का उपयोग नहीं होता है। इसे हटाना एक उचित सुरक्षा उपाय है, और NET_ADMIN की आवश्यकता हर स्थिति में बनी रहती है।
क्लाइंट कनेक्ट हो जाता है लेकिन इंटरनेट नहीं चलता। क्या समस्या है?
बिना ट्रैफ़िक के हैंडशेक का मतलब लगभग हमेशा IP forwarding होता है। पुष्टि करें कि net.ipv4.ip_forward=1 और net.ipv4.conf.all.src_valid_mark=1 अभी भी compose फ़ाइल में मौजूद हैं, क्योंकि हाथ से एडिट की गई कॉपी में अक्सर ये छूट जाते हैं। यदि forwarding चालू है, तो क्लाइंट को मिले DNS सर्वर की जाँच करें। एक टनल जो सारा ट्रैफ़िक VPN के माध्यम से भेजती है लेकिन ऐसे DNS सर्वर की ओर इशारा करती है जिस तक वह अब नहीं पहुँच सकती, वह ब्राउज़र में मृत कनेक्शन जैसी ही दिखती है।
मैं अपने क्लाइंट्स का बैकअप कैसे लूँ?
सब कुछ etc_wireguard नाम के वॉल्यूम में, एक wg0.json फ़ाइल के भीतर रहता है। UI में एक बैकअप बटन भी है जो उसी डेटा को एक्सपोर्ट करता है। किसी भी अपग्रेड से पहले उस फ़ाइल को सर्वर से बाहर कहीं कॉपी कर लें। रिस्टोर करने के लिए, नए कंटेनर के सेटअप चरण के दौरान उस फ़ाइल को अपलोड करें।
क्या मैं wg-easy को reverse proxy के पीछे चला सकता हूँ?
हाँ। प्रॉक्सी को TCP 51821 के सामने रखें, वहाँ TLS terminate करें, और कंटेनर पर INSECURE=true सेट करें ताकि वह प्रॉक्सी से आने वाले plain HTTP hop को स्वीकार कर सके। UDP 51820 को सीधे पब्लिश रखें, क्योंकि VPN ट्रैफ़िक UDP होता है और वह HTTP प्रॉक्सी से होकर नहीं गुजरता है।