Why I Ditched ‘podman generate systemd’ for Quadlet
If you’re running containers on Fedora, you’re likely familiar with the podman generate systemd command. This used to be the standard approach, but it leaves behind a lot of “technical debt.” The generated unit files are often dozens of lines long, containing hardcoded container IDs and making them extremely difficult to maintain. Every time you need to change an environment variable or mount an additional volume, editing the unit file feels like a nightmare.
I’ve used Fedora as my primary dev machine for over two years. When Podman 4.4 introduced Quadlet, I migrated all my personal services to this tool. Quadlet allows you to define containers via concise .container files, similar to systemd configuration. The system automatically compiles them into actual systemd units whenever you reload. It’s very clean and modern.
The biggest advantage is the ability to run rootless (without needing root privileges). On Fedora, Quadlet significantly boosts security without burdening DevOps engineers with complex, specialized configurations.
Preparing the Environment on Fedora
Most Fedora versions from 38 onwards come with the latest Podman pre-integrated. You can quickly check the version with the command:
podman --version
As long as you have version 4.4 or higher, Quadlet is ready to go. If you are using Fedora Minimal, install the necessary package:
sudo dnf install -y podman
An important note for rootless mode: To ensure containers start automatically with the system without requiring a login (via SSH or GUI), enable the linger feature:
loginctl enable-linger $USER
Deploying Your First Container with Quadlet
Forget Docker Compose or long-winded podman run commands. With standard user permissions, you only need to work in the directory: ~/.config/containers/systemd/.
Create the configuration directory if it doesn’t exist:
mkdir -p ~/.config/containers/systemd/
Let’s try setting up an Nginx instance as a personal web server. Create the my-web.container file:
nano ~/.config/containers/systemd/my-web.container
Copy the following configuration content:
[Unit]
Description=Nginx Web Server running with Quadlet
After=network-online.target
[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80
Volume=/home/user/html:/usr/share/nginx/html:Z
Environment=FOO=BAR
[Install]
WantedBy=default.target
Key parameters to note:
- [Unit]:
After=network-online.targetensures the container waits for network availability before starting. - [Container]: This is the heart of the file.
Image: Declares the image to use.PublishPort: Maps port 8080 on the host to port 80 inside the container.Volume: The:Zsuffix is a lifesaver on Fedora. It helps Podman handle SELinux labels automatically, completely avoiding frustrating “Permission denied” errors.
Activating and Managing the Service
After saving the file, Quadlet doesn’t apply changes immediately. You need to tell systemd to rescan the configuration:
systemctl --user daemon-reload
At this point, a service named my-web.service has been automatically created. You can control it like any normal system service:
# Start the service
systemctl --user start my-web.service
# Check operational status
systemctl --user status my-web.service
# Automatically run on boot
systemctl --user enable my-web.service
This process is incredibly smooth. To update the image, just run podman pull nginx:latest and then systemctl --user restart my-web. The system handles destroying the old container and creating a new one; no manual ID management required.
Inspection & Monitoring
Container logs are now part of the systemd journal. Centralized management makes it much easier to track down errors:
journalctl -f --user-unit my-web.service
If you want a closer look from a Podman perspective, the podman ps command still works perfectly. If the service doesn’t appear after a reload, use Quadlet’s debug tool:
/usr/libexec/podman/quadlet -user --dry-run
This command renders the raw systemd unit file. If there are syntax errors in your .container file, you’ll see error messages here instead of having to guess.
Practical Notes on SELinux and Ports
Many people disable SELinux because they find volume mounting annoying. Don’t do that. Instead of setenforce 0, use :Z for private volumes or :z for shared volumes. Fedora will automatically relabel them to protect the system while still allowing container access.
Regarding Ports, Fedora by default blocks non-root users from using ports below 1024 (like 80, 443). The best approach is to use high ports like 8080 or 8443, then use a Reverse Proxy like Caddy or Nginx in front to route traffic. This is both secure and follows rootless standards.
Moving to Quadlet is the right move if you want to manage containers professionally and achieve long-term stability on the Fedora ecosystem.

