SSD Nodes Learn Hosting plans →
تعلیمی Matt Connorتحریر: Matt Connor · اپ ڈیٹ شدہ 2026-08-29

Docker میں wg-easy سے WireGuard ویب UI چلائیں

Docker Compose میں wg-easy چلانے کا درست طریقہ: ports، NET_ADMIN، ضروری sysctls، version 15 کی settings، اور فون کے لیے QR code onboarding۔

آپ کیا بنا رہے ہیں

wg-easy ایک web interface کے ساتھ WireGuard ہے، جو ایک Docker container کے طور پر چلتا ہے۔ یہ آپ کے لیے WireGuard interface manage کرتا ہے اور clients بنانے کے لیے browser UI فراہم کرتا ہے۔ آپ کے بنائے ہوئے ہر client کو ایک config file اور QR code ملتا ہے، اس لیے phone کو VPN سے جوڑنے کے لیے camera کو screen کی طرف کرنا کافی ہوتا ہے۔

Tunnel خود عام WireGuard ہے۔ Kernel module packets منتقل کرتا ہے، اس لیے throughput ہاتھ سے لکھی گئی setup جیسا ہی رہتا ہے۔ آپ کو client lifecycle manage کرنے کی سہولت ملتی ہے: SSH کے ذریعے config file میں ترمیم کیے بغیر peers شامل کرنا، disable کرنا اور delete کرنا۔ اس کے بدلے آپ config پر براہِ راست control چھوڑ دیتے ہیں۔ اسی موضوع پر VPS پر دستی WireGuard setup میں بحث کی گئی ہے۔

آپ کو public IPv4 address والا KVM VPS، Compose plugin کے ساتھ Docker Engine، اور root access درکار ہے۔ ایسی container virtualisation جو host kernel شیئر کرتی ہے، جیسے OpenVZ یا LXC، عموماً WireGuard module load نہیں کر سکتی۔ اس صورت میں container interface کو فعال کرنے میں ناکام ہو جائے گا۔

Version 15 نے settings کو environment سے منتقل کر دیا

آپ کو ملنے والی زیادہ تر guides wg-easy 14 کے لیے لکھی گئی ہیں۔ اس version میں آپ WG_HOST میں اپنے server کا address اور PASSWORD_HASH میں admin password کا bcrypt hash، دونوں environment variables کے طور پر set کرتے تھے۔ Version 15 ازسرنو لکھی گئی ہے۔ سرکاری migration notes میں واضح طور پر بتایا گیا ہے کہ v15، v14 جیسے environment variables استعمال نہیں کرتا، اور ان میں سے زیادہ تر کو web UI کے admin panel میں منتقل کر دیا گیا ہے۔

اس لیے WG_HOST اور PASSWORD_HASH اب کوئی کام نہیں کرتے۔ اگر آپ پرانی compose file copy کریں تو container start ہو جاتا ہے، ان lines کو نظرانداز کرتا ہے، اور پھر browser میں admin account بنانے کو کہتا ہے۔ یہ bug نہیں ہے۔ یہی نیا setup flow ہے۔

July 2026 تک pin کرنے کے لیے major tag 15 ہے۔ latest استعمال کرنے کے بجائے major version pin کریں، کیونکہ major upgrade on-disk config format تبدیل کرتا ہے اور صاف طور پر rollback نہیں ہو پاتا۔

Compose فائل

Stack کے لیے ایک directory بنائیں اور اس میں official compose فائل لکھیں۔ یہ upstream فائل ہے اور اس میں کوئی تبدیلی نہیں کی گئی۔

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

اس کے contents اس طرح نظر آتے ہیں:

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::/64

etc_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 کو بطور default network stack میں تبدیلی کرنے کی اجازت نہیں ہوتی، اور ان میں سے ہر لائن ایک مخصوص رکاوٹ دور کرتی ہے۔

