A production-ready web-based management interface for WireGuard VPN, featuring multi-user support, group management, and comprehensive security features.
- Admin Role: Full system access, user management, global settings
- User Role: Manage own groups and clients
- Secure password hashing with bcrypt
- JWT-based authentication
- Create multiple WireGuard configurations (groups)
- Each group has its own IP range
- Assign group access to users
- Per-group configuration settings
- Auto-restart on startup: Groups enabled by default, automatically restart when container/application starts
- Add unlimited clients to each group
- Automatic IP address allocation
- Per-client settings:
- Custom DNS override
- Custom allowed IPs
- One-click configuration download
- QR code generation (coming soon)
- Per-Group Settings:
- IP range (CIDR notation)
- Listen port
- DNS servers
- MTU
- Persistent keepalive
- System-Wide Defaults (Admin only):
- Default DNS
- Default port
- Default MTU
- Docker-Compatible Auto-Restart: WireGuard interfaces automatically restart when application starts
- System overview dashboard
- Per-group traffic statistics
- Per-client traffic statistics
- Connection logging
- JWT token authentication with configurable expiration
- Role-based access control (RBAC)
- Password hashing with bcrypt
- Optional preshared key support
- Input validation and sanitization
- Command injection prevention
- Security headers (CSP, HSTS, X-Frame-Options, etc.)
- Rate limiting on authentication endpoints
- Health check endpoints for monitoring
- Docker and Docker Compose
- Linux host with WireGuard kernel module
- Clone the repository:
git clone https://github.com/Arthur2500/wireguard-multiclient-webui.git
cd wireguard-multiclient-webui- Create environment file:
cp .env.example .env
# Edit .env and set secure values for SECRET_KEY and JWT_SECRET_KEY- Start the containers:
docker-compose up -d-
Access the web interface at
http://localhost:8080 -
Login with default credentials:
- Username:
admin - Password:
admin
Change the admin password immediately after first login!
- Username:
| Variable | Description | Default |
|---|---|---|
SECRET_KEY |
Flask secret key | (required) |
JWT_SECRET_KEY |
JWT signing key | (required) |
DATABASE_URL |
Database connection string | sqlite:////data/app.db |
WG_CONFIG_PATH |
WireGuard config directory | /etc/wireguard |
WG_DEFAULT_DNS |
Default DNS servers | 1.1.1.1, 8.8.8.8 |
WG_DEFAULT_PORT |
Default listen port | 51820 |
WG_USE_PRESHARED_KEY |
Use preshared keys for all clients | false |
STATS_COLLECTION_INTERVAL |
Automatic stats collection interval (seconds). Set to 10 for real-time stats. Increase (e.g., 60 or 300) for systems with many clients to reduce database I/O. | 10 |
JWT_ACCESS_TOKEN_EXPIRES_HOURS |
Token expiration | 24 |
- 8080: Web interface (HTTP)
- WireGuard ports are configured per-group
WireGuard configurations are organized by group name for easy management:
Interface Names:
- Each group gets a unique WireGuard interface named after the group
- Format:
wg-{sanitized-group-name}(e.g., "Office VPN" →wg-office-vpn) - Names are automatically sanitized (lowercase, special characters removed, max 15 chars)
File Structure:
/etc/wireguard/
├── wg-office-vpn.conf # Server config for "Office VPN" group
├── wg-office-vpn/ # Client configs for "Office VPN" group
│ ├── wg-office-vpn-laptop.conf
│ ├── wg-office-vpn-phone.conf
│ └── wg-office-vpn-tablet.conf
├── wg-marketing.conf # Server config for "Marketing" group
└── wg-marketing/ # Client configs for "Marketing" group
├── wg-marketing-john.conf
└── wg-marketing-jane.conf
This organization:
- Makes it easy to identify which interface belongs to which group
- Keeps related client configurations together in group-specific directories
- Allows easy backup/restore of group configurations
- Simplifies troubleshooting and manual configuration management
cd backend
python -m venv venv
source venv/bin/activate # or `venv\Scripts\activate` on Windows
pip install -r requirements.txt
python run.pycd frontend
npm install
npm startcd backend
python -m pytest tests/ -v- Production Deployment Guide - Complete guide for production deployment
- Security Best Practices - Security hardening and best practices
- Security Audit Report - Comprehensive security assessment
- FAQ - Frequently Asked Questions
- API Documentation - API endpoint reference below
This application implements multiple security layers:
- Authentication: JWT tokens with bcrypt password hashing
- Authorization: Role-based access control
- Input Validation: All inputs sanitized and validated
- Security Headers: CSP, HSTS, X-Frame-Options, and more
- Rate Limiting: Protection against brute force attacks
- Command Injection Prevention: Validated interface names and commands
Important: Before deploying to production, read SECURITY.md and follow all recommendations.
- Change default admin password
- Set secure
SECRET_KEYandJWT_SECRET_KEY - Enable HTTPS with valid certificates
- Configure firewall rules
- Set up regular backups
- Review SECURITY.md completely
The application provides health check endpoints for monitoring:
GET /api/health- Basic health checkGET /api/ready- Readiness check with database connectivity
Use these endpoints with Docker health checks, load balancers, or monitoring systems.
GET /api/health- Health checkGET /api/ready- Readiness check with DB connectivity
POST /api/auth/login- User loginGET /api/auth/me- Get current userPOST /api/auth/change-password- Change password
GET /api/users- List all usersPOST /api/users- Create userPUT /api/users/:id- Update userDELETE /api/users/:id- Delete user
GET /api/groups- List accessible groupsPOST /api/groups- Create groupGET /api/groups/:id- Get group detailsPUT /api/groups/:id- Update groupDELETE /api/groups/:id- Delete groupGET /api/groups/:id/config- Get server config
GET /api/clients/group/:id- List clients in groupPOST /api/clients/group/:id- Create clientGET /api/clients/:id- Get client detailsPUT /api/clients/:id- Update clientDELETE /api/clients/:id- Delete clientGET /api/clients/:id/config- Get client config
GET /api/stats/overview- System overviewGET /api/stats/group/:id- Group statisticsGET /api/stats/client/:id- Client statisticsGET /api/stats/system- System-wide stats (Admin)
┌─────────────────┐ ┌─────────────────┐
│ React SPA │────▶│ Nginx Proxy │
│ (Frontend) │ │ (Optional) │
└─────────────────┘ └────────┬────────┘
│
▼
┌─────────────────┐
│ Flask API │
│ + Gunicorn │
└────────┬────────┘
│
┌────────────┴────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ SQLite/ │ │ WireGuard │
│ PostgreSQL │ │ (wg-quick) │
└─────────────────┘ └─────────────────┘
# Check container status
docker-compose ps
# View logs
docker-compose logs -f backend
# Restart services
docker-compose restart# Check interfaces
sudo wg show
# Verify IP forwarding
sysctl net.ipv4.ip_forward
# Check WireGuard module
lsmod | grep wireguard# Check file permissions
ls -la data/
# Stop and backup before manual intervention
docker-compose down
cp data/app.db data/app.db.backupFor more troubleshooting, see DEPLOYMENT.md.
- Small Deployment (< 50 users): 1 CPU, 1GB RAM
- Medium Deployment (50-500 users): 2 CPU, 2GB RAM
- Large Deployment (500+ users): 4 CPU, 4GB RAM, PostgreSQL
- Increase
STATS_COLLECTION_INTERVALfor systems with many clients - Use PostgreSQL instead of SQLite for > 100 concurrent users
- Increase Gunicorn workers for high traffic
- Enable nginx caching for static assets
See DEPLOYMENT.md for scaling details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please ensure your code follows the existing style and includes appropriate tests.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
If you discover a security vulnerability, please report it responsibly:
- Do not open a public GitHub issue
- Create an issue with [SECURITY] in the title
- See SECURITY.md for full security policy
- WireGuard - Fast, modern, secure VPN tunnel
- Built with Flask, React, and Docker
- Inspired by the need for secure, multi-tenant VPN management
- Documentation: README.md, SECURITY.md, DEPLOYMENT.md, FAQ.md
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- FAQ: See FAQ.md for common questions
Made for the WireGuard community