podman systemd: Run Containers as Services
podman generate systemd writes a systemd unit that manages a container, and Quadlet is the newer declarative way to do the same.
To keep a container running across reboots on a self-hosted runner, wrap it in a systemd unit. The generate command is being superseded by Quadlet .container files.
What it does
podman generate systemd produces a systemd service file that starts and stops a given container or pod. The newer Quadlet approach instead reads a declarative .container unit and generates the service at boot. Either way systemd supervises the container.
Common usage
# generate a unit from a running container
podman generate systemd --new --name app --files
# install as a user service
mkdir -p ~/.config/systemd/user && mv container-app.service ~/.config/systemd/user/
systemctl --user daemon-reload && systemctl --user enable --now container-app.service
# Quadlet: place app.container in ~/.config/containers/systemd/ and reloadOptions
| Flag/Item | What it does |
|---|---|
| --new | Create a fresh container on start instead of reusing one |
| --name | Use container names in the unit instead of IDs |
| --files | Write the unit to a file in the current directory |
| systemctl --user | Manage rootless user services |
| Quadlet .container | Declarative unit auto-converted by Podman |
In CI
For rootless services, use systemctl --user and enable lingering (loginctl enable-linger) so the service survives logout on a self-hosted runner. New setups should prefer Quadlet .container files over podman generate systemd, which is deprecated.
Common errors in CI
"Failed to connect to bus: No such file or directory" running systemctl --user in CI means there is no user session bus; start one with a systemd user instance or use system units. A unit that exits immediately with status often comes from --new recreating a container whose name already exists; remove the old one. Quadlet units that do not appear need a daemon-reload and the file in ~/.config/containers/systemd/.