Running containers as systemd services on Linux has traditionally required generating static systemd unit files using podman generate systemd. However, this older method produced complex, brittle unit files that struggled to adapt to container image updates and configuration changes. Beginning with Podman 4.4, the recommended, enterprise-standard approach is Quadlet. Quadlet allows administrators to write clean, declarative unit description files (such as .container files) that systemd automatically converts into fully managed services on boot.
The Architecture and Advantages of Quadlet
Quadlet operates as a systemd generator. During the early boot phase or whenever systemctl daemon-reload is invoked, Quadlet scans designated directory trees, parses your simplified container definitions, and dynamically synthesises transient, native systemd service units in memory.
- Declarative Simplicity: Instead of managing long
podman runcommand strings, you define container options using structured INI-style syntax. - Native Rootless Support: Works seamlessly within rootless user sessions (
~/.config/containers/systemd/) without requiring root privileges. - Automatic Dependency Handling: Handles volume creation (
.volume), container networks (.network), and pod groupings (.pod) natively. - Self-Healing and Auto-Restart: Fully integrated with systemd’s robust restart timers, watchdog triggers, and journald logging.
Configuring Quadlet File Directories
Quadlet discovers configuration files depending on whether services run rootless or system-wide:
| Service Execution Mode | Standard Configuration Directory | Management Scope |
|---|---|---|
| Rootless (Per-User) | ~/.config/containers/systemd/ |
Runs under your non-root user context; binds unprivileged ports (>1024) |
| System-Wide (Root) | /etc/containers/systemd/ |
Runs under root context; suitable for core infrastructure services |
Creating Your First Declarative .container Unit
To demonstrate Quadlet, let us deploy an automated Nginx web server running rootless with an attached persistent volume and auto-restart policy.
- Create the user configuration directory:
mkdir -p ~/.config/containers/systemd/ - Create a new file named
nginx-web.containerinside that directory:nano ~/.config/containers/systemd/nginx-web.container - Enter the following declarative configuration:
[Unit]
Description=Nginx Web Server Container
After=network-online.target
[Container]
Image=docker.io/library/nginx:alpine
PublishPort=8080:80
Volume=%h/www:/usr/share/nginx/html:ro
AutoUpdate=registry
Network=host
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
In this definition, %h automatically resolves to your user’s home directory. Notice the AutoUpdate=registry directive, which instructs Podman’s auto-update service to pull newer images and restart the service automatically when new releases appear.
Activating and Managing the Service via Systemd
Once your .container file is saved, tell systemd to re-run its generators and discover the newly created unit:
- Reload the user systemd daemon:
systemctl --user daemon-reload - Start the synthesized container service:
systemctl --user start nginx-web.service - Verify the service status:
systemctl --user status nginx-web.service - Enable the service so it starts automatically upon user login:
systemctl --user enable nginx-web.service
Inspecting Generated Systemd Syntax
If you want to inspect the exact systemd unit code that Quadlet generated behind the scenes, use the dry-run generator command:
/usr/libexec/podman/quadlet -user -dryrun
This displays the raw unit file, including the full ExecStart directives and dynamic security parameters generated from your clean configuration.
Enabling User Linger for Autonomous Boot Execution
By default on Linux distributions like Ubuntu, Fedora, and Debian, systemd terminates user processes when a user logs out of their terminal session. To ensure your rootless Quadlet containers start automatically at system boot and continue running in the background without an active session:
loginctl enable-linger $USER
Adopting Podman Quadlet simplifies container life-cycle management across Linux servers, replacing brittle shell scripts with resilient, declarative infrastructure that systemd manages effortlessly.