Skip to main contentSkip to navigation
[email protected]
Client AreaSupport
Hosting Mammoth
HostingMammothYour Data, Our Responsibility
Home
Solutions
Hosting Services
Store
Pricing
About
Blog
API
Contact

Stay Ahead of the Curve

Get the latest insights on cybersecurity, AI innovations, and enterprise data solutions delivered to your inbox.

Hosting Mammoth
HostingMammothEnterprise Solutions

Enterprise-grade data solutions. Hosting, recovery, cybersecurity, and AI-powered services for businesses worldwide.

[email protected]
Sun - Fri, 9:00am - 5:00pm

Services

  • Cloud Hosting
  • Data Recovery
  • Cybersecurity
  • Legal Support
  • MSP Services
  • Web Development
  • AI Services
  • Free Server Migration

Hosting

  • VPS Hosting (NVMe SSD)
  • VDS Hosting (NVMe)
  • Storage VPS (High SSD)
  • GPU Servers
  • Managed Services
  • Cloud Firewall
  • Load Balancer
  • One-Click Apps
  • n8n Hosting
  • Object Storage
  • FAQ

Company

  • Store
  • Pricing
  • About Us
  • Locations
  • Blog
  • Testimonials
  • Contact
  • Affiliate Program
  • White-Label
  • Terms of Service
  • Privacy Policy
  • Browser Cookies
  • SLA

Support

  • Client Area
  • Submit Ticket
  • Knowledge Base
  • Server Status
  • API Documentation

© 2026 Hosting Mammoth. All rights reserved.

Knowledge Base
Getting StartedAccount ManagementVPS HostingGPU ServersStorage VPSCloud FirewallLoad BalancerServer ManagementBilling & PaymentsSupport & TicketsAffiliate ProgramReseller ProgramMarketplace & Appsn8n HostingManaged ServicesServer MigrationAPI & DevelopersSecurityTroubleshootingGlossaryInstall Guides
  1. Home
  2. /
  3. Support
  4. /
  5. Install Guides
  6. /
  7. How To Install Minio Ubuntu
GUIDEInstall Guides

How to Install MinIO on Ubuntu 24.04 — Self-Hosted S3-Compatible Object Storage

29 min read

How to Install MinIO on Ubuntu 24.04 — Self-Hosted S3-Compatible Object Storage

MinIO turns a plain Ubuntu VPS into a high-performance, S3-compatible object store. It speaks the exact same API that Amazon S3 does, so anything built against the AWS SDK — Terraform, Velero, Restic, boto3, rclone, Kubernetes CSI drivers, Nextcloud, Paperless-ngx, backup tools — can point at your MinIO endpoint with nothing more than a URL and two new credentials. What you get in return is predictable flat-rate storage, full data sovereignty, and no surprise egress bill at the end of the month.

This guide walks through a complete production install on Ubuntu 24.04 LTS: from single-drive development mode, to a proper four-drive Single-Node Multi-Drive (SNMD) deployment with erasure coding, to SSE-KMS encryption with KES, Prometheus metrics, lifecycle rules, and an Nginx TLS reverse proxy in front of it all.

Skip the setup? A tuned Ubuntu 24.04 VPS with 400 GB NVMe is the right foundation for self-hosted object storage. Launch a Professional VPS now and follow along.

