Terraform project for the Automated AWS MTProto v2 (MTG) Proxy Deployment.
It provisions:
- one VPC with IPv4 and AWS-assigned IPv6 space
- one public subnet with IPv4 and IPv6 addressing enabled
- an internet gateway and public route table for dual-stack internet access
- one Amazon Linux 2023 EC2 instance
- Elastic IP-backed public IPv4
- public IPv6
- encrypted
gp3root volume sized byroot_volume_size
- an instance profile with:
AmazonSSMManagedInstanceCore- Route53 permissions for ACME DNS challenge
- a security group exposing MTG on
443and the website on8443for IPv4 and IPv6 - a managed Elastic IP for stable public IPv4
- a Route53
Arecord for the configureddomain_name - EC2 user data that installs Caddy with the Route53 plugin, clones the site from GitHub, generates
/etc/caddy/Caddyfile, and installs and configuresmtg
versions.tf: Terraform and provider requirementsvariables.tf: inputs for network, instance, and domain settingsmain.tf: VPC, subnet, routing, EC2 instance, Route53 records, and bootstrapiam.tf: instance role, profile, and Route53 policyoutputs.tf: public outputsuser_data.sh.tftpl: bootstrap template for Amazon Linuxterraform.tfvars.example: example input valuesbackend.hcl.example: example S3 backend configuration for Terraform state
Before using this project, install the following tools on the machine that will run Terraform:
- Terraform
- AWS CLI
- AWS Session Manager plugin
- a GitHub repository with a static website that will be used as the MTG fronting domain
Verify both commands are available:
terraform version
aws --versionPrepare an AWS account and credentials before running Terraform:
- Create or use an AWS account that owns the target infrastructure and domain DNS records.
- Create an IAM user for Terraform automation with AdministratorAccess, or an equivalent permission set that covers EC2, IAM, VPC, Route53, and S3 state access.
- Create an access key pair for that IAM user and store the access key ID and secret access key securely.
- Configure the AWS CLI with those credentials:
aws configureProvide:
- AWS Access Key ID
- AWS Secret Access Key
- default region, for example
eu-north-1 - default output format, for example
json
Confirm the CLI is authenticated:
aws sts get-caller-identityThe domain used by domain_name should be managed by a public Route53 hosted zone:
- Register the domain with your registrar, or use an existing registered domain.
- Create a public hosted zone in Route53 for that domain.
- Update the registrar nameservers so the domain delegates DNS to the Route53 hosted zone.
- Put the hosted zone ID into
route53_zone_idand the domain intodomain_name.
Terraform creates DNS records in that hosted zone, so the zone must already exist before terraform apply.
This project is configured to use the S3 backend for Terraform state.
Example backend config:
bucket = "funmechanics-terraform-state-180940737694"
key = "prod/funmechanics.tfstate"
region = "eu-north-1"
use_lockfile = true
encrypt = trueRecommended bucket settings:
- enable bucket versioning
- enable default SSE-S3 or SSE-KMS encryption
- block all public access
- keep the bucket dedicated to Terraform state
Create the bucket before running terraform init.
Copy the example variables file and adjust values:
cp terraform.tfvars.example terraform.tfvarsCopy the backend config example and fill in your state bucket details:
cp backend.hcl.example backend.hclThen initialize and apply:
terraform init -backend-config=backend.hcl
terraform plan
terraform applyTo start an SSM session to the created instance, use the instance ID from the EC2 console or terraform output and run:
aws ssm start-session --target i-0123456789abcdef0- The bootstrap can clone a public website repository such as
https://github.com/example/example.git. - The active Caddy config is generated directly in userdata at
/etc/caddy/Caddyfile, so the website repository does not need to ship aCaddyfile. - The website content is cloned into
/srv/<site_name>, controlled by the Terraform variablesite_name. - If the site repository becomes private, switch the bootstrap to SSH or another authenticated fetch method.
- Route53 access should be limited to the hosted zone ID for your own domain, for example
Z0123456789EXAMPLE. - The default AWS region is
eu-north-1. - The root EBS volume defaults to
20GiB and is explicitly configured as encryptedgp3throughroot_volume_size. - Terraform must run in a region and availability zone where Amazon Linux 2023 and IPv6-enabled VPC networking are available.
backend.hclshould stay uncommitted if you put environment-specific state paths or bucket names in it.- Bootstrap now installs
mtgviago install github.com/9seconds/mtg/v2@latest, generates a secret withmtg generate-secret --hex domain_name, writes/etc/mtg.toml, and createsmtg.service. - The generated
mtgconfig follows the upstream example structure. - It sets
public-ipv4from EC2 metadata to avoid external IP-discovery requests. - It sets
[domain-fronting].port = 8443and[domain-fronting].ip = 127.0.0.1so the fronting domain matches the website served by this stack. - It enables the upstream-style
[defense.blocklist]withfirehol_level1.netset. - It exposes local Prometheus metrics on
127.0.0.1:3129.