Deployment

Host providers

Configure static hosts or dynamic host discovery from cloud providers.


Overview

Odysseus supports multiple ways to define deployment targets:

  • Static hosts: Fixed list of hostnames or IPs
  • AWS Auto Scaling Groups: Dynamic discovery from AWS

Static hosts

The simplest configuration uses a fixed list of hosts:

servers:
  web:
    hosts:
      - app1.example.com
      - app2.example.com
      - app3.example.com

Hostnames

Use fully qualified domain names:

servers:
  web:
    hosts:
      - web1.prod.example.com
      - web2.prod.example.com

IP addresses

Or direct IP addresses:

servers:
  web:
    hosts:
      - 10.0.1.10
      - 10.0.1.11
      - 10.0.1.12

Mixed

Combine hostnames and IPs:

servers:
  web:
    hosts:
      - app.example.com
      - 10.0.1.10

AWS Auto Scaling Groups

For dynamic infrastructure, Odysseus can discover hosts from AWS Auto Scaling Groups.

servers:
  web:
    aws:
      asg: production-web-asg
      region: us-east-1

Configuration

servers:
  web:
    aws:
      asg: production-web-asg
      region: us-east-1
      use_private_ip: true
      state: InService

asg

Name of the Auto Scaling Group.

region

AWS region where the ASG is located.

use_private_ip

Use private IPs instead of public (default: false).

Set to true when deploying from within the same VPC:

servers:
  web:
    aws:
      asg: production-web-asg
      region: us-east-1
      use_private_ip: true

state

Filter instances by lifecycle state (default: InService).

Only deploy to healthy, in-service instances:

servers:
  web:
    aws:
      asg: production-web-asg
      region: us-east-1
      state: InService

AWS credentials

Odysseus uses standard AWS credential chain:

  1. Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
  2. Shared credentials file (~/.aws/credentials)
  3. IAM instance role (when running on EC2)

Required IAM permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "autoscaling:DescribeAutoScalingGroups"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances"
      ],
      "Resource": "*"
    }
  ]
}

Example: Web and workers

servers:
  web:
    aws:
      asg: production-web-asg
      region: us-east-1
      use_private_ip: true
  jobs:
    aws:
      asg: production-worker-asg
      region: us-east-1
      use_private_ip: true
    cmd: bundle exec sidekiq

Mixing providers

Combine static hosts with dynamic discovery:

servers:
  web:
    aws:
      asg: production-web-asg
      region: us-east-1
  jobs:
    hosts:
      - worker.example.com
    cmd: bundle exec sidekiq

Host resolution

At deploy time, Odysseus resolves all hosts:

odysseus deploy --verbose --image v1.0.0

Output shows resolved hosts:

Resolving hosts for role 'web'...
  AWS ASG 'production-web-asg': 3 instances
    - 10.0.1.10 (i-abc123)
    - 10.0.1.11 (i-def456)
    - 10.0.1.12 (i-ghi789)

Deployment order

For multiple hosts, Odysseus deploys sequentially:

  1. First host: deploy, health check, update routing
  2. Second host: deploy, health check, update routing
  3. And so on...

This ensures zero-downtime during deployments.


Troubleshooting

AWS credentials not found

Error: Unable to locate AWS credentials

Set credentials via environment:

export AWS_ACCESS_KEY_ID=your-key
export AWS_SECRET_ACCESS_KEY=your-secret
odysseus deploy --image v1.0.0

No instances in ASG

Warning: ASG 'production-web-asg' has 0 InService instances

Check your ASG in the AWS console and ensure instances are healthy.

Cannot connect to private IP

When using use_private_ip: true, ensure you're deploying from within the VPC or have VPN access.

# Test connectivity
ssh root@10.0.1.10 "hostname"
Previous
Building images