How to Deploy MinIO Object Storage on VPS for Self-Hosted S3 Storage

Cloud object storage based on the Amazon S3 API specification has become the foundational storage layer for modern software architectures. It powers database backups, static asset delivery, video streaming, user file uploads, and AI training datasets. However, hyperscale cloud providers like AWS S3 and Google Cloud Storage impose steep fees for monthly storage tiers and punishing egress bandwidth pricing.

MinIO is a high-performance, open-source object storage suite 100% compatible with the Amazon S3 API. Built in Go, MinIO is renowned for incredible throughput, capable of saturating 100GbE network interfaces. By deploying MinIO on your own Linux VPS, you establish a private, zero-egress S3 cloud that interfaces seamlessly with WordPress, backup scripts, Nextcloud, and modern applications.

1. Server Hardware Sizing & Architecture

Because MinIO is optimized for raw read/write throughput, disk speed and network bandwidth are primary considerations:

  • Storage Media: High-speed NVMe SSD or attached enterprise block storage. For production clusters, MinIO distributes data across drives using Reed-Solomon erasure coding.
  • RAM: 2GB baseline for standalone instances (4GB to 8GB recommended for heavy concurrent API operations).
  • Ports: Port 9000 for S3 API endpoints and Port 9001 for the web administrative console.

2. Production MinIO Docker Compose Deployment

Deploying MinIO via Docker Compose ensures clean dependency isolation, persistent data mapping, and automated restarts:

services:
  minio:
    image: minio/minio:latest
    restart: unless-stopped
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: minioadmin_user
      MINIO_ROOT_PASSWORD: MyUltraSecurePassword2026!
      MINIO_BROWSER_REDIRECT_URL: https://minio-console.yourdomain.com
      MINIO_SERVER_URL: https://s3.yourdomain.com
    volumes:
      - /opt/minio/data:/data
    networks:
      - minio_net
    ports:
      - "127.0.0.1:9000:9000"
      - "127.0.0.1:9001:9001"
    deploy:
      resources:
        limits:
          memory: 2048M

networks:
  minio_net:
    driver: bridge

Notice that ports 9000 and 9001 are bound strictly to 127.0.0.1. We will terminate SSL and manage public routing through an Nginx reverse proxy.

3. Configuring Nginx Reverse Proxy with TLS Certificates

MinIO requires separate domain endpoints for the S3 API and the web console. Configure an Nginx server block to handle both domains with HTTP/2 and large file upload buffers:

# S3 API Endpoint: s3.yourdomain.com
server {
    listen 443 ssl http2;
    server_name s3.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/s3.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/s3.yourdomain.com/privkey.pem;

    # Allow large uploads (up to 5GB per chunk)
    client_max_body_size 5000M;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 300;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        chunked_transfer_encoding off;
    }
}

# Web Administrative Console: minio-console.yourdomain.com
server {
    listen 443 ssl http2;
    server_name minio-console.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/minio-console.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/minio-console.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:9001;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # Support WebSockets for interactive console metrics
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

4. Managing Buckets and Access Keys via MinIO Client (mc)

While the web console is great for monitoring, the official mc CLI provides powerful programmatic administration:

# Download mc client binary
curl https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc
chmod +x /usr/local/bin/mc

# Configure alias pointing to local MinIO instance
mc alias set local-minio https://s3.yourdomain.com minioadmin_user MyUltraSecurePassword2026!

# Create a production bucket
mc mb local-minio/app-backups

# Generate dedicated read/write service credentials for an application
mc admin user add local-minio backup_agent SecretAgentPass456!
mc admin policy attach local-minio readwrite --user backup_agent

5. Connecting WordPress and Backup Clients to MinIO

Because MinIO follows the standard AWS S3 REST API specifications, any software supporting S3 works out-of-the-box:

  • Endpoint URL: https://s3.yourdomain.com
  • Region: us-east-1 (default dummy region accepted by MinIO)
  • Access Key: Your generated service key ID
  • Secret Key: Your generated secret token
  • S3 Path Style: Enabled (force path-style URLs)

MinIO Production Hardening, TLS Termination & Erasure Coding Guide

When transitioning MinIO from a single-drive development storage target to an enterprise production repository, adhere to these operational benchmarks:

  • Understanding Erasure Coding and Bitrot Protection: On multi-drive VPS setups or attached storage clusters, MinIO partitions data into data and parity blocks using Reed-Solomon erasure coding. This guarantees data survival even if multiple physical drives fail simultaneously and protects against silent bitrot corruption during deep storage archiving.
  • Automating Bucket Lifecycle Policies: Configure automatic object expiration or version pruning using the MinIO CLI to prevent logs and backup tarballs from consuming indefinite disk capacity:
    # Expire backup archives automatically after 30 days
    mc ilm rule add local-minio/app-backups --expire-days 30
    
    # Keep only the last 3 versions of any modified object
    mc ilm rule add local-minio/media-assets --noncurrent-expire-days 14
  • Benchmarking Network & Disk I/O Throughput: Test native read/write performance using MinIO’s built-in speedtest diagnostic utility:
    mc support perf net local-minio
    mc support perf drive local-minio

    On modern NVMe VPS nodes, MinIO consistently delivers sequential read speeds exceeding 1,200 MB/s, outpacing remote public S3 endpoints by orders of magnitude.

  • Configuring Multi-Part Upload Thresholds: For large assets (databases, raw VM images, 4K video), configure clients to utilize 64MB chunked multi-part streaming to maximize parallel socket utilization.

Build Your Private S3 Cloud on CpanelFree Storage VPS

Eliminate costly S3 egress fees. Host your own MinIO object storage cluster with high-capacity NVMe disks, unmetered bandwidth, and total privacy.

Discover CpanelFree Storage VPS →

Leave a Comment