Why MinIO for Homelab Object Storage
The S3 API has become the universal interface for object storage. From backup tools like restic and duplicati, to applications like Immich, Mattermost, and Grafana Loki — everything speaks S3. Running a MinIO instance in your homelab gives you that API locally without depending on AWS, Wasabi, or Backblaze.
MinIO is a high-performance, S3-compatible object store written in Go. It runs as a single binary or Docker container, supports erasure coding for data protection, and ships with a web UI for management. Unlike hosted S3, you control the data, there are no egress fees, and it works perfectly on a single server or a cluster of homelab nodes.
Key features for homelab use:
- S3 API compatibility (works with all S3 SDKs and CLI tools)
- Built-in web console for management
- Erasure coding with configurable parity (N/2 and N/4)
- Bucket versioning and object locking (WORM)
- Identity management with IAM policies
- Prometheus metrics for monitoring
- Lightweight — ~50 MB RAM at idle
Use cases in a homelab include:
- Backup target for restic, borg, duplicati
- Application storage for Immich photos, Mattermost files, Grafana Loki chunks
- Static file hosting with public bucket policies
- S3-compatible test environment before deploying to production AWS
Docker Compose Single-Node Deployment
MinIO is designed to run on a single machine or a cluster. For most homelabs, a single-node deployment with one or more drives is sufficient.
Basic Docker Compose Setup
Create a directory and add this docker-compose.yml:
|
|
The command line is critical: server /data starts MinIO serving on port 9000 (API), and --console-address ":9001" starts the web UI on port 9001. Without --console-address, the console and API share port 9000 with path-based routing, which is less clean for reverse proxy setups.
Replace MINIO_ROOT_USER and MINIO_ROOT_PASSWORD with strong credentials. Store these in your password manager — they are the admin keys for the entire instance.
Deploy with:
|
|
Verify the API is healthy:
|
|
A healthy response is an HTTP 200 with body {"status":"alive"}.
Traefik Reverse Proxy Setup
Exposing MinIO through your Traefik reverse proxy gets you automatic Let’s Encrypt TLS, a clean subdomain, and middleware security. MinIO exposes two services — the S3 API on port 9000 and the Console web UI on port 9001 — so you need two router definitions.
Add labels to the compose service and switch to an internal-only port mapping:
|
|
Two environment variables are important when running behind a reverse proxy:
MINIO_SERVER_URL— tells MinIO the external S3 API URL. S3 clients need this to generate pre-signed URLs correctly.MINIO_BROWSER_REDIRECT_URL— sets the redirect target for Console authentication callbacks. Without this, MinIO redirects to the internal port after login.
After deploying, access the Console at https://minio.gntech.me and the S3 API at https://s3.gntech.me.
Initial MinIO Configuration
Creating Access Keys and Buckets
Log into the MinIO Console. The left sidebar has menu sections for Buckets, Access Keys, Identity, and Monitoring.
Create an access key:
- Go to Access Keys → Create Access Key
- Give it a description (e.g., “restic-backups”)
- Optionally restrict it to specific buckets or paths
- Save the generated key and secret — MinIO shows them only once
Create a bucket:
- Go to Buckets → Create Bucket
- Name it (e.g.,
homelab-backups,immich-photos) - Enable Versioning to protect against accidental overwrites
- Set Object Locking if you need WORM compliance
Bucket Access Policies
MinIO supports both managed policies and raw S3-style bucket policies. From the Console, you can attach built-in policies:
| Policy | Effect |
|---|---|
consoleAdmin |
Full admin access to MinIO itself |
diagnostics |
Read-only monitoring access |
readonly |
Read-only access to all buckets |
readwrite |
Read/write to all buckets |
writeonly |
Write-only (log sink pattern) |
For finer control, use a raw bucket policy in JSON. To make a bucket publicly readable (for static file hosting):
|
|
Paste this into Buckets → [bucket name] → Anonymous in the Console UI.
Multi-Drive Erasure Coding Setup
For production homelabs, running MinIO with multiple disks provides data durability through erasure coding. MinIO splits objects into data and parity shards across drives, tolerating up to half the drives failing.
Docker Compose with Multiple Volumes
Mount each physical or logical drive as a separate volume:
|
|
The command server /data{1...4} tells MinIO to use all four directories as erasure-coded drives. With 4 drives and default parity (N/2), MinIO tolerates 2 drive failures while still serving reads and writes.
Parity levels by drive count:
- 4 drives: EC:4, parity 2 (survives 2 failures)
- 6 drives: EC:6, parity 2-4
- 8 drives: EC:8, parity 2-4
- 12 drives: EC:12, parity 2-6
- 16 drives: EC:16, parity 2-8
MinIO automatically selects optimal parity when not explicitly specified.
Using the MinIO Client (mc)
The MinIO Client (mc) is a command-line tool that works with any S3-compatible service. The easiest way to use it in a homelab is with a Docker alias.
Configure mc
|
|
Basic Operations
|
|
Scripted Bucket Creation
For automated deployments, script bucket and user creation:
|
|
Backup and Migration Strategies
MinIO itself stores S3 data on disk, so you have several backup options.
Using mc Mirror for Backup
Mirror MinIO data to a local directory for offline backup:
|
|
Or to another S3 service (S3-to-S3 replication):
|
|
Restic with MinIO Backend
If MinIO is your backup target, configure restic with the S3 backend:
|
|
MinIO Versioning for Self-Service Recovery
Enable bucket versioning for automatic recovery from accidental deletions:
|
|
List and restore object versions:
|
|
Volume-Level Backup
Stop the container and back up the data directory:
|
|
If your MinIO data directory is on a ZFS dataset, use ZFS snapshots for instant, crash-consistent backups:
|
|
Prometheus Monitoring
MinIO exposes Prometheus metrics at the /minio/v2/metrics/cluster endpoint. Configure Prometheus to scrape it:
|
|
Or scrape directly from Docker metrics if you bind the port:
|
|
Key metrics to alert on:
minio_disk_storage_bytes/minio_disk_free_bytes— disk spaceminio_s3_requests_total— request rateminio_s3_errors_total— error rateminio_heal_objects_total— ongoing healing operations
Resource Usage
MinIO is efficient on modest hardware:
| Resource | Idle | Under Load (10 concurrent clients) |
|---|---|---|
| RAM | 40–60 MB | 200–400 MB |
| CPU | < 0.5% | 2–5% per core |
| Disk | Depends on data stored | I/O-bound on writes |
A single MinIO instance handles hundreds of concurrent S3 clients. For a homelab with 5–10 services using MinIO, the overhead is negligible.
Best Practices
- Use strong credentials —
MINIO_ROOT_USER/MINIO_ROOT_PASSWORDare the root keys. Do not share them with services. Create restricted access keys per application. - Always use HTTPS — MinIO access keys are sent in plain text over HTTP. Run behind Traefik or provide your own TLS certificate.
- Set
MINIO_SERVER_URLcorrectly — without this, pre-signed URLs generated by MinIO will point to the internal container address and break for clients hitting the reverse proxy. - Enable versioning on backup buckets — protects against accidental overwrites or ransomware.
- Use separate access keys per service — if one service is compromised, revoke its key without affecting others.
- Monitor disk space — MinIO continues accepting writes until the disk is full. Set up Prometheus alerting or configure mc admin watchdog thresholds.
- Pin your MinIO version — instead of
:latest, use a specific tag like:RELEASE.2026-04-01T00-00-00Zfor reproducible deployments.
Summary
MinIO brings S3-compatible object storage to your homelab with a lightweight Docker deployment. The S3 API is the lingua franca for modern application storage — backup tools, media servers, and analytics pipelines all speak it natively.
In this guide you deployed MinIO with Docker Compose, configured Traefik reverse proxy for both the S3 API and Console UI, set up erasure coding for data protection, learned the mc client for management and automation, and established backup strategies including versioning and cross-site replication. Deploy it today and give every service in your homelab its own S3 endpoint.