SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-29

wg-easy: WireGuard dengan UI Web di Docker

Jalankan WireGuard dengan UI web wg-easy di Docker Compose. Pelajari port, NET_ADMIN, sysctl penting, serta onboarding ponsel memakai kode QR.

Yang akan Anda bangun

wg-easy adalah WireGuard dengan antarmuka web yang berjalan sebagai satu container Docker. Aplikasi ini mengelola antarmuka WireGuard dan menyediakan UI browser untuk membuat client. Setiap client yang dibuat akan memperoleh file konfigurasi dan kode QR, sehingga ponsel dapat bergabung ke VPN dengan mengarahkan kameranya ke layar.

Tunnel tersebut tetap menggunakan WireGuard biasa. Modul kernel memindahkan paket, sehingga throughput sama seperti pada konfigurasi yang ditulis manual. Keuntungannya adalah pengelolaan siklus hidup client: Anda dapat menambahkan, menonaktifkan, dan menghapus peer tanpa mengedit file konfigurasi melalui SSH. Kekurangannya adalah Anda tidak memiliki kendali langsung atas file konfigurasi tersebut. Hal ini dibahas dalam penyiapan WireGuard manual pada VPS.

Anda memerlukan KVM VPS dengan alamat IPv4 publik, Docker Engine dengan plugin Compose, dan akses root. Virtualisasi container yang berbagi kernel host, seperti OpenVZ atau LXC, biasanya tidak dapat memuat modul WireGuard. Akibatnya, container gagal mengaktifkan antarmuka tersebut.

Versi 15 memindahkan pengaturan dari environment

Sebagian besar panduan yang tersedia ditulis untuk wg-easy 14. Pada versi tersebut, Anda menetapkan WG_HOST ke alamat server dan PASSWORD_HASH ke hash bcrypt untuk password admin, keduanya sebagai environment variable. Versi 15 merupakan penulisan ulang. Catatan migrasi resmi menyatakan dengan jelas bahwa v15 tidak menggunakan environment variable yang sama seperti v14, dan sebagian besar pengaturan tersebut dipindahkan ke panel admin pada web UI.

Karena itu, WG_HOST dan PASSWORD_HASH tidak lagi berfungsi. Jika Anda menyalin file compose lama, container akan berjalan, mengabaikan baris tersebut, lalu meminta Anda membuat akun admin melalui browser. Ini bukan bug. Ini adalah alur setup yang baru.

Per Juli 2026, tag mayor yang perlu dipin adalah 15. Gunakan versi mayor, bukan latest, karena upgrade mayor mengubah format konfigurasi pada disk dan tidak dapat dikembalikan dengan bersih.

File compose

Buat direktori untuk stack tersebut, lalu tulis file compose resmi ke dalamnya. Ini adalah file dari upstream tanpa perubahan.

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

Isinya seperti berikut:

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 adalah volume bernama yang menyimpan kunci server dan setiap client yang Anda buat. Cadangkan volume tersebut. Jika tidak, proses rebuild akan menghapus semua peer Anda. Jika Anda ingin melihat file tersebut pada filesystem host, ganti volume itu dengan bind mount. Sebelum melakukannya, baca perbedaan antara bind mount dan volume bernama karena perilaku izinnya berbeda.

Mengapa memerlukan NET_ADMIN, SYS_MODULE, dan sysctl

Container tidak diizinkan mengubah network stack secara default. Setiap baris ini menghapus satu pembatas tertentu.

NET_ADMIN memungkinkan container membuat interface wg0, menetapkan alamat padanya, dan menulis rute. Tanpanya, container akan start lalu berhenti saat mengaktifkan interface karena ip link add wg0 type wireguard mengembalikan Operation not permitted.

SYS_MODULE bersama mount /lib/modules read-only memungkinkan container memuat kernel module WireGuard jika host belum memuatnya. Module tersebut berada pada kernel host, bukan di dalam image. Karena itu, direktori host harus terlihat oleh container. Pada kernel modern, module ini biasanya sudah terintegrasi. Anda dapat memastikannya dengan sudo modprobe wireguard && echo ok pada host.

