Complete setup instructions for deploying Troshka on Amazon Web Services (AWS).
- AWS account with IAM administrative access
- Troshka backend running (see Common Setup for backend/frontend/database installation)
- AWS CLI installed (optional, for verification)
- Selected AWS region (default: us-east-1)
Create a dedicated IAM user for Troshka operations:
- Sign in to the AWS Console
- Navigate to IAM → Users → Create User
- User name:
troshka - Access type: Programmatic access
- Generate access key pair and save credentials securely
Create a managed policy troshka-policy with the following permission categories:
- EC2: Instance lifecycle (run, start, stop, terminate, reboot, modify), instance type discovery, AMI lookup, VPC/subnet/AZ enumeration, key pair management, tagging
- EBS: Volume lifecycle (create, delete, attach, detach, modify for resize), volume inspection
- VPC: VPC/subnet/Internet Gateway/route table management, VPC attribute modification
- Security Groups: Create, delete, describe, authorize/revoke ingress rules
- Elastic IPs: Allocate, release, associate, disassociate addresses, assign/unassign private IPs
- FSx: File system lifecycle (create, delete, update, describe for FSx OpenZFS), volume management, tagging
- VPC Endpoints: Create, delete, describe, modify VPC endpoints (used for S3 Gateway Endpoint)
- IAM (one-time): CreateServiceLinkedRole for fsx.amazonaws.com
- S3: PutObject, GetObject, DeleteObject, HeadObject, ListBucket on
troshka-imagesbucket (used for library uploads, pattern storage, snapshot exports) - Route53: ChangeResourceRecordSets, GetChange, ListHostedZones (console DNS management)
- IAM (console): CreateRole, GetRole, PutRolePolicy, DeleteRolePolicy, CreateInstanceProfile, GetInstanceProfile, AddRoleToInstanceProfile, PassRole for
troshka-certbot-roleandtroshka-certbot-profile
See infra/iam-policy.json for the complete policy document.
- Navigate to IAM → Policies → Create Policy
- JSON tab → paste contents from
infra/iam-policy.json - Name:
troshka-policy - Create policy
- Navigate to IAM → Users → troshka → Add permissions → Attach policies directly
- Select
troshka-policyand attach
Create an AWS provider in Troshka:
- Navigate to Admin → Providers
- Click "Add Provider" button
- Fill in the form:
- Name:
aws-prod(or your preferred name) - Type: Select "EC2"
- Access Key ID: Your AWS access key (AKIA...)
- Secret Access Key: Your AWS secret key
- Region:
us-east-1(or your preferred region)
- Name:
- Click "Create"
- Click "Test" button to verify credentials
- Wait for success confirmation message
API equivalent
curl -X POST http://localhost:8200/api/v1/providers \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "aws-prod",
"type": "ec2",
"credentials": {
"access_key_id": "AKIA...",
"secret_access_key": "...",
"region": "us-east-1"
}
}'The response includes a provider_id — save this for subsequent operations.
Test Credentials:
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/test \
-H "Authorization: Bearer $TOKEN"Expected response:
{"status": "success", "message": "Provider credentials are valid"}Create a VPC with all required networking infrastructure.
- Navigate to Admin → Providers
- Find your provider in the list
- Click "Setup VPC" button
- Wait for confirmation message
API equivalent
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/create-vpc \
-H "Authorization: Bearer $TOKEN"- VPC: 10.100.0.0/16 CIDR block with DNS support and DNS hostnames enabled
- Subnets: One subnet per availability zone (10.100.1.0/24, 10.100.2.0/24, etc.) with auto-assign public IPs enabled
- Internet Gateway: Attached to VPC with default route (0.0.0.0/0)
- Route Table: Main route table with internet gateway route, associated with all subnets
- Security Group:
troshka-host-sgwith the following rules:- TCP 22 from 0.0.0.0/0 (SSH access)
- TCP 443 from 0.0.0.0/0 (Console VNC proxy — HTTPS TLS termination by troshka-vncd)
- TCP 31337 from backend IP/32 (Troshkad agent API — restricted to backend server)
- UDP 4789 from same security group (VXLAN mesh for multi-host peering)
- S3 Gateway Endpoint: Routes S3 traffic through AWS private network (free, no NAT gateway fees)
All resources are tagged with ManagedBy: troshka for identification.
The Providers page shows VPC details once setup is complete.
API equivalent
List discovered VPCs:
curl http://localhost:8200/api/v1/providers/{provider_id}/discover-vpcs \
-H "Authorization: Bearer $TOKEN"Response includes VPC ID, CIDR block, subnet IDs, and availability zones.
Create an S3 bucket for library items, pattern storage, and snapshot exports.
- Navigate to Admin → Providers
- Find your provider in the list
- Click "Setup S3" button
- Wait for confirmation message
This creates a bucket named troshka-images in the provider's region. The bucket is required for:
- Library item uploads (ISOs, disk images)
- Pattern storage (captured VM state)
- Snapshot exports (backing up project state)
API equivalent
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/create-bucket \
-H "Authorization: Bearer $TOKEN"Choose how to obtain the RHEL host image.
Discover and select a RHEL AMI from the marketplace:
- Navigate to Admin → Providers
- Find your provider in the list
- Click "Discover Images" button
- Wait for the list of available RHEL AMIs to load
- Click "Set as Default" on a RHEL 9 AMI
API equivalent
Discover available RHEL AMIs in the region:
curl http://localhost:8200/api/v1/providers/{provider_id}/discover-images \
-H "Authorization: Bearer $TOKEN"Response includes AMI IDs and descriptions. Select a RHEL 9 AMI and set it as the default:
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/set-image \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"image_id": "ami-..."}'Build a custom RHEL AMI with all required packages pre-installed. This eliminates:
- RHSM registration at boot time
- Package installation delays during provisioning
- PAYG image premium costs
Prerequisites:
- Obtain a Red Hat offline token from https://access.redhat.com/management/api
Build Process:
- Navigate to Settings → Red Hat Integration
- Paste offline token into the "Red Hat Offline Token" field
- Click "Save"
- Navigate to Admin → Providers
- Find your provider in the list
- Click "Build Host Image" button
- Wait approximately 15 minutes for build completion
- Image is automatically set as
default_imagewhen ready
The build progress is shown on the Providers page with a percentage indicator.
API equivalent
# Start build
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/build-image \
-H "Authorization: Bearer $TOKEN"
# Check status
curl http://localhost:8200/api/v1/providers/{provider_id}/image-build-status \
-H "Authorization: Bearer $TOKEN"Status response includes build state, progress percentage, and image ID when complete. The backend polls Red Hat Image Builder API every 30 seconds and auto-refreshes access tokens.
Configure automated DNS management for VNC console access.
- Navigate to Admin → Providers
- Find your provider in the list
- Click "Setup Console" button
- Enter your console domain (e.g.,
console.example.com) in the input field - Click "Submit"
- Wait for confirmation message
- Note the nameservers displayed in the collapsible section
This creates:
- Route53 hosted zone for the console domain
- IAM role
troshka-certbot-rolewith Route53 DNS challenge permissions - IAM instance profile
troshka-certbot-profile(attached to hosts for certbot)
API equivalent
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/setup-console \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"base_domain": "console.example.com"}'Response includes console_nameservers (4 AWS nameservers).
Add NS records in your parent domain zone pointing to the nameservers returned above. Example for console.example.com:
console.example.com. IN NS ns-123.awsdns-12.com.
console.example.com. IN NS ns-456.awsdns-23.net.
console.example.com. IN NS ns-789.awsdns-34.org.
console.example.com. IN NS ns-012.awsdns-45.co.uk.
- Each host gets an A record:
{instance_id}.{base_domain}→ host public IP - Browser connects via WebSocket:
wss://{instance_id}.{base_domain}/ws/{jwt} - Backend issues short-lived JWT (5 min, single-use) signed with host agent token
troshka-vncddaemon on host validates JWT, resolves VNC port, proxies frames- TLS via Let's Encrypt (certbot DNS-01 challenge using Route53 instance profile)
- Auto-renewal via cron:
certbot renew --quiet
Provision a host for running nested VMs.
- Navigate to Admin → Providers
- Find your provider in the list
- Scroll down to the "Hosts" section
- Click "Add Host" button
- Fill in the form:
- Instance Type: Select from dropdown (e.g.,
m5.metalfor production,m8i.xlargefor dev) - Storage Size (GB): Enter desired size (minimum 100, recommended 500 for production)
- Instance Type: Select from dropdown (e.g.,
- Click "Create"
- Wait 3-5 minutes for provisioning to complete
- Host status will change from "provisioning" to "connected" when ready
API equivalent
curl -X POST http://localhost:8200/api/v1/hosts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"provider_id": "...",
"instance_type": "m5.metal",
"storage_size_gb": 500
}'Provisioning takes 3-5 minutes. The API returns immediately with status: "provisioning". Check host status:
curl http://localhost:8200/api/v1/hosts \
-H "Authorization: Bearer $TOKEN"When status: "connected", the host is ready for deployments.
| Instance Type | vCPUs | RAM | Use Case | Notes |
|---|---|---|---|---|
| m5.metal | 96 | 384 GB | Production | Full bare-metal, best nested virt performance |
| c5.metal | 96 | 192 GB | Production | Compute-heavy labs, lower cost than m5.metal |
| m8i.xlarge | 4 | 16 GB | Dev/Testing | Nested virt enabled, cost-effective for testing |
| m8i.2xlarge | 8 | 32 GB | Dev/Testing | More capacity than xlarge, still affordable |
- Development: 100 GB minimum (sufficient for testing workflows)
- Production: 500 GB or more (depends on VM disk sizes and pattern caching)
- Storage is EBS gp3 (provisioned automatically, online resizable via admin UI)
Create an FSx OpenZFS storage pool for live migration and pattern sharing across hosts.
- Navigate to Admin → Storage Pools
- Click "Create Storage Pool" button
- Fill in the form:
- Name:
shared-pool(or your preferred name) - Mode: Select "FSx OpenZFS"
- Provider: Select your provider from dropdown
- Availability Zone: Select an AZ (e.g.,
us-east-1a)
- Name:
- Click "Create"
- Wait approximately 5 minutes for FSx file system creation
Important: All hosts in the pool must be in the same AZ. FSx OpenZFS is single-AZ.
API equivalent
curl -X POST http://localhost:8200/api/v1/storage-pools \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "shared-pool",
"mode": "shared-fsx",
"provider_id": "...",
"availability_zone": "us-east-1a"
}'- FSx OpenZFS file system (~5 min creation time)
- NFS security group rules (TCP 2049)
- Libvirt TLS security group rules (TCP 16514 for control, TCP 49152-49215 for live migration data)
- Mount options:
nconnect=16,cache=none,io=native, LZ4 compression enabled - Pricing: Per-second billing, no minimum commitment (~$53/month for 128 GB storage / 160 MBps throughput)
- Auto-extend: Configurable threshold (default 80%) and increment (default 128 GB)
- Live migration between hosts in the pool
- Shared pattern cache (one download serves all hosts)
- Automatic failover (move projects off failed host to healthy hosts)
Run through this checklist to confirm the setup is working:
- Navigate to Admin → Providers
- Find your provider in the list
- Click "Test" button
- Verify success message appears
API equivalent
curl -X POST http://localhost:8200/api/v1/providers/{provider_id}/test \
-H "Authorization: Bearer $TOKEN"Expected: {"status": "success"}
Verify VPC details are shown on the Providers page with ManagedBy: troshka tag.
API equivalent
curl http://localhost:8200/api/v1/providers/{provider_id}/discover-vpcs \
-H "Authorization: Bearer $TOKEN"Expected: Response includes VPC with ManagedBy: troshka tag
- Navigate to Admin → Providers
- Scroll down to the "Hosts" section
- Verify host shows
status: "connected"with instance ID, public IP, and console domain
API equivalent
curl http://localhost:8200/api/v1/hosts \
-H "Authorization: Bearer $TOKEN"Expected: Host shows status: "connected", instance ID, public IP, console domain
Check that the host's agent version matches the expected version shown on the Providers page. If mismatched, run:
./scripts/update-agent.shAPI equivalent
curl http://localhost:8200/api/v1/hosts/expected-agent-version \
-H "Authorization: Bearer $TOKEN"Compare response with host's agent_version field.
After deploying a VM with a project:
- Navigate to the project's Hosts page
- Click the console icon for a running VM
- Browser should open
https://{instance_id}.{base_domain}with noVNC console - Verify keyboard input and mouse work correctly
Create a minimal project and deploy:
- Navigate to Projects → Create Project
- Add a VM node to the canvas
- Deploy the project
- Verify VM starts successfully (check project Hosts page for VM status)
- Open console and verify VM is running
- Check AWS Console EC2 instances for the host
- Verify instance launched successfully
- Check backend logs for provisioning errors
- Verify security group rules allow port 31337 from backend IP
- Verify DNS delegation (dig
{instance_id}.{base_domain}should return host IP) - Check certbot status on host via
scripts/host-ssh.sh -- 'sudo systemctl status certbot.timer' - Verify troshka-vncd is running:
scripts/host-ssh.sh -- 'sudo systemctl status troshka-vncd' - Check browser console for WebSocket errors
- Verify IAM policy includes FSx permissions
- Check one-time service-linked role exists:
aws iam get-role --role-name AWSServiceRoleForFSx - If missing, create it:
aws iam create-service-linked-role --aws-service-name fsx.amazonaws.com - Verify AZ supports FSx OpenZFS: check AWS FSx documentation for regional availability
- Verify S3 bucket exists and credentials are correct
- Check host has internet access (test with
scripts/host-ssh.sh -- 'curl -I https://s3.amazonaws.com') - Verify S3 Gateway Endpoint is attached to VPC route table
- Check backend logs for S3 API errors
- Common Setup — Backend/frontend/database installation (if not done)
- API Guide — Workflow walkthroughs and full endpoint reference
- Architecture Guide — System design, provider abstraction, agent internals