Podman Quadlet and Deprecated systemd Generation
`podman generate systemd` still runs and opens with `[DEPRECATED]`. It writes a static 35-line unit with the whole `podman run` command inside it; Quadlet reads a nine-line file and regenerates the unit on every reload.
systemd and Quadlet Guide 25 of 47 Intermediate
- OSUbuntu 26.04 LTS (resolute)
- Podman5.7.0
- Runtimecrun 1.21
- Networknetavark 1.16.1
- TimeAbout 11 min
- Reviewed22 August 2026
Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| PODMAN01 | 192.168.0.24 | Ubuntu 26.04 LTS | Primary Container Host | 2 Core | 4 GB | 50 GB |
Before you start
- guide 40 - the comparison is against the Quadlet unit built there.
-
The command tells you itself
It has not been removed, and asking for help is the fastest way to learn its status:
[DEPRECATED] Generate systemd units ... DEPRECATED command: It is recommended to use Quadlets for running containers and pods under systemd.Worth knowing because you will meet it in existing documentation, blog posts and older runbooks - most of the material written about running Podman under systemd predates Quadlet, and it all uses this command.
bash Example session podman generate systemd --help[DEPRECATED] Generate systemd units Description: Generate systemd units for a pod or container. The generated units can later be controlled via systemctl(1). DEPRECATED command:It is recommended to use Quadlets for running containers and pods under systemd. Please refer to podman-systemd.unit(5) for details.Expected resultA
[DEPRECATED]banner and a recommendation to use Quadlet.Success conditionYou can recognise advice that is out of date from the command it uses.
-
What it produces
Run it against a container with
--files --newand it writescontainer-legacy.serviceinto the current directory - a complete, static unit you then copy into~/.config/systemd/user/andenableyourself.Look at what is inside it:
ExecStart=/usr/bin/podman run \ --cidfile=%t/%n.ctr-id \ --cgroups=no-conmon \ --rm \ --sdnotify=conmon \ --replace \ -d \ --name legacy docker.io/library/nginx:alpineThe container's entire definition is a shell command embedded in a unit file, and the image tag is on the last line of it. Also a
--cidfileand three%t/%nexpansions, because without Quadlet'sType=notifywiring the unit has to track the container ID itself.The header says
autogenerated by Podman, which is the trap: it was generated once, and from that moment it is a hand-maintained file. Nothing regenerates it when the container it came from changes.bash Example session podman generate systemd --name legacy --files --new DEPRECATED command:It is recommended to use Quadlets for running containers and pods under systemd. Please refer to podman-systemd.unit(5) for details./home/sysadmin/container-legacy.servicecat container-legacy.service# container-legacy.service# autogenerated by Podman 5.7.0# Sat Aug 22 11:51:54 UTC 2026 [Unit]Description=Podman container-legacy.serviceDocumentation=man:podman-generate-systemd(1)Wants=network-online.targetAfter=network-online.targetRequiresMountsFor=%t/containers [Service]Environment=PODMAN_SYSTEMD_UNIT=%nRestart=on-failureTimeoutStopSec=70ExecStart=/usr/bin/podman run \ --cidfile=%t/%n.ctr-id \ --cgroups=no-conmon \ --rm \ --sdnotify=conmon \ --replace \ -d \ --name legacy docker.io/library/nginx:alpineExecStop=/usr/bin/podman stop \ --ignore -t 10 \ --cidfile=%t/%n.ctr-idExecStopPost=/usr/bin/podman rm \ -f \ --ignore -t 10 \ --cidfile=%t/%n.ctr-idType=notifyNotifyAccess=all [Install]WantedBy=default.targetExpected resultA written filename, then a 35-line unit with a multi-line
podman runinsideExecStart.Success conditionYou have read a generated unit and can find the image tag in it.
-
Why the replacement is better, concretely
Put the two side by side for one ordinary task - change the image tag:
| |
generate systemd| Quadlet | |---|---|---| | what you edit |ExecStart, mid-command, in a generated file |Image=, one line | | after editing |daemon-reload,restart|daemon-reload,restart| | regeneration | none - the file is now yours | every reload | | lives in |~/.config/systemd/user/|~/.config/containers/systemd/| | enablement |systemctl enable|[Install]in the source file | | volumes, networks | flags in the command |Volume=,Network=keys | | auto-update | not supported |AutoUpdate=registry|The difference that matters is the third row. A generated unit is a snapshot; a Quadlet file is a source. Once you have edited a generated unit it has no relationship to the container it was made from, and the usual failure is regenerating it later and silently losing your changes.
Migrating is mostly mechanical: read the flags out of
ExecStartand write them as[Container]keys --pbecomesPublishPort=,-vbecomesVolume=,-ebecomesEnvironment=,--namebecomesContainerName=. Keep your[Service]and[Unit]sections as they are; Quadlet passes both through untouched, which is visible in the generated output in guide 40.One thing genuinely lost:
generate systemdcould produce a unit for a container that already existed, which made it a quick way to capture something you built interactively. Quadlet has no equivalent - you write the file. In practicepodman inspectgives you everything you need to write it.bash Example session rm -f container-legacy.servicepodman rm -f legacylegacyExpected resultThe generated file and its container removed.
Success conditionYou can convert an
ExecStartline into[Container]keys.
Troubleshooting
An old runbook's
podman generate systemdcommand no longer behaves as documented.Why: The command is deprecated and its defaults have shifted -
--newin particular changed what the unit does on restart.Fix:Do not extend it. Convert the unit to Quadlet, which is where the development is.
You migrated to Quadlet and both units now fight over one container name.
Why: The old unit is still enabled in
~/.config/systemd/user/.Fix:
systemctl --user disable --now container-legacy.serviceand delete the file, thendaemon-reload.The generated unit worked and the Quadlet version fails to start.
Why: Usually a flag that has no direct key, or a
[Service]setting that conflicts with the generator's own.Fix:
systemctl --user catthe Quadlet unit and diff it against the old file. Anything with no Quadlet key can still be passed withPodmanArgs=.