Jokku runs your apps on servers you own, with Dokku's commands and its git push. Every instance boots in its own Firecracker microVM, and when you want another server, it joins with one command. From then on your apps spread across all of them — and move by themselves when one dies.
Free and open source · No account, no paid tier · Ubuntu or Debian with KVM
A cluster you can be unkind to. Every line it prints is a line Jokku prints; the # lines are narration.
No paid tier, no cluster edition, no account. Clusters, backups, edges and databases ship in the same single binary as everything else, and the source is on GitHub.
The same command names, argument order and -----> output. If you have a Dokku box, you already know how to use this — and your laptop still needs nothing but git and ssh.
Each instance boots in its own Firecracker VM, with its own kernel — what AWS built to run Lambda. Restarting or updating Jokku leaves every one of them running.
The cluster
There is no multi-server mode, and nothing to configure for one. A cluster is the same Jokku with more servers in it. Ask the first for a join command, paste what it prints into a fresh box, and that box is in: on an encrypted WireGuard mesh, taking traffic, and running apps.
The first server is the control node. It keeps the cluster's state and takes your pushes. If it goes down, the others keep serving what they have; you just can't deploy until it's back — or until restore-cluster rebuilds it from its hourly backup.
A new instance goes to the server with memory free that runs the fewest of that process, so ps:scale myapp web=3 on three servers puts one on each.
Caddy is built into every node and knows every app's domains, so DNS can point at as many of them as you like.
cache.internal reaches the cache app from any app, on whichever server it is on today, over the WireGuard mesh.
nodes:drain starts a copy of each instance elsewhere, waits for it to pass checks, then stops the original.
A volume is copied while its app keeps running, then a short pause for the last writes. A database never moves without its data.
sudo jokku update on the control node updates itself, then every other server, one at a time, while your apps keep serving.
When a server dies
A database never moves without its disk: one with a volume waits for its server, unless the volume is backed up — then it comes back somewhere else from the latest backup. A server that was only cut off stops those apps itself first, so two copies of a database never both think they're the real one.
Power, network, a kernel panic — it stops reporting in.
Every proxy stops sending it requests. Until then, a request that can't reach it retries on another instance.
A minute's grace so a reboot doesn't shuffle anything, then its instances boot on the others.
Backed-up volumes are restored onto another server from their latest backup, and their apps start there.
jokku top
jokku top is the whole cluster, live, in your terminal. Press 6 and every request flies across its app's lane — green, cyan for a redirect, yellow for a 4xx, red for a 5xx — and lands on the instance and server that answered. A slow one crawls, trailing amber. A failure bursts where it lands.
Drawn the way the real one draws it, from internal/tui/traffic.go; the requests are made up in your browser.
Edges
An edge is a small public server — the cheapest VPS will do — that takes your domains' traffic and carries it home over the WireGuard mesh. Your servers dial out to it, so the router stays shut.
It's part of the cluster, so it already knows every app's domains and certificates: domains:add and letsencrypt:enable are the whole job, with nothing to set up anywhere else. Things Jokku doesn't even run, like Home Assistant or a NAS, become apps with external:create.
An edge needs no KVM and runs no apps. It wants TCP 80 and 443 and UDP 443 and 51820 open, and that's all. Add a second in another region and point DNS at both.
Over the mesh it gets your servers' web proxies, your apps' web ports, what you route to it and the API it fetches its routes from. Not ssh, not other machines on your network, and never an app's code or your backups.
The firewall runs in the first proxy a visitor reaches, so a bot hunting for /.env is banned at the edge and its requests never travel up your home connection.
Getting started
Bring a fresh Ubuntu or Debian server with KVM — bare metal, or a VM with nested virtualization on. The installer does the rest, and the SSH keys you logged in with can deploy straight away.
Your SSH keys can deploy straight away.
Your Dockerfile, built and booted, with a URL.
Point DNS at any server you have.
Issued, renewed and redirected for you.
Coming from Dokku
Dokku got the important part right: a git push and a dozen commands, the right size for one person with a lot of small apps. What it can't do is use more than one server — every Dokku box is an island, with its own apps and its own idea of what's running.
Jokku keeps the commands and drops the island. What changes is where your apps run, and how many servers they can use.
| Area | dokku | jokku |
|---|---|---|
| Servers | One | As many as you add |
| Runs apps in | Containers | Firecracker microVMs |
| A server dies | So do its apps | They start on the others |
| storage:mount | A host directory | A disk that moves with its app |
| Databases | postgres:* plugins | db:postgres:*, built in |
| Behind NAT | Open your ports | An edge your servers dial |
Also in the box
Even at home, behind a router with every port closed. All of it is in the one free binary, and all of it works the same on one server or ten.
New instances take traffic once they pass checks. A failed deploy is rejected and the old one keeps serving.
Build a Dockerfile, deploy a whole compose file, or run any image from a registry.
One command each, linked to your app with a URL, on a volume of their own.
Every 15 minutes, incremental and encrypted, to any S3-compatible bucket.
ps:set myapp sleep-after 15m stops an idle app's microVMs. The next request wakes it, held at the proxy while it boots.
A shared password, or users with authenticator codes, before any app. Nothing to change in it.
Scanners hunting for /.env and /wp-login.php get banned for an hour, with nothing to set up.
Follow every instance and every request in one stream, or open a shell inside a running microVM with jokku enter.
Run this on a fresh server with ports 80 and 443 free. Then run jokku cluster:join-command on it when you want the next one.
$curl -fsSL https://raw.githubusercontent.com/wes/jokku/main/install.sh | sudo sh185 installs and updatesacross 33 releases since 7 October 2026
Jokku is young and moving fast. The Firecracker jailer isn't on yet, so treat apps on one server as trusting each other, as you would on Dokku — and check what works today before you move anything important.