Skip to content

MinIO

What Is It?

MinIO is an open-source, S3-compatible object storage server. It implements the Amazon S3 API, so any tool that speaks S3 (AWS CLI, restic, rclone, SDKs) works against a self-hosted MinIO instance without modification. MinIO is commonly used for on-premises backup targets, artifact storage, and development environments that need object storage without a cloud dependency.

MinIO exposes two interfaces on separate ports:

  • S3 API (port 9000) — the machine-readable object storage protocol. This is what backup tools, SDKs, and scripts use.
  • Web console (port 9001) — a browser-based management UI for creating buckets, browsing objects, and managing users. The console is a MinIO-specific feature and not part of the S3 protocol.

Installation

MinIO is deployed as a Docker container. See Technologies: Docker for Docker installation.

# Create a named volume for MinIO data
sudo docker volume create minio-data

# Run MinIO (API on 9000, console on 9001, both localhost-only)
sudo docker run -d \
  --name minio \
  --restart unless-stopped \
  -e MINIO_ROOT_USER=admin \
  -e MINIO_ROOT_PASSWORD=changeme \
  -p 127.0.0.1:9000:9000 \
  -p 127.0.0.1:9001:9001 \
  -v minio-data:/data \
  minio/minio server /data --console-address ":9001"

Choose a strong password

MINIO_ROOT_PASSWORD must be at least 8 characters. Use a proper random password in production.

Named volume vs bind mount

The -v minio-data:/data syntax uses a named volume managed by Docker, stored at /var/lib/docker/volumes/minio-data/_data. This is preferred over a bind mount (-v /some/host/path:/data) because the path is stable, Docker manages it, and it makes backups cleaner.

Key Files and Directories

Path Purpose
/var/lib/docker/volumes/minio-data/ MinIO data on the host (via Docker named volume)
/etc/httpd/conf.d/s3.conf Apache virtual host for the S3 API endpoint

MinIO itself stores configuration entirely in environment variables passed at container startup — there are no config files inside the container.

Configuration

Minimal Working Configuration

The docker run command above is the minimal working configuration. Key environment variables:

MINIO_ROOT_USER
The administrator username (analogous to AWS access key).
MINIO_ROOT_PASSWORD
The administrator password (analogous to AWS secret key). Minimum 8 characters.
--console-address ":9001"
Binds the console to port 9001. Without this, MinIO picks a random port.

Apache Reverse Proxy for the S3 API

To expose the S3 API publicly over HTTPS, proxy it through Apache. Do not open port 9000 in the firewall directly.

<VirtualHost *:443>
    ServerName s3.<vm_name>.sysadm.ee

    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/server.crt
    SSLCertificateKeyFile /etc/pki/tls/private/server.key
    SSLCACertificateFile /etc/pki/tls/certs/ca-chain.crt

    # Pass the original protocol to MinIO (required for presigned URLs)
    RequestHeader set X-Forwarded-Proto "https"
    ProxyPreserveHost On

    # Allow large uploads (S3 PUT operations)
    LimitRequestBody 0

    ProxyPass / http://127.0.0.1:9000/
    ProxyPassReverse / http://127.0.0.1:9000/

    ErrorLog /var/log/httpd/s3-error_log
    CustomLog /var/log/httpd/s3-access_log combined
</VirtualHost>

Common Commands

MinIO Client (mc)

mc is the primary tool for interacting with the S3 API from the command line. It is the standard way to create buckets, inspect objects, and diagnose problems with a MinIO instance — the equivalent of using curl for HTTP debugging.

Download it as a standalone binary (there is no package in the standard CentOS repos):

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

Before using mc, register your MinIO instance as a named alias. This stores the endpoint URL and credentials so you don't repeat them on every command.

Alias name required for scoring

The scoring check expects the alias to be named sysadm. You can use any MINIO_ROOT_USER and MINIO_ROOT_PASSWORD you chose when starting the container.

mc alias set sysadm http://127.0.0.1:9000 <MINIO_ROOT_USER> <MINIO_ROOT_PASSWORD>
# Verify:
mc alias list

Common operations:

# List all buckets
mc ls sysadm

# Create a bucket
mc mb sysadm/inventory-backup

# List objects in a bucket
mc ls sysadm/inventory-backup

# List objects recursively
mc ls --recursive sysadm/inventory-backup

# Copy a file into a bucket
mc cp /etc/hostname sysadm/inventory-backup/

# Remove an object
mc rm sysadm/inventory-backup/hostname

# Show bucket disk usage
mc du sysadm/inventory-backup

# Check server info and status
mc admin info sysadm

mc works with any S3-compatible endpoint

The same mc commands work against AWS S3, other MinIO instances, or any service that implements the S3 API. Just change the alias URL.

Container Management

# Check MinIO is running
sudo docker ps | grep minio

# View MinIO logs
sudo docker logs minio

# Follow logs in real time
sudo docker logs -f minio

# Stop / start
sudo docker stop minio
sudo docker start minio

Logging and Debugging

  • Container logs: sudo docker logs minio shows MinIO startup messages and S3 request logs.
  • Health check: curl http://127.0.0.1:9000/minio/health/live returns HTTP 200 if MinIO is healthy. Useful for scripted monitoring.
  • Port check: ss -tlnp | grep 9000 confirms MinIO is bound to the expected address.

Common issues:

  • Error: Unable to initialize config system — the data directory inside the container is not writable, or the named volume was not created before starting the container.
  • mc: <alias>: Unable to initialize new alias from the provided credentials — wrong MINIO_ROOT_USER / MINIO_ROOT_PASSWORD, or MinIO is not running.
  • Restic S3 connection refused — MinIO is not running or is bound to a different port than expected.

Security Considerations

  • Bind MinIO ports (9000, 9001) to 127.0.0.1 only. Expose the S3 API through Apache (with TLS) and keep the console accessible only via SSH port-forwarding or a separate secured proxy.
  • The MINIO_ROOT_USER/MINIO_ROOT_PASSWORD are equivalent to AWS root credentials — they can do anything. Treat them as secrets.
  • Do not commit MinIO credentials to version control. Use Ansible Vault or environment variables.

Further Reading