Answer Overview
First, verify that the unit file generated by podman generate systemd will restart the container after a reboot. Then add security‑focused systemd directives for privileged containers, and finally avoid conflicts with the podman system service socket.
1. Verify restart‑on‑boot behavior
- Generate the unit (replace
myapp with your container name or ID):
podman generate systemd --new --name myapp > /etc/systemd/system/myapp.service
- Inspect the generated file for the essential directives:
# /etc/systemd/system/myapp.service
[Unit]
Description=myapp container
After=network-online.target
Wants=network-online.target
[Service]
Restart=always
ExecStart=/usr/bin/podman start -a myapp
ExecStop=/usr/bin/podman stop -t 10 myapp
KillMode=none
[Install]
WantedBy=multi-user.target
- Reload systemd and enable the unit:
systemctl daemon-reload
systemctl enable --now myapp.service
- Test the restart logic without a full reboot:
systemctl stop myapp.service # simulates container stop
systemctl start myapp.service # should start the container again
- Confirm the container state matches systemd:
podman ps -a | grep myapp
systemctl status myapp.service
- Optional: simulate a boot by restarting the host or using
systemctl reboot in a test VM, then verify systemctl is-active myapp.service returns active.
2. Security‑hardened directives for privileged containers
If the container requires extra capabilities (e.g., --privileged or specific --cap-add flags), limit the attack surface with systemd sandboxing options. Add these to the [Service] section of the unit:
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_NET_RAW – retain only the capabilities the container truly needs.
AmbientCapabilities= – clear any inherited ambient capabilities.
PrivateDevices=yes – block access to host device nodes.
ProtectSystem=full – make /usr, /boot, /etc read‑only.
ProtectHome=read-only – prevent writes to home directories.
NoNewPrivileges=yes – stop the container from gaining new privileges via setuid binaries.
PrivateTmp=yes, ProtectKernelTunables=yes, ProtectKernelModules=yes, RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX – further kernel‑level hardening.
Example snippet:
[Service]
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_NET_RAW
AmbientCapabilities=
PrivateDevices=yes
ProtectSystem=full
ProtectHome=read-only
NoNewPrivileges=yes
PrivateTmp=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
...
3. Avoiding conflicts with podman system service
The podman.socket unit provides an API socket that podman system service consumes. If you rely on custom ExecStart=/usr/bin/podman start lines, the socket is unnecessary and can cause double‑management.
- Check whether the socket is active:
systemctl status podman.socket
- If you do not need the API socket, disable and mask it:
systemctl disable --now podman.socket
systemctl mask podman.socket
- Alternatively, keep the socket but ensure your custom unit does not also start the container via the API (i.e., do not use
ExecStart=/usr/bin/podman run that contacts the socket). The --new flag to podman generate systemd creates a unit that talks directly to podman binaries, avoiding the socket.
- Verify that only one mechanism manages the container:
podman ps -a # shows container state
systemctl list-units --type=service | grep myapp
Both should agree; if the container appears twice or shows conflicting states, re‑examine whether both the socket unit and your custom unit are trying to start/stop it.
Missing diagnostic detail
To give a definitive recommendation about lingering permissions, please confirm whether you are using rootful or rootless podman. Rootless operation requires loginctl enable-linger $USER for the unit to start after a user logout.