Open source · AGPL-3.0

Self-hosted WireGuard VPN management

A clean web interface for managing WireGuard peers, firewall rules, and user authentication — without depending on any third-party cloud service. Fully transparent, fully yours.

WireGUI devices dashboard showing VPN peers with status, IP addresses, and traffic statistics

Everything you need to manage your VPN

Built for teams and individuals who want full control over their VPN infrastructure.

WireGuard Management

Create and manage VPN peers with automatic IPv4/IPv6 allocation, QR code provisioning, and downloadable .conf files.

Firewall Rules

Per-user nftables chains with CIDR, protocol, and port range support. Network policies apply instantly.

Multi-Factor Auth

TOTP authenticator apps (Google Authenticator, Authy, 1Password) and WebAuthn security keys (YubiKey, Touch ID).

Single Sign-On

OpenID Connect and SAML 2.0 with auto-provisioning. Works with Okta, Auth0, Keycloak, Azure AD, and more.

REST API

Full-featured /api/v0 with token authentication for programmatic management of users, devices, rules, and configuration.

Real-Time Monitoring

Live RX/TX counters, traffic charts, handshake tracking, WAN connectivity checks, and system notifications.

Magic Links

Passwordless email-based login when SMTP is configured. No password to remember, no friction for users.

Session Management

Configurable VPN session durations with automatic peer expiry. Users re-authenticate on schedule.

Dark Mode

User-selectable dark/light theme stored in profile. Auto mode follows system preference.

See it in action

A clean, intuitive interface for every aspect of VPN management.

Login page with email/password and SSO options
Login
Device list showing VPN peers with status, IPs, and traffic stats
My Devices
Add device dialog with QR code and configuration download
Add Device
Account settings with password, SSO, API tokens, and MFA
Account Settings
Admin user management table with roles and status
User Management
Admin view of all devices across users with filtering
Device Administration
Firewall rules with network policies and per-user rules
Firewall Rules
Settings page with client defaults, auth config, and IdP management
Settings & SSO
Diagnostics showing WireGuard interface status and connectivity checks
Diagnostics

Up and running in minutes

Docker Compose is the recommended way to deploy WireGUI.

Production (Docker Compose)

terminal
# Clone the repository
git clone https://github.com/bartei/wiregui.git
cd wiregui

# Start everything
docker compose -f compose.prod.yml up -d

The container runs migrations automatically, manages the WireGuard interface, and requires NET_ADMIN + SYS_MODULE capabilities.

Development

terminal
# Install dependencies
uv sync

# Start PostgreSQL & Valkey
docker compose up -d

# Run migrations and start
alembic upgrade head
uv run python -m wiregui.main

Open http://localhost:13000 — an admin account is created on first run (check the logs for the generated password).

Web UI & API

:13000 TCP

WireGuard VPN

:51820 UDP

Python

3.13+ required

Documentation

Everything you need to deploy and configure WireGUI. See the full wiki for detailed guides.

Authentication

Multiple authentication methods can be used individually or in combination.

Local Authentication

Default

Default email/password login. Can be disabled when SSO is configured.

OpenID Connect

SSO

Integrate with Okta, Auth0, Keycloak, Azure AD, Google Workspace, or any OIDC-compliant provider.

SAML 2.0

SSO

Enterprise single sign-on with auto-provisioning and metadata configuration.

Magic Links

Passwordless

Passwordless email-based login. Requires SMTP configuration.

TOTP

MFA

Time-based one-time passwords. Compatible with Google Authenticator, Authy, 1Password.

WebAuthn

MFA

Hardware security keys (YubiKey) and platform authenticators (Touch ID, Windows Hello).

Deployment

WireGUI is distributed as a Docker image. Migrations run automatically on startup.

Reverse Proxy (nginx)