NET_ADMIN، container کو wg0 interface بنانے، اسے address دینے اور routes لکھنے کی اجازت دیتا ہے۔ اس کے بغیر container شروع ہونے کے بعد interface فعال کرتے وقت بند ہو جاتا ہے، کیونکہ ip link add wg0 type wireguard، Operation not permitted واپس کرتا ہے۔

SYS_MODULE اور read-only /lib/modules mount، container کو WireGuard kernel module load کرنے دیتے ہیں، اگر host نے اسے پہلے سے load نہ کیا ہو۔ یہ module image کے اندر نہیں بلکہ host kernel میں موجود ہوتا ہے، اسی لیے host directory کو container میں قابل رسائی بنانا ضروری ہے۔ جدید kernel میں یہ module عموماً built in ہوتا ہے، اور آپ host پر sudo modprobe wireguard && echo ok سے اس کی تصدیق کر سکتے ہیں۔

net.ipv4.ip_forward=1، kernel کو ایسے packets forward کرنے کی ہدایت دیتا ہے جو خود box کے لیے addressed نہ ہوں۔ اس کے بغیر client connect ہو جاتا ہے، handshake کامیاب ہو جاتا ہے، لیکن internet کے لیے ہر packet drop ہو جاتا ہے۔ نتیجتاً ping 1.1.1.1 timeout ہو جاتا ہے، حالانکہ VPN connected دکھائی دیتا ہے۔

net.ipv4.conf.all.src_valid_mark=1 وہ setting ہے جو لوگوں کو عموماً حیران کرتی ہے۔ WireGuard اپنے outgoing packets کو mark کرتا ہے تاکہ وہ دوبارہ tunnel میں route نہ ہوں۔ Strict reverse path filtering ایسے packet کو دیکھ کر drop کر دیتی ہے جس کا source address متوقع route سے match نہیں کرتا۔ یہ sysctl kernel کو marked packets قبول کرنے کی ہدایت دیتا ہے، اور اسی سے 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 نہیں۔ Upstream خبردار کرتا ہے کہ مختلف settings کے تحت بنائے گئے container پر start چلانے سے network غیر مستقل حالت میں رہ سکتا ہے۔ اگر آپ reboot کے بعد stack دوبارہ چلانا چاہتے ہیں تو restart: unless-stopped پہلے ہی اس کا انتظام کرتا ہے، اور compose services کے boot behaviour میں بتایا گیا ہے کہ یہ policy کیا کرتی ہے اور کیا ضمانت نہیں دیتی۔

web UI TCP 51821 پر listening کرتی ہے۔ پہلی بار کھولنے پر یہ setup page دکھاتی ہے، جہاں آپ admin account بناتے ہیں اور اس host address کی تصدیق کرتے ہیں جس کے ذریعے clients server تک پہنچیں گے۔ یہ host address ہر client config کی Endpoint line میں شامل ہوتا ہے، اس لیے یہ VPS کا public IP یا DNS name ہونا چاہیے۔ اگر یہ غلط ہو تو فون کو دیا گیا QR code ایسے پتے کی طرف اشارہ کرے گا جہاں پہنچنا ممکن نہیں، اور handshake کبھی مکمل نہیں ہوگا۔

اس port کے بارے میں ایک اور بات اہم ہے: wg-easy 15 plain HTTP کو مسترد کرتا ہے، جب تک آپ INSECURE=true set نہ کریں۔ غیر معتبر certificate کے ذریعے HTTPS پر اس تک رسائی حاصل کرنا، یا اس کے سامنے reverse proxy پر TLS terminate کرنا، دونوں درست طریقے ہیں۔ default settings کے ساتھ http:// کے ذریعے رسائی درست نہیں ہے۔

UI port کو انٹرنیٹ پر شائع نہ کریں

Compose فائل 51821 کو ہر interface پر شائع کرتی ہے۔ یہ ایسے box کا login page ہے جو آپ کے traffic کو route کر سکتا ہے، اس لیے اسے پوری دنیا کے لیے کھلا نہیں ہونا چاہیے۔ Docker میں port شائع کرنے سے DOCKER chain میں rules شامل ہوتے ہیں۔ اس chain کا جائزہ ufw سے پہلے لیا جاتا ہے، اس لیے ufw deny rule اس port کو بند نہیں کرتا۔ اس مسئلے کو الگ سے سمجھنا مفید ہے، اور Docker کے شائع کردہ ports کو ufw نظر انداز کیوں کرتا ہے میں اس کی مکمل وضاحت موجود ہے۔

