--- title: "Setting Up Your Cluster" description: "Import an AMI, create a VPC with a public subnet, and launch your first EC2 instance on Spinifex." category: "Getting Started" tags: - setup - vpc - ec2 - quickstart resources: - title: "Spinifex Repository" url: "https://github.com/mulgadc/spinifex" - title: "AWS EC2 CLI Reference" url: "https://docs.aws.amazon.com/cli/latest/reference/ec2/" --- # Setting Up Your Cluster > Import an AMI, create a VPC with a public subnet, and launch your first instance. ## Table of Contents - [1. Import an AMI](#1-import-an-ami) - [2. Create an SSH Key](#2-create-an-ssh-key) - [3. Create a VPC and Public Subnet](#3-create-a-vpc-and-public-subnet) - [4. Launch an Instance](#4-launch-an-instance) - [5. Connect via SSH](#5-connect-via-ssh) - [6. Managing Instances](#6-managing-instances) - [7. Launching the Web UI](#7-launching-the-web-ui) - [Troubleshooting](#troubleshooting) --- ## Overview This guide assumes Spinifex is already installed and running. If not, follow one of the installation guides first: - [Single-Node Install](/docs/install) - [Multi-Node Install](/docs/install-multi-node) - [Source Install](/docs/install-source) ## Instructions ## Prerequisites Ensure the AWS profile is set: ```bash export AWS_PROFILE=spinifex ``` ## 1. Import an AMI ### Option A: Import a bundled image List the bundled images and import one matching your architecture: ```bash spx admin images list ``` ``` NAME | DISTRO | VERSION | ARCH | BOOT debian-13-arm64 | debian | 13 | arm64 | uefi debian-13-x86_64 | debian | 13 | x86_64 | uefi ubuntu-26.04-arm64 | ubuntu | 26.04 | arm64 | uefi ubuntu-26.04-x86_64 | ubuntu | 26.04 | x86_64 | uefi ``` ```bash spx admin images import --name ubuntu-26.04-x86_64 ``` ### Option B: Import a local image file ```bash spx admin images import --file ~/images/ubuntu-26.04.img --distro ubuntu --version 26.04 --arch x86_64 --boot-mode uefi ``` Verify the import and note the AMI ID: ```bash AMI_ID=$(aws ec2 describe-images --query 'Images[0].ImageId' --output text) ``` ## 2. Create an SSH Key ### Option A: Import an existing key ```bash aws ec2 import-key-pair \ --key-name "spinifex-key" \ --public-key-material fileb://~/.ssh/id_rsa.pub ``` ### Option B: Create a new key pair ```bash aws ec2 create-key-pair --key-name spinifex-key \ | jq -r '.KeyMaterial | rtrimstr("\n")' > ~/.ssh/spinifex-key chmod 600 ~/.ssh/spinifex-key ssh-keygen -y -f ~/.ssh/spinifex-key > ~/.ssh/spinifex-key.pub ``` Verify: ```bash aws ec2 describe-key-pairs ``` ## 3. Create a VPC and Public Subnet ### Create a VPC ```bash VPC_ID=$(aws ec2 create-vpc --cidr-block 10.200.0.0/16 \ --query 'Vpc.VpcId' --output text) ``` ### Create an Internet Gateway An Internet Gateway enables instances in public subnets to reach the internet and be reachable from the LAN/WAN. ```bash IGW_ID=$(aws ec2 create-internet-gateway \ --query 'InternetGateway.InternetGatewayId' --output text) aws ec2 attach-internet-gateway \ --internet-gateway-id $IGW_ID \ --vpc-id $VPC_ID ``` ### Create a Subnet Create the subnet your instances will launch into. The routing and public-IP steps below are what make it a *public* subnet. ```bash SUBNET_ID=$(aws ec2 create-subnet \ --vpc-id $VPC_ID \ --cidr-block 10.200.1.0/24 \ --query 'Subnet.SubnetId' --output text) ``` ### Create a Route Table A subnet is only **public** if its route table has a default route to the Internet Gateway. Spinifex does **not** add this route automatically — a new VPC's route table only routes traffic within the VPC (matching AWS). Without a `0.0.0.0/0` route to the IGW, instances in the subnet cannot reach the internet (and inbound connections cannot complete) even with a public IP assigned. ```bash RT_ID=$(aws ec2 create-route-table \ --vpc-id $VPC_ID \ --query 'RouteTable.RouteTableId' --output text) # Default route to the internet via the IGW aws ec2 create-route \ --route-table-id $RT_ID \ --destination-cidr-block 0.0.0.0/0 \ --gateway-id $IGW_ID # Associate the route table with the subnet aws ec2 associate-route-table \ --route-table-id $RT_ID \ --subnet-id $SUBNET_ID ``` ### Enable Auto-Assign Public IP Give every instance launched into the subnet a routable public IP, making it directly reachable from your network. ```bash aws ec2 modify-subnet-attribute \ --subnet-id $SUBNET_ID \ --map-public-ip-on-launch ``` ### Allow SSH and ICMP Every VPC gets a default security group that **blocks inbound traffic from outside the group** (matching AWS). Instances launched without an explicit security group use this default, so you must authorize ingress before you can SSH or ping the instance. ```bash SG_ID=$(aws ec2 describe-security-groups \ --filters Name=vpc-id,Values=$VPC_ID \ --query 'SecurityGroups[0].GroupId' --output text) # Allow SSH from anywhere aws ec2 authorize-security-group-ingress \ --group-id $SG_ID \ --protocol tcp --port 22 --cidr 0.0.0.0/0 # Allow ICMP (ping) from anywhere aws ec2 authorize-security-group-ingress \ --group-id $SG_ID \ --protocol icmp --port -1 --cidr 0.0.0.0/0 ``` **Note:** `0.0.0.0/0` opens these ports to every source. For anything beyond a quick evaluation, scope the `--cidr` to a trusted range. Rule changes apply immediately — no instance restart needed. ### Verify ```bash aws ec2 describe-vpcs --vpc-ids $VPC_ID aws ec2 describe-subnets --subnet-ids $SUBNET_ID aws ec2 describe-route-tables --route-table-ids $RT_ID aws ec2 describe-security-groups --group-ids $SG_ID ``` ## 4. Launch an Instance Launch an instance in the public subnet on a `t3.micro` (2 vCPU / 1 GiB). > **Note:** On an **arm64** host, use `t4g.micro` instead of `t3.micro`. ```bash INSTANCE_ID=$(aws ec2 run-instances \ --image-id $AMI_ID \ --instance-type t3.micro \ --key-name spinifex-key \ --subnet-id $SUBNET_ID \ --count 1 \ --query 'Instances[0].InstanceId' --output text) ``` Wait for the instance to reach `running` state: ```bash aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --query 'Reservations[0].Instances[0].[State.Name, PrivateIpAddress, PublicIpAddress]' \ --output text ``` Expected output: ``` running 10.200.1.4 192.168.1.155 ``` The instance has both a private IP (VPC overlay) and a public IP (from your external pool, routable on your network). ## 5. Connect via SSH SSH directly to the instance's public IP: ```bash PUBLIC_IP=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \ --query 'Reservations[0].Instances[0].PublicIpAddress' --output text) ssh -i ~/.ssh/spinifex-key ec2-user@$PUBLIC_IP ``` > **Note:** cloud-init takes 30-60 seconds to configure the instance. If SSH is refused, wait and retry. Once connected, verify the instance has internet access: ```bash curl -s http://ifconfig.me ``` This should return the instance's public IP or the gateway's SNAT address. ## 6. Managing Instances ### Stop ```bash aws ec2 stop-instances --instance-ids $INSTANCE_ID ``` ### Start ```bash aws ec2 start-instances --instance-ids $INSTANCE_ID ``` ### Terminate ```bash aws ec2 terminate-instances --instance-ids $INSTANCE_ID ``` ### Console Output View the instance's serial console log (useful for debugging boot issues): ```bash aws ec2 get-console-output --instance-id $INSTANCE_ID \ --query 'Output' --output text ``` ### Multi-Node: Check Instance Placement On a multi-node cluster, instances are distributed across nodes: ```bash spx get vms ``` ## 7. Launching the Web UI Spinifex ships with a built-in web console — an alternative to the AWS CLI, SDKs, and Terraform, analogous to the AWS Management Console. Every action in the UI is a standard AWS SigV4 API call, so the same IAM policies and audit behaviour apply.