Overview
AWS offers multiple ways to run Polpo. Pick based on your needs:
| Service | Best for | Persistent storage | Complexity |
|---|
| App Runner | Simplest AWS option | EFS mount | Low |
| ECS Fargate | Production, no servers | EFS mount | Medium |
| EC2 | Full control, cheapest | Local disk or EBS | Low |
Option A: App Runner
App Runner is AWS’s simplest container service — point it at an image and it runs.
-
Create an ECR repository and push the image
aws ecr create-repository --repository-name polpo
# Login, tag, push
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com
docker pull ghcr.io/lumea-labs/polpo:latest
docker tag ghcr.io/lumea-labs/polpo:latest \
YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/polpo:latest
docker push YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/polpo:latest
-
Create the App Runner service
In the AWS Console:
- Source: ECR image
- Port: 3000
- CPU: 1 vCPU, Memory: 2 GB
- Environment variables:
ANTHROPIC_API_KEY=sk-ant-...
- Min/Max instances: 1 / 1
Or via CLI:
aws apprunner create-service \
--service-name polpo \
--source-configuration '{
"ImageRepository": {
"ImageIdentifier": "YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/polpo:latest",
"ImageRepositoryType": "ECR",
"ImageConfiguration": {
"Port": "3000",
"RuntimeEnvironmentVariables": {
"ANTHROPIC_API_KEY": "sk-ant-..."
}
}
},
"AutoDeploymentsEnabled": false
}' \
--instance-configuration '{
"Cpu": "1024",
"Memory": "2048"
}'
App Runner doesn’t natively support persistent volumes. For persistent state, use the EFS integration (see ECS section) or accept that state resets on deploy. For production, ECS Fargate or EC2 is recommended.
Option B: ECS Fargate + EFS
Best for production — serverless containers with persistent storage.
-
Create an EFS file system
aws efs create-file-system \
--creation-token polpo-data \
--performance-mode generalPurpose \
--tags Key=Name,Value=polpo-data
Note the FileSystemId. Create a mount target in your VPC subnet:
aws efs create-mount-target \
--file-system-id fs-XXXXX \
--subnet-id subnet-XXXXX \
--security-groups sg-XXXXX
-
Create a task definition
Save as
polpo-task.json:
{
"family": "polpo",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "1024",
"memory": "2048",
"executionRoleArn": "arn:aws:iam::YOUR_ACCOUNT:role/ecsTaskExecutionRole",
"containerDefinitions": [{
"name": "polpo",
"image": "YOUR_ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/polpo:latest",
"portMappings": [{ "containerPort": 3000 }],
"environment": [
{ "name": "ANTHROPIC_API_KEY", "value": "sk-ant-..." }
],
"mountPoints": [{
"sourceVolume": "workspace",
"containerPath": "/workspace"
}],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/polpo",
"awslogs-region": "us-east-1",
"awslogs-stream-prefix": "ecs"
}
}
}],
"volumes": [{
"name": "workspace",
"efsVolumeConfiguration": {
"fileSystemId": "fs-XXXXX"
}
}]
}
aws ecs register-task-definition --cli-input-json file://polpo-task.json
-
Create the service
aws ecs create-service \
--cluster default \
--service-name polpo \
--task-definition polpo \
--desired-count 1 \
--launch-type FARGATE \
--network-configuration '{
"awsvpcConfiguration": {
"subnets": ["subnet-XXXXX"],
"securityGroups": ["sg-XXXXX"],
"assignPublicIp": "ENABLED"
}
}'
Option C: EC2
The simplest and cheapest option — a regular Linux server.
-
Launch an instance
- AMI: Ubuntu 24.04 LTS
- Type: t3.small (2 vCPU, 2 GB) or t3.medium (2 vCPU, 4 GB)
- Storage: 20 GB gp3
- Security group: Allow TCP 22, 80, 443
-
SSH in and deploy
ssh ubuntu@YOUR_INSTANCE_IP
# Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker ubuntu
newgrp docker
# Deploy
mkdir -p /opt/polpo/workspace && cd /opt/polpo
cat > docker-compose.yml << 'EOF'
services:
polpo:
image: ghcr.io/lumea-labs/polpo:latest
ports:
- "3000:3000"
volumes:
- ./workspace:/workspace
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
restart: unless-stopped
EOF
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env
docker compose up -d
-
Add SSL with Caddy
sudo apt install caddy
echo 'polpo.yourdomain.com { reverse_proxy localhost:3000 }' | sudo tee /etc/caddy/Caddyfile
sudo systemctl reload caddy
Cost estimate
| Setup | Specs | Monthly cost |
|---|
| App Runner | 1 vCPU, 2 GB (always-on) | ~$30 |
| ECS Fargate | 1 vCPU, 2 GB + EFS | ~$40 |
| EC2 t3.small | 2 vCPU, 2 GB | ~$15 |
| EC2 t3.medium | 2 vCPU, 4 GB | ~$30 |
Use EC2 Spot Instances for non-critical workloads — up to 90% cheaper. Polpo’s crash recovery handles interruptions gracefully.