Something useful for internet anonymity is having a VPN you can trust. I recently tried making a repository containing code to create a Wireguard VPN on the fly in DigitalOcean. You can control the logging and where in the world the VPN gets started. All of the code can be found here. Let’s walk through the code.

I am not responsible for any charges you incur by using this code. DigitalOcean will charge you for what resources you use.

Terraform

As usual I will use terraform to create the infrastructure in the cloud. You can find the network terraform under terraform/network. Then you can run the terraform from the terraform directory to create the droplet. Please update the ssh keys in the terraform to be your own IDs. It won’t work otherwise. Also ensure you are giving terraform the do_token variable for DigitalOcean. I declare it in .bashrc as the variable TF_VAR_do_token.

cd terraform/network
terraform init
terraform apply
cd ..
terraform init
terraform apply
cd ..

After this we have our droplet setup. Note the IP Address so we can update ansible_hosts.

Create Certificates

I have certificates in ansible/group_vars/wireguard.yml These are encrypted by ansible-vault. You will need to create your own in that file. This is because I can’t share my own certs publicly.

Dependencies

To create certificates you are required to have installed wireguard and ansible.

wg genkey | tee server_private.key | wg pubkey > server_public.key
wg genkey | tee client_private.key | wg pubkey > client_public.key
read server_private < server_private.key
read server_public < server_public.key
read client_private < client_private.key
read client_public < client_public.key
echo -n "$server_private" | ansible-vault encrypt_string
echo -n "$server_public" | ansible-vault encrypt_string
echo -n "$client_private" | ansible-vault encrypt_string
echo -n "$client_public" | ansible-vault encrypt_string

Copy the values to the corresponding variables in ansible/group_vars/wireguard.yml. Make sure to use the same password for all of the variables and remember that password.

Ansible

In the ansible directory update the ansible_hosts file with the IP created in the terraform step. Then run the ansible code by the following.

ansible-playbook -i ansible_hosts playbooks/wireguard.yml --ask-vault-password

Use the password you used for encrypting the new certs.

What is Ansible Doing?
  1. Install wireguard
sudo apt update && sudo apt install wireguard
  1. Stop wireguard
sudo systemctl stop wg-quick@wg0

This may not be running but we just need to be sure.

  1. Template the server config

The config file template can be found in ansible/playbooks/roles/wireguard/templates/wg0.conf.j2. It is copied to /etc/wireguard/wg0.conf.

  1. Template the client config

The config file template can be found in ansible/playbooks/roles/wireguard/templates/wg0-client.conf.j2. It is copied to ~/Desktop/wg0-client.conf.

  1. Start wireguard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
  1. Enable IPv4 Forwarding

This last step enables IPv4 forwarding for our VPN. This allows our clients to connect to the public internet.

# must be run as root
echo "net.ipv4.ip_forward=1" > /etc/sysctl.conf && sysctl -p

Automation

All of this can be automated except for the generation of certificate data. Once you have updated ansible/group_vars/wireguard.yml you can use the makefile to build the whole thing.

make build

Then if you are using the same computer to connect to the VPN run the following to setup the VPN connection.

make setup-client
make start-vpn

When you are finished with the VPN you can disconnect with stop-vpn.

make stop-vpn

Finally, if you would like to completely delete the VPN so that you don’t incur charges while you aren’t using it destroy can be used.

make destroy

Why?

This setup allows you to be in control of logs, location, and uptime on the VPN. I don’t need a VPN 100% of the time so this works for me quite well. You can always modify this code to meet your needs of location or configuration.