Prebuilding and Running AWS Instances with NixOS, GitHub Actions, and Terraform
The typical strategy for automatically launching Linux VMs in AWS looks
something like this:
Use Packer to create an EC2 instance, connect to
it via SSH, run commands to configure the machine, snapshot the EC2 as an
AMI, and then terminate the instance.
Use Terraform or another deployment script to
launch a new EC2 instance using the AMI as a base.
This process is brittle, requires multiple steps, including launching a new EC2
instance multiple times. Instead, I like to prebuild a NixOS AMI and let
Terraform import the image into AWS and launch the machine in a single action.
In order to generate a valid AMI, the .vhd file must be imported directly
from S3. With Terraform, this can be done using the
aws_ebs_snapshot_import
resource.
Once the AMI is imported, you can reference it in a basic
aws_instance
resource just like any other EC2 launch.
Putting It All Together
Using a GitHub Actions
workflow
you can perform the following steps to automatically launch everything in one
swoop:
Enable
KVM
in GitHub Actions in order to generate the image locally.
Upload the image to
S3,
which can also be done in Terraform instead. One reason to include this step
outside of Terraform is, if you want to sometimes skip building the image to
save time, Terraform doesn’t have to expect the image to always be there on
disk.