سادہ حل یہ ہے کہ UI کو loopback سے bind کریں اور اسے SSH tunnel کے ذریعے استعمال کریں:

    ports:
      - "51820:51820/udp"
      - "127.0.0.1:51821:51821/tcp"
    environment:
      - INSECURE=true

پھر اپنے laptop سے:

ssh -L 51821:127.0.0.1:51821 youruser@your.server.address

اپنے laptop کے browser میں http://127.0.0.1:51821 کھولیں۔ Traffic کو SSH encrypt کرتا ہے، یہ port کسی اور کو جواب نہیں دیتا، اور INSECURE=true یہاں محفوظ ہے کیونکہ plain HTTP hop loopback interface سے باہر نہیں جاتا۔

UDP 51820 کھولیں، اور دونوں firewalls چیک کریں

WireGuard کو انٹرنیٹ سے قابل رسائی UDP 51820 درکار ہے۔ Docker یہ port publish کرتا ہے، لیکن بہت سے providers VPS کے سامنے الگ network firewall رکھتے ہیں، جس کا Docker کو علم نہیں ہوتا۔ دونوں جگہ یہ port کھولیں۔ اگر آپ host firewall کو ufw کے ذریعے manage کرتے ہیں تو VPS کے لیے بنیادی ufw rules خود nftables ہاتھ سے لکھنے کے مقابلے میں مختصر طریقہ ہے۔

چیک کریں کہ container واقعی listening کر رہا ہے:

sudo ss -ulnp | grep 51820

آپ کو listening UDP socket نظر آنا چاہیے۔ اگر اس line پر کچھ بھی نہ ہو تو container نے interface شروع نہیں کیا، اور sudo docker compose logs wg-easy وجہ بتا دے گا۔

فون پر client بنائیں اور scan کریں

UI میں ایک client بنائیں اور اسے ایسا نام دیں جسے آپ بعد میں آسانی سے پہچان سکیں، مثلاً اس device کا نام جس سے یہ متعلق ہے۔ wg-easy اگلا دستیاب tunnel address خود مختص کرتا ہے اور آپ کے لیے key pair تیار کرتا ہے۔ ہر client row میں QR code اور download کے لیے .conf file موجود ہوتی ہے۔

فون پر official WireGuard app install کریں، QR code سے tunnel شامل کرنے کا انتخاب کریں، اور camera کو اپنی screen پر موجود code کی طرف کریں۔ Tunnel اسی نام کے ساتھ ظاہر ہوگا جو آپ نے درج کیا تھا۔ اسے فعال کریں۔ اس کے بعد UI میں client row transfer counters اور حالیہ handshake time دکھانا شروع کر دے گی۔ جب فون tunnel سے منسلک ہو جائے تو وہ ان services تک رسائی حاصل کر سکتا ہے جنہیں آپ نے internet پر publish نہیں کیا۔ اسی طرح فون کہیں سے بھی self-hosted photo server پر upload کرتا رہ سکتا ہے، جبکہ اس server کا دنیا کے لیے کوئی port کھلا نہیں ہوتا۔ یہی طریقہ media کے لیے بھی کام کرتا ہے۔ 90s video store کے طور پر دوبارہ بنایا گیا Jellyfin library hotel room سے browse کرنے کے لیے مفید ہے، جبکہ یہ آپ کے LAN کی طرح private رہتی ہے۔ اسی tunnel پر alerts بھی دوسری سمت میں کام کرتے ہیں۔ self-hosted ntfy server backup job fail ہوتے ہی اس فون پر message push کر سکتا ہے، اور اسے public internet سے آنے والی کسی request کا جواب دینے کی ضرورت نہیں ہوتی۔

