DigitalOcean Personal VPN
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?
- Install
wireguard
sudo apt update && sudo apt install wireguard
- Stop
wireguard
sudo systemctl stop wg-quick@wg0
This may not be running but we just need to be sure.
- 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
.
- 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
.
- Start
wireguard
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
- 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.