| 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 installed |
| Privilege | Rootful and rootless examples; rootless uses user podtest on the lab host |
| Scope | podman login and podman logout, auth file locations, --username, --password-stdin, --authfile, REGISTRY_AUTH_FILE, --compat-auth-file, credential helpers overview, --secret, --get-login, rootless vs rootful stores, authentication troubleshooting, and a reusable CI pattern. Does not cover private registry deployment, TLS or CA trust fixes, registries.conf mirrors, or push workflows in depth. |
| Related guides | Pull images with podman pull |
podman login stores registry credentials on disk so later podman pull, podman push, podman manifest push, and related registry commands can authenticate without prompting every time. It does not open a permanent session with the registry — it writes reusable auth material that Podman reads when a registry operation needs it.
Log in to a container registry
The usual interactive flow names the registry host:
podman login quay.ioPodman prompts for credentials:
Username:
Password:
Login Succeeded!Type your registry username and password (or access token where the registry treats tokens as passwords). Nothing in this flow keeps a long-lived connection open — success means credentials were saved locally.
Confirm which account was stored without printing the password:
podman login --get-login quay.ioWhen you are not logged in, the command fails clearly:
Error: not logged into quay.ioAfter a successful login, --get-login prints the username Podman will send for that registry host.
On the lab host we exercised the same workflow against a private registry at registry.example.com:5001 using non-interactive flags so the transcript stays scriptable. The auth file behavior is identical across registries.
Log in with an explicit username
When the username is already known, pass it on the command line:
podman login --username labuser registry.example.com:5001Podman prompts only for the password. That is handy when a human is at the keyboard and the registry account name is fixed.
Avoid putting the password on the command line:
podman login -u USER -p PASSWORD registry.example.com:5001The password lands in shell history and process listings. Scripts and CI should use --password-stdin instead.
Use --password-stdin for scripts and CI
Pipe the password so it never appears as a CLI argument:
printf '%s' "$REGISTRY_PASSWORD" | podman login --username "$REGISTRY_USER" --password-stdin registry.example.com:5001Sample output:
Login Succeeded!printf '%s' avoids the newline echo often adds and keeps the secret value under your control. The CI platform or secret store supplies $REGISTRY_PASSWORD; the article examples use environment variable names only, not real credentials.
See which auth file received the entry:
printf '%s' "$REGISTRY_PASSWORD" | podman login \
--username labuser \
--password-stdin \
--verbose \
registry.example.com:5001Sample output (tested as rootless user podtest on the lab host):
Used: /run/user/1014/containers/auth.json
Login Succeeded!The Used: line is the fastest way to confirm where Podman wrote credentials on your host.
Where Podman stores credentials
On Linux the default writable auth file for a normal login is under the runtime directory:
${XDG_RUNTIME_DIR}/containers/auth.jsonFor a typical rootless user that often resolves to:
/run/user/$UID/containers/auth.jsonRootful podman login as root on the lab host used a different default path:
/run/containers/0/auth.jsonThat file is JSON. Each registry host maps to a base64-encoded username:password pair — encoding is not encryption. Treat the file like a password store: restrictive permissions and appropriate ownership matter.
Because the default path sits under a runtime directory, it may disappear after reboot or when the user session ends. Do not assume an interactive podman login without --authfile is permanently persistent unless you have verified the path and your session model.
Store credentials in a persistent auth file
When credentials must survive reboots or be shared across several commands, choose the file explicitly:
mkdir -p ~/.config/containersLog in to the persistent file path:
printf '%s' "$REGISTRY_PASSWORD" | podman login --username "$REGISTRY_USER" --password-stdin --authfile ~/.config/containers/auth.json registry.example.com:5001Verbose output confirms the persistent path (tested as user podtest on the lab host):
Used: /home/podtest/.config/containers/auth.json
Login Succeeded!Check permissions — Podman created an owner-only file:
stat -c '%a %U:%G %n' ~/.config/containers/auth.jsonSample output:
600 podtest:podtest /home/podtest/.config/containers/auth.jsonPoint later registry operations at the same file:
podman pull --authfile ~/.config/containers/auth.json registry.example.com:5001/lab/hello:v1The pull succeeds when the registry holds that tag and the credentials in the auth file are valid. Push and manifest commands accept the same --authfile flag.
Rootless vs rootful authentication
Rootless and rootful Podman maintain separate credential stores because they run under different users with different HOME and runtime paths.
Log in as a normal user:
printf '%s' "$REGISTRY_PASSWORD" | podman login \
--username labuser \
--password-stdin \
registry.example.com:5001Log in separately for rootful operations:
printf '%s' "$REGISTRY_PASSWORD" | sudo podman login --username "$REGISTRY_USER" --password-stdin registry.example.com:5001Rootful verbose output on the lab host showed:
Used: /run/containers/0/auth.json
Login Succeeded!Rootless user podtest wrote to /run/user/1014/containers/auth.json instead. A pull that works as your user can still return unauthorized under sudo podman pull until root has its own login or both commands share an explicit --authfile.
How Podman chooses an auth file
--authfile or REGISTRY_AUTH_FILE selects the primary auth file. Without an override, Podman uses ${XDG_RUNTIME_DIR}/containers/auth.json. When credentials are not found there, containers/image can also search persistent containers auth and Docker-compatible files such as ~/.config/containers/auth.json, ~/.docker/config.json, and ~/.dockercfg, subject to credential-helper configuration.
When in doubt, run podman login --verbose once and read the Used: line rather than assuming a single global path.
Override the auth file with --authfile
Isolate credentials for automation or multiple registry identities:
podman login --authfile /secure/path/auth.json --username "$REGISTRY_USER" --password-stdin registry.example.com:5001Every registry command in that workflow must reuse the same path:
podman pull --authfile /secure/path/auth.json registry.example.com:5001/lab/hello:v1Per-command --authfile is ideal for CI jobs, short-lived service accounts, and keeping production registry credentials out of a developer’s default login store.
Set REGISTRY_AUTH_FILE for a session
Export a default auth file for compatible Podman commands in the current shell:
export REGISTRY_AUTH_FILE="$HOME/.config/containers/ci-auth.json"Log in without repeating --authfile:
printf '%s' "$REGISTRY_PASSWORD" | podman login --username "$REGISTRY_USER" --password-stdin registry.example.com:5001Verbose output on the lab host (tested as user podtest):
Used: /home/podtest/.config/containers/ci-auth.json
Login Succeeded!A later pull in the same shell picks up that file automatically:
podman pull registry.example.com:5001/lab/hello:v1Explicit --authfile on a command line overrides REGISTRY_AUTH_FILE. Export the variable only in shells or unit files where every registry operation should share one file.
Write Docker-compatible auth with --compat-auth-file
When another tool must read the same credentials, update a Docker-format config instead of the default Podman auth file:
printf '%s' "$REGISTRY_PASSWORD" | podman login --compat-auth-file ~/.docker/config.json \
--username labuser --password-stdin registry.example.com:5001Sample output (tested as user podtest on the lab host):
Used: /home/podtest/.docker/config.json
Login Succeeded!The file uses the familiar auths object Docker tools expect. This article does not cover Docker credential management in depth — only the Podman flag that produces interoperable output.
Credential helpers
Instead of keeping plaintext-equivalent material in auth.json, Podman and containers-image can delegate to external Docker-compatible credential helpers such as pass or secretservice. Helper binaries are named like docker-credential-pass and docker-credential-secretservice.
Per-registry helper mapping can live in a Docker-compatible auth file:
{
"credHelpers": {
"registry.example.com:5001": "pass"
}
}Global helper preference can also appear in registries.conf:
credential-helpers = [
"pass",
"containers-auth.json"
]The reserved value containers-auth.json means fall back to normal auth-file lookup. Full registries.conf behavior belongs in Configure registries.conf.
Log in with a Podman secret
Avoid placing the password in the shell environment by storing it as a Podman secret first:
printf '%s' "$REGISTRY_PASSWORD" | podman secret create registry-password -Log in referencing that secret:
podman login --username labuser --secret registry-password registry.example.com:5001Sample output (tested as rootless user podtest on the lab host):
Used: /run/user/1014/containers/auth.json
Login Succeeded!Secret creation, rotation, and runtime mounting are covered in Manage Podman secrets. Here the secret only supplies the login password.
Authenticate to Docker Hub
Docker Hub’s registry host is docker.io:
podman login docker.ioAfter login, pulls such as docker.io/library/alpine:latest can use your account’s authenticated quota instead of the lower anonymous pull allowance. This page does not reproduce full toomanyrequests diagnosis — see Fix Docker Hub rate limit when pulls fail with rate-limit errors despite correct credentials.
Authenticate to Quay
Red Hat Quay uses quay.io as the registry host:
podman login quay.ioUse your Quay username and password, or an application token where Quay expects token-based login. Account creation and robot token setup live in Quay’s own documentation — this guide only covers the Podman client side.
Authenticate to a private registry
Name the host and port your organization publishes:
podman login registry.example.com:5001Pull a private image after login:
podman pull registry.example.com:5001/lab/hello:v1If login or pull fails with certificate trust errors, fix CA trust or registry TLS configuration — see Configure Podman for a private registry and Fix x509 certificate signed by unknown authority. Disabling TLS verification is a lab shortcut, not the default answer for production registries.
Check whether credentials already exist
Before logging in again, ask Podman which username is stored:
podman login --get-login registry.example.com:5001Sample output when logged in:
labuserWhen nothing is stored, the same command exits with an error:
podman login --get-login registry.example.com:5001Sample output:
Error: not logged into registry.example.com:5001CI scripts can use --get-login to skip redundant login steps when the auth file already contains the registry.
Log out of a registry
Remove credentials for one host:
podman logout registry.example.com:5001Sample output:
Removed login credentials for registry.example.com:5001Confirm they are gone:
podman login --get-login registry.example.com:5001Sample output:
Error: not logged into registry.example.com:5001Clear every registry entry in the active auth store:
podman logout --allSample output:
Removed login credentials for all registriesLogout updates the local auth file or credential helper. It does not delete images you already pulled, and it does not revoke server-side tokens unless the registry provides that separately. Other users — including root versus your login user — keep their own stores.
Common login and auth errors
| Symptom | Likely cause | Fix |
|---|---|---|
unauthorized: authentication required |
wrong user, token, or registry host | verify hostname, username, and password; confirm you logged in to the same host you pull from |
| Login succeeds but pull fails unauthorized | different auth file or user context | compare podman login --verbose with the pull command; align --authfile, REGISTRY_AUTH_FILE, and rootless vs rootful |
| Credentials gone after reboot | default runtime auth.json |
log in with --authfile under $HOME/.config/containers/ |
CI authentication pattern
A reusable pattern for ephemeral runners:
AUTHFILE="$RUNNER_TEMP/podman-auth.json"
printf '%s' "$REGISTRY_PASSWORD" | podman login \
--authfile "$AUTHFILE" \
--username "$REGISTRY_USER" \
--password-stdin \
"$REGISTRY"
podman pull --authfile "$AUTHFILE" "$REGISTRY/project/image:tag"The same $AUTHFILE path serves login, pull, and push in one job. Let the CI environment delete $RUNNER_TEMP when the job finishes so the credential file does not linger on disk. Adapt variable names to GitHub Actions, GitLab CI, Jenkins, or any runner that exports secrets into the environment — this article stays provider-neutral.
References
Summary
podman login writes registry credentials to an auth file on disk so later pull and push commands can authenticate silently. The default location lives under the runtime directory and may not survive reboot, which surprises operators who expect a permanent login. Use --authfile or REGISTRY_AUTH_FILE when you need persistence, CI isolation, or a shared credential path across several commands.
Rootless and rootful Podman do not share the same default store — sudo podman pull after a user-level login often fails until you log in again as root or standardize on one auth file. For automation, pipe secrets with printf into --password-stdin and never pass -p on the command line. --get-login confirms which username is stored; podman logout removes local entries without deleting pulled images.
When authentication works but TLS or rate limits still block registry access, the fix lives in sibling guides for private registry trust, x509 errors, and Docker Hub quotas — not in repeating podman login with the wrong auth file.

