Iterating and generally making code better is something that sparks a lot of joy in my professional and personal life. I was very happy with my openvpn setup on my local machine, however I wanted to make the setup a bit more user friendly, and a bit more automated and accessible rather than having any potential users endlessly alter their .bashrc or zshrc files.

One way it was determined to do so was to use GitLab or CircleCI as the user will be able to click a few buttons and the OpenVPN EC2 instance would be created. A few more clicks later and the EC2 instance is then easily destroyed!

Docker image

In order to successfully create the OpenVPN EC2 instance from either GitLab or CircleCI, there are a few different options that can be used for the docker image that runs the execution tasks/jobs. A simple Terraform docker image could be used and then each step/stage could install the AWS CLI, AWS Session Manager plugin and custom ssh config to connect to the EC2 instance. That workflow would increase the build time though (and use up precious “free-use” minutes in GitLab and CircleCI), so a better way to do this is with a custom Docker image that contains the following:

  • Terraform
  • AWS Session Manager plugin
  • SSH
  • custom SSH config that connects to the OpenVPN EC2 instance using Session Manager, not SSH

This custom docker image lives here and so far, it has been working out well as demonstrated below!


GitLab has a pretty awesome Free Tier pricing structure where you receive 400 free minutes of CI/CD pipelines per month. What I looked to do with the OpenVPN pipeline is have each build/destroy job complete in around 1 minute each, meaning the user could run the pipelines ~200 times per month free of charge. That absolutely works for my personal use case and may or may not work for others 😄

I put together a sample GitLab template repo which contains an outline of what needs to be done in order to setup the pipeline in GitLab. The .gitlab-ci.yml file can be extended after cloning/forking to include extra regions as well.

I personally am a fan of the “click-button, magic happens” approach and the visuals on the pipeline make it pretty seamless to use:
green check means all is well


CircleCI also has a Free Tier pricing structure that provides users 2,500 credits per week (or 10,000 per month). The credits system is kinda hard to get a good handle on, but each region’s build and destroy job costs about ~30-40 credits, so these pipelines can be run ~63 times a week (or ~250 times per month). These numbers also work for my personal use case, however may not work for others either.

Like I did for GitLab, I put together a sample CircleCI template repo which contains an example of how to setup a this pipeline in CircleCI for the regions you would like an OpenVPN instance in. The config.yml file can also be extended after cloning/forking to include extra regions as well.

Compared to GitLab, the pipelines are a little differently visualized, but can be seen here:

Thumbs up to approve jobs!

Unlike GitLab, I am not as fond on the workflow layout UI in CircleCI. I don’t know if this is a bias to using GitLab far more frequently than CircleCI, but I find the structure of the YAML file a bit more complicated, as compared to GitLab. I’m not a big fan of having to write an explicit approve_build type:approval as a job, as opposed to GitLab’s when: manual for manual approval jobs, but c’est la vie.

Why use CI/CD for OpenVPN?

Interestingly, when I first put together the Terraform module I wasn’t planning on using CI/CD at all. I actually wanted just a static webpage with some sort of a custom frontend that would “turn on” and “turn off” the OpenVPN instance via Terraform and the browser. However, that path seemed like too much hassle, (especially with the question of where to store the Terraform state) for the simple request of “build the server on-click, download the config, destroy on-click”. I also wanted to be able to extend the offering to the community, via a template for doing so. I am not as strong in my front-end skills (yet) as I am with IaC and CI/CD, so maybe I’ll still explore this option again in the future!

Personally, my preference is to use GitLab as my go-to, and CircleCI as a backup. It’s always good to have alternative options (redundancy) in case say GitLab is ever unavailable (or CircleCI is unavailable), and if a user ever goes over the “free-tier” minutes in GitLab, they could use CircleCI instead or vice-versa. Maybe I have accidentally come up with a pattern for Highly Available multi-vendor CI/CD? 😆

If a user happens to go over the “free-tier” minutes in both GitLab or CircleCI, they can always go back to running Terraform from the command line, outlined in this post

Using CI/CD for running this OpenVPN service on-demand has definitely fit my needs in the short term, and I look forward to extending this even further in the future!


  • Using bash or zsh to run Terraform is cool, but IaC in CI/CD is even cooler! It provides UI and button clicking to start and stop servers!
  • GitLab and CircleCI have great free tiers for personal projects
  • Maybe Highly Available multi-vendor CI/CD will become the wave of the future!