⚠️ IMPORTANT Version 2 is currently under development and may contain bugs. It is currently not advised to use this version in production. Use version v1 instead.
Since the project was accepted by the Docker-Sponsored Open Source Program, the Docker image location has moved to: https://hub.docker.com/r/wgportal/wg-portal. Please update the Docker image from h44z/wg-portal to wgportal/wg-portal.
A simple, web based configuration portal for WireGuard. The portal uses the WireGuard wgctrl library to manage existing VPN interfaces. This allows for seamless activation or deactivation of new users, without disturbing existing VPN connections.
The configuration portal supports using a database (SQLite, MySQL, MsSQL or Postgres), OAuth or LDAP (Active Directory or OpenLDAP) as a user source for authentication and profile data.
- Self-hosted - the whole application is a single binary
- Responsive web UI written in Vue.JS
- Automatically select IP from the network pool assigned to client
- QR-Code for convenient mobile client configuration
- Sent email to client with QR-code and client config
- Enable / Disable clients seamlessly
- Generation of wg-quick configuration file (
wgX.conf
) if required - User authentication (database, OAuth or LDAP)
- IPv6 ready
- Docker ready
- Can be used with existing WireGuard setups
- Support for multiple WireGuard interfaces
- Peer Expiry Feature
- Handle route and DNS settings like wg-quick does
- Exposes Prometheus metrics
REST API for management and client deployment(coming soon)
You can configure WireGuard Portal using a yaml configuration file.
The filepath of the yaml configuration file defaults to config/config.yml in the working directory of the executable.
It is possible to override the configuration filepath using the environment variable WG_PORTAL_CONFIG.
For example: WG_PORTAL_CONFIG=/home/test/config.yml ./wg-portal-amd64
.
Also, environment variable substitution in config file is supported. Refer to syntax
By default, WireGuard Portal uses a SQLite database. The database is stored in data/sqlite.db in the working directory of the executable.
The following configuration options are available:
configuration key | parent key | default_value | description |
---|---|---|---|
admin_user | core | admin@wgportal.local | The administrator user. This user will be created as default admin if it does not yet exist. |
admin_password | core | wgportal | The administrator password. If unchanged, a random password will be set on first startup. |
editable_keys | core | true | Allow to edit key-pairs in the UI. |
create_default_peer | core | false | If an LDAP user logs in for the first time and has no peers associated, a new WireGuard peer will be created for all server interfaces. |
create_default_peer_on_creation | core | false | If an LDAP user is created (e.g. through LDAP sync), a new WireGuard peer will be created for all server interfaces. |
self_provisioning_allowed | core | false | Allow registered users to automatically create peers via their profile page. |
import_existing | core | true | Import existing WireGuard interfaces and peers into WireGuard Portal. |
restore_state | core | true | Restore the WireGuard interface state after WireGuard Portal has started. |
log_level | advanced | warn | The loglevel, can be one of: trace, debug, info, warn, error. |
log_pretty | advanced | false | Uses pretty, colorized log messages. |
log_json | advanced | false | Logs in JSON format. |
start_listen_port | advanced | 51820 | The first port number that will be used as listening port for new interfaces. |
start_cidr_v4 | advanced | 10.11.12.0/24 | The first IPv4 subnet that will be used for new interfaces. |
start_cidr_v6 | advanced | fdfd:d3ad:c0de:1234::0/64 | The first IPv6 subnet that will be used for new interfaces. |
use_ip_v6 | advanced | true | Enable IPv6 support. |
config_storage_path | advanced | If a wg-quick style configuration should be stored to the filesystem, specify a storage directory. | |
expiry_check_interval | advanced | 15m | The interval after which existing peers will be checked if they expired. |
rule_prio_offset | advanced | 20000 | The default offset for ip route rule priorities. |
route_table_offset | advanced | 20000 | The default offset for ip route table id's. |
use_ping_checks | statistics | true | If enabled, peers will be pinged periodically to check if they are still connected. |
ping_check_workers | statistics | 10 | Number of parallel ping checks that will be executed. |
ping_unprivileged | statistics | false | If set to false, the ping checks will run without root permissions (BETA). |
ping_check_interval | statistics | 1m | The interval time between two ping check runs. |
data_collection_interval | statistics | 1m | The interval between the data collection cycles. |
collect_interface_data | statistics | true | A flag to enable interface data collection like bytes sent and received. |
collect_peer_data | statistics | true | A flag to enable peer data collection like bytes sent and received, last handshake and remote endpoint address. |
collect_audit_data | statistics | true | If enabled, some events, like portal logins, will be logged to the database. |
listening_address | statistics | :8787 | The listening address of the Prometheus metric server. |
host | 127.0.0.1 | The mail-server address. | |
port | 25 | The mail-server SMTP port. | |
encryption | none | SMTP encryption type, allowed values: none, tls, starttls. | |
cert_validation | false | Validate the mail server certificate (if encryption tls is used). | |
username | The SMTP user name. | ||
password | The SMTP password. | ||
auth_type | plain | SMTP authentication type, allowed values: plain, login, crammd5. | |
from | Wireguard Portal noreply@wireguard.local | The address that is used to send mails. | |
link_only | false | Only send links to WireGuard Portal instead of the full configuration. | |
callback_url_prefix | auth | /api/v0 | OAuth callback URL prefix. The full callback URL will look like: https://wg.portal.local/callback_url_prefix/provider_name/callback |
oidc | auth | Empty Array - no providers configured | A list of OpenID Connect providers. See auth/oidc properties to setup a new provider. |
oauth | auth | Empty Array - no providers configured | A list of plain OAuth providers. See auth/oauth properties to setup a new provider. |
ldap | auth | Empty Array - no providers configured | A list of LDAP providers. See auth/ldap properties to setup a new provider. |
provider_name | auth/oidc | A unique provider name. This name must be unique throughout all authentication providers (even other types). | |
display_name | auth/oidc | The display name is shown at the login page (the login button). | |
base_url | auth/oidc | The base_url is the URL identifier for the service. For example: "https://accounts.google.com". | |
client_id | auth/oidc | The OAuth client id. | |
client_secret | auth/oidc | The OAuth client secret. | |
extra_scopes | auth/oidc | Extra scopes that should be used in the OpenID Connect authentication flow. | |
field_map | auth/oidc | Mapping of user fields. Internal fields: user_identifier, email, firstname, lastname, phone, department and is_admin. | |
registration_enabled | auth/oidc | If registration is enabled, new user accounts will created in WireGuard Portal. | |
provider_name | auth/oauth | A unique provider name. This name must be unique throughout all authentication providers (even other types). | |
display_name | auth/oauth | The display name is shown at the login page (the login button). | |
base_url | auth/oauth | The base_url is the URL identifier for the service. For example: "https://accounts.google.com". | |
client_id | auth/oauth | The OAuth client id. | |
client_secret | auth/oauth | The OAuth client secret. | |
auth_url | auth/oauth | The URL for the authentication endpoint. | |
token_url | auth/oauth | The URL for the token endpoint. | |
redirect_url | auth/oauth | The redirect URL. | |
user_info_url | auth/oauth | The URL for the user information endpoint. | |
scopes | auth/oauth | OAuth scopes. | |
field_map | auth/oauth | Mapping of user fields. Internal fields: user_identifier, email, firstname, lastname, phone, department and is_admin. | |
registration_enabled | auth/oauth | If registration is enabled, new user accounts will created in WireGuard Portal. | |
url | auth/ldap | The LDAP server url. For example: ldap://srv-ad01.company.local:389 | |
start_tls | auth/ldap | Use STARTTLS to encrypt LDAP requests. | |
cert_validation | auth/ldap | Validate the LDAP server certificate. | |
tls_certificate_path | auth/ldap | A path to the TLS certificate. | |
tls_key_path | auth/ldap | A path to the TLS key. | |
base_dn | auth/ldap | The base DN for searching users. For example: DC=COMPANY,DC=LOCAL | |
bind_user | auth/ldap | The bind user. For example: company\ldap_wireguard | |
bind_pass | auth/ldap | The bind password. | |
field_map | auth/ldap | Mapping of user fields. Internal fields: user_identifier, email, firstname, lastname, phone, department and memberof. | |
login_filter | auth/ldap | LDAP filters for users that should be allowed to log in. {{login_identifier}} will be replaced with the login username. | |
admin_group | auth/ldap | Users in this group are marked as administrators. | |
disable_missing | auth/ldap | If synchronization is enabled, missing LDAP users will be disabled in WireGuard Portal. | |
sync_filter | auth/ldap | LDAP filters for users that should be synchronized to WireGuard Portal. | |
sync_interval | auth/ldap | The time interval after which users will be synchronized from LDAP. Empty value or 0 disables synchronization. |
|
registration_enabled | auth/ldap | If registration is enabled, new user accounts will created in WireGuard Portal. | |
debug | database | false | Debug database statements (log each statement). |
slow_query_threshold | database | A threshold for slow database queries. If the threshold is exceeded, a warning message will be logged. | |
type | database | sqlite | The database type. Allowed values: sqlite, mssql, mysql or postgres. |
dsn | database | data/sqlite.db | The database DSN. For example: user:pass@tcp(1.2.3.4:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local |
request_logging | web | false | Log all HTTP requests. |
external_url | web | http://localhost:8888 | The URL where a client can access WireGuard Portal. |
listening_address | web | :8888 | The listening port of the web server. |
session_identifier | web | wgPortalSession | The session identifier for the web frontend. |
session_secret | web | very_secret | The session secret for the web frontend. |
csrf_secret | web | extremely_secret | The CSRF secret. |
site_title | web | WireGuard Portal | The title that is shown in the web frontend. |
site_company_name | web | WireGuard Portal | The company name that is shown at the bottom of the web frontend. |
cert_file | web | (Optional) Path to the TLS certificate file | |
key_file | web | (Optional) Path to the TLS certificate key file |
⚠️ Before upgrading from V1, make sure that you have a backup of your currently working configuration files and database!
To start the upgrade process, start the wg-portal binary with the -migrateFrom parameter. The configuration (config.yml) for WireGuard Portal must be updated and valid before starting the upgrade.
To upgrade from a previous SQLite database, start wg-portal like:
./wg-portal-amd64 -migrateFrom=old_wg_portal.db
You can also specify the database type using the parameter -migrateFromType, supported types: mysql, mssql, postgres or sqlite. For example:
./wg-portal-amd64 -migrateFromType=mysql -migrateFrom=user:pass@tcp(1.2.3.4:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local
The upgrade will transform the old, existing database and store the values in the new database specified in config.yml. Ensure that the new database does not contain any data!
- Public REST API
- Translations
- Documentation
- Audit UI
To build a standalone application, use the Makefile provided in the repository. Go version 1.22 or higher has to be installed to build WireGuard Portal. If you want to re-compile the frontend, NodeJS 18 and NPM >= 9 is required.
# build the frontend
make frontend
# build the binary
make build
- Automatic generation or application of any
iptables
ornftables
rules. - Support for operating systems other than linux.
- Automatic import of private keys of an existing WireGuard setup.
- wgctrl-go and netlink for interface handling
- Gin, HTTP web framework written in Go
- Bootstrap, for the HTML templates
- Vue.JS, for the frontend
Metrics are available if interface/peer statistic data collection is enabled.
Add following scrape job to your Prometheus config file:
# prometheus.yaml
scrape_configs:
- job_name: "wg-portal"
scrape_interval: 60s
static_configs:
- targets: ["wg-portal:8787"]
Exposed metrics:
# HELP wireguard_interface_info Interface info.
# TYPE wireguard_interface_info gauge
# HELP wireguard_interface_received_bytes_total Bytes received througth the interface.
# TYPE wireguard_interface_received_bytes_total gauge
# HELP wireguard_interface_sent_bytes_total Bytes sent through the interface.
# TYPE wireguard_interface_sent_bytes_total gauge
# HELP wireguard_peer_info Peer info.
# TYPE wireguard_peer_info gauge
# HELP wireguard_peer_received_bytes_total Bytes received from the peer.
# TYPE wireguard_peer_received_bytes_total gauge
# HELP wireguard_peer_sent_bytes_total Bytes sent to the peer.
# TYPE wireguard_peer_sent_bytes_total gauge
# HELP wireguard_peer_up Peer connection state (boolean: 1/0).
# TYPE wireguard_peer_up gauge
# HELP wireguard_peer_last_handshake_seconds Seconds from the last handshake with the peer.
# TYPE wireguard_peer_last_handshake_seconds gauge
- MIT License. MIT or https://opensource.org/licenses/MIT