Config display modal now dims background content before showing, following the same pattern as delete confirmation modal. This provides visual consistency across all modals and makes it clear to users when a modal is active. Fixes: wg-admin-bfe
WireGuard VPN Setup for Debian 13
Overview
Personal WireGuard VPN server with IPv4/IPv6 support, client management via wireguard.sh, designed for 1 CPU / 1GB RAM VPS.
Development & Issue Tracking
This project uses beads (bd CLI) for issue tracking and Gitea for external issue tracking.
- Agent instructions: See
AGENTS.mdand.agent/directory for project-specific guidance - Issue tracking: Use
bd readyto find available work - External issues: Gitea at https://gitea.calmcacil.dev
Theming
The TUI supports multiple color themes. Set the THEME environment variable to switch themes:
Available Themes
| Theme | Description | Default |
|---|---|---|
everforest |
Natural green/blue theme (default) | ✅ |
dracula |
Popular dark purple theme | |
default |
Standard blue-based theme | |
dark |
Purple-based dark theme | |
light |
Green-based light theme |
Usage
# Use Everforest (default)
sudo wg-admin-tui
# Use Dracula theme
THEME=dracula sudo wg-admin-tui
# Use default theme
THEME=default sudo wg-admin-tui
# Use light theme
THEME=light sudo wg-admin-tui
Configuration
Configuration is managed through /etc/wg-admin/config.conf. Copy config.example to this location and customize for your environment.
Creating Configuration File
sudo mkdir -p /etc/wg-admin
sudo cp config.example /etc/wg-admin/config.conf
sudo nano /etc/wg-admin/config.conf
Configuration Variables
| Variable | Default | Description |
|---|---|---|
SERVER_DOMAIN |
Required | Server domain or IP address (e.g., vpn.example.com) |
WG_PORT |
51820 | WireGuard UDP port |
VPN_IPV4_RANGE |
10.10.69.0/24 | VPN IPv4 address range |
VPN_IPV6_RANGE |
fd69:dead:beef:69::/64 | VPN IPv6 address range |
WG_INTERFACE |
wg0 | WireGuard interface name |
DNS_SERVERS |
8.8.8.8, 8.8.4.4 | DNS servers for clients |
LOG_FILE |
/var/log/wireguard-admin.log | Log file location |
Example Configuration
# Server domain or IP address (required)
SERVER_DOMAIN=vpn.example.com
# WireGuard UDP port (optional, default: 51820)
WG_PORT=51820
# VPN IPv4 range (optional, default: 10.10.69.0/24)
VPN_IPV4_RANGE=10.10.69.0/24
# VPN IPv6 range (optional, default: fd69:dead:beef:69::/64)
VPN_IPV6_RANGE=fd69:dead:beef:69::/64
# DNS servers (optional, default: 8.8.8.8, 8.8.4.4)
DNS_SERVERS=8.8.8.8, 8.8.4.4
Note: All values are optional except SERVER_DOMAIN. The script will use defaults if not specified.
Configuration Priority
/etc/wg-admin/config.conffile (highest priority)- Environment variables (e.g.,
SERVER_DOMAIN=vpn.example.com ./wireguard.sh install) - Built-in defaults (lowest priority)
Other Directories
- Server-side peer configs:
/etc/wireguard/conf.d/client-*.conf(loaded dynamically) - Client-side configs:
/etc/wireguard/clients/*.conf(for distribution)
Installation
1. Upload script to VPS
scp wireguard.sh calmcacil@your-vps.com:~/
scp config.example calmcacil@your-vps.com:~/
2. Configure the script
# Copy example config and customize
sudo mkdir -p /etc/wg-admin
sudo cp ~/config.example /etc/wg-admin/config.conf
sudo nano /etc/wg-admin/config.conf
# Set at minimum:
# SERVER_DOMAIN=vpn.yourdomain.com
3. Run installation
chmod +x ~/wireguard.sh
sudo ~/wireguard.sh install
Usage
Dynamic client loading
WireGuard automatically loads clients from /etc/wireguard/conf.d/:
- Add/remove client configs in
/etc/wireguard/conf.d/client-*.conf - Run
sudo ~/wireguard.sh load-clientsto reload - Changes are applied immediately without restarting
Add a new client
sudo ~/wireguard.sh add myphone
This creates:
- Server config in
/etc/wireguard/conf.d/client-myphone.conf - Client config in
/etc/wireguard/clients/myphone.conf - QR code in
/etc/wireguard/clients/myphone.qr
List all clients
sudo ~/wireguard.sh list
Show client config
sudo ~/wireguard.sh show myphone
Show QR code
sudo ~/wireguard.sh qr myphone
Remove a client
sudo ~/wireguard.sh remove myphone
Server Management
Check WireGuard status
sudo wg show
Check service status
sudo systemctl status wg-quick@wg0
Restart WireGuard
sudo systemctl restart wg-quick@wg0
Reload clients (automatic on add/remove)
sudo ~/wireguard.sh load-clients
Firewall management
The setup configures nftables with:
- Dual-stack IPv4/IPv6 support in a single ruleset
- Default drop incoming, accept outgoing
- SSH access allowed (port 22)
- WireGuard allowed (UDP 51820)
- Forwarding from wg0 interface allowed
- NAT masquerade for VPN internet access
View firewall rules:
sudo nft list ruleset
Reload firewall:
sudo nft -f /etc/nftables.conf
Note: nftables rules are automatically loaded on boot by the nftables service from /etc/nftables.conf. No manual intervention required after reboot.
Allow additional ports if needed:
sudo nft add rule inet wireguard input tcp dport 80 accept # HTTP
sudo nft add rule inet wireguard input tcp dport 443 accept # HTTPS
Manual Client Configuration
To manually add a client, create a file in /etc/wireguard/conf.d/:
[Peer]
# mydevice
PublicKey = <client_public_key>
AllowedIPs = 10.10.69.2/32, fd69:dead:beef:69::2/128
Then run:
sudo ~/wireguard.sh load-clients
Client Setup
Importing the config
- Desktop: Import
/etc/wireguard/clients/<name>.confinto WireGuard app - Mobile: Scan QR code with WireGuard app, or import config file
Test connectivity
# On client
ping 10.10.69.1
ping -6 fd69:dead:beef:69::1
# Check your IP
curl -4 https://ifconfig.me
curl -6 https://ifconfig.me
Troubleshooting
Check firewall
sudo nft list ruleset
Check IP forwarding
sysctl net.ipv4.ip_forward
sysctl net.ipv6.conf.all.forwarding
View logs
sudo journalctl -u wg-quick@wg0 -f
Check client directory
ls -la /etc/wireguard/conf.d/
Manual reload if needed
sudo ~/wireguard.sh load-clients
Notes
/etc/wireguard/conf.d/- Server-side peer configs, loaded automatically by wireguard.sh/etc/wireguard/clients/- Client-side configs (import to WireGuard apps) and QR codes- Clients are automatically reloaded when added/removed
- IPv4 and IPv6 NAT are configured (MASQUERADE)
- nftables firewall is configured with dual-stack IPv4/IPv6 support
- Single nftables ruleset handles both IPv4 and IPv6
- SSH (port 22) and WireGuard (UDP 51820) are allowed by default
- Keepalive is set to 25 seconds for better stability
- Server private keys are stored in
/etc/wireguard/server_private.key - Server public key is displayed after installation