Deploying / Deployments
Deployments
Every kind of run KamalCloud makes against an environment, and what each one does.
A deployment is one run of Kamal against an environment. Each has a status –
queued, running, succeeded, failed, cancelled – and a log that streams to the page
as it happens.
What a deploy actually does
A deployment is only created when the app’s runner is ready and nothing else is deploying to
the environment. One runs at a time; a second is refused with “Another deployment is already
running”.
- Opens SSH to the runner with the control key.
- Checks that every server in the environment answers over SSH, so a machine that is down is named at the start rather than after a clone and a build.
- For a releasing deployment in an environment that publishes ports, opens those ports on the provider’s cloud firewall.
- Wipes and shallow-clones your repository into the app’s working directory, at the branch
head – or, for a deploy triggered by a tag, at that tag. The clone URL carries a token, so
the log names the clone rather than printing the URL, and
originis reset immediately afterwards. - Reads the repository’s own
config/deploy.ymlfrom that checkout – the exact file about to be deployed – and refuses if anything is blocking. - Writes
config/deploy.<environment>.ymland.kamal/secrets.<environment>beside it. - Runs
kamalfrom the pinned official image, against the runner’s Docker daemon. - Records the version, settles the status, and notifies.
A deploy started by hand always ships the branch head; it cannot name a ref.
The kinds
Releasing
These put a version on the servers. The newest of them names what is running.
| Kind | What it is |
|---|---|
| deploy | Build, push, and boot the new version |
| redeploy | Deploy again without rebuilding from scratch |
| rollback | Boot a version already on the hosts. Nothing is pushed |
| setup | Kamal’s setup: prepare the machines and deploy |
Where an environment publishes a port, the build and the boot are split –
kamal build deliver, then kamal deploy --skip-push with a stop in between – because Kamal
boots the new container before stopping the old, and two containers cannot hold one published
port.
Traffic
These only decide whether kamal-proxy serves.
| Kind | What it is |
|---|---|
| maintenance | Stop serving, show a message you supply |
| live | Serve again |
Any releasing deployment puts an environment back in service too.
Housekeeping
| Kind | What it is |
|---|---|
| bootstrap | kamal setup without the deploy: Docker and the directories, and stop |
| reboot | Restart what is running, from the image already on the hosts. No build |
| lock_release | Clear the deploy lock file left behind by a killed run |
Accessory
accessory_boot, accessory_reboot, accessory_start, accessory_stop,
accessory_restart, accessory_remove – each against one accessory. See
Accessories.
Rolling back
Rollback takes a version that is already on the hosts and boots it. It is the fastest way out of a bad deploy, because nothing is built or pushed. Earlier releases on the environment’s Deployments list each have their own roll-back action.
Deploying on push
With auto-deploy on, a push to the environment’s branch (or any tag, for a tag-triggered environment) creates a deploy by itself. Two things hold one back:
- Skip markers. A head commit whose message contains
[skip ci],[ci skip],[no ci],[skip actions]or[actions skip]is not deployed. - A deploy already running. The push waits rather than being lost: KamalCloud tries again every 30 seconds, up to 20 attempts.
Cancelling
Stop marks the deployment cancelled at once. A job then connects to the runner, kills
Kamal’s container (docker rm -f kamal-cloud-deployment-<id>) and runs kamal lock release, so the
lock is not left behind.
A run that goes silent – a worker restart, a runner reboot, a dropped session – is settled by
a reaper rather than left saying “running” forever. After 15 minutes with no output it is marked
failed (“Interrupted…”) and killed the same way. KAMAL_CLOUD_DEPLOYMENT_STALE_AFTER sets the
interval, in minutes.
The log
Output is streamed over a live channel, batched into the deployment’s log, with ANSI stripped and clone tokens redacted. It survives the page: come back later and the whole run is there.
Who did it
A deployment records the person who pressed the button, and passes their identity to Kamal, so
Kamal’s own record on the machine says who deployed rather than root. A deployment created by
a push records the push instead.
When one fails
The log is Kamal’s own output, kept. Troubleshooting covers the failures that come up first: a clone that could not authenticate, a host that refused the key, a port already allocated, a lock left behind.
Notifications
deployment.succeeded and deployment.failed fire when a releasing deployment settles.
Housekeeping runs and traffic flips do not notify – they are not news. See
Notifications.