Setting up VPN to access private VPC on AWS, and general guidance on how to do that

I am working on a personal project, and by doing it, I am attempting to familiarize myself with working with AWS, and working with IAC tools.

I am using terraform to provision the resources, and serverless framework to deploy my docker images to ECS. That has been working fine.

When I create a database, I connected it to the private VPC, however that means I can test my docker images locally. I did some research, and I understood that most people would set up a VPN that would connect the private network to your network.

To do that, I understood that I need to use EC2, and OpenVPN. Now comes my question, from my understanding terraform is used for provisioning resources, so I can’t use only terraform to do this since I would need SSH access to the machine to configure terraform. That means I would need to use Ansible ?

Is my reasoning correct ? And what are the best practices here, and can someone give me some tips ? I haven’t found a guide on this online, and I am struggling.

This is a perfect use case for something like Tailscale. This is what we do but our setup is a bit different (as we are using EKS). With Tailscale you can easily route to a host on the Tailnet, and shut down the client when not in use.

Alternatively, you can always use SSH port forwarding, but this would require that you maintain the ssh connection on your own when you intend to test against the database locally.

I think you’ve lost yourself in complexity here.

When I create a database, I connected it to the private VPC, however that means I can test my docker images locally.

I presume you mean “I cannot test docker images locally”.

What are you actually trying to do? If your database is in a private subnet (not VPC) and you want to connect to it from your local machine to test something locally then your options are listed here: Scenarios for accessing a DB instance in a VPC - Amazon Relational Database Service

Now comes my question, from my understanding terraform is used for provisioning resources, so I can’t use only terraform to do this since I would need SSH access to the machine to configure terraform. That means I would need to use Ansible ?

Do you want to run your own VPN on an EC2 instead of AWS Client VPN? If so you should be starting here: Get Started With Access Server's Reliable Secure Networking

so if you really want to do this

  1. you need to make a public subnet on your vpc in some az, make this subnet accessible via route table to take in internet traffic, connect the public az subnet route table to the private subnet cidr/db subnet cidr
  2. launch an ec2 in the public subnet
  3. log into ec2 with ssh key install openvpn client, setup vpn client
  4. now you can use the openvpn client as a jump box

I wouldn’t recommend this. It’s easy to spin up the wrong thing and incur a big bill and db connections over vpn is going to be terrible performance.

You can use something like localstack https://docs.localstack.cloud/user-guide/aws/feature-coverage/ to test your terraform https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/test-aws-infra-localstack-terraform.html

You can use AWS Systems Manager to connect (instead of SSH) and even use Systems Manager with Ansible – no need to open your instance ports to the Internet. Or use Ansible itself in Systems Manager.

If you really don’t want to use a tool like Ansible to setup an EC2, you could always use a UserData script.

Now comes my question, from my understanding terraform is used for provisioning resources, so I can’t use only terraform to do this since I would need SSH access to the machine to configure terraform. That means I would need to use Ansible ?

Not really. For this particular task you absolutely can get what you want with just terraform. For any EC2 instance you can provide a piece of injectable script that will execute only once during the first boot. See the User Data in tf and in aws docs, and also read about cloud-init

Ansible in my opinion is a bit overkill here. That would be useful when you’ll want to setup and maybe later re-configure something like a fleet of diverse hosts with different roles, etc. Ansible brings structured approach for doing that.

This is what I do every time when need a quick and disposable lab for my own experiments: spawning just a single t4g.small spot instance (~5-10 cents per day) in a public subnet that acts both as NAT gateway for the private subnets and as a VPN server with Tailscale node on it for connectivity from home. That all is configured with 20 lines of bash script, injected by terraform as UserData.

Honestly for ease of vpn you can use AWS client vpn. There is a cost but it’s probably similar to the cost of running an ec2 with a OpenVPN or pritunl.
Ideally for connecting to ec2 machines you can use ssm to connect via the terminal.

Thank you for the clarification! One more question please, if I am trying to automate this process so maybe I can use for other projects, would it be doable using only terraform, or should I use ansible for this ?

I considered that, but the benefit of using an EC2 instance is that I can close it down whenever I want.

Brother you’re learning, use neither of them until you’ve manually implemented what you’re describing, and verified it’s working.

If you don’t know when you would use Terraform over Ansible then you’re trying to do too much at once.

AWS client VPN is a rebadged OpenVPN, but it’s really, really expensive. Do not leave it running like you would with any normal VPN. Turn it on only for the duration of your task

You could set up OpenVPN yourself on one server, but do it only if you want to learn how to.

Really, if it’s just you, just use ssh and a jumphost in a public subnet. ssh is great.

Another option is to install the AWS SSM agent on your VMs, give them the SSM IAM Role, and then you can connect using the web console (kinda sucks, but it’s easy) or through the cli tool

Makes sense lol, thank you!