Automatically Update Podman Containers with Quadlet

Tested on Red Hat Enterprise Linux 10.2 (Coughlan)
Package podman-5.8.2-5.el10_2.x86_64
Applies to Any Linux host with Podman 4.6+ and systemd
Privilege sudo for rootful examples; systemctl --user for rootless timer units
Scope AutoUpdate=registry and local on Quadlet .container files, podman auto-update dry-run and apply, podman-auto-update.timer, schedule overrides, registry auth prerequisites, rollback behavior, Notify= readiness signals, and silent no-op diagnostics. Assumes you already run Quadlet-managed services. Does not cover Quadlet basics, full registry login, image signing, or generic systemd timer theory.
Related guides Podman Quadlet with systemd
Podman Quadlet troubleshooting

You want a Quadlet-managed container to pick up an updated image without hand-running podman pull and systemctl restart every week. Podman auto-update does that when the container carries the right label, the systemd unit recreates the container on restart, and the image reference can actually move. This guide walks a rootful registry update end to end with before-and-after container IDs, then covers the timer, auth, rollback, and the checks that explain silent no-ops.

The examples below use rootful Quadlet files under /etc/containers/systemd/ and systemctl without --user. Run podman with sudo in the same shell so you inspect the same storage the systemd units use.


Configure AutoUpdate=registry with Quadlet

Before you enable a timer, confirm three prerequisites. Most "nothing happened" reports trace back to one of them.

AutoUpdate=registry needs a fully qualified image name — quay.io/example/web:stable, not web:stable. The systemd unit must recreate the container on restart; Quadlet-generated services recreate the container when the unit is restarted, allowing the updated image to be used. A hand-written service that only runs podman start on an existing container cannot switch that container to a new image. Finally, a digest-pinned reference such as quay.io/example/web@sha256:abc123... does not move when the registry publishes a new build — use a mutable tag (:stable, :v1) that matches your release strategy.

The tested example uses a local lab registry so a second image digest can be published on demand. Replace this image with a fully qualified image from your own registry, such as quay.io/example/web:stable.

Write /etc/containers/systemd/autoweb.container:

ini
[Container]
Image=localhost:5000/autoweb:stable
AutoUpdate=registry
ContainerName=autoweb

[Install]
WantedBy=multi-user.target

Quadlet maps AutoUpdate=registry to Podman's io.containers.autoupdate=registry label on the generated podman run line. Reload systemd after every Quadlet edit:

bash
systemctl daemon-reload

Start the generated service:

bash
systemctl start autoweb.service

Confirm the container is running:

bash
sudo podman ps --filter name=autoweb --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}'

Sample output:

output
CONTAINER ID  IMAGE                            STATUS
f1e61efa1616  localhost:5000/autoweb:stable    Up 12 seconds

The auto-update label is what podman auto-update scans for:

bash
sudo podman inspect autoweb --format '{{index .Config.Labels "io.containers.autoupdate"}}'

Sample output:

output
registry

You can also read the label on the generated unit:

bash
systemctl show autoweb.service -p ExecStart --value

The ExecStart line includes --label io.containers.autoupdate=registry alongside the image reference.

Auto-update restarts the systemd unit when the image changes — a [Service] Restart= policy is not required for that behavior. Add a systemd Restart= policy separately if you also want the service restarted when the application exits independently of auto-update.


Registry vs local auto-update

With AutoUpdate=registry, Podman auto-update contacts the registry for the image referenced by the running container, compares the remote manifest digest to the digest the container uses, pulls when the registry tag points to a different digest, and restarts the systemd unit so Quadlet creates a container from the updated local image.

AutoUpdate=local suits images you build or import on the host. Podman does not pull from a registry for this policy. It compares the image used by the running container with the image of the same name in local container storage. If the local image has changed, Podman restarts the systemd unit.

Example Quadlet file /etc/containers/systemd/autolocal.container:

ini
[Container]
Image=localhost/autoweb-local:stable
AutoUpdate=local
ContainerName=autolocal

[Install]
WantedBy=multi-user.target

Typical local workflows include CI rebuilding and re-tagging over the existing name, an operator running podman build or podman load before auto-update runs, or another tool managing pulls while auto-update only reacts to local storage changes.

Topic registry local
Where it looks remote registry local image store
Registry pull may pull when remote digest differs does not pull as policy behavior
Image reference fully qualified registry path required local image name is central
Best fit registry-published releases local builds, imports, or externally managed pulls

Check for updates with --dry-run

sudo podman auto-update --dry-run shows what would change without pulling or restarting services:

bash
sudo podman auto-update --dry-run

Sample output (tested on the RHEL 10.2 lab host after the registry tag pointed to a different digest):

output
UNIT             CONTAINER               IMAGE                          POLICY      UPDATED
            autoweb.service  f1e61efa1616 (autoweb)  localhost:5000/autoweb:stable  registry    pending

