← All articlesCloud Infrastructure

MinIO S3-Compatible Object Storage: Complete Self-Hosted Guide

Deploy MinIO for S3-compatible object storage on your own servers. Covers single-node and distributed setups, bucket policies, lifecycle rules, and...

Y
Yash Pritwani
13 min read

Why MinIO?

Every application eventually needs object storage — file uploads, backups, static assets, data lake storage. AWS S3 is the standard, but its pricing adds up fast: $23/TB/month for storage plus $0.09/GB for egress. MinIO gives you the exact same S3 API, running on your own hardware, at zero marginal cost.

ProductionWeb ServerApp ServerDatabaseMonitoringStagingWeb ServerApp ServerDatabaseVLANBackupStorage3-2-1 Rule

Server infrastructure: production and staging environments connected via VLAN with offsite backups.

MinIO is not a toy project. It is Kubernetes-native, supports erasure coding, and handles petabyte-scale deployments. Companies like Siemens, VMware, and Samsung run MinIO in production.

Single-Node Docker Setup

For most self-hosted setups, a single-node MinIO deployment is sufficient:

# docker-compose.yml
version: "3.8"
services:
  minio:
    image: minio/minio:latest
    container_name: minio
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: admin
      MINIO_ROOT_PASSWORD: your-secure-password-32chars
      MINIO_BROWSER_REDIRECT_URL: https://s3-console.example.com
      MINIO_SERVER_URL: https://s3.example.com
    volumes:
      - /mnt/storage/minio:/data
    ports:
      - "9000:9000"  # API
      - "9001:9001"  # Console
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.minio-api.rule=Host(`s3.example.com`)"
      - "traefik.http.routers.minio-api.service=minio-api"
      - "traefik.http.services.minio-api.loadbalancer.server.port=9000"
      - "traefik.http.routers.minio-console.rule=Host(`s3-console.example.com`)"
      - "traefik.http.routers.minio-console.service=minio-console"
      - "traefik.http.services.minio-console.loadbalancer.server.port=9001"

Installing the MinIO Client (mc)

The MinIO Client is your Swiss army knife for managing buckets:

Get more insights on Cloud Infrastructure

Join 2,000+ engineers who get our weekly deep-dives. No spam, unsubscribe anytime.

# Install mc
curl -O 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://s3.example.com admin your-secure-password-32chars

# Verify connection
mc admin info myminio

Bucket Operations

# Create buckets
mc mb myminio/uploads
mc mb myminio/backups
mc mb myminio/static-assets

# Set bucket policy — public read for static assets
mc anonymous set download myminio/static-assets

# Upload files
mc cp ./file.pdf myminio/uploads/
mc cp --recursive ./dist/ myminio/static-assets/

# Sync directories (like rsync)
mc mirror ./local-dir myminio/backups/daily/

# List objects
mc ls myminio/uploads/ --recursive --summarize

Lifecycle Rules

Automate data management with lifecycle policies:

{
  "Rules": [
    {
      "ID": "expire-temp-uploads",
      "Status": "Enabled",
      "Filter": {
        "Prefix": "temp/"
      },
      "Expiration": {
        "Days": 7
      }
    },
    {
      "ID": "transition-old-backups",
      "Status": "Enabled",
      "Filter": {
        "Prefix": "backups/"
      },
      "Expiration": {
        "Days": 90
      }
    }
  ]
}

Apply it:

mc ilm import myminio/uploads < lifecycle.json

Using MinIO with Applications

Cloud$5,000/moMigrateBare MetalDocker + LXC$200/mo96% cost reduction

Cloud to self-hosted migration can dramatically reduce infrastructure costs while maintaining full control.

Node.js / TypeScript

import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";

const s3 = new S3Client({
  endpoint: "https://s3.example.com",
  region: "us-east-1",  // Required but ignored by MinIO
  credentials: {
    accessKeyId: "admin",
    secretAccessKey: "your-secure-password-32chars",
  },
  forcePathStyle: true,  // Required for MinIO
});

// Upload a file
async function uploadFile(bucket, key, body: Buffer) {
  await s3.send(new PutObjectCommand({
    Bucket: bucket,
    Key: key,
    Body: body,
    ContentType: "application/pdf",
  }));
}

// Generate presigned URL (valid 1 hour)
async function getPresignedUrl(bucket, key) {
  const command = new GetObjectCommand({ Bucket: bucket, Key: key });
  return getSignedUrl(s3, command, { expiresIn: 3600 });
}

Python

import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.example.com",
    aws_access_key_id="admin",
    aws_secret_access_key="your-secure-password-32chars",
    config=Config(signature_version="s3v4"),
)

# Upload
s3.upload_file("local-file.pdf", "uploads", "documents/file.pdf")

# Download
s3.download_file("uploads", "documents/file.pdf", "downloaded.pdf")

# List objects
response = s3.list_objects_v2(Bucket="uploads", Prefix="documents/")
for obj in response.get("Contents", []):
    print(f"  {obj['Key']} - {obj['Size']} bytes")

Distributed Setup (Multi-Drive)

For production with redundancy, use erasure coding across multiple drives:

services:
  minio:
    image: minio/minio:latest
    command: server /data{1...4} --console-address ":9001"
    volumes:
      - /mnt/disk1:/data1
      - /mnt/disk2:/data2
      - /mnt/disk3:/data3
      - /mnt/disk4:/data4

Free Resource

Free Cloud Architecture Checklist

A 47-point checklist covering security, scalability, cost optimization, and disaster recovery for production cloud environments.

Download the Checklist

With 4 drives and the default erasure coding parity, you can lose any 2 drives and still recover all data.

Backup MinIO Itself

# Mirror entire MinIO to local backup
mc mirror myminio/ /backups/minio-snapshot/ --overwrite

# Or mirror to another MinIO instance
mc mirror myminio/ backup-minio/ --overwrite

Performance Benchmarking

# Run MinIO's built-in benchmark
mc support perf object myminio/ \
  --size 64MiB \
  --concurrent 32 \
  --duration 60s

On a single NVMe drive, expect 1-3 GB/s for sequential writes and 2-5 GB/s for reads.

PromptEmbed[0.2, 0.8...]VectorSearchtop-k=5LLM+ contextReplyRetrieval-Augmented Generation (RAG) Flow

RAG architecture: user prompts are embedded, matched against a vector store, then fed to an LLM with retrieved context.

TechSaaS Integration

At TechSaaS, we use MinIO as the unified storage backend for backups, file uploads across multiple applications, and CI/CD artifact storage. It integrates seamlessly with any tool that speaks the S3 protocol — which is nearly everything.

Want S3-compatible storage without the AWS bill? Contact us at [email protected].

#minio#s3#object-storage#self-hosted#docker

Related Service

Cloud Solutions

Let our experts help you build the right technology strategy for your business.

Need help with cloud infrastructure?

TechSaaS provides expert consulting and managed services for cloud infrastructure, DevOps, and AI/ML operations.

We Will Build You a Demo Site — For Free

Like it? Pay us. Do not like it? Walk away, zero complaints. You will spend way less than hiring developers or any agency.

47+ companies trusted us
99.99% uptime
< 48hr response

No spam. No contracts. Just a free demo.