جو client enable کرنے کے بعد کوئی handshake نہیں دکھاتا، وہ server تک بالکل نہیں پہنچ رہا۔ اس کی وجہ UDP 51820 ہو سکتی ہے، جو provider firewall پر مسدود ہو، یا config میں شامل endpoint address غلط ہو سکتا ہے۔ جو client handshake دکھاتا ہے لیکن internet کام نہیں کرتا، اس میں مسئلہ forwarding یا DNS کا ہوتا ہے۔

Desktop پر .conf file download کریں اور اسے دوبارہ ٹائپ کرنے کے بجائے WireGuard client میں import کریں۔ اس file میں private key صرف ایک بار generate اور صرف ایک بار دکھائی جاتی ہے۔ اس file کو اسی طرح محفوظ رکھیں جیسے آپ SSH private key کو محفوظ رکھتے ہیں۔

UI سے آگے بڑھنے کا وقت

جب تک آپ کے peers انسان اور فون ہیں، wg-easy موزوں tool ہے۔ UI کے ذریعے config files میں ترمیم کرنے کے مقابلے میں کام تیزی سے ہوتا ہے، اور گم شدہ فون کو ایک click سے revoke کیا جا سکتا ہے۔

اس کی حدود اس وقت سامنے آتی ہیں جب آپ ایسا کچھ کرنا چاہیں جسے UI model نہیں کرتا۔ Site-to-site routing میں peer کا AllowedIPs کسی ایک address کے بجائے پورے remote subnet کا احاطہ کرتا ہے۔ عموماً یہی پہلی بڑی رکاوٹ ہوتی ہے۔ ہر peer کے لیے الگ routing rules والے split tunnels، یا آپ کے provisioning tool سے generate کی گئی config، اگلا مرحلہ ہیں۔ اس مقام پر ہاتھ سے کی گئی setup زیادہ مشکل نہیں ہوتی؛ طریقہ صرف مختلف ہوتا ہے۔ سادہ WireGuard guide میں یہی tunnel wg0.conf سے بنانے کا طریقہ موجود ہے۔ اگر آپ control plane چلانا ہی بند کرنا چاہتے ہیں تو WireGuard اور Tailscale کا موازنہ managed option کی وضاحت کرتا ہے۔ یہ تبادلہ مناسب ہے یا نہیں، اس کا انحصار اس بات پر ہے کہ coordination server حقیقتاً کن systems تک پہنچ سکتا ہے۔ اپنا network اس کے حوالے کرنے سے پہلے Tailscale کا trust model ضرور پڑھیں۔ اگلا سوال عموماً cost کا ہوتا ہے، اور Tailscale کا free plan حقیقتاً کیا cover کرتا ہے اتنا کافی ہے کہ گھرانے یا چھوٹی team کو اس کے لیے کچھ ادا نہیں کرنا پڑتا۔ اس حد سے آگے billing devices کے بجائے users کی تعداد کے مطابق ہوتی ہے۔ یہ اس VPS کے bill سے مختلف نوعیت کا خرچ ہے جس کی ادائیگی آپ پہلے ہی کر رہے ہیں۔ اس لیے team migrate کرنے سے پہلے free plan سے آگے بڑھنے پر Tailscale کی لاگت میں دی گئی رقم دیکھیں۔ آپ نے ابھی جو full tunnel بنایا ہے، اس کا وہاں براہ راست equivalent موجود ہے۔ VPS کو Tailscale exit node کے طور پر advertise کرنا server کے ذریعے باہر جانے والا یہی route فراہم کرتا ہے۔ فرق یہ ہے کہ اسے ہر client config میں لکھنے کے بجائے admin console میں approve کیا جاتا ہے۔ Subnet کی رکاوٹ کا بھی equivalent موجود ہے، کیونکہ VPS سے پورے private network کو advertise کرنا tailnet کے ہر device کو اس network تک رسائی دیتا ہے، بغیر اس per-peer AllowedIPs editing کے جس نے آپ کو UI سے آگے بڑھنے پر مجبور کیا۔ اگر آپ dashboard اور automatic mesh routing چاہتے ہیں، لیکن کسی دوسرے فریق کا coordination server نہیں، تو VPS پر اپنا NetBird server چلانا control plane کو آپ کے اپنے hardware پر رکھتا ہے۔ اس کے بدلے DNS اور TLS setup کرنا پڑتا ہے، جس کی ضرورت wg-easy نے کبھی نہیں ڈالی۔

