Fixing Podman Login Credentials Disappearing After Reboot

When you run podman login with rootless Podman, the command succeeds, but after rebooting the machine, pulling a private image looks like you were never logged in. This usually does not mean the registry token suddenly expired. The login data was probably written to a temporary directory.

Symptom

The usual command looks like this:

podman login docker.io

podman pull works right after that. After a reboot, pulling the image again, or starting a Quadlet service that depends on a private image, fails with an unauthenticated or authorization error.

Use --verbose to see which auth file Podman actually used:

podman login --verbose docker.io

If the output contains a line like this, the credentials were written to the runtime directory:

Used: /run/user/1000/containers/auth.json

Cause

The official podman-login(1) documentation states that on Linux, the default authentication file read and written by podman login is:

${XDG_RUNTIME_DIR}/containers/auth.json

For a rootless user, that is commonly:

/run/user/1000/containers/auth.json

/run is usually a temporary filesystem and gets cleared after reboot. The Podman documentation also says this in its examples: the default credentials live under $XDG_RUNTIME_DIR, which is a directory under /run, so they do not persist across reboot.

That is why the problem feels like an “expired login”: the login flow worked, but auth.json disappeared.

Write to a persistent authfile

Write the credentials explicitly to the user configuration directory:

mkdir -p ~/.config/containers
podman login --authfile ~/.config/containers/auth.json docker.io
chmod 600 ~/.config/containers/auth.json

--authfile is the podman login option for specifying the authentication file path. Here we use ~/.config/containers/auth.json because it lives in the user’s home directory and survives system reboots.

If you use another registry, replace docker.io with the registry address:

podman login --authfile ~/.config/containers/auth.json quay.io
podman login --authfile ~/.config/containers/auth.json ghcr.io
podman login --authfile ~/.config/containers/auth.json registry.example.com

Verify it:

podman login --authfile ~/.config/containers/auth.json --get-login docker.io

If it prints your username, this auth file contains login data for that registry.

Set REGISTRY_AUTH_FILE

Adding --authfile only during login is not enough. Later Podman operations, especially pull/run and image pulls triggered by Quadlet, also need to know that they should read this persistent file by default.

Podman supports overriding the default authentication file path with REGISTRY_AUTH_FILE:

export REGISTRY_AUTH_FILE="$HOME/.config/containers/auth.json"

You can test it in the current shell:

podman pull docker.io/library/alpine:latest

To make it permanent for interactive shells, put it in ~/.profile, ~/.bashrc, or ~/.zshrc, depending on the shell you use.

export REGISTRY_AUTH_FILE="$HOME/.config/containers/auth.json"

If the image is pulled by a rootless Quadlet / systemctl --user service, writing the variable to a shell rc file may not pass it to the systemd user manager. You can set the environment variable directly in the Quadlet file under [Service]. This only affects that container service:

[Service]
Environment=REGISTRY_AUTH_FILE=%h/.config/containers/auth.json

After changing the Quadlet file, reload and restart the service:

systemctl --user daemon-reload
systemctl --user restart your-container.service