Leaving MinIO: Garage, VersityGW, and RustFS

Why MinIO had to go
For years MinIO was the obvious answer for self-hosted S3. Then the rug pull started. The condensed timeline:
- November 2024: MinIO Inc. announces AIStor, a commercial AI-focused product, timed to KubeCon NA 2024 (the Enterprise tier reportedly starts around $96k/year for up to 400 TiB). Clear signal that engineering attention had moved upmarket.
- May 2025: MinIO ships RELEASE.2025-05-24, which removes account management, policy management, bucket management, lifecycle/tier management, and site replication from the Community Edition web console. The CLI (
mc) still works, but the admin UI is effectively gutted. The community reaction is loud and unhappy. - December 2025: The
minio/miniorepo goes into maintenance mode. New features stop. Security fixes are handled case-by-case. - February 2026: README updated to “THIS REPOSITORY IS NO LONGER MAINTAINED”. Repo archived.
Independent write-ups: Blocks & Files, It’s FOSS, Vonng “MinIO is Dead”, and InfoQ.
First swap: Garage
I had heard good things about Garage (Rust, AGPLv3, designed for small geo-distributed clusters). On paper it looked perfect for my setup. In practice, running Garage as a single node on a Synology NAS surfaced two problems I never fully diagnosed:
- Intermittent hangs lasting several minutes, during which both the S3 API and any in-flight transfers stalled. My best guess at the time was that the internal scrub or garbage collection loop was acquiring a lock that blocked client I/O on a single-node deployment. I never proved this conclusively (the logs at the verbosity I was running were not specific enough).
- CPU spikes that did not always correlate with traffic.
Garage is explicitly designed for multi-node clusters with at least three nodes. Running it as a single node is technically supported but is not the intended use case, and I think this is what bit me.
Second swap: VersityGW
I moved next to VersityGW (Go, Apache-2.0). The pitch is different: it is not a storage system, it is an S3 gateway in front of a POSIX filesystem. On a Synology that I had already provisioned as a giant Btrfs volume, this fits perfectly. No erasure coding layer, no internal scrub loop, just plain files on disk with metadata in IAM directories. Backups are trivial because everything is just files.
It worked well for most of my buckets immediately. The first thing that bit me was Harbor (my container registry). Hosting Harbor on VersityGW ran into a pile of S3-protocol edge cases around blob finalization, which I never traced to specific commits. Harbor is sensitive to nuances in how CompleteMultipartUpload, HeadObject, and signed-URL GetObject are implemented, and VersityGW’s posix backend was tripping on one or more of those. Rather than file a series of issues against VersityGW for Harbor compatibility, I parked Harbor on a separate backend.
Next was Nextcloud, which uses an S3-compatible primary object store. Nextcloud always sends x-amz-acl: private on PutObject, and VersityGW v1.0–v1.2 responded with 501 NotImplemented. Every upload failed, including thumbnails and chunked file writes. I filed versitygw#1904 with the repro; PR #1875 added an opt-in --disable-acl flag in v1.3.0, and #1911 made “ignore unsupported ACL headers” the default behaviour shortly after. Today on v1.4.1 the issue is gone.
Third addition: RustFS for Harbor and Nextcloud
RustFS (Rust, Apache-2.0) is the project that markets itself most explicitly as a drop-in MinIO replacement. When I needed a second S3 endpoint for the two services VersityGW could not reliably host, RustFS was the obvious choice.
Today I run two S3 backends on the same Synology, fronted by Traefik with separate ingresses:
- VersityGW for backup buckets, document storage, certificate caches, registry mirrors that work fine with a POSIX backend, and most everything else. About 20 buckets.
- RustFS for Harbor (the container registry’s blob store), Nextcloud (with the
x-amz-acllegacy bucket on this side too), apublicbucket with anonymous read for static assets, and three flavours of Kubernetes backup buckets. About 9 buckets.
Both have intermittent issues. Both have responsive maintainers who fix things fast. Neither is what I would call boring infrastructure yet.
Some issues I’ve hit or filed
A non-exhaustive list, mostly so I can find them later when something breaks again.
RustFS
| Upstream issue | Symptom | Resolution |
|---|---|---|
| rustfs#1838 | x86_64 Docker image SIGILLs with exit 132 on launch | The binary was compiled with AVX-requiring instructions but no runtime CPU feature check. The Intel Celeron J4125 in my Synology DS920+ does not have AVX, so RustFS crashed before main(). Maintainer fixed it; current builds work on no-AVX CPUs. |
| rustfs#2047, #2036 | alpha.84 IAM regression: admin API returned “bucket does not exist”, every IAM user got 403 AccessDenied | Downgrade to alpha.80, then upgrade to alpha.90 once fixed. |
| rustfs#2457 | alpha.91 broke signed-URL GetObject with HTTP 502 BadGateway after ~5s. Harbor 500ed on every blob pull, Flux OCIRepository reconciles failed. | Fixed in alpha.92 via PR #2472. |
| rustfs#2497 | alpha.93 went unresponsive after ~24h with s3aws: InternalError: Io error: put_object_part write size < data.size(), w_size=0. Health endpoint still returned ok. Every multipart PUT silently wrote zero bytes. | Roll back to alpha.90. |
| rustfs#2587 | On alpha.94, with RUSTFS_SERVER_DOMAINS set, RustFS fails to start: logs freeze at Starting: /usr/bin/rustfs /data, admin info reports 0/1 drives online, IAM never loads, Harbor 500s on every OCI pull with InvalidAccessKeyId. | Roll back to alpha.90. |
| rustfs#2601 | alpha.95 single-node deployments enter a FaultyDisk / erasure-read-quorum state immediately on first write, S3 returns 500 across the board. | Roll back to alpha.90. |
alpha.96 .usage.json corruption | After running on alpha.96 for ~24h with a transient drive state change, both .usage.json and .usage.json.bkp XL objects became unreadable. Every restart afterward reported Storage resources insufficient and listed zero buckets. Persisted across upgrades. | Quarantine both objects on disk, restart. RustFS regenerates them on demand. Bucket data is fine, only the top-level usage manifest was corrupt. |
| rustfs#3028 | Upgrade to beta.4 on 2026-05-21 made every multipart-uploaded blob in the Harbor bucket return Io error: encrypted object metadata is incomplete. CI broke on a 93 MB Trivy DB pull within an hour. I do not run server-side encryption: the upstream report scoped this to SSE objects, but my reproducer showed it hits plain multipart objects too (any blob whose S3 ETag has the -N suffix). | Rolled back to alpha.90 the same afternoon. Posted the broader-scope reproducer on the issue. |
There are other RustFS issues and PRs I monitor on every release (#2761 Harbor push 500 on finalize, open; #2807 .usage.json read-quorum chain, closed in May 2026 but worth watching for recurrence; #2790 network FS scanner hang, open and unlikely to be fixed; #2996 scanner-timeout hardening PR, merged; #3031 multipart-put write Storage resources insufficient, open). I keep a per-version verdict table in a local skill so that “should I take the Renovate bump?” has an answer that does not depend on me remembering anything.
VersityGW
| Upstream issue | Symptom | Resolution |
|---|---|---|
| versitygw#1904 | PutObject returned 501 NotImplemented whenever the client sent x-amz-acl. Nextcloud broke on every upload. | PR #1875 added --disable-acl in v1.3.0; PR #1911 made the silent-ignore behaviour default. Resolved on v1.4.x. |
VersityGW’s other gotcha for me has been keeping the admin endpoint behind its own ingress with separate auth, because the admin API has full root authority and the public S3 endpoint should never see those calls. Once that was wired up, the system has been quiet.
Garage
No upstream issues filed. The hangs I saw on single-node Synology never produced a reproducer clean enough to send to the maintainers. I might revisit Garage once I can provision three nodes.
So is this production-ready?
If “production-ready” means “I can let it run for months and not look at it”, then VersityGW don’t really know, maybe? RustFS definitely not.
VersityGW’s posix backend is conceptually simple enough that the worst case is “files on disk that any other S3 implementation could also serve”. For backup, document storage, and registry mirrors that is the right shape.
RustFS is younger, in active development, and ships breaking changes inside the same minor-version series. Every Renovate bump is an event that needs a person reading the changelog, cross-referencing open issues against my own logs, and deciding whether to upgrade, hold, or roll back. The good news is that the maintainers are responsive and fixes do land within days. The bad news is that the load-bearing part of my Harbor registry is still on software where I rolled back inside an hour today. I keep alpha.90 warm.
I would not recommend this exact split to someone setting up a homelab from scratch in May 2026. Garage didn’t stick for me, but it’s probably the most mature option to reach for right now if you can afford multiple nodes; single-node was the wrong shape for what I needed. For a single-box setup, honestly I don’t really know. Try both VersityGW and RustFS and see which one sticks with you, but be prepared to debug a bit if you run many things on S3.
I am also keeping an eye on Alarik, another open-source S3-compatible object store.
I am apparently not the only one who ended up here. feld’s “I just want simple S3” surveys the same field (MinIO dead, Garage too heavy, SeaweedFS too slow on their setup) and lands on VersityGW for its filesystem-backed simplicity and speed. And Healthchecks.io moved to self-hosted object storage on VersityGW over Btrfs, after rejecting MinIO, SeaweedFS, and Garage as too operationally heavy for a solo operator. Same reasoning, same pick: an S3 gateway over plain files beats running a distributed storage system you don’t need.
The deeper-tech view (bucket layout, endpoints, what runs where) is in the Technical Deep Dive tab.