Docker ile wg-easy WireGuard Kurulumu ve Yapılandırması
Docker Compose kullanarak wg-easy ile WireGuard VPN kurulumunu yapın. NET_ADMIN yetkileri, gerekli sysctl ayarları ve QR kod ile hızlı mobil cihaz eşleştirme adımlarını inceleyin.
Ne inşa ediyorsunuz
wg-easy, tek bir Docker container içerisinde çalışan, web arayüzüne sahip bir WireGuard uygulamasıdır. WireGuard arayüzünü sizin yerinize yönetir ve istemci oluşturmak için bir tarayıcı arayüzü ekler. Oluşturduğunuz her istemci için bir yapılandırma dosyası ve QR kodu üretilir; böylece bir telefon, kamerasını ekrana tutarak VPN'e dahil olabilir.
Tünelin kendisi standart bir WireGuard bağlantısıdır. Paketler kernel modülü tarafından taşındığı için veri aktarım hızı, elle yapılan bir kurulumla aynıdır. Kazancınız istemci yaşam döngüsüdür: SSH üzerinden yapılandırma dosyası düzenlemek zorunda kalmadan eşleri (peers) ekleyebilir, devre dışı bırakabilir ve silebilirsiniz. Feragat ettiğiniz şey ise, bir VPS üzerinde manuel WireGuard kurulumu konusunun içeriği olan yapılandırma dosyası üzerindeki doğrudan kontroldür.
Yönetebileceğiniz, genel bir IP adresine veya bu adrese yönlendirilmiş bir alan adına sahip bir Linux sunucuya (örneğin bir KVM VPS), x86_64 veya arm64 mimarili bir işlemciye, Docker Engine ve Compose eklentisine ve root erişimine ihtiyacınız vardır. OpenVZ veya LXC gibi ana makine kernel'ını paylaşan container sanallaştırma yöntemleri genellikle WireGuard modülünü yükleyemez ve bu durumda container arayüzü ayağa kaldıramaz.
Sürüm 15 ayarları ortam değişkenlerinden çıkardı
Bulacağınız çoğu kılavuz, WG_HOST değerini sunucu adresinize ve PASSWORD_HASH değerini yönetici parolasının bcrypt özetine ortam değişkeni olarak atadığınız wg-easy 14 sürümü için yazılmıştır. Sürüm 15 tamamen yeniden yazılmıştır. Resmi geçiş notları, v15 sürümünün v14 ile aynı ortam değişkenlerini kullanmadığını ve bunların çoğunun web arayüzündeki yönetici paneline taşındığını açıkça belirtmektedir.
Bu nedenle WG_HOST ve PASSWORD_HASH artık hiçbir işlev görmemektedir. Eski bir compose dosyasını kopyalarsanız, container başlatılır, bu satırları yok sayar ve ardından tarayıcı üzerinden bir yönetici hesabı oluşturmanızı ister. Bu bir hata değildir. Bu, yeni kurulum akışıdır.
Ekim 2026 itibarıyla sabitlenmesi gereken ana etiket 15 şeklindedir. Ana sürümü sabitlemek, latest kullanmaktan daha güvenlidir; çünkü ana sürüm yükseltmeleri disk üzerindeki yapılandırma biçimini değiştirir ve temiz bir geri dönüş sağlamaz. 15 sürümüne geçişle birlikte v14'ün JSON dosyası yerini SQLite veritabanına bırakmıştır.
Compose dosyası
Stack için bir dizin oluşturun ve resmi compose dosyasını bu dizin içine yazın. Bu, isteğe bağlı yorum satırları çıkarılmış upstream dosyasıdır.
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.ymlDosya içeriği şu şekildedir:
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, sunucu anahtarını ve oluşturduğunuz her istemciyi barındıran, wg-easy.db SQLite veritabanında depolanan adlandırılmış bir volume'dür. Bu volume'ü yedekleyin; aksi takdirde yeniden kurulum sırasında tüm eşleriniz silinir. Eğer bu dosyaları host dosya sisteminde görmeyi tercih ederseniz, bunu bir bind mount ile değiştirin. Ancak bunu yapmadan önce bind mount ve adlandırılmış volume arasındaki farklar konusunu okuyun, çünkü izinler farklı şekilde işlemektedir.
Neden NET_ADMIN, SYS_MODULE ve sysctl ayarları gereklidir
Bir container varsayılan olarak ağ yığınına müdahale edemez; bu satırların her biri belirli bir kısıtlamayı kaldırır.
NET_ADMIN, container'ın wg0 arayüzünü oluşturmasına, bir adres atamasına ve yönlendirme kuralları yazmasına olanak tanır. Bu yetki olmadan container başlar ancak arayüzü ayağa kaldırırken ip link add wg0 type wireguard, Operation not permitted hatası döndürdüğü için kapanır.
SYS_MODULE ve salt okunur /lib/modules bağlaması (mount), ana makinede yüklü değilse WireGuard çekirdek modülünün container tarafından yüklenmesini sağlar. Modül imajın içinde değil, ana makinenin çekirdeğinde bulunur; bu nedenle ana makine dizininin görünür olması gerekir. Modern çekirdeklerde modül genellikle yerleşik olarak gelir; bunu ana makinede sudo modprobe wireguard && echo ok komutu ile doğrulayabilirsiniz.
net.ipv4.ip_forward=1, çekirdeğin kendisine gönderilmeyen paketleri iletmesini (forward) sağlar. Bu ayar olmadan istemci bağlanır, el sıkışma başarılı olur ancak internete giden her paket düşürülür; bu yüzden VPN bağlı görünse de ping 1.1.1.1 zaman aşımına uğrar.
net.ipv4.conf.all.src_valid_mark=1 genellikle kullanıcıları şaşırtan ayardır. WireGuard, kendi giden paketlerini işaretler; böylece bu paketler tekrar tünele yönlendirilmez. Sıkı ters yol filtreleme (strict reverse path filtering), kaynak adresi beklenen rota ile eşleşmeyen bir paket gördüğünde onu düşürür. Bu sysctl ayarı, çekirdeğe işaretli paketleri kabul etmesini söyler; tam tünel yapısının kendi kendini bozmasını engelleyen mekanizma budur.
Başlatın ve yönetici hesabını oluşturun
cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -fstart ve stop yerine docker compose up ve docker compose down kullanın. start yalnızca mevcut container'ları yeniden başlatır; dolayısıyla ağ ve sysctl ayarları dahil olmak üzere compose dosyasında yaptığınız hiçbir değişiklik uygulanmaz. up ise değişen her şeyi yeniden oluşturur. Bir yeniden başlatma sonrasında stack'in geri gelmesini istiyorsanız, restart: unless-stopped bunu zaten kapsar; compose servislerinin önyükleme davranışı bu politikanın neyi vaat edip neyi etmediğini açıklar.
Web arayüzü TCP 51821 portunu dinler. İlk ziyarette, yönetici hesabını oluşturacağınız ve istemcilerin sunucuya ulaşmak için kullanacağı ana bilgisayar adresini onaylayacağınız bir kurulum sayfası görüntülenir. Bu ana bilgisayar adresi, her istemci yapılandırmasının Endpoint satırına eklenir; bu nedenle VPS'in genel IP adresi veya DNS adı olmalıdır. Adres yanlışsa, telefona okuttuğunuz QR kodu ulaşılamaz bir noktayı işaret eder ve el sıkışma (handshake) asla tamamlanmaz.
Bu portla ilgili bir husus daha: wg-easy kendi başına TLS sunmaz ve düz HTTP bağlantılarını reddetmez. http:// üzerinden arayüz yine de yüklenir ve bir uyarı başlığı gösterir. Varsayılan ayarların değiştirdiği şey, Secure bayrağını taşıyan oturum çerezidir; bu nedenle genel bir adres üzerinden düz HTTP ile arayüze erişen bir tarayıcı çerezi reddeder ve giriş işlemi kalıcı olmaz. INSECURE=true bu bayrağı kaldırır ve başka hiçbir işlem yapmaz. Ön tarafa TLS termination yapan bir reverse proxy koymak, kendinden imzalı bir sertifika ile olsa bile, wg-easy üzerinde herhangi bir değişiklik gerektirmez.
UI portunu internete açmayın
Compose dosyası, 51821 numaralı portu tüm arayüzlerde erişime açar. Bu port, trafiğinizi yönlendirebilen bir kutunun giriş sayfasıdır ve dünyaya açık olmamalıdır. Docker üzerinde bir portu dışarıya açmak, DOCKER zincirine kurallar ekler. Bu zincir ufw kurallarından önce değerlendirildiği için, ufw ile tanımlanan bir engelleme kuralı bu portu kapatmaz. Bu durum başlı başına anlaşılması gereken bir tuzaktır ve Docker tarafından açılan portların neden ufw kurallarını görmezden geldiği konusu bu durumu detaylıca açıklar.
En basit çözüm, UI arayüzünü loopback arayüzüne bağlamak ve ona bir SSH tüneli üzerinden erişmektir:
ports:
- "51820:51820/udp"
- "127.0.0.1:51821:51821/tcp"
environment:
- INSECURE=trueArdından dizüstü bilgisayarınızdan şu komutu çalıştırın:
ssh -L 51821:127.0.0.1:51821 youruser@your.server.addressDizüstü bilgisayarınızdaki tarayıcıda http://127.0.0.1:51821 adresini açın. Trafik SSH ile şifrelenir ve port başka hiç kimseye yanıt vermez. INSECURE=true değişkeni, oturum çerezinden yalnızca Secure bayrağını kaldırır; böylece tarayıcı giriş bilgilerinizi bu düz HTTP adresi üzerinde tutmaya devam eder. Bu işlem, düz HTTP bağlantısı asla loopback arayüzünden dışarı çıkmadığı için güvenlidir.
UDP 51820 portunu açın ve her iki güvenlik duvarını da kontrol edin
WireGuard'ın kendisi, internet üzerinden UDP 51820 portuna erişilebilmesini gerektirir. Docker bu portu yayınlar ancak birçok sağlayıcı, VPS'in önüne Docker'ın haberdar olmadığı ayrı bir ağ güvenlik duvarı yerleştirir. Portu her iki yerde de açın. Eğer ana makine güvenlik duvarını ufw ile yönetiyorsanız, bir VPS için temel ufw kuralları rehberi, nftables kurallarını elle yazmaktan daha kısa bir yoldur.
Konteynerin gerçekten dinleme yapıp yapmadığını kontrol edin:
sudo ss -ulnp | grep 51820Bir dinleme yapan UDP soketi görmelisiniz. Bu satırda hiçbir şey görünmüyorsa, konteyner arayüzü hiç ayağa kaldırmamış demektir ve sudo docker compose logs wg-easy bunun nedenini belirtecektir.
Bir istemci oluşturun ve telefonda taratın
Arayüzde bir istemci oluşturun ve daha sonra tanıyabileceğiniz, örneğin ait olduğu cihaz gibi bir isim verin. wg-easy bir sonraki boş tünel adresini atar ve sizin için anahtar çiftini oluşturur. Her istemci satırı bir QR kodu ve indirilebilir bir .conf dosyası sunar.
Resmi WireGuard uygulamasını telefona yükleyin, QR kodundan tünel eklemeyi seçin ve kamerayı ekranınızdaki koda doğrultun. Tünel, yazdığınız isimle görünür. Tüneli açtığınızda, arayüzdeki istemci satırı transfer sayaçlarını ve son el sıkışma (handshake) zamanını göstermeye başlar. Bir telefon tünele bağlandığında, internete hiç açmadığınız servislere erişebilir; bu sayede bir telefon, sunucunun dış dünyaya tek bir portu bile açık olmadan her yerden kendi barındırdığınız bir fotoğraf sunucusuna veri yükleyebilir. Aynı yöntem medya için de geçerlidir; 90'ların video dükkanı gibi yeniden tasarlanmış bir Jellyfin kütüphanesi, yerel ağınızdaki kadar gizli kalırken bir otel odasından göz atması keyifli bir deneyim sunar. Uyarılar aynı tünel üzerinden ters yönde çalışır; kendi barındırdığınız bir ntfy sunucusu, bir yedekleme işi başarısız olduğu anda, genel internetten gelen bir isteği yanıtlamak zorunda kalmadan o telefona mesaj gönderebilir.
Etkinleştirdikten sonra el sıkışma göstermeyen bir istemci sunucuya hiç ulaşamıyor demektir. Bu durum, sağlayıcı güvenlik duvarındaki veya yapılandırmaya işlenmiş uç nokta adresindeki UDP 51820 portuna işaret eder. El sıkışma gösteren ancak internet bağlantısı çalışmayan bir istemci ise yönlendirme veya DNS sorununa işaret eder.
Masaüstünde .conf dosyasını indirin ve yeniden yazmak yerine WireGuard istemcisine içe aktarın. Bu dosyadaki özel anahtar bir kez oluşturulur ve bir kez gösterilir. Dosyaya, bir SSH özel anahtarına davrandığınız gibi davranın.
Arayüzün yetersiz kaldığı durumlar
wg-easy, kullanıcılarınız insanlar ve telefonlardan ibaret olduğu sürece doğru araçtır. Arayüz, yapılandırma dosyalarını düzenlemekten daha hızlıdır ve kaybolan bir telefonu sistemden çıkarmak tek bir tıklama ile gerçekleşir.
Arayüzün modellemediği bir özellik istediğinizde sınırlarına ulaşırsınız. Bir eşin (peer) AllowedIPs değerinin tek bir adresi değil, tüm uzak alt ağı kapsadığı noktadan noktaya (site-to-site) yönlendirme, genellikle karşılaşılan ilk engeldir. Eş bazlı yönlendirme kurallarına sahip ayrık tüneller (split tunnels) veya sağlama (provisioning) aracınız tarafından oluşturulan bir yapılandırma, bir sonraki aşamadır. Bu noktada elle yapılan kurulum daha zor değildir, sadece farklıdır ve yalın WireGuard rehberi, aynı tünelin wg0.conf kullanılarak nasıl oluşturulacağını gösterir. Kontrol düzlemini (control plane) tamamen çalıştırmaktan vazgeçmek isterseniz, WireGuard ve Tailscale karşılaştırması yönetilen seçeneği ele alır. Bunun adil bir takas olup olmadığı, koordinasyon sunucusunun gerçekte nelere erişebileceğine bağlıdır; bu nedenle ağınızı teslim etmeden önce Tailscale güven modeli okunmalıdır. Maliyet genellikle bir sonraki sorudur ve Tailscale ücretsiz planının neleri kapsadığı, ticari olmayan kullanım için altı kullanıcıya kadar ücretsizdir; bu sayede bir hane halkı hiçbir ücret ödemezken, küçük bir iş ekibi kişi sayısı az olsa dahi bu kapsama girmez. Bu noktadan sonra faturalandırma cihaz yerine kullanıcı sayısını esas alır; bu, halihazırda ödediğiniz bir VPS'ten farklı bir fatura yapısıdır. Bu nedenle, bir ekibi taşımadan önce ücretsiz plan aşıldığında Tailscale maliyetleri kontrol edilmesi gereken rakamdır. Az önce oluşturduğunuz tam tünelin orada doğrudan bir karşılığı vardır; VPS'i Tailscale çıkış düğümü olarak tanıtmak, her istemci yapılandırmasına yazmak yerine yönetici konsolundan onaylanan aynı sunucu çıkış rotasını sağlar. Alt ağ engeli için de bir karşılık mevcuttur; tüm özel ağı VPS üzerinden tanıtmak, sizi arayüzden uzaklaştıran eş bazlı AllowedIPs düzenlemelerine gerek kalmadan, o ağı tailnet içindeki her cihaza sunar. Eğer o paneli ve otomatik mesh yönlendirmeyi istiyor ancak başkasının koordinasyon sunucusunu kullanmak istemiyorsanız, kendi NetBird sunucunuzu VPS üzerinde çalıştırmak, kontrol düzlemini kendi donanımınızda tutmanızı sağlar; bunun bedeli ise wg-easy'nin sizden hiç istemediği DNS ve TLS kurulumudur.
Eğer yukarıdaki compose sözdizimi WireGuard kısmından ziyade yabancı olduğunuz bölümse, VPS üzerinde Docker Compose temelleri, dosya biçimini ve günlük komutları açıklar.
FAQ
wg-easy neden WG_HOST ve PASSWORD_HASH değişkenlerimi görmezden geliyor?
Bu değişkenler wg-easy 14 sürümüne aittir. Sürüm 15 tamamen yeniden yazılmıştır ve geliştiriciler yapılandırmanın neredeyse tamamını web arayüzündeki yönetici paneline taşımıştır. Container bu değişkenleri okumaz; bu nedenle normal şekilde başlar ve ilk girişte sizden bir yönetici hesabı oluşturmanızı ister. İstemciye yönelik ana bilgisayar adresini kurulum sayfasında ayarlayın.
Çekirdeğimde zaten WireGuard varsa SYS_MODULE gerekli mi?
Hayır. SYS_MODULE ve /lib/modules mount noktaları, ana bilgisayarda modül bulunmadığı durumlarda container'ın modülü yükleyebilmesi için vardır. sudo modprobe wireguard komutunun zaten başarılı olduğu bir ana bilgisayarda bu yetenek kullanılmaz. Bunu kaldırmak makul bir güvenlik sıkılaştırma adımıdır; ancak NET_ADMIN her iki durumda da gereklidir.
İstemci bağlanıyor ancak internete çıkış yok. Sorun nedir?
El sıkışmanın gerçekleştiği ancak trafik akışının olmadığı durumlar neredeyse her zaman yönlendirme (forwarding) ile ilgilidir. net.ipv4.ip_forward=1 ve net.ipv4.conf.all.src_valid_mark=1 satırlarının compose dosyasında mevcut olduğunu doğrulayın; elle düzenlenen kopyalarda bu satırlar genellikle silinir. Yönlendirme aktifse, istemcinin aldığı DNS sunucusunu kontrol edin. Tüm trafiği VPN üzerinden gönderen ancak artık erişemediği bir DNS sunucusuna işaret eden bir tünel, tarayıcıda bağlantı kopukluğu gibi görünür.
İstemcilerimin yedeğini nasıl alırım?
Her şey etc_wireguard adlı volume içerisinde tutulur. Sürüm 15'te bu, container içindeki /etc/wireguard/wg-easy.db konumunda bulunan bir SQLite veritabanı anlamına gelir. Sürüm 15 belgelerinde herhangi bir yedekleme veya dışa aktarma özelliği tanımlanmamıştır; bu nedenle volume'un kendisini yedekleyin: docker compose down komutunu çalıştırın, volume içeriğini sunucu dışında bir yere kopyalayın ve ardından docker compose up -d ile stack'i tekrar ayağa kaldırın. Bu işlemi herhangi bir yükseltme öncesinde yapın. Eski kılavuzlarda bahsedilen wg0.json dosyası wg-easy 14'e aittir. Bu dosya v14 yedekleme düğmesinin dışa aktardığı dosyadır ve v15'te tek kullanım amacı, eski bir kurulumu taşırken kurulum sihirbazında yüklediğiniz dosya olmasıdır.
wg-easy'yi bir reverse proxy arkasında çalıştırabilir miyim?
Evet. Proxy'yi web arayüzü portunun önüne yerleştirin, TLS termination işlemini orada yapın ve INSECURE değişkenini boş bırakın. Container, proxy'den gelen düz HTTP trafiğini olduğu gibi kabul eder; resmi Caddy ve Traefik örneklerinde INSECURE değişkeni hiç ayarlanmaz. Tarayıcı proxy ile HTTPS üzerinden konuştuğu için oturum çerezinin Secure bayrağını korumasını istersiniz; INSECURE=true değişkeni bu bayrağı kaldıran tek ayardır. UDP 51820 portunu doğrudan dışarıya açık tutun, çünkü VPN trafiği UDP tabanlıdır ve bir HTTP proxy üzerinden geçmez.