Run OpenVPN server + stunnel on AWS
- Move here notes from OneNote
- Move the project for CloudFormation
- Use GitHub as persistent storage
- Split the project into modules
- Tasks
- Virtual machine based on a standard Debian image
- Access to the VM only via SSH
- Non standard port (parameter or random?)
- ED25519 key authentication (how to generate and where to store keys?)
- No username-password access
- VM settings
- No root login; use sudo for administrative tasks
- Firewall configured to block all ports except those in use (ufw?)
- Install Docker to run OpenVPN/stunnel in a container
- OpenVPN settings
- Use TLS certificates with passwords
- Route all traffic through stunnel
- Make changes in bootstrap.sh, install scripts, config files, add new files as needed
-
- (recommended) Update stack -> Change LaunchTemplate -> Bump version. ASG delete old instance and create the new one
-
- Add fake parameter (UserDataVersion: 3). ASG delete old instance and create the new one
-
- Manually delete instance. ASG create new instance
Repository's root: bootstrap.sh install/ 01-system.sh 02-packages.sh 03-app.sh config/ app.conf env.sh services/ myapp.service
If you don’t have custom networking yet, use existing default resources:
Find subnets:
- Go to VPC → Subnets
- Pick subnet in your default VPC.
There are two options:
-
Console:
- Go to CloudFormation → Stacks → Create stack → With new resources (standard)
- Choose Upload a template file
- Select your YAML file
- Click Next.
-
CLI:
aws cloudformation create-stack \ --stack-name my-dev-stack \ --template-body file://template.yaml \ --parameters \ ParameterKey=InstanceType,ParameterValue=t3.micro \ ParameterKey=AmiId,ParameterValue=ami-xxxxxxxx \ ParameterKey=ScriptBucket,ParameterValue=my-scripts-bucket \ ParameterKey=ScriptPath,ParameterValue=bootstrap.sh \ --capabilities CAPABILITY_NAMED_IAM
-
In the CloudFormation console, after uploading the template:
- Set parameters:
- InstanceType (e.g.
t3.micro) - AmiId
- ScriptsURL
- BootStrapScript
- Subnet from the step 1
- InstanceType (e.g.
- Click Next until Review
- Acknowledge IAM capabilities if needed
- Click Create stack.
- Set parameters:
-
Wait until the stack reaches CREATE_COMPLETE.
-
Go to EC2 → Instances and confirm:
- One instance is running
- It uses your Launch Template.
-
Use SSM Session Manager (recommended):
- Go to EC2 → Instances → Select instance → Connect → Session Manager
- Open a shell.
-
Check logs:
cat /var/log/cloud-init-output.log cat /var/log/user-data.log
-
Verify that services/processes are running as expected.
-
Edit scripts in GitHub:
- Commit and push changes.
- New instances will automatically pull the latest version on boot.
-
To force recreation of the instance:
- Option A (clean): update the stack with a changed parameter (e.g.
UserDataVersion=2) so Launch Template changes → ASG replaces the instance. - Option B (quick): terminate the instance manually; ASG will create a new one.
- Option A (clean): update the stack with a changed parameter (e.g.
-
Reconnect, check logs, verify behavior.
Whenever you modify the template (e.g. new resources, changed Launch Template fields):
- Run Update stack (console or CLI):
aws cloudformation update-stack \ --stack-name my-dev-stack \ --template-body file://template.yaml \ --parameters ... \ --capabilities CAPABILITY_NAMED_IAM
- Wait for UPDATE_COMPLETE
- Confirm that the ASG created a new instance if Launch Template changed.