Create an EC2 AMI from Official OPNsense 25.1 Nano (raw) Image

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


  1. 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 bzip2 in 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"

    1. Create the vmimport IAM 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
    

    1. 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"
            }
        }
    }
    

    1. 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": []
            }
        ]
    }
    

    1. 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

    Leave a Comment

    Your email address will not be published. Required fields are marked *

    Scroll to Top