Official Terraform module for S4 NAT — a
commercial NAT instance for AWS (flat hourly fee, no per-GB data-processing
charge) sold on the AWS Marketplace.
The module itself is Apache-2.0; the S4 NAT AMI it deploys is a paid
Marketplace product (subscribe first, then pass its AMI id as ami_id).
Mirrored from deploy/terraform/ in the product repository — issues and
changes land there first and are synced here per release.
This module ports the CloudFormation HA pair and solo NAT templates into one Terraform module controlled by ha.
This module is consumed directly from Git (a git:: source) — no Terraform
Registry account or terraform login is required. Pin a released tag with
?ref=:
module "s4_nat" {
source = "git::https://github.com/abyo-software/terraform-aws-s4nat.git//?ref=v1.2.0"
vpc_id = "vpc-0abc"
vpc_cidr = "10.0.0.0/16"
public_subnet_a = "subnet-0a"
public_subnet_b = "subnet-0b"
availability_zone_a = "us-east-1a"
availability_zone_b = "us-east-1b"
active_private_ip = "10.0.0.10"
standby_private_ip = "10.0.1.10"
primary_route_table_id = "rtb-0priv"
ami_id = "ami-xxxxxxxx" # the S4 NAT AMI you subscribed to
# optional:
# stable_egress_ip = true
# active_secondary_ip = "10.0.0.250"
# standby_secondary_ip = "10.0.1.250"
# enable_xdp_fast_path = true
}terraform init fetches it straight from GitHub. The trailing // selects the
repo root as the module directory; keep it before ?ref=.
Use examples/ha for an active/standby pair and examples/single for solo mode. ami_id is required; unlike CloudFormation, this module does not resolve /s4-nat/ami/arm64/latest through SSM. Look it up before apply, for example:
aws ssm get-parameter --name /s4-nat/ami/arm64/latest --query Parameter.Value --output textThe module creates the same core topology as the CloudFormation templates:
- static source/dest-check-disabled ENIs;
- one EIP associated to each node's primary ENI;
- in HA stable-egress mode, a third shared EIP with no Terraform association because natd owns the association lifecycle;
- an EC2 default route in
primary_route_table_idtargeting the active ENI; - extra route table IDs rendered into
/etc/s4-nat/config.tomlfor natd to maintain; - the HA peer instance-id resolution retry loop in user data;
- least-privilege IAM statements, including the
aws:ResourceTag/s4-nat:stackcondition onec2:ModifyInstanceAttribute; - the
S4/NATconntrack utilization CloudWatch alarm.
Terraform replaces EC2 instances delete-then-create by default, so changing ami_id rolls the instances without the in-place CloudFormation update conflict where an attached interface blocks replacement with "Interface in use". For HA, standby-first is still recommended: replace or taint the standby instance and apply, then replace the active instance and apply.
Set stable_egress_ip = true with active_secondary_ip and standby_secondary_ip. The shared EIP is allocated but deliberately not associated in Terraform; natd associates it to the route owner secondary private IP and moves it during failover.
The CloudFormation dashboard is intentionally not ported yet. TODO: add an optional dashboard with the same metric widgets.