Skip to main content
This guide walks through creating a Talos AMI for AWS, importing it into your AWS account, and launching EC2 instances that can be registered with Omni.

Step 1: Set your AWS region

Define the AWS region where you want to create your Omni machines.
REGION=<your-aws-region> # e.g. us-east-1

Step 2: Identify the VPC

Your EC2 instances must run inside a VPC. Most AWS accounts have a default VPC available. First list the VPCs in your region:
aws ec2 describe-vpcs --region $REGION
Then capture the default VPC:
VPC_ID=$(aws ec2 describe-vpcs \
  --region $REGION \
  --query "Vpcs[?IsDefault].VpcId" \
  --output text)

echo $VPC_ID
This command stores the VPC ID in the VPC_ID variable.

Step 3: Create a subnet

Next, create a subnet within the VPC. The subnet CIDR must fall within the VPC CIDR range. For example, if the VPC uses 172.31.0.0/16, you can create a subnet such as 172.31.128.0/20.
SUBNET_ID=$(aws ec2 create-subnet \
  --region $REGION \
  --vpc-id $VPC_ID \
  --cidr-block 172.31.128.0/20 \
  --query "Subnet.SubnetId" \
  --output text)

echo $SUBNET_ID
The subnet ID will be used later when launching EC2 instances.

Step 4: Create a security group

First, create a security group that will be attached to the EC2 instances.
SECURITY_GROUP=$(aws ec2 create-security-group \
  --region $REGION \
  --group-name omni-aws-sg \
  --description "Security group for Omni EC2 instances" \
  --query "GroupId" \
  --output text)

echo $SECURITY_GROUP
Next, update the security group to allow all internal traffic within the same group. This allows Kubernetes applications running on different machines to communicate with each other:
aws ec2 authorize-security-group-ingress \
  --region $REGION \
  --group-id $SECURITY_GROUP \
  --protocol all \
  --port -1 \
  --source-group $SECURITY_GROUP

Step 5: Register machines to your Omni account

Talos provides an official AWS AMI that you can use directly. However, if you need to customize the AMI, for example by adding custom labels or system extensions, you must create a custom Talos AMI and bake those customizations into the image. If you plan to create a custom Talos AMI, skip this step and continue to Step 6.
The official Talos AWS AMI includes the ecr-credential-provider system extension by default.
To register AWS EC2 instances to your Omni account using the official Talos AMI, you must add a join config to the EC2 instance user data and boot the instance with the Talos Omni AMI. This ensures the machine automatically joins your Omni account when it starts. To register your AWS EC2 instances:
  1. Define environment variables that specify the machines you want to register.
These are example values. Adjust them to match your machine specifications.
  1. Retrieve the official Talos AWS AMI:
AMI=$(curl -sL https://github.com/siderolabs/talos/releases/download/${TALOS_VERSION}/cloud-images.json \
  | jq -r '.[] | select(.region == "'"$AWS_REGION"'") | select(.arch == "'"$ARCH"'") | .id')

echo "Using AMI: $AMI"
  1. Generate the join configuration. This configuration allows the Talos machines to register with Omni when they boot:
USER_DATA=$(omnictl jointoken machine-config)
  1. Launch the EC2 instances:
aws ec2 run-instances \
  --region $AWS_REGION \
  --image-id $AMI \
  --instance-type $INSTANCE_TYPE \
  --count $CONTROL_PLANE_NO  \
  --iam-instance-profile Name=$AUTOSCALER_INSTANCE_PROFILE_NAME \
  --user-data "$USER_DATA" \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=role,Value=autoscaler-controlplane-machine}]'

Step 6: Create a custom Talos AWS AMI

If you need to customize the Talos AMI (for example by adding custom labels or system extensions), you must build a custom image with those extensions included. In this step, you will:
  1. Download the Talos AWS disk image from Omni
  2. Upload it to Amazon S3
  3. Import it into EC2 as a snapshot
  4. Register the snapshot as an AMI

6.1: Download the Talos AWS image

You can download the Talos AWS image from the CLI or the UI:
To download the Talos AWS image from the UI:
  1. Log into your Omni account.
  2. Go to the Overview page.
  3. Click Download Installation Media.
  4. Select AWS AMI (amd64) or AWS AMI (arm64) depending on your instance architecture.
  5. Add any required system extensions or labels.
  6. Click Download.
