Automating / CLI
CLI
kamal-cloud -- a thin CLI over the API. Reads answer; changes wait.
kamal-cloud is one file of standard-library Ruby, served by your KamalCloud install. No bundler, no
gems, no toolchain – whatever #!/usr/bin/env ruby finds has to be able to run it, and that is
the whole dependency list.
Installing
curl -fsSL https://kamalcloud.example.com/install | sh -s -- kc_xxxxxxxx
That fetches the CLI into ~/.local/bin and logs it in with the token you passed.
~/.local/bin is on the path of most modern distributions and needs no sudo, which is the
point. Where it is not on yours, the script says so. Leave the token off and it installs without
connecting.
The script needs ruby on the machine, and stops before downloading anything if there is none.
Neither the install script nor the CLI carries a secret, so both can be read before they are run. The token is yours and is passed by whoever runs it.
Already installed? Connect it by hand:
kamal-cloud login --url https://kamalcloud.example.com --token kc_xxxxxxxx
The token is checked against /api/v1/actions before anything is saved, so a typo is a message
rather than a config file that silently does not work. The profile is written to
~/.config/kamal-cloud/config.json, readable only by you (mode 0600).
Looking
kamal-cloud servers # every machine, with its OS and status
kamal-cloud server 12 # one machine in full
kamal-cloud apps # applications and their environments
kamal-cloud actions # what this KamalCloud can be asked to do
Add --json to any of them for the raw response instead of a table.
Asking
Each of these creates a change request and returns its id. Nothing happens until a person approves it in the browser.
kamal-cloud deploy 7 # an environment
kamal-cloud harden 12 firewall # one security fix on a server
kamal-cloud backup 3 # an accessory
kamal-cloud request servers.create name=web-3 server_type=cx42 location=nbg1 \
image=ubuntu-24.04 connection="Production Hetzner"
kamal-cloud harden takes a server id and one step: firewall, web_ports, cloud_firewall,
ssh_password_auth, ssh_root_login, ssh_keepalive, fail2ban, fail2ban_aggressive,
automatic_updates, upgrade, swap or storage. kamal-cloud actions lists them too, and
Hardening says what each does.
Following a request
kamal-cloud requests # everything, newest first
kamal-cloud requests --status pending
kamal-cloud request-status 41
kamal-cloud wait 41 # block until somebody decides
kamal-cloud wait is the one that makes this usable from a script: propose, block, and carry on when
a human has said yes. It asks every 3 seconds, prints the result once the request is applied, and
exits 1 if it was rejected or failed – so a pipeline stops there rather than carrying on.
Overriding a profile once
kamal-cloud servers --url https://other.example.com --token kc_yyyy
Useful for a second install, or in CI where the token comes from the environment rather than from a config file.
In CI
Issue a read-only token for anything that only needs to look. Where a pipeline should propose a deploy, issue a write token, and remember that the pipeline cannot complete the deploy on its own – that is the arrangement, not a limitation to work around.