OpenVPN deployment with Terraform and Ansible
As the number of machines and services that you manage increases, manually creating and configuring your infrastructure is not scalable. As such, provisioning and configuration management tools, such as Terraform and Ansible are extremely useful. I’m going to show how to automate the deployment of OpenVPN on Azure.
OpenVPN
Occasionally, I want to mask my IP address to unlock geo-restricted content. Instead of paying a monthly fee to a VPN provider, a viable alternative is to create a temporary virtual machine on a cloud provider, install OpenVPN, and then destroy it, which is cheap. With automation, this process is very fast. If you want to learn more about OpenVPN and Public Key Infrastructure (PKI), check this book. For production use, there are additional security steps that should be taken, especially on the PKI side.
You can follow these instructions to deploy your own OpenVPN server:
- Clone the GitHub repository
- Generate an SSH key (ssh-keygen) or set an admin password for the server
- Create infrastructure using Terraform (check README)
- Edit the inventory.ini or your /etc/hosts to include the server IP
- Run the Ansible playbook (check README)
- Start OpenVPN client (openvpn –config playbooks/out/client-host.conf)
- Destroy infrastructure when done (check README)
Demo project structure
1 | ├── playbooks |
Terraform
Terraform is the most popular tool to provision resources on public clouds. The infrastructure is defined with a declarative domain-specific-language (DSL) called HashiCorp Configuration Language (HCL). It saves the infrastructure state in a local file, provides locking and allows to plan the changes before applying them. When working with multiple people, remote state should be used to prevent concurrent runs.
As each cloud provider is different, there are multiple terraform providers. With Terraform we can keep the entire infrastructure as code and others can review changes, which helps reduce human errors. Initial configurations of the operating system (OS) can be specified, which is helpful. Many companies choose to build their own OS image. Here’s a sample of a terraform config file:
1 | resource "azurerm_virtual_machine" "demo-instance" { |
Ansible
Ansible is an agentless configuration management tool, which uses SSH to push and execute playbooks. Playbooks contain sequences of tasks and should be idempotent. For reusable code check Ansible Roles. I’ve developed a playbook to install OpenVPN on CentOS:
1 |
|
I didn’t include all the tasks here because they would take too much space. At first, some required packages are installed and then easy-rsa is used to generate server and client certificates. Then, OpenVPN and the firewall are configured. Lastly, any changes to the server config will trigger a service reload and with the client config automatically transferred, you are able to use your VPN. It is also possible to configure OpenVPN to use your own DNS server if you want to do DNS analytics or block ads with Pi-Hole, which is what I’ve done with Ad Pruner. Another cool use case is to setup port forwarding (with additional iptables rules), as an alternative to ngrok. If you want to better organize your IaaC and automate provisioning I can recommend Terragrunt and Atlantis.
Closing thoughts
There is a lot to say about infrastructure and application deployment. Immutable vs mutable infrastructure, push vs pull configuration management, kubernetes and containers vs virtual machines, cloud managed services vs self hosted, but I leave all these for another day.