--- title: "Migrate an AWS EC2 instance to E2E" description: "Export an AWS EC2 instance as an image, bring it through E2E Object Storage, and import it as a custom node image." content_type: "how-to" product: "node" platform: "MyAccount" url: "/myaccount/node/how-to/migrate-an-aws-ec2-instance-to-e2e/" topic: ["images-and-snapshots"] relationships: {"requires":["/myaccount/node/how-to/install-the-opennebula-context-package/","/myaccount/object-storage/how-to/create-a-bucket/","/myaccount/object-storage/how-to/generate-an-access-key/"]} --- # Migrate an AWS EC2 instance to E2E Moving an existing AWS EC2 workload to E2E means exporting it from AWS as an image, passing it through an E2E Object Storage bucket, and importing it as a custom node image. The steps take you from the EC2 instance to a running E2E node. ## Prepare the EC2 instance Install and enable the OpenNebula context package on the EC2 instance before you export it; an image exported without it boots on E2E but has no network. See [Install the OpenNebula context package](/myaccount/node/how-to/install-the-opennebula-context-package/) for the commands for your distribution. ## Export the instance from AWS Do these steps from any machine where you can install the AWS CLI, with an AWS account that can create IAM roles and export images. 1. In the AWS Console, power off the instance, then open **EC2 → Actions → Image → Create Image** to create an AMI of it. Note the AMI ID, which starts with `ami-`. 2. Install the AWS CLI if you do not have it. On Linux: ```bash frame="none" curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install ``` 3. Configure it with your AWS access key, secret key, and the region the instance is in: ```bash frame="none" aws configure ``` The command asks for four values in turn: **AWS Access Key ID**, **AWS Secret Access Key**, **Default region name** (for example `ap-south-1`), and **Default output format** (press Enter to keep the default). 4. Create an S3 bucket in the same AWS region to hold the exported image. Replace `` with a name of your own in this step and in every later command on this page. 5. AWS writes the export through a role named `vmimport`, which you create. Save this trust policy as `trust-policy.json`: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "vmie.amazonaws.com" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "vmimport" } } } ] } ``` Then create the role, giving the full path to the file after `file://`: ```bash frame="none" aws iam create-role --role-name vmimport \ --assume-role-policy-document "file://trust-policy.json" ``` 6. Give the role access to your bucket. Save this policy as `role-policy.json`, with your bucket name in both `Resource` lines: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:GetBucketLocation", "s3:GetObject", "s3:ListBucket", "s3:PutObject", "s3:GetBucketAcl" ], "Resource": ["arn:aws:s3:::", "arn:aws:s3:::/*"] }, { "Effect": "Allow", "Action": [ "ec2:ModifySnapshotAttribute", "ec2:CopySnapshot", "ec2:RegisterImage", "ec2:Describe*" ], "Resource": "*" } ] } ``` Attach it to the role: ```bash frame="none" aws iam put-role-policy --role-name vmimport --policy-name vmimport \ --policy-document "file://role-policy.json" ``` 7. Export the AMI in RAW format: ```bash frame="none" aws ec2 export-image --image-id --disk-image-format RAW \ --s3-export-location S3Bucket=,S3Prefix=exports/ ``` The command prints an export task ID that starts with `export-ami-`. 8. Watch the export until it finishes. Replace `` with the ID from the previous step: ```bash frame="none" aws ec2 describe-export-image-tasks --export-image-task-ids ``` The `Status` field reads `active` while the export runs and `completed` when the RAW file is in your bucket under `exports/`. 9. Download the RAW file from the S3 bucket to your machine: ```bash frame="none" aws s3 cp s3:///exports/.raw . ``` ## Import the exported image into E2E 1. [Create a bucket](/myaccount/object-storage/how-to/create-a-bucket/) in E2E Object Storage, and [generate an access key](/myaccount/object-storage/how-to/generate-an-access-key/) with Bucket Admin permission on it. 2. Upload the RAW file to that bucket; see [Connect with the mc client](/myaccount/object-storage/how-to/connect-with-the-mc-client/) for the command. 3. On the **Saved Images** page, click **Import Custom Images** and import the uploaded file. In Delhi, the **Private EOS Bucket** tab reads it with your access key; with **Public URL**, turn on **Download** for the bucket first. See [Import a custom image](/myaccount/images/how-to/import-a-custom-image/) for each field and the format and size limits the import checks. 4. Once the image reaches **Ready**, launch a node from it and confirm your application runs. Once the node is running, connect to it and confirm your application works the same as it did on EC2, then decommission the original instance once you are satisfied it is a clean move. ## If something goes wrong | Symptom | What to do | | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | The imported image boots but has no network | The OpenNebula context package was not installed before the AMI was created. Install it on a running E2E node and save a new image, or redo the export with the context package installed first. | | `aws ec2 export-image` fails with a permission error | The `vmimport` role is missing, or its inline policy does not cover the export bucket. Re-create the role and policy in AWS. | | The `mc` upload to E2E fails | Confirm the access key has Bucket Admin permission, and that the bucket's Public Access Config allows upload and download. | | The image stays **Creating** and never reaches **Ready** | The object's URL is not reachable: the bucket is not public, or the link expired. Make it public again and retry the import. | For anything else that goes wrong with the import itself, see [Troubleshooting image import and export](/myaccount/node/troubleshooting/image-import-export/). Keep the imported image after the move; you can build more nodes from it.