server {
    listen 443 ssl;
    server_name vpn.example.com;

    location / {
        proxy_pass http://localhost:13000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }
}

Reverse Proxy (Caddy)

vpn.example.com {
    reverse_proxy localhost:13000
}

Caddy handles TLS certificates and WebSocket proxying automatically.

Backup

The database is the single source of truth. WireGuard interface state is fully reconciled from the database on startup.

docker compose exec postgres pg_dump -U wiregui wiregui > backup.sql

LAN-to-Peer Routing

When "Allow local network to reach peers" is enabled in Admin → Rules → Network Policies, WireGUI configures its firewall to accept traffic from your LAN to VPN peers. However, your LAN's default gateway (router) also needs a static route so it knows to send traffic destined for the WireGuard subnet to the WireGUI server instead of out to the internet.

Without this route, LAN devices can't reach VPN peers even if the policy is enabled — the router will forward WireGuard-subnet traffic to its WAN gateway where it gets dropped. The static route tells the router: "to reach the VPN subnet, forward packets to the WireGUI server."

In the examples below, we use the default WireGUI subnets and assume the WireGUI server's LAN IP is 192.168.1.100. Adjust these values to match your environment.

Value Example Source
WireGuard IPv4 subnet 10.3.2.0/24 WG_WG_IPV4_NETWORK
WireGuard IPv6 subnet fd00::3:2:0/120 WG_WG_IPV6_NETWORK
WireGUI server LAN IP 192.168.1.100 Your network

Linux Gateway

Run on the gateway, or add to /etc/network/interfaces / netplan for persistence.

# IPv4
ip route add 10.3.2.0/24 via 192.168.1.100

# IPv6
ip -6 route add fd00::3:2:0/120 via <server-ipv6-lan-addr>

To persist with netplan:

# /etc/netplan/01-static-routes.yaml
network:
  version: 2
  ethernets:
    eth0:
      routes:
        - to: 10.3.2.0/24
          via: 192.168.1.100

Generic Router (Web UI)

Most consumer and business routers have a static routes section under Advanced or Routing.

Field Value
Destination10.3.2.0
Subnet Mask255.255.255.0
Gateway / Next Hop192.168.1.100
InterfaceLAN

MikroTik / RouterOS

/ip route add dst-address=10.3.2.0/24 \
    gateway=192.168.1.100
/ipv6 route add dst-address=fd00::3:2:0/120 \
    gateway=<server-ipv6-lan-addr>

Ubiquiti / EdgeOS / VyOS

set protocols static route 10.3.2.0/24 \
    next-hop 192.168.1.100
set protocols static route6 fd00::3:2:0/120 \
    next-hop <server-ipv6-lan-addr>
commit; save

OPNsense / pfSense

Navigate to System → Routes → Configuration and add a new gateway and route.

Field Value
Destination network10.3.2.0/24
Gateway192.168.1.100

Cisco IOS

ip route 10.3.2.0 255.255.255.0 192.168.1.100
ipv6 route fd00::3:2:0/120 <server-ipv6-lan-addr>

Verification

From any LAN device, confirm the route is working:

# Should show the WireGUI server (192.168.1.100) as the next hop
traceroute 10.3.2.1

# Ping a connected peer (the peer must be online)
ping 10.3.2.2

If the traceroute shows your WAN gateway instead of the WireGUI server, the static route is missing or not applied.

Configuration Reference

All settings use the WG_ prefix and can be set via environment variables or a .env file.

Variable Default Description
WG_DATABASE_URL postgresql+asyncpg://wiregui:wiregui@localhost/wiregui PostgreSQL connection string
WG_REDIS_URL redis://localhost:6379/0 Valkey/Redis connection
WG_SECRET_KEY change-me-in-production JWT signing + Fernet encryption key
WG_WG_ENABLED false Enable WireGuard interface management
WG_WG_ENDPOINT_HOST localhost Public endpoint for client configs
WG_WG_ENDPOINT_PORT 51820 WireGuard listen port
WG_WG_IPV4_NETWORK 10.3.2.0/24 IPv4 tunnel network
WG_WG_IPV6_NETWORK fd00::3:2:0/120 IPv6 tunnel network
WG_ADMIN_EMAIL admin@localhost Initial admin email
WG_ADMIN_PASSWORD (auto-generated) Initial admin password
WG_EXTERNAL_URL http://localhost:13000 Public-facing URL
WG_IDP_CONFIG_FILE (none) Path to YAML with OIDC/SAML IdP definitions

REST API

Full programmatic access via /api/v0. Manage users, devices, rules, and configuration with API tokens.

Create a device
curl -X POST https://vpn.example.com/api/v0/devices/ \
  -H "Authorization: Bearer wgui_xxxx" \
  -H "Content-Type: application/json" \
  -d '{"name": "laptop", "user_id": 1}'

Generate API tokens from the Account Settings page. Tokens use the Authorization: Bearer header.

Endpoints

All endpoints require API token authentication

GET /api/health no auth
GET /api/v0/users/

List all users

POST /api/v0/users/

Create user

GET /api/v0/devices/

List all devices

POST /api/v0/devices/

Create device

GET /api/v0/rules/

List firewall rules

POST /api/v0/rules/

Create rule

GET /api/v0/configuration/

Get configuration

PUT /api/v0/configuration/

Update configuration

+ PUT, DELETE for each resource

Against enshittification

This project exists because infrastructure software should serve its users, not its investors. Too many VPN tools have been enshittified — features locked behind paid tiers, telemetry quietly added, self-hosting made deliberately painful.

WireGUI is AGPL-licensed specifically to prevent this. If you run it, you own it. If you modify it and offer it as a service, you share the source. No bait-and-switch, no open-core grift, no "community edition" that mysteriously lacks the features you actually need.

Software that manages your network traffic should be fully transparent and fully yours.

Built with

NiceGUI FastAPI SQLModel PostgreSQL Valkey Alembic authlib + webauthn WireGuard nftables Python 3.13