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

CommandWhat it does
mc mb myminio/my-bucketCreate a new bucket
mc cp file.txt myminio/my-bucket/Upload a file
mc ls myminio/my-bucketList bucket contents
mc mirror /local/dir myminio/my-bucketSync a local directory to a bucket
mc anonymous set download myminio/my-bucketMake 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

ProblemSolution
SignatureDoesNotMatchVerify access/secret keys match; ensure client uses S3v4 signatures
Connection refused on port 9000Check MinIO is running (systemctl status minio); verify firewall allows 9000/9001
Slow uploads/downloadsUse mc mirror with --multi-threaded for parallelism; check disk I/O with iotop
”Bucket already exists” errorBucket names are global within the instance; choose a unique name
TLS certificate errorsPlace 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.