Skip to content
Help / Troubleshooting

Troubleshooting

The things that go wrong first, and what they mean.

The environment will not deploy

The environment page lists what is blocked before you press anything, and the deploy refuses on the same rules, so the two never disagree. The usual ones:

“This app has no runner” / “runner is not ready”. Prepare a runner, or point the app at one that is prepared.

“Nowhere to deploy”. The environment has no hosts, and deploy.yml names none either. Attach a server.

“A role with no machine here”. Your deploy.yml declares a role with nothing placed against it. Kamal would fall back to the repository’s own address – after kamal init, a placeholder pointing at somebody else’s machine. Place a host.

“A secret this deploy reads is not set”. Your deploy.yml names something under env.secret that the environment does not have. Add it under variables.

“These machines are reached differently”. Kamal takes one SSH user and port per destination. Every machine in the environment has to agree on both, or be split into separate environments.

“TLS cannot be issued across these machines”. The primary role has several hosts and domains, and kamal-proxy cannot share Let’s Encrypt issuance between them. Supply a certificate pair, or put a load balancer in front.

“The Kamal service was renamed”. The service name follows the app name, and Kamal names volumes and proxy routes after the service. Renaming strands both. Name the app back, or remove the environment and add it again under the new name.

“postgres is already on host”. Another environment of the same app runs an accessory of that name on that machine, and Kamal would give both one container name and one data directory. Rename one of them.

“No hostname on a shared machine”. Other apps deploy to that machine too, and without a hostname this one would become kamal-proxy’s default route. Add a domain.

“Template reads its own address”. An app from a template that bakes its URL into its data needs a domain before its first deploy.

The deploy failed

Read the deployment’s log – it is kept, and it is Kamal’s own output.

Clone failed. The git connection cannot reach the repository. Check the connection is still installed and the repository is still in its scope.

Cannot connect to a host. The runner reaches your servers with the account’s deploy key. Check the server’s SSH key page. A machine built outside KamalCloud needs the key put on it.

Host key mismatch. The machine at that address is not the machine KamalCloud met before – a rebuild, or a recycled address. Remove the server from KamalCloud and register it again.

Port already allocated. Two containers cannot hold one published port. KamalCloud splits the deploy for environments with ports, but two environments publishing the same port on one machine will collide.

Build is slow. Check the runner’s architecture against your servers’. A mismatch means a multi-arch build, which is much slower than one.

A deploy is stuck saying “running”

A worker that restarted, a runner that rebooted, a dropped session. KamalCloud settles these itself: a deployment whose row has not been touched for 15 minutes is reaped and marked failed. Output touches the row about once a second, so a live run never looks that quiet. A self-hosted install can change the limit with KAMAL_CLOUD_DEPLOYMENT_STALE_AFTER, in minutes.

If you would rather not wait, stop it. Stopping marks the row, then runs docker rm -f on the deployment’s container on the runner and releases Kamal’s lock. A reaped run is killed the same way.

If a run left Kamal’s lock file behind, Release lock on the environment clears it. Only do that when you are sure nothing is actually deploying.

Nothing happened at all

Look at the bottom of Activity for failed background jobs – a backup that never started, a notification that never went. Re-queue or discard from there.

Push does not deploy

Every one of these has to be true:

  • Auto-deploy is on for that environment. It is off by default.
  • The push matches the trigger: the environment’s branch for push, any tag for tag.
  • The changed paths match the environment’s path patterns, if it has any.
  • The commit message carries none of [skip ci], [ci skip], [no ci], [skip actions] or [actions skip].

A push that lands while a deploy is already running is not lost: it tries again every 30 seconds, up to 20 times.

Then check the git connection’s webhook is still registered on the repository.

The domain does not work

Check DNS on the domain resolves it and compares against the machines the environment actually runs on. Inspect fetches it and reports the certificate and headers.

If DNS is right and it still fails, the usual cause is that the certificate has not been issued yet – kamal-proxy requests one on first request – or that the machine’s firewall is not letting 80 and 443 through. If the machine has no firewall on, that is not it. If it has one, Hardening’s web_ports fix opens them; firewall opens them too, as it turns one on.

I am locked out of a server

If a firewall was turned on outside KamalCloud without SSH open, or password logins were turned off before your key was on: use the provider’s own console.

For Hetzner, Provider access on the server page asks Hetzner for a new root password and uses it once to put the key back, so nobody needs to know the old one. It really does change the root password. It cannot help a machine that refuses password logins altogether – which one built with an SSH key usually does – and then the one-line command, run from the provider’s web console, is the way in.

The provider token stopped working

provider.rejected fires at critical severity, because every machine behind that connection goes quiet at once. Verify the connection to confirm, then paste a new token. Nothing at the provider is affected.

A backup did not reach every bucket

backup.incomplete means it reached some. The backup page names which. Usually one bucket’s credentials expired – Verify each one.

Also worth checking: buckets at the same company as the machine are not separate places. One suspension takes both.

Still stuck

Every long-running record keeps its log. The deployment, the backup, the task run, the hardening run – open the record and read what it actually said. Nearly everything in KamalCloud fails with the remote command’s own output rather than a summary of it.