اگر اوپر دی گئی Compose syntax آپ کے لیے WireGuard کے بجائے غیر مانوس حصہ تھی، تو VPS پر Docker Compose کی بنیادی باتیں file format اور روزمرہ کے commands کی وضاحت کرتی ہیں۔

FAQ

wg-easy میرے WG_HOST اور PASSWORD_HASH کو نظرانداز کیوں کرتا ہے؟

یہ variables wg-easy 14 سے متعلق ہیں۔ Version 15 ازسرنو تیار کیا گیا ہے، اور upstream نے تقریباً تمام configuration web UI کے admin panel میں منتقل کر دی ہے۔ Container ان دونوں variables میں سے کسی کو بھی نہیں پڑھتا۔ اس لیے یہ معمول کے مطابق start ہوتا ہے اور پہلی بار کھولنے پر آپ سے admin account بنانے کو کہتا ہے۔ Setup page پر client-facing host address درج کریں۔

اگر میرے kernel میں پہلے ہی WireGuard موجود ہے تو کیا مجھے SYS_MODULE درکار ہے؟

نہیں۔ SYS_MODULE اور /lib/modules mount اس لیے موجود ہیں کہ host پر module نہ ہونے کی صورت میں container اسے load کر سکے۔ ایسے host پر جہاں sudo modprobe wireguard پہلے ہی کامیاب ہو، یہ capability استعمال نہیں ہوتی۔ اسے ہٹانا hardening کا ایک مناسب قدم ہے، لیکن NET_ADMIN ہر صورت میں درکار ہے۔

Client connect ہو جاتا ہے، لیکن internet دستیاب نہیں۔ مسئلہ کیا ہے؟

بغیر traffic کے handshake تقریباً ہمیشہ forwarding کے مسئلے کی نشاندہی کرتا ہے۔ تصدیق کریں کہ net.ipv4.ip_forward=1 اور net.ipv4.conf.all.src_valid_mark=1 اب بھی compose file میں موجود ہیں، کیونکہ ہاتھ سے edit کی گئی copy میں یہ اکثر حذف ہو جاتے ہیں۔ اگر forwarding فعال ہے تو client کو موصول ہونے والے DNS server کو چیک کریں۔ اگر tunnel تمام traffic کو VPN کے ذریعے بھیجتا ہو، لیکن ایسے DNS server کی طرف اشارہ کرتا ہو جس تک اب رسائی نہ ہو، تو browser میں یہ صورتِ حال بالکل dead connection جیسی دکھائی دیتی ہے۔

میں اپنے clients کا backup کیسے بناؤں؟

تمام data etc_wireguard named volume میں موجود wg0.json file میں محفوظ ہوتا ہے۔ UI میں backup button بھی موجود ہے، جو اسی data کو export کرتا ہے۔ کسی بھی upgrade سے پہلے اس file کی copy server سے باہر کسی محفوظ جگہ پر رکھیں۔ Restore کرنے کے لیے fresh container کے setup مرحلے میں اسے upload کریں۔

کیا میں wg-easy کو reverse proxy کے پیچھے چلا سکتا ہوں؟

ہاں۔ Proxy کو TCP 51821 کے سامنے رکھیں، وہیں TLS terminate کریں، اور container پر INSECURE=true set کریں تاکہ یہ proxy سے آنے والے plain HTTP hop کو قبول کرے۔ UDP 51820 کو براہِ راست published رکھیں، کیونکہ VPN traffic UDP استعمال کرتا ہے اور HTTP proxy سے نہیں گزرتا۔