net.ipv4.ip_forward=1 membuat kernel meneruskan paket yang tidak ditujukan ke host itu sendiri. Tanpanya, client dapat terhubung dan handshake berhasil, tetapi setiap paket menuju internet akan dibuang. Akibatnya, ping 1.1.1.1 mengalami timeout meskipun VPN terlihat terhubung.

net.ipv4.conf.all.src_valid_mark=1 adalah bagian yang sering mengejutkan pengguna. WireGuard menandai paket keluar miliknya sendiri agar paket tersebut tidak dirutekan kembali ke dalam tunnel. Reverse path filtering yang ketat melihat paket dengan alamat sumber yang tidak sesuai dengan rute yang diharapkan, lalu membuangnya. sysctl ini memberi tahu kernel untuk menerima paket yang ditandai. Inilah yang mencegah full tunnel menghentikan koneksinya sendiri.

Jalankan dan buat akun admin

cd /etc/docker/containers/wg-easy
sudo docker compose up -d
sudo docker compose logs -f

Gunakan docker compose up dan docker compose down, bukan start dan stop. Upstream memperingatkan bahwa start pada container yang dibuat dengan pengaturan berbeda dapat membuat jaringan berada dalam kondisi tidak konsisten. Jika Anda ingin stack kembali berjalan setelah reboot, restart: unless-stopped sudah menangani hal tersebut. Penjelasan tentang perilaku boot layanan compose menjelaskan hal-hal yang dijamin dan tidak dijamin oleh kebijakan tersebut.

Web UI mendengarkan pada TCP 51821. Saat pertama kali dibuka, UI menampilkan halaman penyiapan untuk membuat akun admin dan mengonfirmasi alamat host yang akan digunakan client untuk mengakses server. Alamat host tersebut dicantumkan pada baris Endpoint di setiap konfigurasi client. Karena itu, alamat tersebut harus berupa IP publik atau nama DNS VPS. Jika alamatnya salah, QR code yang Anda berikan kepada ponsel akan mengarah ke lokasi yang tidak dapat dijangkau dan handshake tidak pernah selesai.

Ada satu hal lagi tentang port tersebut: wg-easy 15 menolak HTTP biasa kecuali Anda menetapkan INSECURE=true. Mengaksesnya melalui HTTPS dengan sertifikat yang tidak tepercaya atau melakukan TLS termination pada reverse proxy di depannya sama-sama dapat digunakan. Mengaksesnya melalui http:// dengan pengaturan default tidak dapat digunakan.

Jangan publikasikan port UI ke Internet

File compose memublikasikan 51821 pada setiap interface. Port tersebut mengarah ke halaman login untuk mesin yang dapat merutekan trafik Anda, sehingga tidak boleh dibuka untuk semua orang. Memublikasikan port di Docker menulis aturan ke dalam chain DOCKER, yang dievaluasi sebelum ufw. Karena itu, aturan penolakan ufw tidak menutup port tersebut. Perangkap ini penting untuk dipahami secara khusus, dan alasan port yang dipublikasikan Docker mengabaikan ufw membahasnya secara lengkap.

Perbaikan sederhananya adalah mengikat UI ke loopback lalu mengaksesnya melalui tunnel SSH:

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

Kemudian, dari laptop Anda:

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

Buka http://127.0.0.1:51821 di browser pada laptop Anda. Trafik dienkripsi oleh SSH, port tersebut tidak merespons koneksi dari pihak lain, dan INSECURE=true aman digunakan di sini karena hop HTTP biasa tidak pernah meninggalkan interface loopback.

Buka UDP 51820 dan periksa kedua firewall

WireGuard memerlukan UDP 51820 agar dapat dijangkau dari Internet. Docker memublikasikan port tersebut, tetapi banyak provider menempatkan firewall jaringan terpisah di depan VPS yang tidak diketahui Docker. Buka port tersebut di kedua tempat. Jika Anda mengelola firewall host dengan ufw, aturan ufw dasar untuk VPS lebih singkat daripada menulis nftables secara manual.