Column meanings:

  • UNIT — systemd service Podman will restart
  • CONTAINER — current container ID and name
  • IMAGE — image reference from the container config
  • POLICYregistry or local
  • UPDATEDpending when the registry tag points to a different digest, false when nothing to do, true after a successful apply

For scripting, use JSON:

bash
sudo podman auto-update --dry-run --format json

After the host is current, the same command reports "Updated": "false".


Apply an update and verify it

Dry-run is planning. sudo podman auto-update pulls (when policy requires it), restarts the unit, and prints a result table.

Record the running container ID before you apply an update:

bash
sudo podman ps --filter name=autoweb --format '{{.ID}}'

Sample output (tested on the RHEL 10.2 lab host, before apply):

output
f1e61efa1616

Capture the image digest the container was created from:

bash
sudo podman inspect autoweb --format '{{.Image}}'

Sample output (tested on the RHEL 10.2 lab host, before apply):

output
sha256:52f7048cca7806193e2dcd38a36bbd5f2166ee7dc054310559bf72436c1a480f

Apply the update:

bash
sudo podman auto-update

Sample output (tested on the RHEL 10.2 lab host):

output
Trying to pull localhost:5000/autoweb:stable...
Getting image source signatures
...
            UNIT             CONTAINER               IMAGE                          POLICY      UPDATED
            autoweb.service  f1e61efa1616 (autoweb)  localhost:5000/autoweb:stable  registry    true

UPDATED is true and the pull lines confirm a different digest was pulled. The proof that systemd recreated the container is a new container ID after the unit restart:

bash
sudo podman ps --filter name=autoweb --format '{{.ID}}'

Sample output (tested on the RHEL 10.2 lab host, after apply):

output
07c0dd9cbbfc

The ID changed from f1e61efa1616 to 07c0dd9cbbfc, which means systemd created a fresh container rather than restarting the old instance in place. The same pattern works for local policy — after rebuilding localhost/autoweb-local:stable locally, dry-run showed pending and sudo podman auto-update reported UPDATED true with a new container ID.


Enable the podman-auto-update timer

Podman ships systemd units for scheduled checks:

text
podman-auto-update.service
podman-auto-update.timer

On the lab host the system timer was disabled until we enabled it:

bash
systemctl status podman-auto-update.timer

Sample output:

output
○ podman-auto-update.timer - Podman auto-update timer
     Loaded: loaded (/usr/lib/systemd/system/podman-auto-update.timer; disabled; preset: disabled)
     Active: inactive (dead)
    Trigger: n/a
   Triggers: ● podman-auto-update.service

Enable and start it when you want daily checks without cron:

bash
systemctl enable --now podman-auto-update.timer

For rootless Quadlet services under ~/.config/containers/systemd/, use the user timer from the same package (/usr/lib/systemd/user/podman-auto-update.timer). Enable it in the user session (systemctl --user enable --now podman-auto-update.timer) and ensure lingering is enabled so user timers fire after logout. Rootful and rootless timer wiring is similar, but the scope (system vs --user) must match where your Quadlet units live.


Change the update schedule

Read the installed calendar rather than assuming midnight. On RHEL 10.2 with Podman 5.8.2:

bash
systemctl cat podman-auto-update.timer

Sample output:

output
[Timer]
OnCalendar=daily
RandomizedDelaySec=900
Persistent=true

OnCalendar=daily fires once per day. RandomizedDelaySec=900 spreads load across a 15-minute window after that trigger. list-timers shows the next run on this host:

bash
systemctl list-timers podman-auto-update.timer

Sample output:

output
NEXT                        LEFT LAST PASSED UNIT                     ACTIVATES
Mon 2026-08-24 00:04:24 IST  20h -         - podman-auto-update.timer podman-auto-update.service

1 timers listed.

Your NEXT time will differ; it is derived from the calendar plus the random delay.

Override the vendor timer instead of editing /usr/lib/systemd/system/podman-auto-update.timer directly:

bash
systemctl edit podman-auto-update.timer

Example drop-in that runs at 02:00 daily:

ini
[Timer]
OnCalendar=
OnCalendar=*-*-* 02:00:00

An empty OnCalendar= clears the vendor value before you set a new one. Reload is automatic when you save the drop-in; confirm with systemctl list-timers podman-auto-update.timer.


Private registry authentication

Private registries require credentials in the auth file the auto-update run can read. Log in as the same identity that owns the containers — for rootful Quadlet units, that is root:

bash
sudo podman login quay.io

Auto-update runs under the podman-auto-update.service context for rootful units. If pulls fail with authentication required during timer runs but work interactively, the service likely cannot see your user auth file. See Log in to a container registry for auth-file paths, credential helpers, and the io.containers.autoupdate.authfile label when you must point a specific container at a non-default auth file.


Rollback when an update fails

