TL;DR — Quick Summary

Deploy MinIO as a self-hosted S3-compatible object store. Configure buckets, access policies, TLS encryption, and troubleshoot common connectivity errors.

Why MinIO?

AWS S3 is powerful but expensive and locked to Amazon’s cloud. MinIO gives you the same S3 API — on your own hardware. It’s used by organizations like:

  • Development teams who need a local S3 mock that uses the real S3 protocol.
  • On-premises enterprises with data sovereignty requirements.
  • Homelab enthusiasts who want object storage without cloud bills.

Prerequisites

  • Linux server (Ubuntu 22.04 or RHEL 9).
  • At least 4 GB RAM and a dedicated data disk.
  • Root or sudo access.

Step 1: Install MinIO

Single-Node Setup (Quickest)

# Download the binary
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
sudo mv minio /usr/local/bin/

# Create data directory
sudo mkdir -p /data/minio
sudo chown $(whoami):$(whoami) /data/minio

# Set root credentials
export MINIO_ROOT_USER=minioadmin
export MINIO_ROOT_PASSWORD=StrongPassword123!

# Start MinIO
minio server /data/minio --console-address ":9001"
  • API endpoint: http://your-server:9000
  • Web Console: http://your-server:9001

Systemd Service (Production)

# /etc/systemd/system/minio.service
[Unit]
Description=MinIO Object Storage
After=network.target

[Service]
User=minio-user
EnvironmentFile=/etc/default/minio
ExecStart=/usr/local/bin/minio server /data/minio --console-address ":9001"
Restart=always

[Install]
WantedBy=multi-user.target

Environment file /etc/default/minio:

MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=StrongPassword123!
MINIO_VOLUMES="/data/minio"
sudo systemctl daemon-reload
sudo systemctl enable --now minio

Step 2: Install the MinIO Client (mc)

wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/

# Configure an alias pointing to your MinIO instance
mc alias set myminio http://localhost:9000 minioadmin StrongPassword123!

Common mc Commands

Command What it does
mc mb myminio/my-bucket Create a new bucket
mc cp file.txt myminio/my-bucket/ Upload a file
mc ls myminio/my-bucket List bucket contents
mc mirror /local/dir myminio/my-bucket Sync a local directory to a bucket
mc anonymous set download myminio/my-bucket Make a bucket publicly readable

Step 3: Connect Applications (S3 SDK)

Any S3-compatible SDK works with MinIO. Here’s a Python (boto3) example:

import boto3

s3 = boto3.client(
    's3',
    endpoint_url='http://minio-server:9000',
    aws_access_key_id='minioadmin',
    aws_secret_access_key='StrongPassword123!',
    config=boto3.session.Config(signature_version='s3v4'),
)

# Upload a file
s3.upload_file('local-file.pdf', 'my-bucket', 'remote-file.pdf')

# List objects
for obj in s3.list_objects_v2(Bucket='my-bucket')['Contents']:
    print(obj['Key'])

Key point: Always set force_path_style: true (or equivalent) when using non-AWS S3 endpoints, and use Signature Version 4.


Troubleshooting

Problem Solution
SignatureDoesNotMatch Verify access/secret keys match; ensure client uses S3v4 signatures
Connection refused on port 9000 Check MinIO is running (systemctl status minio); verify firewall allows 9000/9001
Slow uploads/downloads Use mc mirror with --multi-threaded for parallelism; check disk I/O with iotop
“Bucket already exists” error Bucket names are global within the instance; choose a unique name
TLS certificate errors Place public.crt + private.key in ~/.minio/certs/; restart MinIO

Summary

  • MinIO is a drop-in S3 replacement you can host yourself.
  • Use mc (MinIO Client) for CLI operations and boto3/aws-cli for application integration.
  • Always use S3v4 signatures and force_path_style: true.
  • Run as a systemd service in production with credentials in /etc/default/minio.