Table of Contents

  • What is MinIO?
  • Why Self-Host Object Storage?
  • Prerequisites
  • Step 1: Update System and Prepare Drives
  • Step 2: Install MinIO from the Official .deb
  • Step 3: Create the System User and Directories
  • Step 4: Single-Node Single-Drive (Development)
  • Step 5: Single-Node Multi-Drive with Erasure Coding (Production)
  • Step 6: Configure the systemd Service
  • Step 7: Install the mc Client
  • Step 8: Buckets, Policies, and Users
  • Step 9: Nginx TLS Reverse Proxy
  • Step 10: Server-Side Encryption with KES
  • Step 11: Prometheus Metrics and Monitoring
  • Step 12: Lifecycle Rules and Retention
  • Comparison: MinIO vs AWS S3 vs B2 vs Wasabi
  • Troubleshooting
  • FAQ
  • Next Steps
  • What is MinIO?

    MinIO is a high-performance, open-source object storage server written in Go. It implements the Amazon S3 API with a very high level of fidelity — so high that MinIO is frequently used as a drop-in replacement for S3 in local development, CI pipelines, and private-cloud production deployments. Its design goals are simple: speak S3, run anywhere, and saturate the underlying hardware.

    MinIO ships as a single static binary with no external database, no ZooKeeper, no etcd, and no managed control plane. State lives on the data drives themselves, encoded with Reed-Solomon erasure coding. You start the binary, point it at one or more drives, and you have object storage. That simplicity is the reason it shows up so often underneath Kubernetes registries, machine-learning data lakes, backup targets for Velero and Restic, media stores for Nextcloud and PhotoPrism, and tiering backends for Paperless-ngx.

    Operationally, MinIO runs in four topologies. Single-Node Single-Drive (SNSD) is a one-binary, one-path mode used for local development and CI — no redundancy, no erasure coding, instantly available. Single-Node Multi-Drive (SNMD) takes 4 or more drives on a single host and applies erasure coding across them, giving you drive-failure tolerance on a single machine. Multi-Node Multi-Drive (MNMD) spreads an erasure set across 4 or more machines so that whole nodes can fail. Site replication ties multiple MNMD clusters together across data centers for disaster recovery. This tutorial installs SNSD first for familiarity, then SNMD for production.

    Why Self-Host Object Storage?

    Object storage is one of the few workloads where the economics of self-hosting are genuinely compelling, especially at or beyond a few terabytes of stored data:

    • No egress fees. AWS S3 charges roughly USD 90 per TB of egress. Backblaze B2 charges USD 10 per TB. MinIO on your own VPS charges whatever your provider's bandwidth costs, which at VPS-Server.host is unmetered on all Professional plans.
    • Predictable flat-rate pricing. A Professional VPS is a fixed monthly bill regardless of how many PUT, GET, or LIST requests you make. S3 meters every one of those operations.
    • Data sovereignty. For EU-hosted VPS, your data lives under GDPR jurisdiction with no US CLOUD Act exposure. Useful for legal, medical, and financial workloads.
    • Genuinely compatible API. Anything built against the AWS SDK — aws s3 cp, boto3, Terraform's s3 backend, Velero, Restic, rclone, Kubernetes objectbucket.io — works unchanged.
    • Low latency. Your object store sits on the same LAN, or the same machine, as the workloads using it. First-byte latency drops from tens of milliseconds to single digits.
    • Full feature set. Erasure coding, object versioning, bucket replication, object locking (WORM), SSE-S3, SSE-KMS, lifecycle rules, and audit logs are all included in the open-source AGPL build.
    • No per-request billing surprises. A misconfigured client that lists a bucket in a loop costs you nothing. On S3 it costs USD 0.005 per 1,000 LIST operations, which adds up fast.
    The inflection point depends on workload. For pure cold archive (write-once, read-never) Backblaze B2 is cheaper than self-hosting below about 5 TB. For anything with meaningful read traffic — backups that get restored, media that gets served, ML datasets that get iterated — self-hosted MinIO is cheaper from the first terabyte.

    Prerequisites

    Before you start, make sure you have:

    • A VPS running Ubuntu 24.04 LTS with root or sudo access
    • SSH access to the server
    • At least 8 GB of RAM (16 GB recommended for production)
    • At least 4 drives or mount points for production SNMD (can be separate block volumes or separate directories on a single fast NVMe for dev)
    • A domain name pointing at your server if you want HTTPS via Let's Encrypt
    • Open ports: 9000 (S3 API) and 9001 (console), fronted by 443/TCP once Nginx is in place
    Recommended Plan: CloudCore Professional
    >
    For a production MinIO deployment storing a few hundred GB to a couple of TB, the Professional VPS plan is the right fit:
    >
    - 8 vCPU cores
    - 16 GB RAM
    - 400 GB NVMe SSD
    - Unmetered bandwidth
    - EUR 29.99/month
    >
    NVMe is a big deal for MinIO because erasure coding reads and writes shards in parallel. A single fast NVMe outperforms a mirror of rotating disks by an order of magnitude on small-object workloads. For 4 TB+ deployments, size up to the Storage tier or attach block volumes.

    Connect to your server:

    bash
    ssh root@your-server-ip

    Step 1: Update System and Prepare Drives

    Update the system first:

    bash
    sudo apt update && sudo apt upgrade -y
    sudo apt install -y wget curl gnupg ca-certificates xfsprogs

    MinIO strongly recommends XFS on the data drives. XFS handles extremely large directories and sparse files better than ext4, and it is the only filesystem MinIO officially supports for production.

    Prepare four data paths (SNMD)

    If your VPS has separate block storage volumes attached as /dev/vdb, /dev/vdc, /dev/vdd, /dev/vde, format and mount each as XFS:

    bash
    for disk in vdb vdc vdd vde; do
      sudo mkfs.xfs -f /dev/$disk
    done

    sudo mkdir -p /mnt/disk1 /mnt/disk2 /mnt/disk3 /mnt/disk4

    Get the UUIDs and add them to /etc/fstab:

    bash
    sudo blkid /dev/vdb /dev/vdc /dev/vdd /dev/vde

    Add entries like this to /etc/fstab (substitute your UUIDs):

    text
    UUID=xxxx-1 /mnt/disk1 xfs defaults,noatime 0 2
    UUID=xxxx-2 /mnt/disk2 xfs defaults,noatime 0 2
    UUID=xxxx-3 /mnt/disk3 xfs defaults,noatime 0 2
    UUID=xxxx-4 /mnt/disk4 xfs defaults,noatime 0 2

    Mount everything:

    bash
    sudo mount -a
    df -h /mnt/disk*

    No extra drives? Use four paths on one NVMe

    If you are deploying on a single NVMe VPS and only want to learn the SNMD workflow, four subdirectories on the same filesystem work for development:

    bash
    sudo mkdir -p /mnt/data/disk{1,2,3,4}

    This does not give you any real redundancy — losing the one underlying disk loses all shards — but it exercises erasure coding so your config and operational patterns carry over when you move to real multi-drive hardware.

    Step 2: Install MinIO from the Official .deb

    MinIO publishes signed .deb packages for every release. This is the recommended production install path because it drops in a systemd unit, a minio-user, and sane file layout.

    bash
    wget https://dl.min.io/server/minio/release/linux-amd64/minio_20260401000000.0.0_amd64.deb
    sudo dpkg -i minio_20260401000000.0.0_amd64.deb

    Check the install and the binary version:

    bash
    minio --version

    Expected output:

    text
    minio version RELEASE.2026-04-01T00-00-00Z

    The package installs:

    • The minio binary at /usr/local/bin/minio
    • A systemd unit at /etc/systemd/system/minio.service
    • A default env file placeholder at /etc/default/minio

    Step 3: Create the System User and Directories

    Create the dedicated minio-user system user (if the package did not already create it) and hand it ownership of the data paths:

    bash
    sudo groupadd -r minio-user 2>/dev/null || true
    sudo useradd -M -r -g minio-user minio-user 2>/dev/null || true

    sudo chown -R minio-user:minio-user /mnt/disk1 /mnt/disk2 /mnt/disk3 /mnt/disk4

    MinIO refuses to run as root by default. This is deliberate — a compromised MinIO process should not have root on the host.

    Step 4: Single-Node Single-Drive (Development)

    For a quick development install on one drive, write the env file and point MinIO at a single path:

    bash
    sudo tee /etc/default/minio > /dev/null <<EOF
    MINIO_VOLUMES="/mnt/data/minio-dev"
    MINIO_OPTS="--console-address :9001"
    MINIO_ROOT_USER=admin
    MINIO_ROOT_PASSWORD=ChangeMe_Minimum12Chars!
    EOF

    sudo mkdir -p /mnt/data/minio-dev sudo chown -R minio-user:minio-user /mnt/data/minio-dev

    About MINIO_ROOT_USER and MINIO_ROOT_PASSWORD: these are the cluster's initial superuser credentials. The username must be 3+ characters, the password 8+ (treat 16+ as the real floor). Anyone with these credentials has full control over every bucket and every object. In production you create scoped users with the mc client immediately after first boot and then rotate the root password — the root account is for bootstrap only.

    Start MinIO:

    bash
    sudo systemctl enable --now minio
    sudo systemctl status minio

    Open http://your-server-ip:9001 and log in with admin / your password. You are running. This SNSD deployment supports buckets, objects, and most S3 operations, but it does not support object versioning or site replication — those require erasure coding.

    Step 5: Single-Node Multi-Drive with Erasure Coding (Production)

    For production, switch MINIO_VOLUMES to reference all four drives at once. MinIO will apply Reed-Solomon erasure coding across them on first boot and will refuse to change topology later without rebuilding.

    bash
    sudo tee /etc/default/minio > /dev/null <<EOF
    

    MinIO production config — SNMD with 4 drives

    MINIO_VOLUMES="/mnt/disk{1...4}" MINIO_OPTS="--console-address :9001 --address :9000" MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=$(openssl rand -base64 32)

    Region (shows up in S3 API responses)

    MINIO_REGION=eu-central-1

    Browser redirect URL after login

    MINIO_BROWSER_REDIRECT_URL=https://console.storage.example.com

    Public server URL (presigned URLs reference this)

    MINIO_SERVER_URL=https://s3.storage.example.com EOF

    sudo chmod 640 /etc/default/minio sudo chown root:minio-user /etc/default/minio

    The {1...4} expansion is MinIO-native — it tells the server that all four paths are part of one erasure set. On the first start MinIO picks a default parity for a 4-drive set of EC:2, meaning it can survive the loss of 2 drives and still serve reads and writes. You can override this with MINIO_STORAGE_CLASS_STANDARD=EC:3 to trade capacity for durability.

    Erasure coding in one paragraph

    Every object written to an erasure-coded MinIO is split into N data shards and M parity shards (together they form the erasure set). The shards are written in parallel across your drives. Reading an object only needs N-of-(N+M) shards to reconstruct it, so you can lose up to M drives in the set and still recover every object. With four drives and default EC:2 parity, each write produces 2 data shards and 2 parity shards — usable capacity is 50% of raw, and you tolerate 2 drive failures. With 16 drives and EC:4 parity the usable capacity climbs to 75% while still tolerating 4 simultaneous drive losses. The math scales linearly with drive count and parity choice.

    Restart MinIO to pick up the new config:

    bash
    sudo systemctl restart minio
    sudo journalctl -u minio -n 50 --no-pager

    You should see log lines confirming the erasure set:

    text
    API: http://10.0.0.5:9000  http://127.0.0.1:9000
    Console: http://10.0.0.5:9001 http://127.0.0.1:9001
    Status: 4 Online, 0 Offline.

    Step 6: Configure the systemd Service

    The installed unit file is sensible but benefits from a couple of production tweaks. Drop an override:

    bash
    sudo systemctl edit minio

    Add:

    ini
    [Service]
    

    Raise the open file limit — object stores create lots of FDs

    LimitNOFILE=1048576

    Pin memory behavior

    MemoryAccounting=yes TasksMax=infinity

    Ensure restart on crash

    Restart=on-failure RestartSec=5s

    Wait for network

    After=network-online.target Wants=network-online.target

    Apply:

    bash
    sudo systemctl daemon-reload
    sudo systemctl restart minio

    Step 7: Install the mc Client

    mc is the official MinIO Client. It speaks S3 against MinIO, AWS S3, Backblaze B2, Wasabi, and any other S3-compatible backend — you register each one as an alias and then use familiar commands like cp, ls, mirror, and rm.

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

    Register your local MinIO as an alias called local:

    bash
    mc alias set local http://127.0.0.1:9000 admin YOUR_ROOT_PASSWORD
    mc admin info local

    mc admin info prints cluster health, drive status, and throughput — the single most useful command for day-to-day operations.

    Step 8: Buckets, Policies, and Users

    Create a bucket, upload an object, and verify.

    bash
    mc mb local/backups
    mc cp /etc/hostname local/backups/hostname.txt
    mc ls local/backups

    Enable object versioning

    Versioning keeps every write as an immutable version. It is the foundation for ransomware-resistant backup targets and for S3 object lock (WORM).

    bash
    mc version enable local/backups
    mc version info local/backups

    Create a scoped user and access key

    Never hand out the root credentials. Create a user scoped to only the buckets they need.

    bash
    mc admin user add local backup-bot $(openssl rand -base64 24)

    Create a JSON policy that grants read-write on the backups bucket only:

    bash
    cat > /tmp/backup-policy.json <<'EOF'
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": ["s3:*"],
          "Resource": ["arn:aws:s3:::backups", "arn:aws:s3:::backups/*"]
        }
      ]
    }
    EOF

    mc admin policy create local backup-rw /tmp/backup-policy.json mc admin policy attach local backup-rw --user backup-bot

    Now any S3 client — Restic, Velero, rclone, the AWS CLI — can authenticate with that access key and write only to backups.

    Bucket policies for public read

    If you are hosting static assets, make an individual bucket publicly readable:

    bash
    mc anonymous set download local/public-assets

    Step 9: Nginx TLS Reverse Proxy

    Running MinIO behind Nginx lets you terminate TLS from Let's Encrypt, attach a real domain, and hide the console on a separate subdomain. Use two server blocks — one for the S3 API (s3.example.com) and one for the console (console.example.com).

    bash
    sudo apt install -y nginx certbot python3-certbot-nginx

    Write the config:

    bash
    sudo tee /etc/nginx/sites-available/minio > /dev/null <<'EOF'
    

    S3 API endpoint

    server { listen 443 ssl http2; server_name s3.example.com;

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

    # Allow large multipart uploads client_max_body_size 0; client_body_buffer_size 128k; proxy_buffering off; proxy_request_buffering off;

    chunked_transfer_encoding off;

    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 ""; } }

    Web console

    server { listen 443 ssl http2; server_name console.example.com;

    ssl_certificate /etc/letsencrypt/live/console.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/console.example.com/privkey.pem;

    client_max_body_size 0;

    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; proxy_set_header X-NginX-Proxy true;

    # Console websocket support real_ip_header X-Real-IP; proxy_connect_timeout 300; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; chunked_transfer_encoding off; } } EOF

    sudo ln -s /etc/nginx/sites-available/minio /etc/nginx/sites-enabled/ sudo certbot --nginx -d s3.example.com -d console.example.com sudo nginx -t && sudo systemctl reload nginx

    Two points that trip up almost every first install:

    • client_max_body_size 0; disables Nginx's upload size cap. MinIO objects can be up to 5 TB; Nginx's default 1 MB cap will break multipart uploads immediately.
    • proxy_request_buffering off; streams uploads directly to MinIO instead of buffering them on disk at Nginx first.

    Step 10: Server-Side Encryption with KES

    MinIO supports three encryption modes. SSE-C (customer-provided keys) requires the client to send the key with every request. SSE-S3 encrypts with a MinIO-managed key. SSE-KMS encrypts with keys held in an external KMS — this is the production-grade option.

    For SSE-KMS, MinIO uses KES (Key Encryption Service), a small daemon that sits between MinIO and a root KMS (Vault, AWS KMS, GCP KMS). KES handles per-bucket key derivation, key caching, and key rotation so MinIO never talks directly to the root KMS.

    Install KES

    bash
    wget https://github.com/minio/kes/releases/latest/download/kes-linux-amd64 -O kes
    chmod +x kes
    sudo mv kes /usr/local/bin/
    kes --version

    Generate the KES identity

    KES uses mutual TLS. Generate a self-signed CA and two cert/key pairs — one for the KES server, one for the MinIO client that authenticates against it.

    bash
    sudo mkdir -p /etc/kes
    cd /etc/kes
    sudo kes identity new --key server.key --cert server.crt kes-server
    sudo kes identity new --key minio.key --cert minio.crt minio-client
    sudo kes identity of minio.crt

    The last command prints the identity hash for MinIO. You will reference it in the KES config.

    Minimal KES config

    bash
    sudo tee /etc/kes/kes.yaml > /dev/null <<EOF
    address: 0.0.0.0:7373
    admin:
      identity: disabled
    tls:
      key:  /etc/kes/server.key
      cert: /etc/kes/server.crt
    policy:
      minio-policy:
        allow:
          - /v1/key/create/*
          - /v1/key/generate/*
          - /v1/key/decrypt/*
        identities:
          - <PASTE_MINIO_IDENTITY_HASH_HERE>
    keystore:
      fs:
        path: /var/lib/kes-keys
    EOF

    sudo mkdir -p /var/lib/kes-keys

    In production, swap the fs keystore for a Vault backend so keys never touch local disk.

    Wire MinIO to KES

    Append to /etc/default/minio:

    bash
    MINIO_KMS_KES_ENDPOINT=https://127.0.0.1:7373
    MINIO_KMS_KES_CERT_FILE=/etc/kes/minio.crt
    MINIO_KMS_KES_KEY_FILE=/etc/kes/minio.key
    MINIO_KMS_KES_CAPATH=/etc/kes/server.crt
    MINIO_KMS_KES_KEY_NAME=minio-default-key

    Start KES (run as a proper systemd unit in production) and restart MinIO:

    bash
    sudo systemctl restart minio

    Enable SSE-KMS on a bucket so every object written to it is encrypted automatically:

    bash
    mc encrypt set sse-kms minio-default-key local/confidential
    mc encrypt info local/confidential

    Step 11: Prometheus Metrics and Monitoring

    MinIO exposes Prometheus-compatible metrics at four endpoints: /minio/v2/metrics/cluster, /minio/v2/metrics/node, /minio/v2/metrics/bucket, and /minio/v2/metrics/resource. These cover request rates, latency histograms, drive health, erasure set state, and replication lag.

    Generate a scrape token:

    bash
    mc admin prometheus generate local

    That prints a ready-to-paste Prometheus job. Drop it into your Prometheus config:

    yaml
    scrape_configs:
      - job_name: minio
        bearer_token: <TOKEN_FROM_ABOVE>
        metrics_path: /minio/v2/metrics/cluster
        scheme: https
        static_configs:
          - targets: ['s3.example.com']

    If you are not already running Prometheus, follow our install Prometheus on Ubuntu guide — it pairs naturally with MinIO and Grafana ships an official MinIO dashboard (ID 13502).

    Useful alert expressions:

    • minio_cluster_nodes_offline_total > 0 — cluster has a down node
    • minio_cluster_drive_offline_total > 0 — drive failure
    • rate(minio_s3_requests_errors_total[5m]) > 0.05 — 5XX error rate spike
    • minio_cluster_usage_total_bytes / minio_cluster_capacity_raw_total_bytes > 0.85 — capacity at 85%

    Step 12: Lifecycle Rules and Retention

    Lifecycle rules let you automatically expire, transition, or delete noncurrent object versions. They are identical in syntax to S3 lifecycle rules, so existing tooling Just Works.

    Expire old backups after 90 days:

    bash
    mc ilm rule add \
      --expire-days 90 \
      local/backups

    Expire noncurrent versions after 30 days (for versioned buckets):

    bash
    mc ilm rule add \
      --noncurrent-expire-days 30 \
      local/backups

    Tier cold objects to a cheap remote S3 backend after 60 days:

    bash
    mc ilm tier add minio local cold-tier \
      --endpoint https://s3.us-east-005.backblazeb2.com \
      --access-key B2_KEY --secret-key B2_SECRET \
      --bucket cold-archive --region us-east-005

    mc ilm rule add \ --transition-days 60 \ --transition-tier cold-tier \ local/backups

    Object lock and WORM

    For compliance workloads — immutable logs, regulatory archives — enable object locking at bucket creation (it cannot be turned on afterwards):

    bash
    mc mb --with-lock local/audit-logs
    mc retention set --default COMPLIANCE 7y local/audit-logs

    Objects written to that bucket cannot be deleted or modified for seven years by anyone, including the root user.

    Comparison: MinIO vs AWS S3 vs B2 vs Wasabi

    DimensionMinIO (self-hosted)AWS S3 StandardBackblaze B2Wasabi
    Storage cost (per TB-month)~EUR 8-12 (VPS amortized)USD 23USD 6USD 6.99
    Egress cost (per TB)Free (unmetered VPS)USD 90USD 10Free (with caveats)
    Request costFreeUSD 0.005 per 1k LISTUSD 0.004 per 10kFree
    Minimum retentionNoneNoneNone90 days
    Data sovereigntyYour VPS, any regionAWS regions2 US + 1 EU regionMulti-region
    APIS3 (native)S3S3S3
    Max object size5 TB5 TB10 TB5 TB
    Erasure codingYes (Reed-Solomon)ManagedManagedManaged
    EncryptionSSE-S3, SSE-KMS, SSE-CSSE-S3, SSE-KMS, SSE-CSSE-B2SSE-C
    Break-even vs MinIO—< 1 TB~5 TB~5 TB
    The break-even calculation assumes you actually use the storage. If you write 4 TB once and never read it, Backblaze B2 at USD 24/month beats a Professional VPS on pure storage cost. If you read 4 TB back twice a month, MinIO beats B2 immediately (USD 80 of B2 egress versus zero on MinIO) and beats S3 by two orders of magnitude.

    CloudCore pricing snapshot

    PlanvCPU / RAMStorageGood forMonthly
    Starter4 / 8 GB200 GB NVMeSNSD dev, small backup targetEUR 14.99
    Professional (recommended)8 / 16 GB400 GB NVMeSNMD production, Nextcloud / Paperless backing storeEUR 29.99
    Business12 / 32 GB800 GB NVMeMulti-tenant MinIO + KES + Prometheus stackEUR 59.99
    Storage8 / 16 GB4 TB HDD + 100 GB NVMeCold-archive MinIO target for Velero / ResticEUR 49.99
    All CloudCore plans include unmetered bandwidth, so egress from your MinIO is genuinely free.

    Troubleshooting

    ProblemCauseSolution
    ERROR Unable to initialize backend: Drive path /mnt/disk1 has unexpected contentExisting files on a drive MinIO tries to claimWipe with sudo rm -rf /mnt/disk1/* /mnt/disk1/.minio.sys and restart
    Specified drives are inconsistent on SNMD startupDrives have mismatched prior erasure-set metadataStart all drives from a clean state; MinIO cannot merge two different sets
    5xx errors via Nginx on large uploadsclient_max_body_size default 1 MBSet client_max_body_size 0; and proxy_request_buffering off;
    SignatureDoesNotMatch from clientClock drift between client and serverRun sudo timedatectl set-ntp true on both ends
    Console login works, S3 API returns 403User has no policy attachedmc admin policy attach local readwrite --user USER
    MINIO_KMS_KES_ENDPOINT is unreachableKES down or wrong TLS certcurl -k https://127.0.0.1:7373/v1/status then check journalctl -u kes
    High disk usage with few objectsVersion history and multipart debrismc ls --versions --recursive local/bucket and configure lifecycle expiration
    Slow PUT throughputClient not using multipart uploadsUse mc cp or clients that default to multipart for objects > 64 MB

    Viewing logs

    bash
    sudo journalctl -u minio -f
    sudo journalctl -u kes -f

    Cluster health

    bash
    mc admin info local
    mc admin heal local --recursive --dry-run

    mc admin heal repairs shards that drift out of sync after a transient drive error. Always dry-run first.

    FAQ

    Is MinIO really S3-compatible?

    Yes. MinIO implements the AWS S3 API with very high fidelity. Tools built against the S3 SDK — the AWS CLI, boto3, Terraform, Velero, Restic, rclone, Kubernetes CSI drivers — work against MinIO by pointing them at your endpoint and swapping the access keys. The exceptions are niche services like Glacier restore workflows, RequestPayment, and some Analytics APIs, which MinIO deliberately does not implement. For 99% of real-world use cases, swapping from S3 to MinIO is a one-line endpoint change.

    How many drives do I need to run MinIO in production?

    For a production deployment with erasure coding, the minimum is 4 drives on a single node (Single-Node Multi-Drive, or SNMD). A 4-drive set with default EC:2 parity tolerates the loss of 2 drives. For higher durability and availability, run Multi-Node Multi-Drive (MNMD) with at least 4 nodes and 4 drives per node — this survives the loss of whole machines, not just individual drives. MinIO's own recommendation for serious production is 4 nodes x 4 drives minimum.

    How does MinIO compare to SeaweedFS and Garage?

    SeaweedFS is a blob-store-first system that grew S3 compatibility later. It uses a master/volume architecture optimized for huge numbers of small files and has a lower memory footprint. Garage is a newer Rust-based S3 store designed explicitly for geo-distributed three-node deployments on cheap hardware. MinIO sits between them: higher performance than Garage, broader enterprise features than SeaweedFS, and by far the most mature S3 API coverage. Pick MinIO when you need the full S3 feature set or are replacing existing AWS tooling. Pick Garage for three-node multi-site on a shoestring. Pick SeaweedFS for billions of small objects.

    Can I run MinIO on a single drive for development?

    Yes. Single-Node Single-Drive (SNSD) mode is explicitly supported for development and CI environments. It skips erasure coding entirely, has no redundancy, and does not support object versioning or site replication — but it starts instantly against a single filesystem path and behaves identically to a production MinIO for everything else. This is what you want for local integration tests against S3-backed services like Nextcloud, Paperless-ngx, or PhotoPrism.

    Do I need KES for server-side encryption?

    For SSE-S3 with a single static key, you can set MINIO_KMS_SECRET_KEY directly and skip KES — but the key is static and lives in an env file alongside the service. For proper SSE-KMS with key rotation, per-tenant keys, and an audit trail, run KES in front of a Vault, AWS KMS, or GCP KMS backend. KES is MinIO's recommended production KMS and is required for multi-tenant encryption key management. For any compliance-sensitive workload — HIPAA, PCI, GDPR with customer data — KES plus Vault is the supported answer.

    What backup tools work with MinIO?

    Every S3-aware backup tool works. Restic is the most common pick for server filesystem backups — it deduplicates client-side and speaks S3 natively. Velero is the standard for Kubernetes cluster and PV backups. Duplicati and Kopia give you GUI backup clients. rclone is the swiss-army knife for sync between any pair of cloud storages. Point any of them at your MinIO endpoint and they see it as S3.

    How do I migrate from AWS S3 to MinIO?

    mc mirror is the fastest path. Register AWS as an alias, register MinIO as an alias, and mirror:

    bash
    mc alias set aws https://s3.amazonaws.com AKIA... SECRET
    mc alias set local https://s3.example.com admin PASSWORD
    mc mirror --preserve --watch aws/my-bucket local/my-bucket

    The --preserve flag keeps timestamps and metadata; --watch runs continuously and picks up new writes. Cut the application over once the initial mirror is complete and the watch catches up. For very large buckets, do the bulk copy with the AWS S3 CLI's sync and then use mc mirror --watch for the delta — network throughput to AWS is usually the bottleneck, not MinIO ingest.

    Next Steps

    Now that MinIO is running, wire it into the rest of your stack:

    • Set up Prometheus and Grafana — follow our Prometheus install guide and import MinIO's official Grafana dashboard (ID 13502) for cluster-wide visibility.
    • Use MinIO as Nextcloud primary storage — see install Nextcloud and configure S3 as the primary object store so every uploaded file lands directly in MinIO.
    • Back up Paperless-ngx to MinIO — Paperless-ngx supports S3 export; point its backup job at a versioned MinIO bucket with object lock for tamper-proof document archives.
    • Store PhotoPrism originals in MinIO — PhotoPrism can offload original photos to S3 while keeping thumbnails locally; MinIO on a Storage plan VPS gives you unlimited-feeling photo storage at a flat rate.
    • Compare with SeaweedFS or Garage — if your workload is millions of tiny files or explicitly geo-distributed, read our SeaweedFS install guide and Garage install guide to pick the right tool.
    • Read the official docs — MinIO's own Linux install documentation is thorough and kept current with every release.

    Ready to host your own S3?
    >
    A Professional VPS with 16 GB RAM and 400 GB NVMe is the sweet spot for a serious self-hosted MinIO — enough headroom for a 4-drive erasure set, KES, Prometheus, and a reverse proxy on one machine.
    >
    - 8 vCPU, 16 GB RAM, 400 GB NVMe
    - Unmetered bandwidth — no egress surprises
    - EU-hosted for GDPR-friendly object storage
    - Ubuntu 24.04 LTS images ready in 60 seconds
    >
    Deploy Your Professional VPS Now — Plans start at EUR 29.99/month.

    Was this article helpful?

    ← Back to Install GuidesBrowse all categories →

    Still have questions?

    Contact Support →Submit a Ticket