Skip to main content

Overview

AWS offers multiple ways to run Polpo. Pick based on your needs:
ServiceBest forPersistent storageComplexity
App RunnerSimplest AWS optionEFS mountLow
ECS FargateProduction, no serversEFS mountMedium
EC2Full control, cheapestLocal disk or EBSLow

Option A: App Runner

App Runner is AWS’s simplest container service — point it at an image and it runs.
  1. 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
    
  2. 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.
  1. 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
    
  2. 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
    
  3. 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.
  1. 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
  2. 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
    
  3. 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

SetupSpecsMonthly cost
App Runner1 vCPU, 2 GB (always-on)~$30
ECS Fargate1 vCPU, 2 GB + EFS~$40
EC2 t3.small2 vCPU, 2 GB~$15
EC2 t3.medium2 vCPU, 4 GB~$30
Use EC2 Spot Instances for non-critical workloads — up to 90% cheaper. Polpo’s crash recovery handles interruptions gracefully.