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