Skip to content
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”.

  1. Opens SSH to the runner with the control key.
  2. 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.
  3. For a releasing deployment in an environment that publishes ports, opens those ports on the provider’s cloud firewall.
  4. 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 origin is reset immediately afterwards.
  5. Reads the repository’s own config/deploy.yml from that checkout – the exact file about to be deployed – and refuses if anything is blocking.
  6. Writes config/deploy.<environment>.yml and .kamal/secrets.<environment> beside it.
  7. Runs kamal from the pinned official image, against the runner’s Docker daemon.
  8. 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.