Periksa apakah container benar-benar sedang listening:

sudo ss -ulnp | grep 51820

Anda seharusnya melihat socket UDP yang sedang listening. Jika tidak ada apa pun pada baris tersebut, container tidak pernah berhasil mengaktifkan interface, dan sudo docker compose logs wg-easy akan menyebutkan penyebabnya.

Buat klien dan pindai pada ponsel

Di UI, buat klien dan beri nama yang akan Anda kenali nanti, misalnya berdasarkan perangkat yang menggunakannya. wg-easy mengalokasikan alamat tunnel bebas berikutnya dan membuat pasangan kunci untuk Anda. Setiap baris klien menyediakan kode QR dan file .conf yang dapat diunduh.

Instal aplikasi WireGuard resmi pada ponsel, pilih opsi untuk menambahkan tunnel dari kode QR, lalu arahkan kamera ke kode pada layar Anda. Tunnel akan muncul dengan nama yang Anda masukkan. Aktifkan tunnel tersebut. Baris klien di UI akan mulai menampilkan penghitung transfer dan waktu handshake terbaru. Setelah ponsel terhubung ke tunnel, ponsel dapat mengakses layanan yang tidak pernah Anda publikasikan ke internet. Dengan demikian, ponsel dapat terus mengunggah foto ke server foto yang di-host sendiri dari mana saja tanpa server tersebut membuka satu pun port ke jaringan publik. Cara yang sama berlaku untuk media. Library Jellyfin yang dibuat ulang sebagai toko video tahun 90-an nyaman dijelajahi dari kamar hotel, sementara layanan tersebut tetap privat seperti saat berada di LAN Anda. Peringatan juga dapat berjalan melalui tunnel yang sama, karena server ntfy yang di-host sendiri dapat mengirim pesan ke ponsel tersebut segera setelah tugas pencadangan gagal, tanpa pernah menerima permintaan dari internet publik.

Klien yang tidak menampilkan handshake setelah diaktifkan sama sekali tidak dapat menjangkau server. Periksa UDP 51820, baik pada firewall provider maupun alamat endpoint yang tertanam dalam konfigurasi. Klien yang menampilkan handshake tetapi tidak dapat menggunakan internet biasanya bermasalah pada forwarding atau DNS.

Pada desktop, unduh file .conf dan impor file tersebut ke klien WireGuard, bukan mengetiknya kembali. Kunci privat dalam file tersebut dibuat satu kali dan ditampilkan satu kali. Perlakukan file tersebut seperti Anda memperlakukan kunci privat SSH.

Kapan harus beralih dari UI

wg-easy adalah alat yang tepat selama peer Anda berupa orang dan ponsel. UI lebih cepat daripada mengedit file konfigurasi, dan pencabutan akses ponsel yang hilang dapat dilakukan dengan satu klik.

