The 401 UNAUTHORIZED error when you pull quay.io/minio/minio is not fixed with credentials: MinIO took public access away from that repository, and it fails for every tag. The fix is to switch the image to cgr.dev/chainguard/minio or pgsty/silo in your compose file, your Kubernetes deployment or your Helm chart values. This guide reproduces the error in Docker, k3s, BuildKit and the official chart, explains why Quay answers 401 and tests each fix. I tested it on 27 October 2026 on arm64 Linux with Docker 29.5.2, Compose v2.40.3 and k3s v1.37.0. There is a Spanish version of this guide.

Key takeaways

  • quay.io/minio/minio and quay.io/minio/mc return 401 for every tag: latest, RELEASE.2025-10-15T17-29-55Z and the 2024 versions the Helm chart pins.
  • Quay gives an anonymous user an empty permission on minio/minio, the same 401 it gives for a repository that does not exist, while the minio namespace still publishes 94 repositories.
  • quay.io/minio/aistor/minio does pull, but it is AIStor: without a license, creating a bucket fails with Access denied. No license is installed.
  • cgr.dev/chainguard/minio:latest (RELEASE.2026-10-23T20-06-51Z) and pgsty/silo:RELEASE.2026-10-26T00-00-00Z both started in Compose and in k3s.
  • In the MinIO Helm chart 5.4.0, change image and mcImage to pgsty/silo and the release starts.

If the message you see is pull access denied for minio/minio, you are coming from Docker Hub: the pull access denied for minio/minio guide covers that case and building from source.

The error: failed to resolve reference quay.io/minio/minio 401 UNAUTHORIZED

The message says the registry rejected the manifest request because you are not authorized, and it is the same in docker pull, docker compose pull and docker compose up when the image is not cached. This is what I got on 27 October 2026:

$ docker pull quay.io/minio/minio:RELEASE.2025-10-15T17-29-55Z
Error response from daemon: unknown: failed to resolve reference
"quay.io/minio/minio:RELEASE.2025-10-15T17-29-55Z": unexpected status
from HEAD request to https://quay.io/v2/minio/minio/manifests/
RELEASE.2025-10-15T17-29-55Z: 401 UNAUTHORIZED

$ docker compose up -d
 minio Pulling
 minio Error unknown: failed to resolve reference "quay.io/minio/minio:
 RELEASE.2025-10-15T17-29-55Z": unexpected status from HEAD request to
 https://quay.io/v2/minio/minio/manifests/RELEASE.2025-10-15T17-29-55Z:
 401 UNAUTHORIZED

In your terminal each message is a single line. I tried latest, RELEASE.2025-09-07T16-13-09Z, RELEASE.2025-04-22T22-12-26Z and RELEASE.2025-10-15T17-29-55Z, the last one ever published: all four fail the same way. So does quay.io/minio/mc. The tag makes no difference, so hunting for an older version does not help.

What does the same 401 look like in Kubernetes, BuildKit and other tools?

Each client wraps the 401 in its own text, but the cause is the same. This table collects what each one returned for the same image:

Tool Message you will see
docker pull, Compose unexpected status from HEAD request ... 401 UNAUTHORIZED
Kubernetes (containerd) failed to pull and unpack image ... 401 UNAUTHORIZED, then ImagePullBackOff
docker build with COPY --from failed to resolve source metadata for quay.io/minio/mc:latest
skopeo 1.22.3 unauthorized: access to the requested resource is not authorized
crane UNAUTHORIZED: access to the requested resource is not authorized

In Kubernetes the error shows up in the pod events. I reproduced it on k3s v1.37.0 running inside Docker with a kubectl run of the image; this is the event kubectl describe pod showed:

Warning  Failed  kubelet  Failed to pull image
"quay.io/minio/minio:RELEASE.2025-10-15T17-29-55Z": failed to pull and
unpack image "quay.io/minio/minio:RELEASE.2025-10-15T17-29-55Z": failed
to resolve reference "quay.io/minio/minio:RELEASE.2025-10-15T17-29-55Z":
unexpected status from HEAD request to https://quay.io/v2/minio/minio/
manifests/RELEASE.2025-10-15T17-29-55Z: 401 UNAUTHORIZED
Warning  Failed  kubelet  Error: ErrImagePull
Warning  Failed  kubelet  Error: ImagePullBackOff

