- Add WGRplane component documentation to AGENTS.md - Update README.md with combined WireGuard Policy + WGRplane docs - Fix .gitignore (remove .gitea/ from ignore)
WireGuard Policy Firewall + WGRplane Control Plane
A complete WireGuard management solution combining two powerful components:
- WireGuard Dynamic Policy Firewall - A lightweight, robust iptables/ipset policy engine that restricts and controls WireGuard peer traffic directly from
wg0.confusing custom#Accesscomments. - WGRplane - A Go-native control plane application with Vue 3 frontend, providing a modern web dashboard for WireGuard management with real-time monitoring, peer CRUD, and hybrid firewall enforcement.
📑 Table of Contents
Policy Firewall (Shell Scripts)
- Architecture & Data Flow
- Installation
- Prerequisites
- wg0.conf Integration
- CLI Usage
- Systemd Integration
WGRplane (Go App)
- WGRplane Overview
- WGRplane Architecture
- WGRplane Features
- WGRplane Tech Stack
- WGRplane API Endpoints
- WGRplane Installation
🎯 Architecture & Data Flow
wg0.conf: The standard WireGuard configuration. Contains standard[Peer]configs alongside a custom#Accesstag.wg-sync-policy.sh: Safely parseswg0.confand generates a structured/etc/wireguard/policy.jsonatomically.wg-policy-engine.sh: Readspolicy.jsonto generate robust rules, applyingiptablesandipsetdirectly to the system.- Watcher Daemon: Monitors
wg0.conffor changes viainotifywaitand triggers the pipeline seamlessly when updates are made.
📁 Installation
The easiest way to install is using the provided install.sh script, which automatically installs dependencies, copies all scripts to /usr/local/bin/, sets up the systemd daemon, and enables the service.
# Install everything
sudo ./install.sh install
# Uninstall everything
sudo ./install.sh uninstall
Building the Installer (For Developers)
If you modify any of the source .sh or .service files, you must rebuild the install.sh script using the provided builders.
On Linux (Bash):
./build.sh
On Windows (CMD/PowerShell):
build.bat
📦 Prerequisites
| Package | Required | Install |
|---|---|---|
jq |
Yes | apt install jq |
inotify-tools |
Yes (for watcher daemon) | apt install inotify-tools |
ipset |
Optional | apt install ipset |
If ipset is not installed, the engine will automatically fall back to per-rule iptables whitelist entries. This works fine for small deployments. For large numbers of clients/targets, ipset is recommended for O(1) lookup performance.
⚙️ Integrasi ke wg0.conf
To integrate the engine, you need to append hooks into your wg0.conf interface block, and declare the #Access tags under each peer.
1. Interface Block (Hooks)
Add the PostUp and PostDown scripts so the engine initializes correctly during VPN startup and removes traces upon shutdown.
⚠️ WireGuard does NOT support multiline values. Every command must be on a
PostUp = ...orPostDown = ...line. Bare commands without thePostUp =prefix will causeConfiguration parsing error.
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = <SERVER_PRIVATE_KEY>
# Policy engine: auto-handles NAT, IP forwarding, and dynamic firewall rules
PostUp = /usr/local/bin/wg-sync-policy.sh; /usr/local/bin/wg-policy-engine.sh
# Policy engine: cleanup all firewall and routing traces
PostDown = /usr/local/bin/wg-policy-cleanup.sh
2. Peer Block (#Access Tags)
For each client, use the #Access comment line. Define the destinations (targets) the peer is allowed to access. You can separate multiple IPs or CIDRs with commas or semicolons.
⚠️ WARNING: Do NOT use
SaveConfig = true! WireGuard'sSaveConfigfeature overwriteswg0.confdirectly and strips all comments, which will permanently delete all#Accesstags. If you are using a Web UI/Dashboard, make sure it does not strip unknown comments when saving.
[Peer]
PublicKey = <CLIENT_1_PUBKEY>
AllowedIPs = 10.0.0.2/32
#Access 192.168.1.10/32, 192.168.12.0/24
[Peer]
PublicKey = <CLIENT_2_PUBKEY>
AllowedIPs = 10.0.0.3/32
#Access = 10.0.0.1/32
[Peer]
PublicKey = <CLIENT_3_PUBKEY>
AllowedIPs = 10.0.0.4/32
#Access
# ^ (Empty Access implies internet-only, client isolation applies)
⚠️ Important constraint: Why #Access instead of just using AllowedIPs directly?
WireGuard uses AllowedIPs for Cryptokey Routing (deciding which tunnel interface to route outbound packets). If you put an internal server IP inside the server's wg0.conf AllowedIPs block, WireGuard will aggressively capture and redirect packets bound for that internal server into the VPN client's tunnel. The #Access comment separates routing parameters from firewall parameters cleanly.
🛠 wg-policy-ctl CLI Usage
You don't need to manually interact with iptables or .json files. Use the wg-policy-ctl wrapper.
# View the health of the firewall engine and active locks
wg-policy-ctl status
# View the raw, parsed JSON policy
wg-policy-ctl policy
# Inspect active iptables rules
wg-policy-ctl rules
# Check memory sets mapping IP targets (ipset)
wg-policy-ctl ipset
# Manually re-sync rules immediately
wg-policy-ctl reload
# Inspect dropped packets (rate-limited log output)
wg-policy-ctl log
# See connection statistics, how many targets loaded
wg-policy-ctl stats
# Force validation of the policy schema
wg-policy-ctl validate
🔧 Systemd Integration (Watcher Daemon)
If you use the install.sh script, the daemon is automatically installed, enabled, and started for you. It monitors wg0.conf for changes and triggers the pipeline seamlessly.
Manual File Installation (If not using install.sh)
Place the three provided systemd unit files into /etc/systemd/system/.
| Systemd File | Location | Description |
|---|---|---|
wg-policy.service |
/etc/systemd/system/wg-policy.service |
The main daemon that runs wg-sync-watch.sh |
wg-policy-health.timer |
/etc/systemd/system/wg-policy-health.timer |
Triggers the health check every 5 minutes |
wg-policy-health.service |
/etc/systemd/system/wg-policy-health.service |
Executes the actual health check logic |
# Example copy command
cp wg-policy.service wg-policy-health.timer wg-policy-health.service /etc/systemd/system/
2. Enable & Start Services
After copying the files, reload systemd to recognize them, then enable and start the services.
systemctl daemon-reload
systemctl enable wg-policy.service
systemctl enable wg-policy-health.timer
systemctl start wg-policy.service
systemctl start wg-policy-health.timer
Check the watcher logs:
journalctl -u wg-policy.service -f
🚀 WGRplane Overview
WGRplane is a Go-native WireGuard control plane application with a Vue 3 frontend, providing a modern web dashboard for WireGuard management. It features a single Go binary backend, SPA frontend, dynamic policy firewall integration, and glassmorphism UI design.
The application lives in the /app directory. For full documentation, see app/README.md.
🏗 WGRplane Architecture
wg0.conf (with/without #Access)
↓
┌─────────────────────────────────────────────┐
│ WGRplane (Go Binary :10087) │
│ ┌───────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Gorilla │ │ GORM │ │ nftables │ │
│ │ Mux Router│ │ SQLite │ │ Engine │ │
│ └───────────┘ └──────────┘ └──────────┘ │
│ ┌───────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Webhook │ │ Scheduler│ │ WebSocket│ │
│ │ Engine │ │ Cron │ │ Hub │ │
│ └───────────┘ └──────────┘ └──────────┘ │
│ ┌───────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Auth │ │ SMTP │ │ Plugins │ │
│ │ JWT/TOTP │ │ Email │ │ TG/Slack │ │
│ └───────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────┘
↓ HTTP/WebSocket
┌─────────────────────────────────────────────┐
│ Frontend (Vue 3 + TypeScript + Tailwind) │
│ Glassmorphism UI, i18n, Dark/Light mode │
└─────────────────────────────────────────────┘
Hybrid Mode
WGRplane supports two server modes:
forward- Directly applies nftables rules on the local machine. Peer policies are enforced vianftcommands.standalone- Acts as a control plane that triggers webhooks to remote WireGuard servers. Policy enforcement happens on the remote side.
2-Column Policy
Each peer has two independent policy columns:
| Column | Function |
|---|---|
| AllowAccess | List of CIDRs the peer can access (internal targets) |
| AllowInternet | Boolean flag. If true, peer gets unlimited internet access (MASQUERADE) |
Peers without any rules are isolated from other peers and the internet by default.
✨ WGRplane Features
- Go-Native Architecture: Single Go binary handles all API, database, webhooks, scheduler, and nftables. No Python/Flask needed.
- Complete Peer CRUD: Add, edit, delete peers. Generate QR codes for mobile client import. Export
.confconfiguration files. - Hybrid Mode:
forwardmode (local nftables) orstandalonemode (webhook to remote servers). - 2-Column Policy UI: "Allow Access" column (firewall whitelist CIDR) and "Allow Internet" toggle per peer.
- Real-time Monitoring: WebSocket broadcasts peer statistics and traffic every 5 seconds.
- Automated Scheduling: Daily cron jobs to delete expired peers, restrict over-limit peers, and reset monthly data usage.
- Security: API Key authentication (
wg-rplane-datadunia), JWT Bearer tokens, and TOTP (2FA). - Webhook Engine: Integration with remote servers (Mikrotik, etc.). Retry with exponential backoff, custom headers, Go templates.
- Plugin System: Telegram, Slack, and Traffic Logger notifications.
- i18n & Themes: Multi-language (English, Indonesian, Chinese). Dark/Light/Auto mode.
- Glassmorphism UI: Futuristic design with frosted glass cards, buttons, and inputs.
🛠 WGRplane Tech Stack
| Component | Technology |
|---|---|
| Backend | Go, Gorilla Mux, GORM (SQLite via glebarez/sqlite) |
| Frontend | Vue 3, TypeScript, Vite, TailwindCSS 4, vue-i18n 9 |
| Auth | JWT (golang-jwt/v5), TOTP (pquerna/otp), API Key |
| WebSockets | gorilla/websocket |
| Webhooks | Go net/http with retry + exponential backoff |
| Scheduling | robfig/cron v3 |
| QR Code | skip2/go-qrcode |
| jordan-wright/email (SMTP) | |
| Firewall | Bash, iptables, ipset, nftables, inotify-tools, jq |
| Container | Docker (multi-stage build), docker-compose |
🌐 WGRplane API Endpoints Summary
All endpoints are served on port 10087. For complete API documentation with request/response details, see app/README.md or visit /swagger/ on your running instance.
Authentication
| Method | Header | Notes |
|---|---|---|
| API Key | wg-rplane-datadunia: <KEY> |
Set via env var WG_API_KEY. Default: test-api-key |
| JWT | Authorization: Bearer <TOKEN> |
Expires in 15 minutes. Secret via env var JWT_SECRET |
| TOTP | X-TOTP: <CODE> |
Required if user enables TOTP |
Main Endpoints
| Endpoint | Method | Description |
|---|---|---|
/api/servers |
GET/POST |
List all servers / Create new server |
/api/servers/{id} |
GET/PUT/DELETE |
Get/Update/Delete server |
/api/servers/{id}/peers |
GET/POST |
List peers / Create new peer |
/api/peers/{id} |
PUT/DELETE |
Update/Delete peer |
/api/peers/{id}/config |
GET |
Download WireGuard .conf file |
/api/peers/{id}/qrcode |
GET |
Generate QR code PNG for mobile import |
/api/servers/{id}/webhooks |
GET/POST |
List/Create webhooks |
/api/stats |
GET |
Global statistics |
/ws/stats |
WebSocket | Real-time stats broadcast (5s interval) |
/swagger/ |
- | Interactive Swagger UI documentation |
📦 WGRplane Installation
Option 1: Docker Compose (Recommended)
# Clone repository
git clone https://git.datadunia.com/hainzero/WGRplane.git
cd 03.wireguard-policy
# Start WGRplane and WireGuard
docker compose up -d
# Access dashboard at http://localhost:10087
Option 2: Install Script
# Run automated installer (Ubuntu/Debian/CentOS)
sudo ./install.sh install
# Uninstall
sudo ./install.sh uninstall
Option 3: Manual Build
# Build Go binary
cd app
go build -o ../wgrplane .
cd ..
# Build frontend
cd app/frontend
npm install && npm run build
cd ../..
# Run
./wgrplane
# Server starts on :10087
Option 4: Systemd Service
# Install service file
sudo cp wgrplane.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable wgrplane.service
sudo systemctl start wgrplane.service
# View logs
journalctl -u wgrplane.service -f
📁 Project Structure
03.wireguard-policy/
├── app/ # Go backend + Vue frontend
│ ├── main.go # Bootstrap server, routing, init DB
│ ├── handlers.go # REST API route handlers
│ ├── models.go # GORM models (Server, Peer, Webhook, SMTP)
│ ├── auth.go # JWT, TOTP, API key auth middleware
│ ├── nftables.go # nftables rule management (mode forward)
│ ├── webhook.go # Webhook engine with retry/backoff
│ ├── scheduler.go # Cron jobs (expiry, data limit, reset)
│ ├── stats.go # WebSocket Hub for real-time stats
│ ├── frontend/ # Vue 3 SPA (TypeScript, TailwindCSS)
│ └── docs/ # Swagger documentation
├── wg-sync-policy.sh # Parse wg0.conf → policy.json
├── wg-policy-engine.sh # Apply policy.json → iptables/ipset
├── wg-sync-watch.sh # inotifywait watcher daemon
├── wg-policy-ctl # CLI wrapper for policy management
├── wg-policy-cleanup.sh # Cleanup script for PostDown
├── wg-policy.service # Systemd unit for watcher daemon
├── wgrplane.service # Systemd unit for Go backend
├── install.sh # Automated installer (Docker + services)
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Docker Compose stack
└── README.md # This file
For detailed WGRplane documentation including webhooks, plugins, scheduler, and frontend details, refer to app/README.md.