Containers at boot.
systemd units, linger, and pods.
Yesterday’s containers vanished after a reboot. Wrap them as systemd user units so they auto-start even when nobody is logged in, and build a three-container pod for the API stack.
cuser2 rebooted the box and the containers from yesterday simply did not come back. That is not a bug, it is the default: rootless containers are tied to the user’s session and go away with it. cuser2 needs them starting at boot whether or not anyone is logged in, and while we are in there, the API stack, app plus redis plus postgres, wired together as a single podman pod so it can be managed as one thing.
Two facts explain both the disappearance and the fix. A rootless user’s services die at logout unless enable-linger keeps their manager running, and a generated systemd unit that points at a container by ID breaks the instant you recreate that container. enable-linger plus the —new flag, which makes the unit rebuild the container from its spec, are the whole answer.
The ticket
id cuser2 sudo loginctl enable-linger cuser2 sudo -iu cuser2 podman --version
Concept review. Linger, units, and pods.
man podman-generate-systemd man podman-pod man loginctl
By default systemd stops a user’s services at logout, so a rootless container dies with them. enable-linger keeps the user’s manager running independently, so units start at boot and survive logout. A pod is a group of containers that share a network namespace, like a Kubernetes pod, reachable from each other over localhost, with a single set of port mappings defined on the pod.
--new unit recreates the container from its spec at start --name NAME generate for one container or pod --files write .service files instead of stdout --restart-policy=always restart on failure
Enable linger and recreate the containers
sudo loginctl enable-linger cuser2
loginctl show-user cuser2 | grep -i linger # Linger=yes
mkdir -p ~/.config/systemd/user ~/webcontent ~/redis-data
echo "<h1>cuser2 web</h1>" > ~/webcontent/index.html
podman run -d --name dev-web -p 8081:80 \
-v ~/webcontent:/usr/share/nginx/html:ro,Z nginx:latest
podman run -d --name dev-cache -p 6380:6379 \
-v ~/redis-data:/data:Z redis:latestGenerate and enable systemd units
Generate a portable unit for each container, then, and this is the step people miss, stop and remove the manually started container before enabling the unit, or systemd hits a name conflict trying to start its own copy.
cd ~/.config/systemd/user podman generate systemd --new --name dev-web --files --restart-policy=always podman generate systemd --new --name dev-cache --files --restart-policy=always podman stop dev-web dev-cache podman rm dev-web dev-cache systemctl --user daemon-reload systemctl --user enable --now container-dev-web.service systemctl --user enable --now container-dev-cache.service podman ps
Build the api-stack pod
Create the pod with its port mappings, then add each container with —pod. The containers reach each other over localhost inside the pod.
podman pod create --name api-stack -p 8082:8080 -p 5433:5432
mkdir -p ~/postgres-data
podman run -d --pod api-stack --name api-db \
-e POSTGRES_PASSWORD=secret -e POSTGRES_USER=apiuser -e POSTGRES_DB=apidb \
-v ~/postgres-data:/var/lib/postgresql/data:Z postgres:latest
podman run -d --pod api-stack --name api-redis redis:latest
podman run -d --pod api-stack --name api-app \
-v ~/webcontent:/usr/share/nginx/html:ro,Z nginx:latest
podman pod ps
podman ps --podSystemd units for the pod
Generating from the pod name writes a unit for the pod and one for each container, and the pod unit pulls in the container units. Stop the manual pod first, then enable.
cd ~/.config/systemd/user podman generate systemd --new --name api-stack --files --restart-policy=always ls pod-* container-api-* podman pod stop api-stack podman pod rm api-stack systemctl --user daemon-reload systemctl --user enable --now pod-api-stack.service podman pod ps; podman ps
The reboot test
The real proof. Reboot, and because linger is on, everything should come back without anyone logging in.
exit sudo systemctl reboot # after reboot, without logging in as cuser2: sudo -iu cuser2 podman ps # all five containers up systemctl --user status pod-api-stack.service
Exam questions
Write the command first.
Q1. Display all systemd user services for the current user.
Q2. Generate a systemd unit for an existing container webserver that recreates it at start, saved to the user’s config directory.
Q3. Configure a rootless container mycache to start at boot and survive logout. Show every step.
Answers.
# A1 systemctl --user list-units --type=service | grep container- # A2 cd ~/.config/systemd/user podman generate systemd --new --name webserver --files --restart-policy=always systemctl --user daemon-reload # A3 (order matters) sudo loginctl enable-linger $(whoami) podman run -d --name mycache redis:latest podman generate systemd --new --name mycache --files podman stop mycache && podman rm mycache systemctl --user daemon-reload systemctl --user enable --now container-mycache.service
Final checklist: confirm everything works
If every check passes, the ticket is done.
# 1. cuser2 linger enabled loginctl show-user cuser2 | grep -i linger # 2. dev-web and dev-cache as enabled user units systemctl --user list-units --type=service | grep container-dev # 3. api-stack pod has app, db, redis and auto-starts podman pod ps # 4. after a reboot all five containers return without login # 5. all three exam commands written from scratch # 6. tracker entry checked off
Reply to cuser2: boot persistence solved. dev-web and dev-cache are systemd user units, the api-stack pod runs app, db, and redis as one managed unit, and the reboot test passed. Everything returns without an active login thanks to enable-linger.