The BuildKit case tends to go unnoticed. A Dockerfile with COPY --from=quay.io/minio/mc:latest /usr/bin/mc /usr/bin/mc kept building on my machine because the image was cached; with docker build --pull --no-cache it failed with the 401. Your CI, which starts with no cache, will hit it on the first run.

Why does quay.io return 401 if the image used to be public?

Because MinIO removed public access to the repository, and Quay answers 401 both for a private repository and for one that does not exist. I checked by asking quay.io/v2/auth for an anonymous pull token. For minio/kes the token grants "actions":["pull"]; for minio/minio it grants "actions":[]. With that token the manifest returns 401 for minio/minio, for minio/mc and for a made-up repository, minio/zz-no-existe-xyz.

The rest of the minio namespace is still open. The Quay API lists 94 public repositories, including kes, warp, operator and a whole series under aistor/. Only the community edition server and client are missing.

registry-stack issue 1402[1] dates the change to about 13:00 UTC on 24 September 2026. One of their CI runs pulled the image at 12:50 and the next one failed.

The reason is in the MinIO repository README[2], archived since April: "The MinIO community edition is now distributed as source code only. We will no longer provide pre-compiled binary releases for the community version." The same text points to AIStor Free and AIStor Enterprise as alternatives. There is no official community image in any registry. GitHub search shows the trickle of broken projects since then: LibreChat[3] on 25 September, a Snowflake Iceberg workshop[4] on 10 October and more this month.

Does the quay.io/minio/aistor/minio image work?

Not as a free replacement. quay.io/minio/aistor/minio:latest pulls without an account and reports RELEASE.2026-09-19T17-05-25Z with License: MinIO AIStor License. It starts and formats the drive, but without a license it stays locked, as its own container log says:

WARN: No valid license found, running in offline mode. All S3
operations are denied. Please install a valid license using
'mc license update' to restore service.

$ mc mb a/pruebas
mc: <ERROR> Unable to make bucket `a/pruebas`. Access denied. No
license is installed. Please install a valid license using
'mc license update' to enable service.

AIStor Free exists, but it is a different product, with a different license you have to install on the server. If you only swap the image, your application gets Access denied on every S3 request. I did not test with a license, so I cannot tell you how it behaves with one installed.

Fix in Docker Compose: which image to use now

Change the image: line to one of these two. Both pull without an account, publish arm64 and amd64 variants and are maintained today:

Image Version on 27 October 2026 User Maintainer
cgr.dev/chainguard/minio:latest RELEASE.2026-10-23T20-06-51Z 65532 Chainguard, from its fork
pgsty/silo:RELEASE.2026-10-26T00-00-00Z RELEASE.2026-10-26T00-00-00Z root Pigsty, community fork

Chainguard builds the image from its MinIO fork[5]. The fork got a security fix on 22 September and dependency updates on 23 October 2026. Silo[6], the Pigsty fork, has 4,340 stars and shipped releases on 18 and 26 October. This is the compose file I left running with Chainguard:

services:
  minio:
    image: cgr.dev/chainguard/minio:latest
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: ${MINIO_ROOT_USER}
      MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
    volumes:
      - datos:/data
    ports:
      - "127.0.0.1:9000:9000"
volumes:
  datos:

With a fresh volume it started first time and /minio/health/live returned 200; with Silo on the same image: line, so did it. If your volume already holds data written by the old image, which ran as root, Chainguard first needs a chown to 65532. The pull access denied for minio/minio guide shows the exact error and the command. Chainguard only publishes latest on its free tier, so pin the image by digest if you want reproducible deployments; Silo has per-version tags.

Fix in Kubernetes and in the MinIO Helm chart

In Kubernetes you change the deployment’s image, and Kubernetes replaces the pod stuck in ImagePullBackOff. I tested it on k3s with a Deployment that used the Quay image:

kubectl set image deployment/minio minio=cgr.dev/chainguard/minio:latest
kubectl rollout status deployment/minio

The new pod went to Running, but the MinIO log showed Rename across devices not allowed, because it had no volume on /data. With an emptyDir or a PersistentVolumeClaim mounted on /data and securityContext: {fsGroup: 65532} on the pod, it started cleanly and /minio/health/live answered HTTP/1.1 200 OK. If you do not have a test cluster yet, the guide to installing k3s in your homelab sets one up on a single machine.

