Zum Inhalt springen
← Alle Beiträge
· 4 Min. Lesezeit·Emre Yurtbay

Podman 6.0: einen rootless Container als systemd-Service mit Quadlet betreiben

Wie Sie mit Podman 6.0 und Quadlet einen rootless Container als sauberen, autostart-fähigen systemd-Service betreiben – mit lauffähigem Caddy-Beispiel und den typischen Stolperfallen.

PodmanQuadletsystemdRootlessContainerSelf-HostingDevOps

Wer von Docker Compose kommt, kennt das Muster: ein Container als Dienst, der beim Booten hochfährt und nach einem Absturz neu startet. Unter Podman übernimmt diese Rolle nicht Compose, sondern systemd – und seit einiger Zeit beschreibt man solche Dienste deklarativ mit Quadlet. Sie schreiben eine kurze .container-Datei, systemd generiert daraus eine vollwertige Service-Unit. In Podman 6.0 (Juni 2026) ist Quadlet der Standardweg und noch enger integriert. Dieser Beitrag stellt einen einzelnen rootless Dienst auf die Beine: eine .container-Datei ablegen, daemon-reload, starten, prüfen, autostart-fähig machen.

Was Quadlet macht – und wann es passt

Quadlet ist ein systemd-Generator, der zur Laufzeit aus einer .container-Datei eine .service-Unit erzeugt. Sie pflegen keine handgeschriebenen Units mit langen ExecStart=podman run ...-Zeilen mehr, sondern eine kompakte, ini-artige Beschreibung im vertrauten Compose-Stil (Image, Ports, Volumes, Umgebungsvariablen). Das passt genau dann, wenn Sie einen oder wenige Dienste auf einem Host rootless und autostart-fähig betreiben wollen – etwa auf einem VPS oder Self-Hosting-Server. Für Orchestrierung über mehrere Knoten bleibt Kubernetes das Mittel der Wahl.

Rootless bedeutet: Der Container läuft im User-Namespace Ihres normalen Logins, nicht als root. Entsprechend arbeiten wir durchgehend mit systemctl --user, nicht mit dem System-systemd.

Ein Hinweis zu Podman 6.0 vorweg: cgroup v1 wird nicht mehr unterstützt, ebenso wenig CNI, slirp4netns und iptables. Rootless-Netzwerk läuft über pasta, Firewalling über nftables. Auf einem aktuellen Linux (cgroup v2, netavark/pasta) ist das der Normalfall – auf sehr alten Hosts sollten Sie das vor dem Upgrade prüfen.

Der minimale Dienst

Wir betreiben einen einfachen Webserver (Caddy) als rootless Service. Legen Sie die Quadlet-Datei im rootless-Suchpfad ab:

mkdir -p ~/.config/containers/systemd

Datei ~/.config/containers/systemd/web.container:

[Unit]
Description=Caddy web server (rootless, Quadlet)
After=network-online.target
Wants=network-online.target

[Container]
Image=docker.io/library/caddy:2
PublishPort=8080:80
Volume=web-content:/usr/share/caddy:Z
Environment=TZ=UTC

[Service]
Restart=on-failure

[Install]
WantedBy=default.target

Danach den Generator einlesen lassen und den Dienst starten:

systemctl --user daemon-reload
systemctl --user start web.service
systemctl --user status web.service

status sollte active (running) zeigen. Ein kurzer Test:

curl -I http://localhost:8080

Caddy antwortet auf Port 8080; das benannte Volume web-content legt Podman beim ersten Start automatisch an.

Die Bausteine der .container-Datei

  • [Container] ist der Kern. Image= gibt das Image an (voll qualifiziert, inklusive Registry, um Mehrdeutigkeiten zu vermeiden). PublishPort=8080:80 mappt Host-Port 8080 auf Container-Port 80. Volume=web-content:/usr/share/caddy:Z bindet ein benanntes Volume ein; das :Z setzt das SELinux-Label passend, falls Ihr System SELinux nutzt. Environment= setzt Umgebungsvariablen.
  • [Service] enthält klassische systemd-Service-Optionen. Restart=on-failure sorgt für den Neustart nach einem Absturz – das Pendant zur Compose-Restart-Policy.
  • [Install] mit WantedBy=default.target verankert den Dienst so, dass er beim Hochfahren der User-Session mitstartet.

Der Ablauf im Ueberblick:

   web.container  (~/.config/containers/systemd/)
          |
          |  systemctl --user daemon-reload
          v
   +---------------------+
   |  Quadlet-Generator  |  erzeugt Unit zur Laufzeit
   +----------+----------+
              |
              v
       web.service  (transient)
              |
              |  systemctl --user start web.service
              v
   +---------------------+
   |  rootless Container |  caddy:2   ->  Host :8080
   +---------------------+

Autostart ohne aktives Login

WantedBy=default.target allein genügt nicht, wenn niemand eingeloggt ist: Der User-Manager läuft standardmäßig nur, solange eine Session offen ist. Damit Ihr Dienst nach einem Reboot auch ohne Login startet, aktivieren Sie Linger für Ihren Benutzer:

loginctl enable-linger

Ab jetzt startet systemd Ihren User-Manager beim Boot und hält ihn nach dem Logout am Leben – der Container läuft dauerhaft.

Drei typische Stolperfallen

1. Servicename ist der Dateiname, nicht der Container-Name. Aus web.container wird web.service. Sie steuern den Dienst also mit systemctl --user start web.service – nicht über einen im Container gesetzten Namen. Verwechslungen führen zu „Unit not found“.

2. Kein systemctl enable für Quadlet-Dienste. Die generierten Units sind aus Sicht von systemd transient und lassen sich nicht mit systemctl enable für den Boot verankern. Der Autostart wird ausschließlich über [Install] WantedBy= in der .container-Datei plus daemon-reload gesteuert. Ein enable-Versuch schlägt fehl.

3. Ports unter 1024 gehen rootless nicht ohne Weiteres. Als normaler Benutzer dürfen Sie privilegierte Ports (< 1024) standardmäßig nicht binden. Deshalb PublishPort=8080:80 statt 80:80. Wollen Sie den Dienst nach außen auf Port 80/443 anbieten, setzen Sie einen Reverse Proxy davor oder passen net.ipv4.ip_unprivileged_port_start an – für den Einstieg bleiben Sie bei einem hohen Host-Port.

Wie es weitergeht

Damit steht ein sauberes, rootless Muster, das sich auf jeden weiteren Dienst überträgt: .container-Datei, daemon-reload, --user start, enable-linger. Naheliegende nächste Schritte sind eigene Netzwerke (.network) und Volumes (.volume) als weitere Quadlet-Dateien sowie das Zusammenfassen mehrerer Container in einem Pod (.pod). Die Details stehen in der offiziellen Dokumentation: podman-systemd.unit (Quadlet) und die Podman-Dokumentation.

Hinweis: Die Beiträge dieses Blogs werden unter Einsatz von KI erstellt und vor der Veröffentlichung redaktionell geprüft. Die redaktionelle Verantwortung trägt Emre Yurtbay (siehe Impressum).

Projekt besprechen