Building a Dual-Hop VPN with Terraform and V2Ray
Ahead of a trip where I knew everyday tools would be blocked, I built a multi-hop VPN from scratch with Terraform, Docker, V2Ray, and Nginx, and recently open-sourced it.
In July 2025 I was preparing for an extended trip to a country where I knew I'd run into network restrictions: no GitHub, no Google, limited access to half the tools I use daily. Rather than trust a commercial VPN, I decided to build my own. Over a couple of weekends I put together a dual-hop setup using Terraform, Docker, V2Ray, and Nginx. It worked well enough that I kept using it for months, and I recently cleaned it up into an open-source project.
How it works
Traffic flows through two hops. A relay node in one AWS region picks up the encrypted connection and passes it along to an exit node in a different region, and that exit node is the one that actually reaches the open internet. From the outside the relay looks like a normal HTTPS site serving static content, so there's nothing obvious to fingerprint or block.
Why I built it this way
Partly practical, partly curiosity. I work with AWS and infrastructure-as-code day to day, so this was a chance to wire together a bunch of services I already know (EC2 provisioning, security groups, Elastic IPs, TLS certificate automation, Docker orchestration) into something end-to-end.
Things I'm happy with
One-command deploy. A single terraform apply provisions both EC2 instances and handles TLS certificates via a Cloudflare DNS challenge. It also drops a ready-to-import client config onto your machine, and tearing everything down is just as quick.
QR code generator. I wrote a small Python CLI that generates a VMess URI and QR code so you can set up a phone client in about ten seconds. Scan the code with v2Box or v2rayNG and you're connected.
Sensible security defaults. SSH is locked to a single IP, inter-node traffic is restricted by security group, and TLS auto-renews via cron. Nothing is left open that doesn't need to be.
Stack
Terraform • AWS (EC2, Elastic IP, Security Groups) • V2Ray • Nginx • Docker • Certbot • Cloudflare DNS • Python
Source
The project is on GitHub: v2ray-dual-region.
Related
How Much Should You Order? A Stochastic Optimization Demo You Can Play With
I built a web app that solves a textbook inventory problem in a non-textbook way: it optimizes a reorder policy over thousands of simulated demand futures instead of one forecast.
Optimizing Your Time Off: A PTO Planner Built on CP-SAT
I built a web app that treats vacation planning as a constrained optimization problem. CP-SAT sweeps a Pareto frontier over vacation-block counts and hands back three strategies to pick from.