SELF-HOST, WITHOUT THE GUESSWORK

How to Self-Host MinIO on a VPS (Production Setup)

Run MinIO S3-compatible object storage on your own VPS. Store files without cloud storage fees.

How to Self-Host MinIO on a VPS (Production Setup)

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

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

  1. Click "Create Bucket"
  2. Enter a bucket name (lowercase, no spaces)
  3. Configure versioning and locking (optional)
  4. 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

Upload fails with 403

Console shows blank page

Slow upload/download speeds

Internal links

From across the StoicSoft network

Hand-curated reads on the same topic from sister sites in the StoicSoft family.