When running containers with Podman in rootless mode, a significant challenge emerges: containers started in a user session will stop when the session ends, even if they have the restart=always policy. This occurs because rootless containers are bound to the user session by default and do not persist across logouts or reboots.
SystemD and Quadlet address this limitation. Introduced in Podman 4.4, Quadlet simplifies SystemD service integration by replacing the deprecated podman generate systemd command. With Quadlet, we can ensure that rootless containers persist across reboots and user logouts, leveraging SystemD’s service management capabilities.
Setting Up a Container as a Rootless SystemD Service
To integrate a Podman container with SystemD using Quadlet, create .container files in the ~/.config/containers/systemd/ directory. The following example demonstrates an NGINX web server setup.
Step 1: Create the Quadlet Configuration File
Create webserver.container:
[Unit]
Description=Webserver
[Container]
Image=docker.io/library/nginx:alpine
PublishPort=8080:80
[Service]
Restart=always
[Install]
WantedBy=default.target
Why WantedBy=default.target?
For rootless services, using WantedBy=default.target is critical. Specifying only multi-user.target will prevent the service from starting automatically after reboot, since this target applies to system-wide (rootful) services, not user services.
To verify proper enablement at boot:
systemctl --user is-enabled webserver
An output of “enabled” confirms correct configuration.
Step 2: Reload and Start the Service
systemctl --user daemon-reload
systemctl --user enable --now webserver
Step 3: Verify Service Creation
Unlike systemctl --user daemon-reload, which provides no error messages for invalid files, you can verify proper service generation with:
systemctl --user cat webserver
If this command fails to return expected unit content, syntax errors or missing directives likely exist in the .container file.
Note: Even
journalctl --useroften provides little useful information, makingsystemctl --user catone of the most effective diagnostic tools for Quadlet service issues.
Adding a PostgreSQL Database with Persistent Storage
A more complex example demonstrates deploying a PostgreSQL container with persistent volumes.
Step 1: Define the Database Container
Create project-postgres.container:
[Unit]
Description=Postgres DB Project
[Container]
Image=docker.io/library/postgres:14-alpine
Environment=POSTGRES_USER=podman
Environment=POSTGRES_PASSWORD=mysecretpassword
Environment=POSTGRES_DB=training
PublishPort=5432:5432
Volume=project-postgres.volume:/var/lib/postgresql/data
[Install]
WantedBy=default.target
Step 2: Define the Persistent Volume
Create project-postgres.volume:
[Unit]
Description=Postgres Project Volume
[Volume]
Step 3: Reload and Enable Services
systemctl --user daemon-reload
systemctl --user enable --now project-postgres
Verify proper service creation:
systemctl --user cat project-postgres
Rootless vs. Rootful Considerations
Configuration locations and commands differ between rootless and rootful services:
Rootless services are placed in ~/.config/containers/systemd/ with user-scoped commands:
systemctl --user daemon-reload
systemctl --user enable --now webserver
Rootful services go into /etc/containers/systemd/ with privileged commands:
sudo systemctl daemon-reload
sudo systemctl enable --now webserver
What’s Next?
A forthcoming article will demonstrate deploying multiple interconnected containers, creating pods, and automating Quadlet file generation using Podlet.
For additional information, consult the official Podman SystemD Unit documentation.