feat: add Docker deployment, update install script, and project configs
- Add Dockerfile and docker-compose.yml for containerized deployment - Rewrite install.sh for Docker-based setup (multi-distro support) - Add Go module files (go.mod, go.sum) for WGRplane backend - Add wgrplane.service systemd unit for Go backend - Add CI verification scripts in scripts/ - Update README.md with Docker deployment docs - Update .gitignore for binaries and .sisyphus/
This commit is contained in:
@@ -1,68 +1,337 @@
|
||||
# WireGuard Dynamic Policy Firewall
|
||||
# WGRplane
|
||||
|
||||
A lightweight, robust, and highly dynamic iptables/ipset policy firewall engine designed to restrict and control WireGuard peer traffic (egress traffic mapping) straight from `wg0.conf`.
|
||||
**WireGuard Control Plane with Dynamic Policy Firewall.**
|
||||
|
||||
Rather than allowing all VPN clients to reach any part of your internal network, this tool isolates clients from each other by default and reads a custom `#Access` comment inside `wg0.conf` to automatically generate strict `iptables` rules and `ipset` whitelists per-client on the fly.
|
||||
WGRplane is a Go-native WireGuard management dashboard paired with a shell-based dynamic iptables/ipset policy engine. It gives you full peer lifecycle management, per-peer firewall policies, webhook integrations, and a glassmorphism-styled Vue 3 frontend.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Architecture & Data Flow
|
||||
## Overview
|
||||
|
||||
1. **`wg0.conf`**: The standard WireGuard configuration. Contains standard `[Peer]` configs alongside a custom `#Access` tag.
|
||||
2. **`wg-sync-policy.sh`**: Safely parses `wg0.conf` and generates a structured `/etc/wireguard/policy.json` atomically.
|
||||
3. **`wg-policy-engine.sh`**: Reads `policy.json` to generate robust rules, applying `iptables` and `ipset` directly to the system.
|
||||
4. **Watcher Daemon**: Monitors `wg0.conf` for changes via `inotifywait` and triggers the pipeline seamlessly when updates are made.
|
||||
WGRplane operates in two complementary layers:
|
||||
|
||||
| Layer | What it does |
|
||||
|-------|-------------|
|
||||
| **WGRplane (Go + Vue 3)** | Web dashboard and REST API for managing WireGuard servers, peers, webhooks, SMTP, and scheduling. |
|
||||
| **Policy Firewall (Shell)** | Dynamic iptables/ipset engine that reads `#Access` comments from `wg0.conf` to enforce per-peer egress rules. |
|
||||
|
||||
### Hybrid Mode
|
||||
|
||||
The Go backend supports two server modes:
|
||||
|
||||
- **`forward`** -- The WGRplane instance directly applies nftables rules on the local machine. Peer access policies are enforced immediately via `nft` commands.
|
||||
- **`standalone`** -- The instance 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 | Purpose |
|
||||
|--------|---------|
|
||||
| **AllowAccess** | List of CIDRs the peer can reach (internal targets). |
|
||||
| **AllowInternet** | Boolean flag. When `true`, the peer gets unrestricted internet egress. |
|
||||
|
||||
Peers with neither rule are isolated from each other and from the internet by default.
|
||||
|
||||
---
|
||||
|
||||
## 📁 Installation
|
||||
## Architecture
|
||||
|
||||
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.
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "WGRplane Dashboard"
|
||||
A[Vue 3 Frontend] -->|HTTP/WebSocket| B[Go REST API :10087]
|
||||
end
|
||||
|
||||
subgraph "Go Backend"
|
||||
B --> C[(SQLite DB)]
|
||||
B --> D[Webhook Engine]
|
||||
B --> E[Scheduler Cron]
|
||||
B --> F[nftables Engine]
|
||||
B --> G[SMTP / Email]
|
||||
B --> H[Plugin Manager]
|
||||
end
|
||||
|
||||
subgraph "Policy Firewall"
|
||||
I[wg0.conf #Access] -->|inotifywait| J[wg-sync-watch.sh]
|
||||
J --> K[wg-sync-policy.sh]
|
||||
K -->|atomic write| L[policy.json]
|
||||
L --> M[wg-policy-engine.sh]
|
||||
M --> N[iptables / ipset]
|
||||
end
|
||||
|
||||
D -.->|peer_created/updated/deleted| O[External Webhooks]
|
||||
F -.->|forward mode| N
|
||||
E -.->|daily/monthly| P[Peer Lifecycle]
|
||||
```
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
wg0.conf (#Access comments)
|
||||
↓ inotifywait detects change
|
||||
wg-sync-watch.sh (debounced trigger)
|
||||
↓
|
||||
wg-sync-policy.sh (parses wg0.conf → policy.json, atomic write)
|
||||
↓
|
||||
wg-policy-engine.sh (reads policy.json → iptables/ipset rules)
|
||||
↓
|
||||
Active firewall rules (WG_POLICY chain)
|
||||
```
|
||||
|
||||
### Tech Stack
|
||||
|
||||
| Component | Technology |
|
||||
|-----------|------------|
|
||||
| **Backend** | Go 1.25, Gorilla Mux, GORM (SQLite) |
|
||||
| **Frontend** | Vue 3, TypeScript, Vite, TailwindCSS 4, vue-i18n 9 |
|
||||
| **Auth** | JWT (golang-jwt), TOTP (pquerna/otp), API Key |
|
||||
| **Webhooks** | Go net/http with retry + exponential backoff |
|
||||
| **Scheduling** | robfig/cron v3 |
|
||||
| **Firewall** | Bash, iptables, ipset, nftables, inotify-tools, jq |
|
||||
| **Container** | Docker (multi-stage build), docker-compose |
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Option 1: Docker Compose (Recommended)
|
||||
|
||||
```bash
|
||||
# Install everything
|
||||
# Clone the repository
|
||||
git clone https://git.datadunia.com/hainzero/WGRplane.git
|
||||
cd 03.wireguard-policy
|
||||
|
||||
# Start both WGRplane and WireGuard
|
||||
docker compose up -d
|
||||
|
||||
# Access the dashboard
|
||||
# http://localhost:10087
|
||||
```
|
||||
|
||||
The compose stack runs:
|
||||
- **WGRplane** on port `10087` (Go API + Vue frontend)
|
||||
- **WireGuard** container with host networking for kernel module access
|
||||
|
||||
### Option 2: Install Script
|
||||
|
||||
```bash
|
||||
# Run the automated installer (Ubuntu/Debian/CentOS)
|
||||
sudo ./install.sh install
|
||||
|
||||
# Uninstall everything
|
||||
# Uninstall
|
||||
sudo ./install.sh uninstall
|
||||
```
|
||||
|
||||
### Building the Installer (For Developers)
|
||||
The install script handles Docker installation, repository cloning, `.env` creation, and service startup.
|
||||
|
||||
If you modify any of the source `.sh` or `.service` files, you must rebuild the `install.sh` script using the provided builders.
|
||||
### Option 3: Manual Build
|
||||
|
||||
**On Linux (Bash):**
|
||||
```bash
|
||||
./build.sh
|
||||
# Build the Go binary
|
||||
cd app
|
||||
go build -o ../wgrplane .
|
||||
cd ..
|
||||
|
||||
# Build the frontend
|
||||
cd app/frontend
|
||||
npm install && npm run build
|
||||
cd ../..
|
||||
|
||||
# Run
|
||||
./wgrplane
|
||||
# Server starts on :10087
|
||||
```
|
||||
|
||||
**On Windows (CMD/PowerShell):**
|
||||
```cmd
|
||||
build.bat
|
||||
### Option 4: Systemd Service
|
||||
|
||||
```bash
|
||||
# Install the 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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📦 Prerequisites
|
||||
## API Documentation
|
||||
|
||||
| Package | Required | Install |
|
||||
|---------|----------|---------|
|
||||
| `jq` | **Yes** | `apt install jq` |
|
||||
| `inotify-tools` | **Yes** (for watcher daemon) | `apt install inotify-tools` |
|
||||
| `ipset` | Optional | `apt install ipset` |
|
||||
All API endpoints are served on port `10087`. Authentication is via API key header (`wg-rplane-datadunia`) or JWT Bearer token with optional TOTP.
|
||||
|
||||
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.
|
||||
### Authentication
|
||||
|
||||
| Method | Header | Notes |
|
||||
|--------|--------|-------|
|
||||
| API Key | `wg-rplane-datadunia: <KEY>` | Set via `WG_API_KEY` env var. Default: `test-api-key`. |
|
||||
| JWT | `Authorization: Bearer <TOKEN>` | 15-minute expiry. Set secret via `JWT_SECRET` env var. |
|
||||
| TOTP | `X-TOTP: <CODE>` | Required if user has TOTP enabled. |
|
||||
|
||||
### Servers
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/servers` | `GET` | List all registered WireGuard servers. |
|
||||
| `/api/servers` | `POST` | Create a new server entry. Body: `{name, mode, publicKey, endpoint}`. |
|
||||
| `/api/servers/{id}` | `GET` | Get a single server by ID. |
|
||||
| `/api/servers/{id}` | `PUT` | Update server fields (name, mode, publicKey, endpoint). |
|
||||
| `/api/servers/{id}` | `DELETE` | Delete a server and cascade-remove its peers and webhooks. |
|
||||
|
||||
### Peers
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/servers/{id}/peers` | `GET` | List all peers for a server. |
|
||||
| `/api/servers/{id}/peers` | `POST` | Create a new peer. Body: `{publicKey, ip, allowAccess, allowInternet}`. Applies nftables rules in `forward` mode or triggers webhooks in `standalone` mode. |
|
||||
| `/api/peers/{id}` | `PUT` | Update a peer. Computes diffs and applies incremental nftables changes. |
|
||||
| `/api/peers/{id}` | `DELETE` | Delete a peer. Cleans up nftables rules and triggers webhooks. |
|
||||
| `/api/peers/{id}/config` | `GET` | Download the peer's WireGuard `.conf` file. |
|
||||
| `/api/peers/{id}/qrcode` | `GET` | Get a QR code PNG image of the peer config (for mobile import). |
|
||||
|
||||
### Webhooks
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/servers/{id}/webhooks` | `GET` | List webhooks for a server. |
|
||||
| `/api/servers/{id}/webhooks` | `POST` | Create a webhook. Body: `{name, url, template, customBody, customHeaders, subscribedActions, isEnabled, verifySSL}`. |
|
||||
| `/api/webhooks/{id}` | `DELETE` | Delete a webhook. |
|
||||
|
||||
### SMTP Settings
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/settings/smtp` | `GET` | Get current SMTP configuration. |
|
||||
| `/api/settings/smtp` | `POST` | Save SMTP settings for email notifications. |
|
||||
|
||||
### Statistics
|
||||
|
||||
| Endpoint | Method | Description |
|
||||
|----------|--------|-------------|
|
||||
| `/api/stats` | `GET` | Global stats: total servers, peers, webhooks. |
|
||||
| `/api/servers/{id}/stats` | `GET` | Per-server stats: peer count, webhook count, server details. |
|
||||
|
||||
### WebSocket
|
||||
|
||||
| Endpoint | Protocol | Description |
|
||||
|----------|----------|-------------|
|
||||
| `/ws/stats` | WebSocket | Real-time stats broadcast (5-second interval). Connects to the Hub for live peer/traffic updates. |
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Integrasi ke `wg0.conf`
|
||||
## Webhook Payload Spec
|
||||
|
||||
To integrate the engine, you need to append hooks into your `wg0.conf` interface block, and declare the `#Access` tags under each peer.
|
||||
Webhooks are triggered on peer lifecycle events (`peer_created`, `peer_updated`, `peer_deleted`, `policy_changed`). The engine supports three template modes: `default` (raw JSON), `mikrotik` (RouterOS-formatted), and `custom` (Go template).
|
||||
|
||||
### 1. Interface Block (Hooks)
|
||||
Add the `PostUp` and `PostDown` scripts so the engine initializes correctly during VPN startup and removes traces upon shutdown.
|
||||
### Default Payload
|
||||
|
||||
> **⚠️ WireGuard does NOT support multiline values.** Every command must be on a `PostUp = ...` or `PostDown = ...` line. Bare commands without the `PostUp =` prefix will cause `Configuration parsing error`.
|
||||
```json
|
||||
{
|
||||
"event": "peer_created",
|
||||
"timestamp": "2026-05-03T10:30:00Z",
|
||||
"server": {
|
||||
"id": 1,
|
||||
"name": "wg-server-01",
|
||||
"mode": "forward",
|
||||
"publicKey": "abc123...",
|
||||
"endpoint": "vpn.example.com:51820"
|
||||
},
|
||||
"peer": {
|
||||
"id": 2,
|
||||
"publicKey": "xyz789...",
|
||||
"ip": "10.0.0.2",
|
||||
"allowAccess": ["192.168.1.0/24", "10.10.0.0/16"],
|
||||
"allowInternet": true,
|
||||
"enabled": true,
|
||||
"dataLimitGB": 0,
|
||||
"expiresAt": "0001-01-01T00:00:00Z"
|
||||
},
|
||||
"policy": {
|
||||
"action": "created",
|
||||
"changes": ["peer_created"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Mikrotik Template
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "created",
|
||||
"peer": {
|
||||
"public_key": "xyz789...",
|
||||
"ip": "10.0.0.2",
|
||||
"allow_access": "[\"192.168.1.0/24\"]",
|
||||
"allow_internet": true
|
||||
},
|
||||
"server": {
|
||||
"name": "wg-server-01",
|
||||
"mode": "forward"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Webhook Features
|
||||
|
||||
- **Retry with backoff**: Failed deliveries retry up to 3 times with exponential backoff (2s, 4s, 8s).
|
||||
- **SSL verification**: Toggleable per-webhook via `verifySSL`.
|
||||
- **Custom headers**: Per-webhook header injection via `customHeaders` JSON.
|
||||
- **Global webhooks**: Set `isGlobal: true` to fire across all servers.
|
||||
- **Action filtering**: Subscribe to specific events via `subscribedActions` array.
|
||||
|
||||
---
|
||||
|
||||
## UI Features
|
||||
|
||||
The frontend is a Vue 3 + TypeScript SPA with a glassmorphism design language.
|
||||
|
||||
### Design System
|
||||
|
||||
- **Glassmorphism**: Frosted glass cards, buttons, and inputs with backdrop blur effects.
|
||||
- **TailwindCSS 4**: Utility-first styling with full dark mode support via `dark:` variants.
|
||||
- **Responsive**: Mobile-first layout that adapts to all screen sizes.
|
||||
|
||||
### Features
|
||||
|
||||
| Feature | Description |
|
||||
|---------|-------------|
|
||||
| **Multi-language (i18n)** | English, Indonesian, and Chinese via vue-i18n 9. Locale auto-detected from browser. |
|
||||
| **Theme Switching** | Dark / Light / Auto (follows system preference) via `@vueuse/core`. |
|
||||
| **Real-time Stats** | WebSocket connection broadcasts live peer counts and traffic data every 5 seconds. |
|
||||
| **Charts** | Traffic visualization via Chart.js + vue-chartjs. |
|
||||
| **Toast Notifications** | Non-intrusive alerts via vue-sonner. |
|
||||
| **QR Code Import** | Generate scannable QR codes for quick mobile WireGuard client setup. |
|
||||
|
||||
### Frontend Structure
|
||||
|
||||
```
|
||||
app/frontend/src/
|
||||
├── App.vue # Root component with theme/i18n providers
|
||||
├── main.ts # App bootstrap (Vue, Router, i18n)
|
||||
├── router/ # Vue Router definitions
|
||||
├── i18n/ # Locale files (en.json, id.json, zh.json)
|
||||
├── components/ # Glass UI components (Card, Button, Input, Toggle)
|
||||
├── composables/ # Vue composables (useTheme, etc.)
|
||||
├── views/ # Page components (Dashboard, Servers, Peers, Settings)
|
||||
└── types/ # TypeScript type definitions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Policy Firewall (`#Access`)
|
||||
|
||||
The shell-based policy engine enforces per-peer firewall rules directly from `wg0.conf`.
|
||||
|
||||
### How It Works
|
||||
|
||||
1. Add `#Access` comments under each `[Peer]` block in `wg0.conf`.
|
||||
2. The watcher daemon (`wg-sync-watch.sh`) detects file changes via `inotifywait`.
|
||||
3. `wg-sync-policy.sh` parses the config and writes `policy.json` atomically.
|
||||
4. `wg-policy-engine.sh` reads the JSON and applies iptables/ipset rules.
|
||||
|
||||
### Example `wg0.conf`
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
@@ -70,20 +339,9 @@ 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's `SaveConfig` feature overwrites `wg0.conf` directly and **strips all comments**, which will permanently delete all `#Access` tags. If you are using a Web UI/Dashboard, make sure it does not strip unknown comments when saving.
|
||||
|
||||
```ini
|
||||
[Peer]
|
||||
PublicKey = <CLIENT_1_PUBKEY>
|
||||
AllowedIPs = 10.0.0.2/32
|
||||
@@ -92,82 +350,126 @@ AllowedIPs = 10.0.0.2/32
|
||||
[Peer]
|
||||
PublicKey = <CLIENT_2_PUBKEY>
|
||||
AllowedIPs = 10.0.0.3/32
|
||||
#Access = 10.0.0.1/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)
|
||||
#Access
|
||||
# Empty Access = 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.
|
||||
### Why `#Access` Instead of `AllowedIPs`?
|
||||
|
||||
WireGuard uses `AllowedIPs` for Cryptokey Routing. Putting destination IPs in the server's `AllowedIPs` would cause WireGuard to route traffic for those IPs into the client tunnel. The `#Access` comment cleanly separates firewall policy from routing configuration.
|
||||
|
||||
### CLI: `wg-policy-ctl`
|
||||
|
||||
```bash
|
||||
wg-policy-ctl status # Health check, lock status, rule counts
|
||||
wg-policy-ctl policy # View raw policy.json
|
||||
wg-policy-ctl rules # Inspect active iptables rules
|
||||
wg-policy-ctl ipset # View ipset mappings
|
||||
wg-policy-ctl reload # Force re-sync and re-apply
|
||||
wg-policy-ctl log # View dropped packet logs
|
||||
wg-policy-ctl stats # Connection statistics
|
||||
wg-policy-ctl validate # Validate policy.json schema
|
||||
```
|
||||
|
||||
### Prerequisites
|
||||
|
||||
| Package | Required | Install |
|
||||
|---------|----------|---------|
|
||||
| `jq` | Yes | `apt install jq` |
|
||||
| `inotify-tools` | Yes (watcher daemon) | `apt install inotify-tools` |
|
||||
| `ipset` | Optional | `apt install ipset` |
|
||||
|
||||
Without `ipset`, the engine falls back to per-rule iptables entries. This works for small deployments. For large peer counts, `ipset` provides O(1) lookup performance.
|
||||
|
||||
---
|
||||
|
||||
## 🛠 `wg-policy-ctl` CLI Usage
|
||||
## Scheduler
|
||||
|
||||
You don't need to manually interact with `iptables` or `.json` files. Use the `wg-policy-ctl` wrapper.
|
||||
The Go backend runs three background cron jobs:
|
||||
|
||||
```bash
|
||||
# View the health of the firewall engine and active locks
|
||||
wg-policy-ctl status
|
||||
| Schedule | Job | Action |
|
||||
|----------|-----|--------|
|
||||
| Daily 2:00 AM | `deleteExpiredPeers` | Removes peers past their `ExpiresAt` date. |
|
||||
| Daily 3:00 AM | `restrictOverLimitPeers` | Disables peers that exceeded `DataLimitGB`. |
|
||||
| 1st of month | `resetMonthlyUsage` | Resets `CurrentDataUsageBytes` to zero for all peers. |
|
||||
|
||||
# View the raw, parsed JSON policy
|
||||
wg-policy-ctl policy
|
||||
---
|
||||
|
||||
# Inspect active iptables rules
|
||||
wg-policy-ctl rules
|
||||
## Plugins
|
||||
|
||||
# Check memory sets mapping IP targets (ipset)
|
||||
wg-policy-ctl ipset
|
||||
The plugin system provides a simple notification interface. Built-in plugins include:
|
||||
|
||||
# Manually re-sync rules immediately
|
||||
wg-policy-ctl reload
|
||||
- **TelegramNotifier** -- Sends Telegram messages on events.
|
||||
- **SlackNotifier** -- Sends Slack messages on events.
|
||||
- **TrafficLogger** -- Logs traffic events for debugging.
|
||||
|
||||
# Inspect dropped packets (rate-limited log output)
|
||||
wg-policy-ctl log
|
||||
Plugins are loaded at startup via `PluginManager.LoadPlugins()` and receive events through `Trigger(event, payload)`.
|
||||
|
||||
# See connection statistics, how many targets loaded
|
||||
wg-policy-ctl stats
|
||||
---
|
||||
|
||||
# Force validation of the policy schema
|
||||
wg-policy-ctl validate
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `WG_API_KEY` | `test-api-key` | API key for header-based authentication. |
|
||||
| `JWT_SECRET` | `secret` | Secret for JWT token signing. |
|
||||
| `APP_FRONTEND_DIR` | `/var/www/frontend` | Path to built frontend assets. |
|
||||
| `WG_RPLANE_MODE` | `forward` | Default server mode (`forward` or `standalone`). |
|
||||
|
||||
### Database
|
||||
|
||||
WGRplane uses SQLite by default (`wgrplane.db`). Models auto-migrate on startup:
|
||||
|
||||
- **Server** -- WireGuard server entries with mode and endpoint.
|
||||
- **Peer** -- Peer entries with IP, access rules, data limits, expiry.
|
||||
- **Webhook** -- Webhook configurations with templates and action filters.
|
||||
- **SMTPSettings** -- SMTP server configuration for email notifications.
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
03.wireguard-policy/
|
||||
├── app/ # Go backend + Vue frontend
|
||||
│ ├── handlers.go # REST API route handlers
|
||||
│ ├── main.go # Server bootstrap, routes
|
||||
│ ├── models.go # GORM models (Server, Peer, Webhook, SMTP)
|
||||
│ ├── auth.go # JWT, TOTP, API key auth middleware
|
||||
│ ├── nftables.go # nftables rule management (forward mode)
|
||||
│ ├── webhook.go # Webhook engine with retry/backoff
|
||||
│ ├── scheduler.go # Cron jobs (expiry, data limit, reset)
|
||||
│ ├── stats.go # WebSocket Hub for real-time stats
|
||||
│ ├── email.go # SMTP email notifications
|
||||
│ ├── plugins.go # Plugin system (Telegram, Slack, Logger)
|
||||
│ ├── validation.go # Input validators (IP, CIDR, PublicKey)
|
||||
│ ├── wg.go # WireGuard key generation, config export
|
||||
│ ├── i18n.go # Backend i18n (en/id/zh)
|
||||
│ ├── frontend/ # Vue 3 SPA (TypeScript, TailwindCSS)
|
||||
│ └── active.{en,id,zh}.json # Translation files
|
||||
├── wg-sync-policy.sh # Parses wg0.conf → policy.json
|
||||
├── wg-policy-engine.sh # Applies policy.json → iptables/ipset
|
||||
├── wg-sync-watch.sh # inotifywait watcher daemon
|
||||
├── wg-policy-ctl # CLI wrapper for 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
|
||||
├── build.sh / build.bat # Installer rebuild scripts
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Systemd Integration (Watcher Daemon)
|
||||
## License
|
||||
|
||||
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 |
|
||||
|
||||
```bash
|
||||
# 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.
|
||||
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
journalctl -u wg-policy.service -f
|
||||
```
|
||||
This project builds upon concepts from WGDashboard (donaldzou/WGDashboard) with modifications for policy.json API integration and dynamic firewall enforcement.
|
||||
|
||||
Reference in New Issue
Block a user