Zero-downtime Docker deployments over SSH.

No Kubernetes. No complexity. Deploy containers to your own servers with automatic HTTPS via Caddy.

Deploy with confidence

Odysseus deploys containerized applications to your servers using SSH and Docker. New containers start, pass health checks, and receive traffic before old ones stop. If anything goes wrong, the old container keeps running.

Caddy runs as a container on each server, handling reverse proxying and automatic HTTPS certificates via Let's Encrypt. No manual nginx configs, no certbot.

$ odysseus deploy --config deploy.yml --build
Odysseus Deploy
Service: my-saas-api
Image: my-saas-api:latest
Distribute: pussh (SSH)
01 > Building and distributing
01 Building image
01 Pushing image to server-prod-01
02 > Deploying service
02 Starting Caddy
02 Caddy already running
02 Starting container
02 Health check
02 Caddy route update
02 Draining old container
02 Draining old container
02 Draining old container
03 Deployment successful in 36.9s

Features

Zero-downtime deploys

New containers start and pass health checks before old ones stop. Traffic switches seamlessly with no dropped requests.

Automatic HTTPS

Caddy handles SSL certificates via Let's Encrypt automatically. Define your domain in config, Odysseus does the rest.

No registry required

Push images directly to servers via SSH using pussh. Or use a Docker registry if you prefer — both modes supported.

Minimal server requirements

Just Docker and SSH access. Caddy is deployed as a managed container automatically — no manual installation.

Roles & accessories

Deploy web servers, background workers, databases, and Redis from one config. Each role can have different resources and commands.

Encrypted secrets

Built-in AES-encrypted secrets management. Generate a key, encrypt your secrets file, and deploy with confidence.

Health checks

Configurable HTTP health checks with thresholds. Containers only receive traffic after passing consecutive checks.

Plugin architecture (Sails)

Extend Odysseus with deploy strategy plugins. Rolling deploys, canary releases, and more — each as a separate gem.

How it works

Your machine

odysseus deploy

Your server

Docker + Caddy

1

Build

Docker image built locally or on a remote build host

2

Push

Image transferred to servers via SSH (pussh) or pulled from registry

3

Start

New container starts on the Docker network

4

Health check

Odysseus polls the health endpoint until it passes

5

Route

Caddy updated to send traffic to the new container

6

Drain & cleanup

Old container drained and stopped, old containers cleaned up

# deploy.yml
service: myapp
image: myapp
servers:
  web:
    hosts:
      - app.example.com
    options:
      memory: 4g
proxy:
  hosts:
    - myapp.example.com
  app_port: 3000
  ssl: true
  ssl_email: admin@example.com
accessories:
  db:
    image: postgres:17
    hosts:
      - db.example.com
    volumes:
      - postgres_data:/var/lib/postgresql/data
ssh:
  user: root
  keys:
    - ~/.ssh/id_ed25519

One YAML file. That's it.

Servers & roles

Define web servers, workers, and their resource limits. Deploy different configurations to different hosts.

Automatic HTTPS proxy

Set your domain and port. Caddy handles certificates, routing, and health-check-based traffic switching.

Accessories

Databases, Redis, and other services managed alongside your app. Named volumes are automatically namespaced to prevent collisions.

Quick Start

From zero to deployed.

bash
$ gem install odysseus-cli
# Create deploy.yml in your project root
$ odysseus deploy --build --image v1.0.0
Deployed. Traffic live on v1.0.0.

Odysseus Pro

Advanced deploy strategies, web dashboard, and audit logs for production-critical infrastructure.

Learn more