Anda akan menemui batasnya ketika membutuhkan sesuatu yang tidak dimodelkan oleh UI. Routing site-to-site, ketika AllowedIPs milik sebuah peer mencakup seluruh subnet jarak jauh, bukan hanya satu alamat, biasanya menjadi batas pertama. Split tunnel dengan aturan routing per peer, atau konfigurasi yang dibuat oleh alat provisioning Anda, menjadi batas berikutnya. Pada titik itu, konfigurasi manual tidak lebih sulit; caranya hanya berbeda. Panduan WireGuard standar menunjukkan tunnel yang sama menggunakan wg0.conf. Jika Anda ingin berhenti menjalankan control plane sepenuhnya, Perbandingan WireGuard dengan Tailscale membahas opsi terkelola. Apakah pilihan itu sepadan bergantung pada jaringan yang benar-benar dapat dijangkau oleh server koordinasi. Model kepercayaan Tailscale perlu dibaca sebelum Anda memberikan akses ke jaringan Anda. Biaya biasanya menjadi pertanyaan berikutnya. Cakupan paket gratis Tailscale cukup untuk membuat rumah tangga atau tim kecil tidak perlu membayar. Setelah melewati batas tersebut, penagihan dihitung berdasarkan pengguna, bukan perangkat. Bentuk tagihannya berbeda dari VPS yang sudah Anda bayar. Karena itu, periksa biaya Tailscale setelah melewati paket gratis sebelum memigrasikan tim. Tunnel penuh yang baru saja Anda buat memiliki padanan langsung di sana. Mengiklankan VPS sebagai exit node Tailscale memberikan rute keluar melalui server yang sama. Persetujuannya dilakukan di konsol admin, bukan ditulis ke setiap konfigurasi client. Batas subnet juga memiliki padanan. Mengiklankan seluruh jaringan privat dari VPS memberikan jaringan tersebut kepada setiap perangkat di tailnet tanpa perlu mengedit AllowedIPs per peer, yang sebelumnya membuat Anda harus beralih dari UI. Jika Anda menginginkan dashboard dan routing mesh otomatis tersebut, tetapi tidak ingin menggunakan server koordinasi milik pihak lain, Menjalankan server NetBird sendiri pada VPS menjaga control plane tetap pada perangkat keras milik Anda. Konsekuensinya, Anda harus mengatur DNS dan TLS yang tidak diperlukan oleh wg-easy.

Jika sintaks compose di atas yang belum dikenal, bukan bagian WireGuard-nya, Dasar-Dasar Docker Compose pada VPS menjelaskan format file dan perintah yang digunakan sehari-hari.

FAQ

Mengapa wg-easy mengabaikan WG_HOST dan PASSWORD_HASH saya?

Variabel tersebut digunakan oleh wg-easy 14. Versi 15 ditulis ulang, dan upstream memindahkan hampir seluruh konfigurasi ke panel admin pada antarmuka web. Container tidak membaca kedua variabel tersebut, sehingga container berjalan normal lalu meminta Anda membuat akun admin saat pertama kali diakses. Tetapkan alamat host yang diakses client pada halaman penyiapan tersebut.

Apakah SYS_MODULE diperlukan jika kernel saya sudah memiliki WireGuard?

Tidak. SYS_MODULE dan mount /lib/modules tersedia agar container dapat memuat module saat host belum memilikinya. Pada host yang sudah berhasil menjalankan sudo modprobe wireguard, capability tersebut tidak digunakan. Menghapusnya merupakan langkah hardening yang wajar, tetapi NET_ADMIN tetap diperlukan.

Client terhubung, tetapi tidak ada Internet. Apa masalahnya?

Handshake tanpa trafik hampir selalu menunjukkan masalah forwarding. Pastikan net.ipv4.ip_forward=1 dan net.ipv4.conf.all.src_valid_mark=1 masih ada dalam file compose, karena salinan yang diedit secara manual sering kehilangan keduanya. Jika forwarding aktif, periksa server DNS yang diterima client. Tunnel yang mengirim seluruh trafik melalui VPN tetapi mengarah ke server DNS yang tidak lagi dapat dijangkaunya akan terlihat seperti koneksi yang tidak berfungsi pada browser.

Bagaimana cara mencadangkan client saya?

Semua data berada dalam named volume etc_wireguard, di dalam file wg0.json. UI juga memiliki tombol backup yang mengekspor data yang sama. Salin file tersebut ke lokasi di luar server sebelum melakukan upgrade apa pun. Pemulihan dilakukan dengan mengunggah file saat langkah penyiapan pada container baru.

Dapatkah saya menjalankan wg-easy di balik reverse proxy?

Ya. Tempatkan proxy di depan TCP 51821, lakukan terminasi TLS di sana, lalu tetapkan INSECURE=true pada container agar menerima hop HTTP biasa dari proxy. Tetap publikasikan UDP 51820 secara langsung karena trafik VPN menggunakan UDP dan tidak melewati HTTP proxy.