I have had a little spare time recently to revisit my beloved terraform-aws-openvpn-ephemeral repo and module and give it a much-needed cleanup. As a result, I’ve now published an official version 1.0.0 and I am super stoked with how it operates! Further, I even set up an openvpn-ephemeral-github-actions-template repo using GitHub Actions as another method to use CI/CD with this module, building off the previous work using GitLab and CircleCI.

Build Back Better

It’s been about a year since I last made any meaningful updates to the openvpn-ephemeral terraform module as I was attempting to use the service from my machine and noticed a few different odd and interesting errors. As I reviewed the module, I had a “wow, this code is terrible” moment as I questioned the architecture choices I had made previously. In a way, I am happy because while I could have easily made these newer architectural decisions back then, the service and module were still launched and usable this time last year. Now after reviewing the architecture I have realized that it was way overcomplicated (and still might be) but as they say “perfect is the enemy of good enough”. Version 0 previously released worked just fine, but now, it works even better.

So what were the changes? For starters, the previous setup required AWS SSM Manager to download the created OpenVPN file created by the EC2 instance. AWS SSM Manager is in my opinion, non-trivial to set up, especially when you are relying on your own personal machine or containers in CI/CD to use AWS SSM Manager to download the files you need from an EC2 instance. An easier solution? S3!

By swapping out downloading the OpenVPN file via AWS SSM Manager for S3, basically, Terraform creates a private S3 bucket and the EC2 instance creates the OpenVPN file and uploads the file there. Then, Terraform also downloads the OpenVPN file from S3 for you. This negates the need for a tls_private_key pem certificate and aws_key_pair resources as well! Having to use AWS SSM Manager to scp the file securely is a bit clunky and be just as securely achieved using a private S3 bucket that only your AWS Account has access to.


Another thing I realized was that using local Terraform state and passing it around in CI/CD for GitLab and CircleCI was also completely unnecessary and can be efficiently changed by using Terragrunt. Terragrunt has a superior way than Terraform to set up a remote S3/DynamoDB backend for your Terraform State and Locks, and example terragrunt.hcl files are provided in the updated examples.

Using a remote S3/DynamoDB backend for the Terraform State means that you can set up a private repo in SCM and then download that repo from any machine, run your Terragrunt commands and the OpenVPN instance will be created for you. This has great advantages in case the state is ever compromised mid-run; you can simply download the state elsewhere and fix things, rather than having to manually go and clean up the resources previously.

Improved Docker Image

One of the changes I am most proud and fond of is the creation of the terragrunt-awscli Docker image. The image is created with just two lines!

FROM alpine/terragrunt
RUN apk add --no-cache aws-cli

The alpine/terragrunt image has Terragrunt and Terraform, so this new terragrunt-awscli image just adds the aws-cli on top. This is done as Terraform downloads the OpenVPN file from S3 via the AWS CLI, so it needs to be present.

Previously, the Docker image terraform-aws-ssh was used. This image was around ~272MB whereas the terragrunt-awscli image is only 90MB!

everyone loves small docker images!

This should result in faster builds in CI/CD, saving precious minutes on the free tier in GitLab, CircleCI and … GitHub Actions!

GitHub Actions

I have been using GitHub Actions in my professional life recently, and it is quite a different CI/CD tool compared to GitLab, CircleCI or Jenkins, to which I have previously been exposed.

However, I have been impressed with GitHub Actions simplicity. I’ve come to accept that to have a decent CI/CD pipeline, you need to write some decent YAML. I put together this openvpn-ephemeral-github-actions-template repo, similar to the circleci-template and gitlab-template counterparts to show how to use GitHub Actions with the OpenVPN Terraform module.

It kind of sucks that with GitHub Actions you have to have separate workflows for OpenVPN create and destroy processes, as having “manual approvals” or pauses in workflows is quite convoluted to set up in GitHub Actions. However, this is not the end of the world and honestly makes for an easy UI experience for start and stop. I would rank GitHub Actions as a solid second choice behind GitLab for using CI/CD with this workflow. GitLab slightly edges out and takes the first position because it has Manual Approval buttons for each create and destroy jobs, so you can have one workflow file for all your regions, rather than have these separated as you do for GitHub Actions. The CircleCI workflow is definitely still the least desirable of the three 😀

GitHub Actions also has a decent free tier of 2,000 CI/CD minutes per month, equating to ~500 minutes per week. The build and destroy jobs take roughly 4-5 mins each at max so the VPN could be started and stopped around 14 times per day before you would hit the free tier limits. More than enough for my personal use case!

Where to next?

Not being able to sit still, I am already thinking about how to make this service offering even better, and there are certainly a lot of obvious solutions to consider. I will probably set up things in Terraform as an Auto Scaling Group that scales to 0 when you are done with the instance. This would allow for a faster startup time (presumably) as you are not having to create the instance, role, policy and bucket from scratch each time you wish to create.

I definitely also want to use the learnings from version 1 and earlier, to set up a service that has a complete front-end for even easier use when creating OpenVPN access. A simple password-protected site where you click the region you want a VPN for and it downloads the OpenVPN profile file for you surely can’t be that hard right?


  • Refactoring your code is awesome, and you should try and use fewer resources whenever possible
  • GitHub Actions is a solid CI/CD tool for starting/stopping OpenVPN EC2 instances
  • Releasing Version 1 of anything will release your own endorphins!