Skip to content

Amazon Web Services (AWS)

To run an ARROW appliance in AWS you turn its disk image into an AMI, then launch EC2 instances from that AMI. ARROW builds a stream-optimized VMDK for this. The one thing worth knowing up front is that the import goes through import-snapshot rather than import-image: ARROW ships a custom Linux kernel, and import-image runs kernel checks that reject it, whereas import-snapshot imports the raw disk and skips those checks entirely.

Your AWS build downloads as a ZIP containing the .vmdk disk image, a plain-text instructions file, and an automated import script (bash for macOS and Linux, PowerShell for Windows). The script is the path of least resistance; the manual steps below are here for when you want to understand or customize what it does.


You need the AWS CLI, configured with aws configure.

The account you use needs enough permission to move the image through S3 and turn it into an AMI:

  • s3:PutObject, s3:GetObject, s3:ListBucket
  • ec2:ImportSnapshot, ec2:DescribeImportSnapshotTasks
  • ec2:RegisterImage, ec2:RunInstances, ec2:Describe*
  • iam:CreateRole, iam:PutRolePolicy for the one-time vmimport role setup

Extract the ZIP and make the script executable:

Terminal window
unzip kali-arrow-client-aws-*.zip
cd kali-arrow-client-aws-*/
chmod +x import-to-aws.sh

Run it with no arguments to do the full import:

Terminal window
./import-to-aws.sh

It uploads the VMDK to your S3 bucket (skipping the upload if the file is already there), creates the vmimport service role if you do not have one, imports the VMDK as an EBS snapshot with a live progress bar, and registers a UEFI, ENA-enabled, gp3-backed AMI from it. It then offers to launch an instance, walking you through VPC, subnet, security group, key pair, and instance type, and finally offers to remove the VMDK from S3.

The snapshot import is the slow part, typically 15 to 60 minutes depending on image size, so expect to wait.

If you already have an imported AMI and just want to launch from it, use launch mode. With no argument it lists your ARROW AMIs to choose from; pass an AMI ID to go straight to it:

Terminal window
./import-to-aws.sh --launch
./import-to-aws.sh --launch ami-0123456789abcdef0

When you are done with an image, cleanup mode finds and offers to delete your ARROW AMIs and their EBS snapshots, plus the vmimport role and its policies:

Terminal window
./import-to-aws.sh --cleanup

The PowerShell script behaves identically. Extract the ZIP and run it:

Terminal window
Expand-Archive kali-arrow-client-aws-*.zip -DestinationPath .\aws-import
cd aws-import
.\Import-To-AWS.ps1

The same modes apply: default import, -Launch (optionally with -AmiId "ami-..."), and -Cleanup.

Terminal window
.\Import-To-AWS.ps1
.\Import-To-AWS.ps1 -Launch
.\Import-To-AWS.ps1 -Launch -AmiId "ami-0123456789abcdef0"
.\Import-To-AWS.ps1 -Cleanup

If you would rather run the steps yourself, here is exactly what the script automates.

Terminal window
aws s3 cp kali-arrow-client-aws.vmdk s3://<your-bucket>/vm-imports/

Step 2: Create the vmimport IAM role (one time)

Section titled “Step 2: Create the vmimport IAM role (one time)”

AWS imports snapshots through a service role named vmimport. You create it once per account. Start with the trust policy in trust-policy.json:

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "vmie.amazonaws.com"},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {"sts:Externalid": "vmimport"}
}
}]
}

Create the role:

Terminal window
aws iam create-role --role-name vmimport \
--assume-role-policy-document file://trust-policy.json

Then grant it access to your bucket and the EC2 import actions in role-policy.json (replace <your-bucket>):

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:GetObject",
"s3:ListBucket",
"s3:PutObject",
"s3:GetBucketAcl"
],
"Resource": [
"arn:aws:s3:::<your-bucket>",
"arn:aws:s3:::<your-bucket>/*"
]
}, {
"Effect": "Allow",
"Action": [
"ec2:ModifySnapshotAttribute",
"ec2:CopySnapshot",
"ec2:RegisterImage",
"ec2:Describe*",
"ec2:ImportSnapshot"
],
"Resource": "*"
}]
}

Attach it:

Terminal window
aws iam put-role-policy --role-name vmimport \
--policy-name vmimport \
--policy-document file://role-policy.json
Terminal window
aws ec2 import-snapshot \
--description "ARROW VM Image" \
--disk-container '{
"Description": "ARROW VM Image",
"Format": "vmdk",
"UserBucket": {
"S3Bucket": "<your-bucket>",
"S3Key": "vm-imports/kali-arrow-client-aws.vmdk"
}
}'

Poll the task until it completes:

Terminal window
aws ec2 describe-import-snapshot-tasks \
--import-task-ids import-snap-xxxxxxxxx

Take the SnapshotId from the completed import and register an AMI from it. The --boot-mode uefi and --ena-support flags are not optional here; ARROW images need both to boot and network correctly.

Terminal window
aws ec2 register-image \
--name "kali-arrow-client" \
--description "ARROW VM Image" \
--architecture x86_64 \
--root-device-name /dev/sda1 \
--boot-mode uefi \
--ena-support \
--block-device-mappings '[{
"DeviceName": "/dev/sda1",
"Ebs": {
"SnapshotId": "snap-xxxxxxxxx",
"VolumeType": "gp3",
"DeleteOnTermination": true
}
}]' \
--virtualization-type hvm
Terminal window
aws ec2 run-instances \
--image-id ami-xxxxxxxxx \
--instance-type t3.xlarge \
--key-name <key-pair> \
--security-group-ids <sg-id> \
--subnet-id <subnet-id> \
--count 1

t3.large (2 vCPU, 8 GB) is the practical minimum. t3.xlarge (4 vCPU, 16 GB) is the sweet spot for most work and what we recommend. Step up to m5.2xlarge (8 vCPU, 32 GB) when you need the headroom.


import-image fails with a kernel error. That is expected, and the reason ARROW uses import-snapshot, which bypasses the kernel check. Use the provided script or the manual snapshot import.

The snapshot import sits at 0%. Give it 5 to 10 minutes. AWS often reports no progress before it starts moving.

The AMI shows “pending”. Registration takes a few minutes. Wait on it with aws ec2 wait image-available --image-ids ami-xxx.

The instance will not boot. Confirm the AMI was registered with --boot-mode uefi and --ena-support. Missing either is the usual cause.

You cannot SSH in. Open inbound port 22 in the instance’s security group.

The desktop does not load. ARROW VMs include noVNC; connect on port 6901 if it is configured.

The password does not work. Credentials are generated at build time. Retrieve them from the ARROW Portal on your device’s details page.