How to Generate systemd Service Files from Podman Containers

Generate systemd service files from Podman containers using the podman generate systemd command with the --new flag.

You rebooted and the container vanished

You ran podman run -d --name web nginx. The container started. You tested the endpoint. It works. You closed the laptop, went to sleep, and rebooted in the morning. The container is gone. You try systemctl enable web and get Unit web.service could not be found. You are stuck recreating the command manually every time the system restarts.

You need the container to behave like a proper system service. You need it to start on boot, restart on crash, integrate with systemctl, and survive reboots without manual intervention.

What's actually happening

Podman containers are processes. When the process dies, the container stops. The --restart flag helps, but it does not give you dependency ordering. If your database container needs the network, --restart might try to start before NetworkManager is ready. Systemd solves this. It manages dependencies, logs via journald, and handles restarts with backoff policies.

podman generate systemd bridges the gap. It reads the current container configuration and writes a systemd unit file that recreates that container exactly. Modern Fedora uses Quadlet files for this. The generator creates a .container file, which is the preferred format over the older .service files. Quadlet files are cleaner, easier to read, and integrate better with Podman's native options.

Config files in /etc/systemd/system/ are for user modifications. Never edit files in /usr/lib/systemd/system/. After creating or changing a unit file, you must run systemctl daemon-reload. Systemd caches unit metadata. Without reloading, systemd ignores your changes.

Reboot before you debug. Half the time the symptom is gone.

Generate the unit file

Run the generator against a running container. The --new flag is the most important part. It tells Podman to write a unit that creates a fresh container instance on boot. Without --new, the unit tries to start the existing container ID, which won't exist after a reboot.

Here's how to generate a Quadlet unit file from a running container and save it to the system directory.

podman generate systemd --new --name web > /etc/systemd/system/web.container
# --new ensures the unit creates a new container instance on boot
# --name targets the specific running container to clone the config from
# Output goes to /etc/systemd/system/ so systemd picks it up automatically

The output is a .container file. This is the Quadlet format. It contains sections like [Unit], [Container], and [Install]. The [Container] section holds Podman-specific directives. The generator captures ports, volumes, environment variables, and resource limits.

If your container uses named volumes, the generator may create separate .volume files. Check the output. If you see references to volume units, ensure those files exist in the same directory. Systemd will fail to start the container if a required volume unit is missing.

Run systemctl daemon-reload immediately after writing the file. Systemd does not watch the filesystem for changes. You must reload the configuration explicitly.

systemctl daemon-reload
# Reloads the systemd manager configuration to recognize the new unit file

Trust the package manager. Manual file edits drift, snapshots stay.

Enable and verify

Enable the unit for boot and start it immediately. The --now flag combines enable and start in one step.

systemctl enable --now web.container
# Enables the unit for boot and starts it immediately

Verify the service is active. Check the status and recent logs.

systemctl status web.container
# Shows active state, main PID, and recent log lines

If the service is active, check the logs for errors. Use journalctl with the unit filter.

journalctl -xeu web.container
# -x adds explanatory text, -e jumps to the end, -u filters by unit name

The -x flag adds explanatory text to log lines. This helps when you see a cryptic error code. The -e flag jumps to the end of the log. Most sysadmins type journalctl -xeu <unit> muscle-memory style.

Run journalctl first. Read the actual error before guessing.

Common pitfalls

If you omit --new, the generated unit contains ContainerName= pointing to the current ID. On reboot, that ID is invalid. The service fails immediately. Check the error. It will say something like Failed to start container <id>.

Failed to start container 8a3b2c1d4e5f: no such container

This error means the unit is trying to start a container that no longer exists. Regenerate the unit with --new.

Rootless containers require special handling. If you run containers as a normal user, the unit file belongs in the user systemd directory. The generator detects this if run as the user, but you must enable it with --user.

podman generate systemd --new --name web > ~/.config/systemd/user/web.container
# Rootless containers use the user systemd directory
systemctl --user daemon-reload
# Reload user manager configuration
systemctl --user enable --now web.container
# Enable and start in the user session

If you put a rootless unit in /etc/systemd/system/, it will fail with permission errors. The system manager runs as root. It cannot manage rootless containers directly. Use systemctl --user for rootless services.

Images change. The unit file pins the image ID by default. If you update the image, the container won't update until you regenerate the unit or use auto-update. Fedora provides podman-auto-update.timer for this. If the unit has WantedBy=podman-auto-update.target, the container gets updated automatically.

[Install]
WantedBy=multi-user.target podman-auto-update.target
# multi-user.target starts the service at boot
# podman-auto-update.target integrates with the auto-update timer

SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. The generated unit usually sets the right labels. If you see denials, check the logs. Do not disable SELinux to fix container issues.

Snapshot the system before the upgrade. Future-you will thank you.

When to use this vs alternatives

Use podman generate systemd --new when you have a running container and want to capture its exact configuration as a bootable service.

Use manual Quadlet files when you want a clean, version-controlled definition without relying on a running instance to generate the template.

Use podman auto-update when you want containers to pull new images automatically, but remember this requires the container to be managed by systemd or the auto-update timer.

Use the --restart flag when you are testing interactively and don't need full systemd integration yet.

Use podman pod generate systemd when your application spans multiple containers that must start and stop together.

If the boot menu is gone, GRUB rescue is your friend, not your enemy.

Where to go next