launchroom
How it works

Architecture

A control plane that stores what you want to run, launchroomd on every server that applies it, and apps that keep serving when the dashboard is down.

launchroom has two parts:

  • The control plane is the dashboard and the services it needs, installed on your first server.
  • launchroomd runs on every server, the first one included. It turns what the control plane wants into running containers, routes and firewall rules.

Your apps run on the servers, not in the control plane. They keep serving when the dashboard is offline.

The big picture

                 ┌──────────────── Control plane (your first server, ./launchroom) ────────────────┐
  Browser ─HTTPS─▶ Caddy ─▶ dashboard  (web UI, API, webhooks, the API servers talk to)              │
                 │          horizon    (background jobs: deployments, builds, git, alerts)           │
                 │          reverb     (live updates in the browser, "check now" nudges to servers)  │
                 │          scheduler  (periodic work)                                               │
                 │          postgres · valkey                                                        │
                 │          zot        (image registry)                                              │
                 │          headscale  (private network coordination, idle with one server)          │
                 │          launchroomd + dockerd-guard  (the same as on every other server)         │
                 └──────────────────────────────────────────────────────────────────────────────────┘
                                   ▲  HTTPS, signed, always opened by the servers
            ┌──────────────────────┼───────────────────────┐
     ┌──────┴───────┐       ┌──────┴───────┐        ┌──────┴───────┐
     │ Serve traffic│       │ Run apps     │        │ Build        │   roles combine freely
     │ launchroomd  │       │ launchroomd  │        │ launchroomd  │
     │ Caddy        │       │ your apps    │        │ BuildKit     │
     └──────────────┘       └──────────────┘        └──────────────┘

The dashboard's server is a server like any other. It runs launchroomd with the same code path, so a single VPS can build, run and serve your apps next to the dashboard.

Servers page: three server cards in Berlin, Helsinki and New York with roles, CPU and memory sparklines, then system load, a world map of locations, a 'How it fits together' diagram from Internet to edge and build servers, and an at-a-glance summary.Servers page: three server cards in Berlin, Helsinki and New York with roles, CPU and memory sparklines, then system load, a world map of locations, a 'How it fits together' diagram from Internet to edge and build servers, and an at-a-glance summary.
Your servers, where they are, what they do and how they connect.

What runs where

ComponentWhereWhat it does
dashboardControl planeThe web UI, the REST API, git webhooks, and the API launchroomd talks to. Holds everything you configure.
horizonControl planeBackground workers: deployments, builds, git sync, backups, alerts.
reverbControl planeRealtime updates in the browser, live logs, and content-free "check now" nudges to servers.
schedulerControl planePeriodic work: liveness checks, backup schedules, DNS checks, updates.
PostgresControl planeThe control plane's database. Backed up by launchroom itself.
ValkeyControl planeQueues, cache and locks; shared certificate storage for multiple edges.
ZotControl planeThe image registry: your built images, build caches and mirrors of base images.
HeadscaleControl planeCoordinates the private network. Idle until a second server joins.
launchroomdEvery serverApplies the server's desired state, runs builds and backups, reports status, metrics and logs.
dockerd-guardEvery serverHolds the Docker socket and lets launchroomd use only a narrow, checked part of Docker's API.
CaddyServers that serve trafficPublic HTTPS, certificates, load balancing to replicas. Configured only by the local launchroomd.
BuildKitBuild serversBuilds images, started when needed.
Tailscale clientEvery server, once the private network is onPrivate WireGuard connections between servers.

Details on what launchroomd does: launchroomd. The network between servers: The private network.

Desired state, not remote commands

The dashboard never logs into a server and never runs commands on one. Instead, it works with desired state:

  1. You describe what you want. Services, variables, domains, replicas and connections are stored in the dashboard. Edits collect as staged changes until you deploy.
  2. Deploy freezes it. Every deploy records an immutable revision of the environment.
  3. The scheduler places it. It decides which replica runs on which server, following roles, labels and capacity.
  4. Each server gets its document. The dashboard writes, for each affected server, the complete list of what it should run: containers, networks, volumes, routes and firewall rules. The document is versioned and signed.
  5. launchroomd converges. It fetches its document (nudged within a second, with polling as a fallback), compares it with what's running and fixes the difference, in a repeating loop. It only touches objects that have launchroom's labels.
  6. It reports back. Status, health and metrics go to the dashboard, which moves deployments forward from there.

Builds, one-off commands such as migrations, backups and log fetches are separate tasks. Servers with the right role pick them up, run them and report the result.

What this means in practice:

  • A server that was offline catches up by fetching the latest document. There is nothing to replay.
  • After a reboot, the server returns to its desired state by itself.
  • A half-applied deploy can't leave a server in a mixed state.

When the dashboard is down

The control plane runs on one server. While it is down:

  • Your apps keep running and serving. Every server keeps its last desired state on disk and keeps applying it. Containers restart on their own, Caddy keeps its routes and certificates, and HTTPS for custom domains is approved by the local launchroomd.
  • The private network keeps working between servers that already know each other.
  • Scheduled jobs keep running. launchroomd starts cron services itself.
  • Nothing changes. Deploys, builds, new servers and dashboard access wait until it is back. Certificate renewals wait too. Certificates are renewed weeks before they expire.

When the dashboard comes back, every server checks in and continues. If its server is lost for good, install a new one from backup with --restore. See Restore and disaster recovery.

Other failures

What failsWhat you seeWhat launchroom does
A serverIts replicas stop; edges skip them within secondsAfter about 90 seconds, stateless replicas move to healthy servers. Databases stay put until it returns or you replace it.
A build server mid-buildThe build stops thereThe build is retried on another build server. Same commit, same plan, same result.
A deploy's health checkThe new version never gets trafficThe new containers are removed and the old version keeps serving. The deployment shows why.
The registryNo new pulls or pushesServers keep running and restarting what they already pulled.
launchroomd on a serverNothing on that server changesContainers keep running; launchroomd restarts, re-reads its state and re-applies firewall rules and routes.

One server or many

One server is the default and a complete setup. The control plane, Caddy, your apps and their builds share the machine. There is no private network and nothing extra to run. launchroom suggests a second server for reliability, but doesn't present a single server as a problem.

More servers join with one command each. When the second joins, the private network turns on. A common order:

  1. a build machine at home
  2. a second edge for high-availability ingress
  3. more servers that run apps
  Internet ─▶ VPS (public)                              Home (behind NAT, nothing inbound)
              Caddy, dashboard, registry,  ◀═ WireGuard ═ build machine: launchroomd, BuildKit
              your apps                    direct, or relayed over HTTPS 443

The control plane itself is not highly available. It is one server, backed up and restorable. Apps don't depend on it to serve requests.

Next steps

On this page