The official Helm chart breaks twice. Version 5.4.0 on charts.min.io, the last one published, pins quay.io/minio/minio:RELEASE.2024-12-18T13-15-44Z for the server and quay.io/minio/mc:RELEASE.2024-11-21T17-21-54Z for the job that creates the buckets. After a helm install both pods sat in ImagePullBackOff. This values file fixes it:

image:
  repository: docker.io/pgsty/silo
  tag: RELEASE.2026-10-26T00-00-00Z
mcImage:
  repository: docker.io/pgsty/silo
  tag: RELEASE.2026-10-26T00-00-00Z

Apply it with helm upgrade your_release minio/minio --reuse-values -f silo-values.yaml. I picked Silo because its image ships /usr/bin/mc, which is what the chart’s job calls, plus the docker-entrypoint.sh the server uses.

The server started as Silo Object Storage Server and, from a pod running the same image, mc mb created a bucket against the service. The chart’s own job did not create it in my test: I started k3s without CoreDNS to save memory, so it could not resolve the service name. A cluster with DNS will not have that problem.

Fix in a Dockerfile that copies mc from the image

If your Dockerfile copies the client with COPY --from=quay.io/minio/mc, copy it from Silo instead. Its /usr/bin/mc is a symbolic link, so copy the real binary, mcli, and give it the usual name:

FROM mirror.gcr.io/library/alpine:3.22
COPY --from=docker.io/pgsty/silo:RELEASE.2026-10-26T00-00-00Z \
     /usr/bin/mcli /usr/bin/mc

The resulting image returned mc version RELEASE.2026-10-26T00-00-00Z and the binary is 28.7 MB. If your case is the createbuckets container in a compose file, the pull access denied for minio/mc guide tests three replacements for that pattern.

If you would rather not depend on a fork

Both images above are forks, and the MinIO code is archived. That leaves two paths.

The first is to build MinIO and mc yourself from the GitHub tags and push the result to your private Docker image registry; the Docker Hub guide includes a tested 22-line Dockerfile. The second is to leave MinIO: the MinIO to Garage migration copies the buckets with rclone to a lighter store, and the RustFS migration keeps the console, users and versioning.

Stay on a fork if you need a MinIO feature the destination lacks. In that case pin the version and watch the security advisories of the fork you choose, because the original repository no longer publishes any.

Frequently asked questions

Does docker login quay.io fix it?

I did not test with a Quay account. The anonymous token for minio/minio comes back with no permissions and the repository API answers Requires authentication, the same answer it gives for a made-up repository. MinIO has not announced account access to those images, so there is no reason to expect a personal account to fix it.

Why does my compose file start on one server and not on another?

Because the server that starts has the image cached, and Compose does not pull an image it already has. On my machine docker compose up -d started with quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z cached, and docker compose pull failed with the 401. A new machine, a CI runner or a freshly added Kubernetes node has no such cache.

Can I trust the Chainguard and Silo images?

Both are actively maintained and have a public fork you can review. Chainguard is a container image company; its catalogue of minimal images signs every image. Silo is a Pigsty community project with no affiliation to MinIO. Both keep the original AGPLv3 license, according to their --version output.

Conclusion

The quay.io/minio/minio 401 has been permanent since 24 September 2026 and does not depend on the tag or on your setup. To get unstuck, switch the image to cgr.dev/chainguard/minio:latest or to pgsty/silo with a fixed tag, in Compose, in Kubernetes or in the Helm chart’s image and mcImage values. Do not use the AIStor image from Quay without a license, because it denies every S3 operation. Then decide calmly whether to stay on a fork or migrate to Garage or RustFS.

Sources: [1] MinIO, archived repository README[2], [2] registry-stack, issue 1402 on the Quay 401[1], [3] Quay, minio/minio repository API[7], [4] MinIO, Helm chart values[8], [5] Chainguard, MinIO image[9], [6] Chainguard, MinIO fork[5], [7] Pigsty, Silo fork[6], [8] LibreChat, issue 259[3], [9] Snowflake Labs, apache-iceberg-from-zero issue 9[4].

Sources

  1. registry-stack issue 1402
  2. MinIO repository README
  3. LibreChat
  4. Snowflake Iceberg workshop
  5. its MinIO fork
  6. Silo
  7. Quay, minio/minio repository API
  8. MinIO, Helm chart values
  9. Chainguard, MinIO image