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:

  1. Manually create and start a container with podman run
  2. Generate a systemd unit file from that running container
  3. Copy the generated file to the right location
  4. 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 service
  • After=network.target - Start after network is available

[Container] - Container-specific configuration (replaces podman run flags)

  • Image - The container image to use
  • AutoUpdate=registry - Automatically check for image updates (used with podman 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:

  1. Reads uptime-kuma.container
  2. Generates a native systemd service file (usually in /run/user/1000/systemd/generator/)
  3. 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.


Resources