Getting started

Overview

Deploy web apps in containers to any server running Docker, with zero downtime.

What is dash?#

dash deploys containerized web apps to your own servers — bare metal, cloud VMs, anything you can SSH into that runs Docker. It builds your image, pushes it to a registry, pulls it on your hosts, and switches traffic to the new containers with zero downtime, using dash-proxy to swap requests between old and new versions seamlessly.

dash began as a fork of basecamp/kamal and made a clean break in 2026. It ships the features upstream wouldn't merge — proxy load balancing, readiness gates, response caching, traffic shaping, SAN certificate batching, wildcard certificates — and moves at its own pace. Existing kamal deployments upgrade in place: the server's .kamal/ directory renames itself to .dash/ on the next deploy, KAMAL_* env vars are still set alongside their DASH_* twins, and a .kamal/ directory in your repo is still read. In 4.0 the proxy container, network and volumes are renamed too — dash migrates each host itself, carrying the certificate store across, at the cost of a short outage per host while the container is replaced. See From kamal for the migration story.

How a deploy works#

One command, five steps:

  1. Builddocker build your app image (locally or on a remote builder), tagged with the current git SHA.
  2. Push — push the image to your registry, then pull it on every server.
  3. Gate — acquire the deploy lock and run readiness checks.
  4. Boot — start new containers alongside the old ones, wait for the healthcheck to pass.
  5. Switch — tell the proxy to route traffic to the new containers, then stop the old ones. Requests in flight finish on the old version; new requests hit the new one.

Everything is plain SSH + Docker — no control plane, no agents on your servers, no lock-in. The entire deployment is described in one file, config/deploy.yml.

config/deploy.yml
service: myapp
image: my-user/myapp

servers:
  - 192.168.0.1
  - 192.168.0.2

proxy:
  ssl: true
  host: app.example.com

registry:
  username: my-user
  password:
    - DASH_REGISTRY_PASSWORD

Beyond kamal#

The proxy features upstream does not have.

FeatureWhat it gives you
Load balancingOne host fronts the whole fleet — auto-activates for multi-host roles, shareable between apps.
SAN batching & wildcardsBatch domains onto shared SAN certificates, issue wildcards via DNS-01, learn TLS hostnames from your app at runtime.
Response cachingAn RFC 9111 shared cache in front of your app, administered with dash proxy cache.
Traffic shapingRate limiting, IP allow/deny lists, per-path timeouts, read routing, session affinity, scale to zero.
Readiness gatesdash doctor diagnoses servers, registry, proxy, ports, DNS, and certificates before you deploy.

The shared basics — services, roles, accessories, hooks — work the way upstream kamal's do, and the Configuration pages here are generated from the gem itself, so they always match the installed version.

Where next#