podman auto-update enables rollback by default (--rollback=true). When a different image digest is pulled and systemd reports the restart as failed, Podman can revert to the previous image and restart the unit again. Rollback only works when systemd detects the failure — if the unit reaches active (running) before the application is actually ready, auto-update may treat the update as successful even when the process exits seconds later.

Improve rollback detection with Notify=

When the application natively supports systemd notification, tell Quadlet to wait for a real readiness signal:

ini
[Container]
Notify=true

When the app does not call sd_notify but you have a meaningful health check, tie service readiness to Podman health state:

ini
[Container]
HealthCmd=/usr/bin/curl -f http://localhost:8080/health
HealthInterval=30s
Notify=healthy

This example assumes the container image contains /usr/bin/curl; use a health command available inside your own image.

On Podman 5.8.2 the generated unit uses --sdnotify=healthy, and the service stays in activating until Podman reports healthy. That is not identical to in-app sdnotify — it validates whatever your HealthCmd exercises — but it is often enough for rollback to see a failed restart when the new image does not pass the check. Health check directive details live in Podman Quadlet container file.

Disable rollback for troubleshooting

To keep a failed new image in place for debugging:

bash
sudo podman auto-update --rollback=false

Default rollback is preferable when service availability matters. Turn it off only for controlled troubleshooting sessions.


Troubleshooting auto-update

Symptom Likely cause Fix
Dry-run lists no units missing io.containers.autoupdate label add AutoUpdate=registry or local in Quadlet; daemon-reload and recreate
Registry policy never pulls short Image= name use a fully qualified reference such as quay.io/example/web:stable
Registry policy never pulls digest-pinned Image= switch to a mutable tag that matches your release process
local policy never updates image rebuilt under a different name tag the new build over the same name the unit uses
Pull works manually, timer fails auth not visible to auto-update service sudo podman login for rootful units; check auth-file label
Update runs but old code shows unit only starts an existing container use Quadlet or a unit that recreates the container on restart
Timer never fires podman-auto-update.timer disabled systemctl enable --now podman-auto-update.timer (or --user)
Expected registry pull with local policy wrong policy for remote updates use AutoUpdate=registry when the registry is the source of truth
podman shows no container wrong storage scope use sudo podman for rootful Quadlet units under /etc/containers/systemd/

Work through sudo podman auto-update --dry-run first — it answers whether Podman sees a candidate update before you chase timer or auth issues. Timer and service history live in journalctl -u podman-auto-update.service and journalctl -u autoweb.service (add --user for rootless timers).


References


Summary

Podman auto-update on Quadlet-managed containers comes down to three ideas: label the unit with AutoUpdate=registry or local, use an image reference that can actually change, and let systemd recreate the container when the unit restarts. Quadlet writes the io.containers.autoupdate label for you and generates a service that recreates the container when restarted, which is the lifecycle auto-update requires. For rootful units under /etc/containers/systemd/, run podman with sudo so verification commands see the same containers systemd manages.

sudo podman auto-update --dry-run is the fastest way to see pending updates and policy per unit. A manual sudo podman auto-update run should change the container ID when the registry tag points to a different digest. Enable podman-auto-update.timer when you want that check daily; read OnCalendar and RandomizedDelaySec on your distribution instead of guessing the schedule.

Rollback protects you when the restart after an update fails, but only if systemd sees that failure. Use Notify=true when the app supports sdnotify; otherwise consider Notify=healthy with a real health command. When updates silently do nothing, verify the fully qualified image name, mutable tag, running timer, and dry-run output before you reopen registry credentials or Quadlet syntax.


Frequently Asked Questions

1. Does Podman auto-update work with the latest tag?

Yes, when you use a mutable tag such as latest, stable, or v1 with AutoUpdate=registry and a fully qualified image reference. A digest-pinned reference such as image@sha256:abc never moves, so auto-update has nothing new to detect.

2. Why does podman auto-update report nothing changed?

Common causes are a short image name without a registry host, a digest-pinned Image line, a registry tag that still points to the same digest as the running container, a unit that only starts an existing container instead of recreating it, missing registry auth, or a stopped podman-auto-update timer when you expected scheduled runs.

3. What is the difference between AutoUpdate registry and local?

Registry policy compares the running container image to the remote registry and may pull when the registry tag points to a different digest before restarting the systemd unit. Local policy compares the image used by the running container with the image of the same name in local container storage and restarts the unit when the local image has changed — it never pulls from a registry as part of the policy.

4. Do I need podman-auto-update.timer if I run podman auto-update manually?

No. The timer only schedules periodic checks. You can run sudo podman auto-update or sudo podman auto-update --dry-run on demand for rootful Quadlet units. Production hosts usually enable the timer so updates happen without a cron job.

5. What happens when an auto-update restart fails?

By default Podman rolls back to the previous image and restarts the unit again. Rollback only triggers when systemd reports the restart as failed, which is why sdnotify readiness and Notify=healthy matter for applications that start a PID before they are actually ready.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)