Back openDesk Edu for a sovereign, open-source education â every vote counts.
Vote nowSave products you love by clicking the heart icon.
SeaweedFS end to end: master/volume/filer architecture, logical volumes, replication, the S3 gateway, K8up backups, mirroring, and the TLS saga.
MinIO has become the de-facto standard for self-hosted S3-compatible storage. It provides a drop-in replacement for AWS S3 that runs anywhere â laptop, bare metal, Kubernetes â with the same API semantics.
The key architectural decision: MinIO replaces local filesystem storage with an S3 API. This decouples your application data from the server it runs on. Backups, replication, and disaster recovery become S3-native operations rather than filesystem scripts.
MinIO implements the same S3 API that AWS S3 uses. Any tool that speaks S3 works with MinIO:
import boto3
client = boto3.client(
"s3",
endpoint_url="http://minio:9000",
aws_access_key_id="minioadmin",
aws_secret_access_key="<password>",
)
client.create_bucket(Bucket="data")
client.upload_file("backup.sql", "data", "backups/daily.sql")
This compatibility extends to all S3 features MinIO supports:
What MinIO does NOT support (compared to AWS S3):
For most self-hosted workloads, the supported feature set is complete.
MinIO requires a root user (access key + secret key). Unlike AWS IAM, there's no separate root account â the credentials you set in .env are the superadmin:
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=a-strong-32-character-password
Important limitations:
mc admin user infoMinIO maps a local filesystem path (/data) to the S3 API. Each bucket becomes a subdirectory:
/data/
âââ .minio.sys/ # MinIO internal metadata
âââ data/ # S3 bucket "data"
â âââ uploads/
â âââ archives/
âââ backups/ # S3 bucket "backups"
âââ logs/ # S3 bucket "logs"
This flat file structure means you can browse MinIO data directly on disk (read-only â never write directly to /data outside MinIO).
For production deployments with multiple disks, MinIO's erasure coding provides RAID-like resilience without RAID overhead:
# With 4 data + 2 parity drives, tolerate 2 drive failures
docker compose run --rm minio server /disk{1..6}
Erasure coding uses Reed-Solomon encoding â data is split into N data shards and M parity shards. Storage overhead is M/N. For 4+2, overhead is 50% but tolerates 2 simultaneous drive failures.
The Nginx proxy in this stack serves three purposes:
MinIO's default configuration has conservative limits. The Nginx proxy overrides these for applications that need large uploads:
client_max_body_size 5G;
client_body_buffer_size 10M;
proxy_request_buffering off;
Setting proxy_request_buffering off is critical for uploads over 1GB â without it, Nginx buffers the entire request body to disk before sending to MinIO, causing writes for large uploads to stall.
Object storage is bandwidth-intensive. Rate limiting prevents any single client from saturating the network connection:
limit_req zone=minio_api burst=200 nodelay;
The burst size of 200 allows short spikes while enforcing a sustained rate limit of 100 requests/second.
S3 API connections can be long-lived (especially for multipart uploads):
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
These prevent Nginx from killing idle S3 connections prematurely.
The backup-agent container implements a layered backup strategy:
mc mirror --overwrite --watch local/data remote/data
The --watch flag enables continuous sync â changed files are mirrored immediately. For scheduled backups (e.g., nightly), omit --watch and run on a cron schedule.
Configure a remote endpoint (Backblaze B2, AWS S3, Wasabi) and mc mirror all buckets to the remote. The advantage of object-to-object backup vs. file-level backup:
mc mirror transfers only changed objectsAutomatically expire old data using bucket lifecycle rules:
{
"Rules": [
{
"ID": "expire-old-backups",
"Status": "Enabled",
"Expiration": {
"Days": 30
}
}
]
}
This runs at the MinIO level â no external cron job required.
MINIO_ROOT_PASSWORD (24+ characters, alphanumeric + symbols)minio server /disk{1..N})/minio/v2/metrics/clusterMINIO_VERSION to a specific release, not :latestmc mirror remote/data local/data in reversemc admin heal on a weekly cron for degraded drive detectionmc mirror is more reliable than filesystem-level backup for object storage