Skip to main content

Administering it from your own machine

ohm is remote-first. Once an endpoint is configured, commands run against the API rather than locally, and --local forces local execution. So an administrator's own machine needs the tool and nothing else about the product.

Three steps: install the tool, let your address through to the server's API, and store a connection.

Install the tool​

The tool is the antelao-ohm package. Add the repository's signing key, add the repository, install it:

sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://packages.antelao.io/raw/pgp/6AF95B6FF57CCE21.asc | sudo tee /etc/apt/keyrings/antelao.asc > /dev/null
. /etc/os-release && printf 'Types: deb\nURIs: https://packages.antelao.io/%s\nSuites: %s\nComponents: main\nArchitectures: %s\nSigned-By: /etc/apt/keyrings/antelao.asc\n' "$VERSION_CODENAME" "$VERSION_CODENAME" "$(dpkg --print-architecture)" | sudo tee /etc/apt/sources.list.d/antelao.sources > /dev/null
sudo apt-get update && sudo apt-get install -y antelao-ohm

The repository has one suite per supported release: bookworm (Debian 12), trixie (Debian 13) and noble (Ubuntu 24.04). The command above takes the suite from your machine's own release. Signed-By scopes the key to this one repository, so it signs nothing else on your machine.

The key's full fingerprint is 9BCA9361422F68BE90FC438D6AF95B6FF57CCE21. Compare it with what gpg --show-keys /etc/apt/keyrings/antelao.asc prints before you install anything from the repository; see Verify a download.

Not the one-liner installer

antelao-ohm-installer.sh, from Install the server, does the same apt work and then ends by running ohm install - which lays a whole host. On your own machine you want the package and not that last step.

Installing the package does not make the machine a server on its own: the systemd units ship disabled, and laying a host is always the explicit act of running ohm install, should this machine ever become one.

It is not weightless, though. The package's dependencies bring Docker Engine, the Docker client and ICU with it, because the same binary has to be able to install a host when you ask it to.

A machine that is to become a developer's own copy of the product, rather than a console for administering other people's, is a different thing with its own install mode - see the developer workstation.

First, let your address in​

A fresh install closes the management API to the outside. It answers the server itself, and the private ranges 10.0.0.0/8 and 192.168.0.0/16, and nothing else: a call from any other address has its connection closed, with no error message. Before your machine can use the API, do one of these:

  • Come in over an SSH tunnel or a VPN that arrives from the server itself or from those private ranges. Nothing needs changing on the server:

    ssh -N -L 5312:127.0.0.1:5312 admin@pelmo.example.com

    and use https://localhost:5312 as the connection's address below.

  • Add your address in the console, under Security > Firewall, on the Rules tab: open api, add your address or range to what the surface admits, and save. It applies within half a minute. Saving rules needs an edition that carries them:

  • Name it at install, with apiAllow in the bootstrap document, or --api-allow or ANTELAO_INSTALL_API_ALLOW on the installer. On a server that is already installed, sudo ohm install --api-allow 203.0.113.7 adds the address in a repair, whatever the edition. These addresses are not firewall rules, so they stay admitted on a server without a license: the api tab shows them as locked entries, and Reset removes them. A server that dropped such an address before 0.18.0 gets it back with that repair. A repair takes the server offline while it runs, and on a server installed without an agent allow-list it also narrows who may reach the agent's page to this server and the addresses you name.

The provider's firewall comes on top of this: open port 5312 there to your own address only, or not at all if you use the tunnel. The same applies to a console that registers this server as an environment: its address has to be let in the same way.

Store a connection​

Local only
$ ohm connection add --name pelmo --url https://pelmo.example.com:5312

The API answers on 5312 with TLS, on every interface, and on 5311 without TLS, on the server itself only. From another machine use 5312. 5311 can be reached from elsewhere only through an SSH tunnel, which also keeps the key, sent in a header, off the network.

The key is an API key issued for this machine on the server's Security > API keys (Issue a key, surface Management API). The console key that ohm server info --show-secrets shows does not work here: over the network it acts only for a person signed in to the console. See Keys and credentials. The key is prompted for and masked when you leave --api-key out, which keeps it out of your shell history.

While the server's certificate is self-signed, your machine does not trust it, and ohm refuses the connection with a message that names the certificate's fingerprint. Trust the server for this one connection rather than for the whole machine: --ca-file names the .crt file from the server's trust kit, and --certificate-sha256 pins the certificate's fingerprint instead. Either is stored with the connection and checked on every call.

Local only
$ ohm connection add --name pelmo --url https://pelmo.example.com:5312 --ca-file pelmo-ca.crt
Remote or localagainst pelmo
$ ohm instance list --server pelmo

--server accepts either a stored connection name or a base URL. Without it, the default stored connection is used, or the OHM_API_URL and OHM_API_KEY environment variables.

Every state-changing remote command enqueues a background job and streams its log until it finishes. A handful of commands have no remote form, because they build or repair the very thing a remote call would travel over. Those are marked Local only throughout the command reference. The ohm user commands that change a console account are refused remotely with an issued API key, too: run them on the server itself (see What an issued key cannot do).