The downloaded Talos AWS image will contain a compressed archive similar to:
aws-amd64.tar.gz
Extract the archive:
tar -xzf aws-amd64.tar.gz
This command will produce a disk image similar to disk.raw:

6.2: Create S3 bucket

The disk image must be uploaded to an S3 bucket before it can be imported into EC2. Bucket names must be globally unique. The following command creates a bucket with a globally unique name using a timestamp.
BUCKET="omni-aws-$(date +%s)"

aws s3api create-bucket \
  --bucket $BUCKET \
  --region $REGION \
  --create-bucket-configuration LocationConstraint=$REGION

6.3: Upload the disk image to S3

Upload the extracted disk image to the S3 bucket:
aws s3 cp disk.raw s3://$BUCKET/omni-aws.raw

6.4: Import the disk image as an EC2 snapshot

Next, import the uploaded disk image into EC2 as a snapshot.
IMPORT_TASK=$(aws ec2 import-snapshot \
  --region $REGION \
  --description "Omni AWS" \
  --disk-container "Format=raw,UserBucket={S3Bucket=$BUCKET,S3Key=omni-aws.raw}" \
  --query "ImportTaskId" \
  --output text)

echo $IMPORT_TASK

6.5: Monitor the snapshot import

You can check the status of the import task using:
aws ec2 describe-import-snapshot-tasks \
  --region $REGION \
  --import-task-ids $IMPORT_TASK
Once the import completes, retrieve the snapshot ID:
SNAPSHOT=$(aws ec2 describe-import-snapshot-tasks \
  --region $REGION \
  --import-task-ids $IMPORT_TASK \
  --query "ImportSnapshotTasks[0].SnapshotTaskDetail.SnapshotId" \
  --output text)

echo $SNAPSHOT
You will use this snapshot in the next step to register the AMI.

Step 7: Register the AMI

Create an AMI from the snapshot.
AMI_ID=$(aws ec2 register-image \
  --region $REGION \
  --block-device-mappings "DeviceName=/dev/xvda,Ebs={DeleteOnTermination=true,SnapshotId=$SNAPSHOT,VolumeSize=14,VolumeType=gp2}" \
  --root-device-name /dev/xvda \
  --virtualization-type hvm \
  --architecture x86_64 \
  --ena-support \
  --name omni-aws-ami \
  --query "ImageId" \
  --output text)

echo $AMI_ID

Step 8: Launch EC2 instances

Finally, create EC2 instances using the AMI.
aws ec2 run-instances \
  --region $REGION \
  --image-id $AMI_ID \
  --count 1 \
  --instance-type t3.small \
  --subnet-id $SUBNET_ID \
  --security-group-ids $SECURITY_GROUP \
  --associate-public-ip-address \
  --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=omni-aws-ami}]"

Cleanup

If you no longer need the resources created in this guide, remove them to avoid unnecessary AWS charges.

Terminate the EC2 instance

First, terminate the EC2 instance created from the AMI. You can find the instance ID with:
INSTANCE_ID=$(aws ec2 describe-instances \
  --region $REGION \
  --filters "Name=image-id,Values=$AMI_ID" \
  --query "Reservations[*].Instances[*].InstanceId" \
  --output text)

echo $INSTANCE_ID
Terminate the instance:
aws ec2 terminate-instances \
  --region $REGION \
  --instance-ids $INSTANCE_ID

Deregister the AMI

Next, deregister the AMI created earlier:
aws ec2 deregister-image \
  --region $REGION \
  --image-id $AMI_ID

Delete the snapshot

After deregistering the AMI, delete the snapshot used to create it:
aws ec2 delete-snapshot \
  --region $REGION \
  --snapshot-id $SNAPSHOT

Remove the disk image from S3

Delete the uploaded disk image:
aws s3 rm s3://$BUCKET/omni-aws.raw

Delete the S3 bucket

After removing the object, delete the bucket:
aws s3 rb s3://$BUCKET

Delete the security group

Remove the security group created for the EC2 instances:
aws ec2 delete-security-group \
  --region $REGION \
  --group-id $SECURITY_GROUP

Delete the subnet

Finally, delete the subnet created earlier:
aws ec2 delete-subnet \
  --region $REGION \
  --subnet-id $SUBNET_ID