Garage vs MinIO for Home Object Storage: When S3 Compatibility Isn’t Enough to Restore
Duncan Pell
August 25, 2026
The first time I trusted an S3-compatible bucket as a backup target, the upload job was green for six months. The restore was not. restic found a pack it could not read. rclone said the object was there and then handed me a 404 on a part. The console showed a bucket. The API had been “compatible enough” for writes that never came home.
MinIO was the default answer for years: Docker Compose, a root user, a console, erasure coding if you had the disks. Garage showed up for people who wanted a smaller binary and a cluster story that did not feel like a rejected AWS interview. Both speak enough S3 to fool a tutorial. Neither is S3. The difference shows up when you restore, when you version, when a client sends a header the server shrugs at, and when you thought a single-node “cluster” was a backup strategy.
If your product is “I can get last month’s photos back,” compatibility is a marketing word. Completeness is a restore drill.
What MinIO still is in a closet
MinIO is the familiar appliance. You give it disks, you get a console, you create a bucket, you paste an access key into restic or Paperless or a homegrown uploader. Erasure coding on a four-drive box is why a lot of people picked it over a folder of files. The operational muscle memory is everywhere. When something breaks, you can search the error and find a GitHub issue from 2021.
The less familiar part is the product around the binary. Licensing and feature splits have moved. The open path is still usable at home. It is not the same mental model as “MinIO is just S3 in Docker” from the blog you bookmarked in 2020. If you need a feature you saw in a screenshot of their enterprise console, check whether your build has it before you design a restore around it.
MinIO also likes to be a cluster even when you are one machine. That is fine until you treat the extra process as safety. One host, one power supply, one USB enclosure: erasure coding does not beat a house fire. I use MinIO as a protocol endpoint, not as an offsite. Offsite is another endpoint or a USB disk I have actually mounted.
What Garage is selling
Garage is a Deuxfleurs project aimed at small, sometimes geo-distributed deployments. The pitch is lighter ops than MinIO-as-cluster and an S3 API that is good enough for the clients indie hosts actually run. Configuration is explicit. Layout of nodes and capacity is something you think about instead of inheriting from a “just add four drives” demo.
That explicitness is why I like it for two houses or two NUCs. It is also why a Saturday MinIO refugee can feel lost. There is less console theater. There is more “did I assign this disk to the right zone.” If you wanted a GUI more than a layout, you will bounce back to MinIO and that is allowed.
Garage’s S3 coverage is intentionally incomplete. That is not an insult. It is a warning label. If your restore path uses a corner of the API MinIO implemented because someone needed object lock, Garage may not be your bucket. If your restore path is get-object and list-objects from restic, you are in the center of the Venn diagram.

Compatibility that writes and fails to read
S3 is a pile of verbs. PutObject and GetObject are the brochure. Multipart upload, list with pagination, copy, tagging, versioning, lifecycle, notifications, select, object lock, checksum algorithms, and the difference between path-style and virtual-hosted URLs are the rest. Backup tools wander around that pile.
restic is relatively polite. rclone can be configured to be polite or to use every flag. Nextcloud primary storage and random “S3 backup” WordPress plugins are not polite. They will send a header, get a silent ignore, and write a metadata file that only they can read — until they cannot.
The restore failure I see most is not “wrong password.” It is incomplete multipart: the upload looked done, a part never committed, the index in the backup tool points at an object that is a tombstone. MinIO and Garage will both let you get into that state if the client is sloppy and you never ran a check. The tool’s check or prune is not optional. A green cron is optional in the worst way.
The second failure is versioning. You enabled versioning because it sounded like backups. You filled a disk with delete markers. The restore pulled the latest version, which was empty, because a sync client uploaded a zero-byte file after a laptop crash. S3 versioning is not a time machine you understand until you have listed versions by hand. I keep versioning off on backup buckets and I let restic own history.
Path style, regions, and TLS names
Homelab S3 dies on DNS more than on disks. Virtual-hosted style wants bucket.s3.home.example. Path style wants s3.home.example/bucket. Some clients default to the AWS style and never work behind a wildcard you did not create. MinIO’s docs have been around this block for years. Garage will not invent your Traefik routes.
Region strings are another fake compatibility. AWS clients send us-east-1. Your server wants garage or us-east-1 or empty. The write succeeds after you cargo-cult a region. The restore from another machine uses a different default and signs the request for a different region. You will swear the bucket is empty. It is not. The signature is.
TLS is the third. A public ACME cert on a real name is boring and good. A LAN-only MinIO with a homemade CA is fine until the restore laptop does not have the CA. I have “failed” a restore because I was on a phone hotspot and the name did not resolve. The data was in the closet. Compatibility did not matter. Routing did.

When I pick MinIO
I pick MinIO when I want a console I can show my future tired self, when the clients are a mixed bag of plugins, and when I am staying on one box with a pile of disks. I still run a restore to a scratch directory every quarter. I still do not call erasure coding an offsite. I pin a version of the image because surprise upgrades and S3 are a mean combination.
I also pick MinIO when a vendor integration literally says MinIO in the docs. Compatibility is sometimes social. The plugin was tested on MinIO’s quirks. Garage might work. The support thread will not.
When I pick Garage
I pick Garage when I want two small nodes, a layout I can explain, and clients I have already tested: restic, rclone, maybe a self-hosted app with a short S3 allowlist. I test the restore on day one from a third machine. If the app needs object lock or a notification queue, I stop and go back to MinIO or to a real object store I pay for.
I like Garage’s honesty about being small. I do not like surprising a restore with a missing API. The way to like it is a written list of verbs your tools use. If you cannot write the list, you are not ready to switch implementations. You are ready to lose a Saturday.
The restore drill that decides
Pick a file you care about. Back it up through the real job, not a hand-crafted aws-cli put. Destroy the local copy. Restore to a new path. Open the file. Check the hash if you are the sort of person who has a hash. Do this after a reboot of the object node. Do this after you rotate a key. Do this from a laptop that is not the one that wrote the backup.
If that drill fails, the brand of S3 clone is a footnote. If it passes on MinIO and fails on Garage with the same tool, you learned something about compatibility that a feature table would have softened. If it passes on both, pick the one whose upgrade and layout you will actually maintain.
Disk full is the last compatibility lie. Both servers will accept writes until they cannot. The client may retry, split a multipart, or mark the snapshot complete from a partial index. I alert on free bytes the way I alert on a handshake. A bucket that lists objects is not a bucket that can take tomorrow’s increment.
S3 compatibility is a sales sentence. A restore is a file you can open. MinIO is the closet appliance with a long search history. Garage is the small cluster with a shorter API and a clearer layout. Use either as a protocol, not as a religion. Keep a copy that is not that protocol — a restic rest-server, a USB disk, a second vendor — until the drill has bored you. Boredom is the goal. Surprise is how packs go missing while the bucket still lists objects like nothing happened.