This project installs and configures my debian-based Wireguard VPN configuration and a management UI (WG Portal). In addition, since exposing a VPN to the internet can be a security risk if you don't know what you're doing, this project also sets up some features and services to enhance the server security. The VPN can be installed in two different methods.
- Vanilla Wireguard, which installs and configures a plain Wireguard service. Note: The steps performed during the vanilla Wireguard installation are based on the How to set up wireguard on ubuntu 20.04 article from Digital Ocean.
- Wireguard through PiVPN. Note: The steps performed during the PiVPN Wireguard installation are based on the PiVPN official website.
- Wireguard through Wireguard Portal, which provdes a management UI and a wrapper around wgctrl-go and netlink, for interface handling. Note: The steps performed during the Wireguard Portal installation are based on the Wireguard Portal official website.
This project also provides a way to migrate wireguard configurations from one host to another while keeping existing peers working.
This project contains multiple playbooks that can run in sequence or separately.
playbooks/prepare.yml
: This playbook creates a new ansible user with a new private key in the target machine and changes the default ssh port.
playbooks/main.yml
: This playbook runs the major chunk of the VPN setup. It runs the following ansible roles:
rafael-c-alexandre.security
rafel-c-alexandre.ntp
and installs a Wireguard server (by default in /etc/wireguard/${INTERFACE}.conf)
), plus generates the requested clients configs (by default in /etc/wireguard/configs
).
playbooks/backup.yml
: This playbook backs up the current wireguard configuration, depending on the installation mode. It creates a $PROJECT_ROOT/migration/wireguard-migration.zip
path where the backed up data is stored.
The recommend installation guide is as follows:
-
Ensure the Raspberry Pi has Pi OS installed and SSH running and reachable.
-
Get the PI IP address or hostname through
ip a
(or any other network-related tool) or in the router UI. -
Add the IP address/hostname in an inventory file such as
inventories/hosts.ini
. -
Clone or download this repository to your local drive.
-
Run
ansible-galaxy install -r requirements.yml
inside this directory to install required Ansible roles and collections. -
To prepare the ansible environment,
- Change host in
inventories/hosts.ini
file. - Edit any ansible variables in the
configs/ansible_pre_prepare.cfg
file, namelyremote_user
andprivate_key_file
. - Add any custom playbook configuration variables in a new
configs/config_pre_prepare.yml
file.
- Change host in
-
In order to copy the configurations needed for the
prepare
playbook, in the root folder, run
cp configs/ansible_pre_prepare.cfg ansible.cfg && cp configs/config_pre_prepare.yml config.yml && cp inventories/hosts.ini inventory
- In the root folder, run
ansible-playbook playbooks/prepare.yml
- Because the ssh config and other properties were changed, we need to update our configs:
- Edit any ansible variables in the
configs/ansible_after_prepare.cfg
file, namelyremote_user
andprivate_key_file
. - Add any custom configuration variables in a new
configs/config_after_prepare.yml
file, for instance, the two samba usernames (for me and my partner), respective shares, plus the common shared one.
- Edit any ansible variables in the
- In order to copy the configurations needed for the
main
playbook, in the root folder, run
cp configs/ansible_after_prepare.cfg ansible.cfg && cp configs/config_after_prepare.yml config.yml && cp inventories/hosts.ini inventory
- In the root folder, run
ansible-playbook playbooks/main.yml
Note: In order to migrate a previously backed up wireguard setup, the variable wireguard_migration_zip_path
needs to be defined and pointing at the .zip file where the migration data is stored. The playbook is then run the same way.
- (Optional). If you just want to run the Wireguard-related task, to either setup the VPN or generate/edit/delete a peer, you can run
ansible-playbook playbooks/main.yml --tags wireguard
This set of playbooks does pretty much everything automatically. However, some actions still require manual intervention.
If wireguard is to be used without WG Portal management UI, the following actions should be performed:
-
If the VPN host is behid a device that performs NAT, port forwarding should be configured on that device to route any traffic on Wireguard's port (by default 51820) to the VPN host. Conversely, if the VPN host has a public IP address, this step is not necessary.
-
In order to get the peers set up, we need to retrieve the configs from the peer configs folder. The main.yml playbook also installs qrencode, which is an handy tool to generate QR codes out of the Wireguard peer config files, which can then be scanned with a mobile device. Example:
ssh $USER@$VPN_HOST:$VPN_PORT -i ${IDENTITY_FILE}
qrencode -t ansiutf8 < /etc/wireguard/configs/${CLIENT}.conf
Alternatively, the configs can be downloaded from the server through tools like scp. Example:
scp $USER@$VPN_HOST:$VPN_PORT:/etc/wireguard/configs/${PEER} ${DESIREDTARGETLOCATION} -i ${IDENTITY_FILE}
If wireguard is to be used with WG Portal management UI, the following actions should be performed:
- Navigate ton the UI, login and edit the already created wg interface (in server mode) by selecting the Peer Defaults tab.
- Add the following values:
- Endpoint (server_hostname:wireguard_port)
- IP networks (the IP addresses range from which the peers will get addresses)
- Allowed IP Addresses (which target IP ranges should be routed through the VPN interface)
- DNS (DNS servers which the peer should use when connectd to the VPN)
- Save and exit.
You can override any of the defaults configured in default.config.yml
by creating a config.yml
file and setting the overrides in that file. For example, you can customize the wireguard ip addresses, interfaces and peers to be generated with something like:
---
---
ssh_pub_key_relative_location: ~/.ssh/ansible.pub
ssh_config_path: /etc/ssh/sshd_config
ssh_port: 2849
wireguard_port: 51820
sys_ctl_path: "/etc/sysctl.conf"
wireguard_interface: wg0
wireguard_installation_mode: pivpn # 'vanilla_wireguard', 'pivpn' or "wireguard_portal".
# Migratation zip file path, relative to the playbooks folder
# wireguard_migration_zip_path:
wireguard_conf_dir: /etc/wireguard
wireguard_peers_allowed_ips:
- 0.0.0.0/0
- ::0/0
wireguard_dns:
- 9.9.9.9
- 149.112.112.112
wireguard_server_interface: "{{ wireguard_interface }}"
wireguard_server_addresses:
- 10.8.0.1/24
- fd11:5ee:bad:c0de::a9c:1801/64
wireguard_server_mtu: 1420
wireguard_server_listen_port: "{{ wireguard_port }}"
wireguard_server_default_interface: eth0
# Define the following variable if there is a dynamic DNS record
# for the VPN server.
# wireguard_server_ddns_name: pivpn.ddns.net
wireguard_peers: []
# PiVPN related configs
pivpn_dhcpReserv: 1
pivpn_install_home: /root
pivpn_install_user: root
pivpn_VPN: wireguard
pivpn_pivpnNET: 10.8.0.0
pivpn_subnetClass: 24
pivpn_pivpnPROTO: udp
pivpn_pivpnPORT: "{{ wireguard_port }}"
pivpn_pivpnDNS1: 9.9.9.9
pivpn_pivpnDNS2: 149.112.112.112
pivpn_UNATTUPG: 0
pivpn_pivpnenableipv6: 1
pivpn_pivpnNETv6: "fd11:5ee:bad:c0de::"
pivpn_subnetClassv6: 64
pivpn_pivpnDEV: "{{ wireguard_interface }}"
pivpn_IPv6dev: "{{ wireguard_interface }}"
pivpn_pivpnINSTALLED_PACKAGES: "(grepcidr bsdmainutils wireguard-tools qrencode)"
# Define the following two variable if the VPN server
# is behind a NAT gateway.
# pivpn_IPv4addr: 192.168.2.13/24
# pivpn_IPv4gw: 192.168.2.254
# Wireguard portal related configs
wireguard_portal_version: v2.0.0-beta.7
wireguard_portal_host: 192.168.1.68
wireguard_portal_port: 8888
wireguard_portal_binary_directory: /opt/wg-portal
wireguard_portal_log_file_path: /var/log/wg-portal.log
wireguard_portal_logrotate_config_path: /etc/logrotate.d/wg-portal
security_ufw_rules:
- rule: allow
to_port: "{{ ssh_port }}"
protocol: tcp
comment: allow-ssh
- rule: allow
to_port: "{{ wireguard_port }}"
protocol: udp
comment: allow-wireguard
Any variable can be overridden in config.yml
; see the supporting roles' and documentation for a complete list of their available variables.
This project is continuously tested on GitHub Actions, where all its playbooks are tested in sequence (including both VPN installation options).
MIT