This post shows how to convert the official OPNsense 25.1 Nano disk image (.img.bz2) into an EC2 AMI using VM Import/Export:
- Upload the RAW disk image to S3
- Import it as an EBS snapshot (
import-snapshot) - Register the snapshot as an AMI (
register-image)
CLI environment used in this post: AWS CloudShell
- Upload the OPNsense image to S3
CloudShell provides 1 GB of persistent storage in $HOME per region. The downloaded .bz2 file may be under 1 GB, but the decompressed .img is several GB, so don’t extract the image into $HOME.
Instead, install bzip2 and stream-decompress directly into S3 (no large local .img file):
- Install
bzip2in CloudShell
sudo yum install -y bzip2
- Stream decompress → upload to S3
wget -qO- "https://pkg.opnsense.org/releases/25.1/OPNsense-25.1-nano-amd64.img.bz2" \
| bzip2 -dc \
| aws s3 cp - "s3://my2-opnsense-imgs/OPNsense-25.1-nano-amd64.img"
- Create the
vmimportIAM Role (only once)
This is a service role that VM Import/Export assumes to work in your account.
You do NOT attach this role to your IAM user. Your CloudShell identity only needs permission to call the import/register APIs.
trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "vmie.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
role-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::my2-opnsense-imgs",
"arn:aws:s3:::my2-opnsense-imgs/*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:ModifySnapshotAttribute",
"ec2:CopySnapshot",
"ec2:RegisterImage",
"ec2:Describe*"
],
"Resource": "*"
}
]
}
aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json
aws iam put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json
- Import the Snapshot
aws ec2 import-snapshot \
--description "OPNSense 25.1 Nano" \
--disk-container "{
\"Format\": \"RAW\",
\"UserBucket\": {
\"S3Bucket\": \"my2-opnsense-imgs\",
\"S3Key\": \"OPNsense-25.1-nano-amd64.img\"
}
}"
{
"Description": "OPNSense 25.1 Nano",
"ImportTaskId": "import-snap-47c1424cdee9fe71t",
"SnapshotTaskDetail": {
"DiskImageSize": 0.0,
"Format": "RAW",
"Progress": "0",
"Status": "active",
"StatusMessage": "pending",
"UserBucket": {
"S3Bucket": "my2-opnsense-imgs",
"S3Key": "OPNsense-25.1-nano-amd64.img"
}
}
}
- Monitor Import Progress
watch -n10 -d aws ec2 describe-import-snapshot-tasks --import-task-ids import-snap-47c1424cdee9fe71t
{
"ImportSnapshotTasks": [
{
"Description": "OPNSense 25.1 Nano",
"ImportTaskId": "import-snap-47c1424cdee9fe71t",
"SnapshotTaskDetail": {
"DiskImageSize": 3221225472.0,
"Format": "RAW",
"SnapshotId": "snap-0a0edc8d038426df4",
"Status": "completed",
"UserBucket": {
"S3Bucket": "my2-opnsense-imgs",
"S3Key": "OPNsense-25.1-nano-amd64.img"
}
},
"Tags": []
}
]
}
- Register the Snapshot as an AMI
aws ec2 register-image \
--name "OPNSense 25.1 Nano" \
--root-device-name "/dev/sda1" \
--virtualization-type "hvm" \
--block-device-mappings '{"DeviceName":"/dev/sda1","Ebs":{"SnapshotId":"snap-0a0edc8d038426df4","VolumeSize":10,"VolumeType":"gp3"}}' \
--boot-mode "legacy-bios" \
--architecture "x86_64"
Did this guide save you time?
Support this site