MinIO is S3-compatible object storage you can run anywhere. Same API as AWS S3, but on your own infrastructure.
Self-hosting MinIO means predictable storage costs. No egress fees, no per-request pricing.
What you will have at the end
- MinIO running at
https://minio.your-domain.com - MinIO Console at
https://console.minio.your-domain.com - Automatic SSL via Traefik
- S3-compatible API for your applications
Step 1: Prepare the server
sudo apt update && sudo apt upgrade -y
Install Docker if needed:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
Step 2: Create directory structure
mkdir -p ~/apps/minio/data
cd ~/apps/minio
Ensure the data directory has enough space for your storage needs.
Step 3: Create docker-compose.yml
services:
traefik:
image: traefik:v2.11
command:
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --certificatesresolvers.letsencrypt.acme.tlschallenge=true
- [email protected]
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
ports:
- 80:80
- 443:443
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- letsencrypt:/letsencrypt
restart: unless-stopped
minio:
image: quay.io/minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
MINIO_BROWSER_REDIRECT_URL: https://console.minio.your-domain.com
volumes:
- ./data:/data
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 30s
timeout: 20s
retries: 3
labels:
# API endpoint
- traefik.enable=true
- traefik.http.routers.minio-api.rule=Host(`minio.your-domain.com`)
- traefik.http.routers.minio-api.entrypoints=websecure
- traefik.http.routers.minio-api.tls=true
- traefik.http.routers.minio-api.tls.certresolver=letsencrypt
- traefik.http.routers.minio-api.service=minio-api
- traefik.http.services.minio-api.loadbalancer.server.port=9000
# Console
- traefik.http.routers.minio-console.rule=Host(`console.minio.your-domain.com`)
- traefik.http.routers.minio-console.entrypoints=websecure
- traefik.http.routers.minio-console.tls=true
- traefik.http.routers.minio-console.tls.certresolver=letsencrypt
- traefik.http.routers.minio-console.service=minio-console
- traefik.http.services.minio-console.loadbalancer.server.port=9001
volumes:
letsencrypt:
Step 4: Configure environment variables
Create .env file:
# MinIO credentials (use strong values!)
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=$(openssl rand -base64 32)
cat > .env << EOF
MINIO_ROOT_USER=$MINIO_ROOT_USER
MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD
EOF
echo "MinIO Root Password: $MINIO_ROOT_PASSWORD"
Save these credentials securely. They are your S3 access keys.
Step 5: Deploy
docker compose up -d
Step 6: Access the console
Visit https://console.minio.your-domain.com and log in with your credentials.
Step 7: Create your first bucket
- Click "Create Bucket"
- Enter a bucket name (lowercase, no spaces)
- Configure versioning and locking (optional)
- Set access policy (private by default)
Step 8: Configure S3 client
Use any S3-compatible client or SDK:
# Install MinIO client
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
# Configure alias
mc alias set myminio https://minio.your-domain.com $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
# Test
mc ls myminio
Step 9: Use with applications
For applications expecting S3:
# Environment variables
AWS_ACCESS_KEY_ID=your-minio-root-user
AWS_SECRET_ACCESS_KEY=your-minio-root-password
AWS_ENDPOINT_URL=https://minio.your-domain.com
AWS_REGION=us-east-1 # MinIO ignores this but some SDKs require it
Backup strategy
MinIO data is in the mounted volume. Back it up like any other data.
#!/bin/bash
# Daily backup script
BACKUP_DIR=/backups/minio/$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
# Use mc mirror for efficient backup
mc mirror myminio/ $BACKUP_DIR/data/
# Or tar the data directory (stop MinIO first for consistency)
# docker compose stop minio
# tar -czf $BACKUP_DIR/minio-data.tar.gz ~/apps/minio/data
# docker compose start minio
For production, consider MinIO's built-in replication to another MinIO instance.
Troubleshooting
Cannot connect with S3 SDK
- Verify endpoint URL includes https://
- Check credentials match exactly
- Some SDKs need
force_path_style: truefor MinIO - Verify the bucket exists
Upload fails with 403
- Check bucket policy allows writes
- Verify access key permissions
- Review MinIO logs:
docker compose logs minio
Console shows blank page
- Clear browser cache
- Verify MINIO_BROWSER_REDIRECT_URL matches your console domain
- Check Traefik routing:
docker compose logs traefik
Slow upload/download speeds
- SSD storage significantly improves performance
- Check network bandwidth
- Consider enabling MinIO caching for read-heavy workloads
Internal links
- Tutorial: Deploy Docker Compose to VPS
- Tutorial: Self-Host Supabase
- Comparison: AWS S3 Alternatives
- ServerCompass: One-click MinIO deployment
From across the StoicSoft network
Hand-curated reads on the same topic from sister sites in the StoicSoft family.
Deploy HandbookCoolify vs Dokploy: Self-Hosted PaaS Comparison
Both let you run your own Heroku. Which one should you pick for your VPS?
Read on deployhandbook.com
Deploy HandbookBest Self-Hosted PaaS (2026): Coolify, Dokploy, CapRover, ServerCompass
A practical comparison of self-hosted PaaS options. Run your own Heroku alternative on a VPS for a fraction of the cost.
Read on deployhandbook.com
