-
Notifications
You must be signed in to change notification settings - Fork 0
Provisioning a Podman Host
podman-api does not run containers itself — it drives a rootless
podman.socket on each target host over SSH. This page turns a fresh Linux box
into such a target. Commands below are for Debian 13 (trixie), validated
end-to-end; adapt the package step for other distros.
SSH in and note these — they go straight into the hosts/<id>.yaml later:
ssh debian@<host>
whoami; id -u # the user and its uid (socket path uses the uid)
cat /etc/os-release # distro/version
uname -m # archsudo apt-get update
sudo apt-get install -y podman uidmap slirp4netns
podman --version # Debian 13 ships podman 5.x, matching the v5 bindings
podman info --format '{{.Host.Security.Rootless}}' # expect: trueThe socket must survive logout, so enable lingering for the user, then start
the user podman.socket:
sudo loginctl enable-linger "$USER"
export XDG_RUNTIME_DIR="/run/user/$(id -u)"
systemctl --user enable --now podman.socket
systemctl --user is-active podman.socket # active
ls -l "$XDG_RUNTIME_DIR/podman/podman.sock" # e.g. /run/user/1000/podman/podman.sock
podman ps # smoke testThe socket path is /run/user/<uid>/podman/podman.sock — record it.
If
podman pswarns about "no systemd user session", that's expected over a non-login SSH session; lingering keeps the socket alive regardless.
podman-api connects as ssh://<user>@<host><socket> using a named identity
file. Use a key the daemon host holds and the target authorises:
# on the podman-api host, confirm the key the server accepts:
ssh -v <user>@<host> true 2>&1 | grep -i "Server accepts key"Best practice is a dedicated key per host (e.g. prod-1.id_ed25519) so you
can rotate one target without touching others.
Drop a file into the directory podman-api scans with -hosts-dir:
# hosts/prod-1.yaml
id: prod-1
addr: debian@<host> # ssh://user@host (default port 22)
socket: /run/user/1000/podman/podman.sock
ssh_key: /etc/podman-api/keys/prod-1.id_ed25519
labels:
env: prod
region: ap-south-1addr: unix connects to a local socket directly (dev only). Anything else
opens an SSH tunnel using ssh_key. Real host files are git-ignored; commit
only a sanitised example.
With the daemon running (see Deploying):
curl -s -H "Authorization: Bearer $TOK" http://127.0.0.1:8080/hosts/prod-1/healthz
# {"status":"ok"}
curl -s -H "Authorization: Bearer $TOK" http://127.0.0.1:8080/hosts/prod-1
# ... "podman_version":"5.x.y" ...A successful podman_version means the SSH tunnel, identity, and socket path
are all correct. A full apply→list→delete then confirms play kube, secrets,
and port mapping — see Operating.
The -tags=integration tests use a local socket. To exercise them on this
box directly, install Go and run make test-integration there, or rely on the
podman-in-podman CI job (Building).
The optional ingress feature (-ingress-enabled, see Operating) runs a
managed Caddy pod that must publish :80 and :443 on the host. Under
rootless podman those ports are blocked until you lower the unprivileged-port
floor, persistently:
echo 'net.ipv4.ip_unprivileged_port_start=80' | \
sudo tee /etc/sysctl.d/99-podman-ingress.conf
sudo sysctl --system
sysctl net.ipv4.ip_unprivileged_port_start # => ... = 80Without it the Caddy pod fails to start (cannot expose a privileged port). Hosts that never run ingress can skip this. Running Caddy rootful is not supported — podman-api drives every host over the single rootless user socket from § 2.
For HTTP-01 to issue certs, the host's :80/:443 must be reachable from the
internet and each instance domain must already resolve to this host
(operator-managed DNS).
- Troubleshooting — SSH tunnel failures, socket path mistakes.
- Deploying — the daemon that consumes this host file.