If you wanted to run podman containers as a systemd service in the past, podman-generate-systemd was the way to go. Now in 2025, their Docs1 say this:
DEPRECATED: Note: podman generate systemd is deprecated. We recommend using Quadlet files when running Podman containers or pods under systemd. There are no plans to remove the command. It will receive urgent bug fixes but no new features.
What are Quadlets?
Quadlets are configuration files that define containers, pods, networks, and volumes in a declarative way. They live in ~/.config/containers/systemd/
(for rootless) or /etc/containers/systemd/
(for root) with extensions like .container
, .pod
, .network
, or .volume
.
When systemd starts, a systemd generator called podman-systemd-generator
reads these quadlet files and automatically converts them into native systemd service units. This happens before systemd starts any services, so by the time the system is booting, your containers are already registered as proper systemd services.
Why Quadlets over podman-generate-systemd?
The old approach (podman-generate-systemd
) required you to:
- Manually create and start a container with
podman run
- Generate a systemd unit file from that running container
- Copy the generated file to the right location
- Hope nothing changed later
This was imperative and error-prone. If you updated the container, you had to regenerate the unit file.
Quadlets are declarative:
- You describe what you want in a
.container
file - systemd automatically generates and manages the service unit
- Changes to the quadlet file are picked up on
daemon-reload
- No manual synchronization needed
Quadlets also provide:
- Native systemd integration (proper dependencies, ordering, logging)
- Support for pods, networks, and volumes as first-class objects
- Automatic container updates with
AutoUpdate=registry
- Better lifecycle management (systemd handles everything)
Let’s see how that works by converting a simple podman container to a quadlet.
Regular (rootless) podman
We’re using Uptime Kuma to monitor Services and Websites. The command2 to create that container is this:
podman run -d --name uptime-kuma --restart always -v /home/user/podman/uptime-kuma:/app/data --network=host docker.io/louislam/uptime-kuma:latest
Details on some of the parameters:
Restart the container in any circumstance.
--restart always
The configuration data must be persistent after reboots or if the container is removed.
-v /home/user/podman/uptime-kuma:/app/data
To reach other services, on the Host System as well as externally, we tell Podman to use the host network.
--network=host
Quadlet
Let’s first remove the container
podman stop uptime-kuma
podman rm uptime-kuma
Now let’s create a Systemd Container File3 for the new Container.
$EDITOR ~/.config/containers/systemd/uptime-kuma.container
[Unit]
Description=Uptime Kuma
After=network.target
[Container]
Image=docker.io/louislam/uptime-kuma:latest
AutoUpdate=registry
Network=host
Volume=/home/user/podman/uptime-kuma:/app/data
[Service]
Restart=always
[Install]
WantedBy=default.target
Understanding the Quadlet File
The quadlet file structure mirrors systemd unit files but with container-specific sections:
[Unit] - Standard systemd unit metadata
Description
- Human-readable name for the serviceAfter=network.target
- Start after network is available
[Container] - Container-specific configuration (replaces podman run
flags)
Image
- The container image to useAutoUpdate=registry
- Automatically check for image updates (used withpodman auto-update
)Network=host
- Equivalent to--network=host
Volume
- Mount host directories (equivalent to-v
)
[Service] - Service behavior
Restart=always
- Restart policy (replaces--restart always
)
[Install] - Systemd installation settings
WantedBy=default.target
- Enable the service to start on boot
Start the container
systemctl --user daemon-reload
systemctl --user start uptime-kuma
When you run daemon-reload
, systemd triggers the podman-systemd-generator, which:
- Reads
uptime-kuma.container
- Generates a native systemd service file (usually in
/run/user/1000/systemd/generator/
) - Registers it with systemd
You now manage the container like any systemd service:
systemctl --user status uptime-kuma
systemctl --user stop uptime-kuma
systemctl --user restart uptime-kuma
journalctl --user -u uptime-kuma -f # View logs
Autostart
Does it start automatically after reboot or other issues? Yes, thanks to two things in the quadlet file:
[Service]
Restart=always
[Install]
WantedBy=default.target
The [Install]
section tells the quadlet generator to enable the service at boot - it does this automatically when you run systemctl --user daemon-reload
. No separate systemctl enable
command needed.
The Restart=always
ensures the container restarts if it crashes or stops for any reason (just like the --restart always
flag in podman run
).
Beyond Basic Containers
Quadlets support more than just containers:
Pods (.pod
files) - Run multiple containers as a unit
[Pod]
PodName=my-app
PublishPort=8080:8080
Networks (.network
files) - Define custom networks
[Network]
NetworkName=my-network
Subnet=10.89.0.0/24
Volumes (.volume
files) - Manage persistent storage
[Volume]
VolumeName=my-data
You can then reference these in your .container
files:
[Container]
Pod=my-app.pod
Network=my-network.network
Volume=my-data.volume:/app/data
The systemd generator handles all the dependencies automatically.