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 — nothing to host, pay for, or authenticate against. Install the docker-pussh plugin on the machine you deploy from; registry-based deploys aren't officially supported yet.

Minimal server requirements

Just Docker and SSH access — any Linux distro works. Odysseus setup can install Docker for you on a fresh Ubuntu host. Caddy is deployed as a managed container automatically — no manual installation.

Host setup and diagnosis

Odysseus setup prepares a fresh Ubuntu host — deploy user, docker group, your key, Docker itself — enough for one host, with provisioning at scale left to OpenTofu or equivalent. Odysseus doctor reads a host back and reports whether it can be used, however it was prepared.

Roles & dependencies

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)

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
dependencies:
  db:
    image: postgres:17
    hosts:
      - db.example.com
    volumes:
      - postgres_data:/var/lib/postgresql/data
ssh:
  user: deploy
  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.

Dependencies

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
# One-time: the docker pussh plugin, which carries images to your servers
$ mkdir -p ~/.docker/cli-plugins && curl -fsSL https://github.com/psviderski/unregistry/releases/latest/download/docker-pussh-$(uname -s)-$(uname -m) -o ~/.docker/cli-plugins/docker-pussh && chmod +x ~/.docker/cli-plugins/docker-pussh
# Create deploy.yml in your project root
$ odysseus deploy --build
# Version comes from your commit — outside a git repo, pass --image TAG instead
Deployed. Traffic live on 4f2a91c83b0e.

Odysseus Pro

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

Learn more