What is supported today
Image-based deploys and compose are the expected path on Podman. Dockerfile and Railpack source builds are not verified on Podman yet: builds use a BuildKit that runs inside
dockerd, and Podman has no embedded BuildKit. Build on another node or in CI and deploy the image.
Server installs are Linux only. On a macOS laptop, levelrail-cli dev is the path; see Local development.
How the installer chooses
install.sh --runtime auto|docker|podman|existing (or LEVELRAIL_RUNTIME):
For Podman the installer enables
podman.socket, writes APP_CONTAINER_RUNTIME_SOCKET=unix:///run/podman/podman.sock into the same systemd drop-in as the other APP_* settings, and makes the levelrail unit require podman.socket instead of docker.service. Set LEVELRAIL_PODMAN_SOCKET to use another socket path. An upgrade keeps the runtime an install chose.
install.sh --check prints the same rows: the detected runtime, its version, rootful or rootless, and the support label. It exits non-zero only on a real failure, such as --runtime podman with no Podman installed.
Manual Podman setup
Install Podman with your distro first (apt install podman, dnf install podman).
Rootful, as root:
install.sh --runtime podman, or set APP_CONTAINER_RUNTIME_SOCKET=unix:///run/podman/podman.sock in the levelrail service drop-in yourself.
Rootless, as the user that will own the containers (the installer only prints these, it never runs user-level commands for another user):
APP_CONTAINER_RUNTIME_SOCKET at that socket path. Rootless Podman cannot publish ports 80 and 443 unless you lower net.ipv4.ip_unprivileged_port_start.
Podman notes
- Source builds (Dockerfile and Railpack) need BuildKit, which Podman does not have. A source deploy on Podman fails with the class
build_engine_unsupported. Deploy a prebuilt image, or run Docker on the build node. - Podman answers 404 for the engine’s registry digest lookup. Levelrail treats that as “unknown”, not “missing”, and lets the node pull the image itself, so short names such as
nginx:1.27-alpinework. - App networks are carved from
APP_NETWORK_POOL(default10.88.0.0/14). The block10.88.0.0/16is skipped because Podman’s default network uses it. - Compose
portsare not published on the host as written. A service port is published on a random loopback port for ingress, so do not rely on the host port you wrote in the compose file. See Compose apps. - The exposure controller needs the iptables DOCKER-USER chain. On Podman with netavark and nftables that chain is absent, so the controller reports it once and exposure rules are not applied.
Verify
container_runtime check reports Docker or Podman, rootful or rootless, and which setting chose the socket. See Security for what that detection covers.
Roadmap
- Test against a real Podman host in CI, then promote it from best-effort.
- A source-build story for Podman (an external BuildKit), once it is verified.
- Other runtimes only on demand.