Right, so you’ve built this beautiful, perfectly configured EC2 instance. It’s a work of art. The packages are all the right versions, the config files are pristine, and it only took you three days of your life you’ll never get back. Now, the smart thing to do is to turn this snowflake into a reusable AMI. But what if the entire AWS US-East-1 region decides to take an unscheduled nap? Your brilliant AMI is stuck there, napping along with it. This is why we copy AMIs across regions. It’s not just a good idea; it’s the digital equivalent of not keeping all your eggs, your backups, and your grandmother’s china in one very flammable basket.

The process itself is straightforward, but the devil, as always, is in the details. AWS gives you two main ways to do this: the cheerful, point-and-click console, and the powerful, scriptable CLI. We’ll use the CLI because you’re not here to click buttons all day.

The Basic Copy Operation

At its core, you use the copy-image command. You tell it the source region, the source AMI ID, and what to name the copy in your destination region. Here’s the incantation:

aws ec2 copy-image \
  --region us-west-2 \          # The destination region
  --source-region us-east-1 \   # The region where your masterpiece currently lives
  --source-image-id ami-0c55b159cbfafe1f0 \ # The unique ID of your source AMI
  --name "My-Server-DR-Backup"  # A name for the new AMI in the destination region

If the gods of IAM permissions are smiling, you’ll get a JSON response with the new AMI ID in the destination region. Note that this new ID is completely different from the source one. AWS generates new IDs per region, because of course it does.

Why it works this way: When you initiate a copy, AWS isn’t just zipping up a file and FTPing it over. The source AMI is backed by snapshots of EBS volumes (or an instance store, but we don’t talk about instance stores for DR). The copy-image command triggers the creation of a complete, independent copy of those underlying snapshots in the destination region. This is crucial—your DR copy has no dependency on the source region whatsoever.

The Snapshot Snag: Copying Encrypted AMIs

Here’s where you might faceplant. The above command works flawlessly if your source AMI uses unencrypted EBS volumes. The moment you encrypted that root volume for a well-deserved security pat on the back, you introduced a permissions hurdle.

You see, by default, the EBS snapshots that back your encrypted AMI are encrypted with a specific KMS key in your source region. That key doesn’t exist in us-west-2. The copy-image command will promptly tell you it doesn’t have the permissions to decrypt the source snapshot. Thanks, AWS.

To solve this, you must explicitly grant the copy operation permission to use the source KMS key. This is done by adding a grant to the key itself. You need the key ID from the source region.

# First, in the SOURCE region (us-east-1), grant the cross-account role (it's always the same) permission to use the key for decryption.
# Replace 'kms-key-id' with your actual key ID from us-east-1.
aws kms create-grant \
    --region us-east-1 \
    --key-id alias/my-ami-key \
    --grantee-principal arn:aws:iam::783225319266:role/EC2CrossAccountImageCopy \ # This is AWS's fixed account ID for copying
    --operations Decrypt

Now, you can run your copy-image command again. It will succeed, and the new AMI in the destination region will be encrypted. By default, it will use the default EBS encryption key of the destination account and region. If you want it encrypted with a specific customer-managed key in the destination region, you have to specify that too. The full, no-holds-barred command looks like this:

aws ec2 copy-image \
  --region us-west-2 \
  --source-region us-east-1 \
  --source-image-id ami-0c55b159cbfafe1f0 \
  --name "My-Server-Encrypted-DR-Backup" \
  --kms-key-id alias/my-dr-key-in-oregon # The KMS key alias in the DESTINATION region

The Waiting Game and How to Win It

Initiate the copy and… now you wait. This isn’t an instantaneous metadata change. AWS is physically copying the entire contents of your snapshot across continents. A multi-gigabyte image can take anywhere from minutes to hours. Do not, I repeat, do not write automation that assumes the AMI is available immediately after the copy-image call returns.

You need to poll for its state. Use a loop with describe-images until the state changes from pending to available.

# Poll the destination region until the new AMI is available
NEW_AMI_ID="ami-0a1b2c3d4e5f60079" # The ID you got from the copy-image response

while true; do
    STATE=$(aws ec2 describe-images --region us-west-2 --image-ids $NEW_AMI_ID --query 'Images[0].State' --output text)
    echo "AMI status: $STATE"
    if [ "$STATE" = "available" ]; then
        echo "AMI is ready for action!"
        break
    fi
    sleep 60
done

Best Practices and Gotchas

  1. Tag Everything: When you copy an AMI, most of its tags do not come along for the ride. You must manually apply tags like Name, Environment, Application to the new AMI and its associated snapshots in the destination region. This is a fantastic place for automation to forget something and create a mess.
  2. Permissions are a Two-Region Affair: Your IAM user/role needs ec2:CopyImage permission in the destination region and ec2:DescribeImages in the source region. Don’t lock yourself out.
  3. Clean Up: DR copies are vital, but they cost money. That snapshot storage in a second region isn’t free. Implement a lifecycle policy to delete old DR AMIs and their snapshots after a certain period. Your finance department will thank you.
  4. Test, You Maniac: The single biggest pitfall is never testing the copy. Once your AMI is available in the DR region, launch a trivial instance from it (a t3.nano will do) to verify it boots and is configured correctly. There is no cosmic horror greater than finding out your DR image is corrupt during an actual disaster.