MinIO Guide: Installation, Configuration, and Monitoring⚓︎
MinIO is a high-performance, S3 compatible object storage server. It's ideal for storing unstructured data such as photos, videos, log files, backups, and container/VM images. This guide will walk you through various aspects of setting up, configuring, and monitoring MinIO on a Linux environment.
1. Linux Package Installation⚓︎
For a direct installation on a Linux system (Debian/Ubuntu based):
Download the MinIO Server package:
Choose the appropriate package for your architecture and desired version from the MinIO downloads page.
#Download .deb package
wget [https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20250228095516.0.0_amd64.deb](https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20250228095516.0.0_amd64.deb) -O minio.deb
#Install the package
sudo dpkg -i minio.deb
#Create a data directory where MinIO will store its data.
mkdir ~/minio
#Launch the MinIO server
minio server ~/minio --console-address :9001
http://YOUR_SERVER_IP:9000 and the console at http://YOUR_SERVER_IP:9001. You'll see the root user and password in the startup logs – change these immediately for any non-testing setup! 2. Configuring MinIO with systemd⚓︎
Running MinIO as a systemd service ensures it starts on boot and can be managed like other system services.
-
Create a MinIO user and group (Recommended):
-
Create the systemd service file: The path can vary, but
/usr/lib/systemd/system/minio.serviceor/etc/systemd/system/minio.serviceare common.File:
/usr/lib/systemd/system/minio.service(or/etc/systemd/system/minio.service)SystemdNote: Ensure[Unit] Description=MinIO Documentation=https://docs.min.io Wants=network-online.target After=network-online.target AssertFileIsExecutable=/usr/local/bin/minio [Service] Type=notify WorkingDirectory=/usr/local # Or the directory where your MinIO binary and data reside # IMPORTANT: Change User and Group if you created a dedicated one User=minio-user Group=minio-user # Optional: If you have a separate configuration directory # PermissionsStartOnly=true # ExecStartPre=/bin/mkdir -p /etc/minio/certs # ExecStartPre=/bin/chown minio-user:minio-user /etc/minio/certs ProtectProc=invisible EnvironmentFile=-/etc/default/minio ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi" ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES # Let systemd restart this service always Restart=always # Specifies the maximum file descriptor number that can be opened by this process LimitNOFILE=1048576 # Turn-off memory accounting by systemd, which is buggy. MemoryAccounting=no # Specifies the maximum number of threads this process can create TasksMax=infinity # Disable timeout logic and wait until process is stopped TimeoutSec=infinity # Disable killing of MinIO by the kernel's OOM killer OOMScoreAdjust=-1000 SendSIGKILL=no [Install] WantedBy=multi-user.target # Built for ${project.name}-${project.version} (${project.name})AssertFileIsExecutableandExecStartpoint to the correct path of yourminiobinary. -
Create the environment configuration file: This file
/etc/default/miniostores MinIO startup variables.File:
/etc/default/minioBashSecurity Alert: Change# Volume to be used for MinIO server. # Example: MINIO_VOLUMES="/mnt/data1 /mnt/data2 /mnt/data3 /mnt/data4" # For a single drive/path: MINIO_VOLUMES="/path/to/minio" # IMPORTANT: Ensure this path exists and has correct permissions for minio-user # Use if you want to run MinIO on a custom port and address. # Default is ":9000" for API and ":9001" for console if not specified. MINIO_OPTS="--address :9000 --console-address :9001" # Root user for the server. # IMPORTANT: CHANGE THESE DEFAULT CREDENTIALS FOR PRODUCTION! MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin_strong_password_please_change # Set this for MinIO to reload entries with 'mc admin service restart' MINIO_CONFIG_ENV_FILE=/etc/default/minio # Optional: Specify the MinIO configuration directory # MINIO_CONFIG_DIR=/etc/minioMINIO_ROOT_USERandMINIO_ROOT_PASSWORDto strong, unique credentials. Ensure theMINIO_VOLUMESpath exists and is writable by theminio-user. -
Reload systemd, enable, and start the service:
3. MinIO Client (mc) Installation⚓︎
The MinIO Client (mc) is a command-line tool for interacting with MinIO and S3-compatible services.
#Download the `mc` binary
wget [https://dl.min.io/client/mc/release/linux-amd64/mc](https://dl.min.io/client/mc/release/linux-amd64/mc)
#Make it executable
chmod +x mc
#Move it to your PATH
sudo mv mc /usr/local/bin/mc
4. MinIO Client Admin Commands⚓︎
To use mc admin commands, you first need to set up an alias for your MinIO server.
-
Set up an alias: Replace
myminiowith your preferred alias name,http://YOUR_MINIO_IP:9000with your MinIO server's API address, and use theMINIO_ROOT_USERandMINIO_ROOT_PASSWORDyou configured.Bash(The example uses# If running MinIO via systemd as minio-user, you might need to run mc commands as that user # sudo -u minio-user mc alias set myminio [http://192.168.21.1:9000](http://192.168.21.1:9000) minioadmin minioadmin_strong_password_please_change mc alias set myminio http://YOUR_MINIO_IP:9000 YOUR_ROOT_USER YOUR_ROOT_PASSWORD192.168.21.1:9000and default credentials. Update these accordingly.) -
Common admin commands: (If MinIO is run by
minio-userandmcneeds access to its config, you might needsudo -u minio-user mc ...)- Get server info:
- Check for updates and update MinIO (if supported by your deployment):
- View server logs:
- Trace API calls:
- Get user info:
5. Running MinIO with Docker⚓︎
Docker provides a convenient way to run MinIO in an isolated environment.
- Install Docker: Follow the official instructions for your distribution, e.g., for Debian: Install Docker Engine on Debian
Direct Docker Run⚓︎
This method is quick for testing but less manageable for production than Docker Compose MinIO Docker Quickstart Guide
-
Create a data directory on the host:
-
Run the MinIO container:
--user $(id -u):$(id -g)is often used for rootless, or specify UID/GID (e.g.,1000:1000).- IMPORTANT: Change default credentials.
Using Docker Compose⚓︎
Docker Compose is recommended for managing multi-container applications and for easier configuration management.
-
Create a
docker-compose.ymlfile:File:
docker-compose.ymlYAMLSecurity & Permissions: * Changeversion: '3.7' # Or a newer compatible version services: minio: image: quay.io/minio/minio container_name: minio1 # To run as a specific user (e.g., current user or a dedicated one) # Ensure the user has write access to the volume mount path on the host. user: "1000:1000" ports: - "9000:9000" # MinIO API port - "9001:9001" # MinIO console port environment: # IMPORTANT: CHANGE THESE DEFAULT CREDENTIALS FOR PRODUCTION! - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin_strong_password_please_change # Optional: Link to Prometheus for console monitoring (see Prometheus section) # - MINIO_PROMETHEUS_URL=http://prometheus:9090 volumes: # Mount a host directory to /data in the container for persistent storage - /path/to/minio:/data # Ensure this host path exists and has correct permissions command: server /data --console-address ":9001" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 restart: always # Optional Prometheus service (see Prometheus section for prometheus.yml) # prometheus: # image: prom/prometheus # container_name: prometheus # ports: # - "9090:9090" # volumes: # - ./prometheus:/etc/prometheus # Mount your prometheus.yml here # command: # - '--config.file=/etc/prometheus/prometheus.yml' # restart: alwaysMINIO_ROOT_USERandMINIO_ROOT_PASSWORD. * Ensure the host volume path (e.g.,/path/to/minio) exists and that the user specified byuser:(e.g., UID 1000) has write permissions to it. Ifuser:is not set, the container runs as root, which might cause permission issues on the host volume if not managed carefully. -
Run Docker Compose:
-
Update configuration and recreate container: If you modify
docker-compose.yml:
Docker Management⚓︎
Common commands for managing Docker containers:
docker ps -a # List all containers (running and stopped)
docker logs -f minio1 # Tail logs of the 'minio1' container
docker inspect minio1 # Show detailed information about 'minio1'
docker rm minio1 # Remove the 'minio1' container (must be stopped first)
docker exec -it minio1 id # Check the user under which the container's process is running
6. Monitoring MinIO⚓︎
As seen in the docker-compose.yml example, MinIO exposes health check endpoints.
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7e204abad298 quay.io/minio/minio "/usr/bin/docker-ent…" 10 minutes ago Up 10 minutes (healthy) 0.0.0.0:9000-9001->9000-9001/tcp, :::9000-9001->9000-9001/tcp minio1
Note: MinIO does not have traditional log levels like DEBUG, INFO, WARN. You primarily rely on traces and metrics. See GitHub Discussion #14213
Custom MinIO Trace Service with systemd
This setup captures all MinIO administrative trace logs into a file, managed by a systemd service. This is useful if you're not using Docker and want persistent trace logging.
-
Create a script to run the trace command: Ensure the
mcaliasmyminiois configured for the user who will run this script (e.g., root or minio-user). File:/usr/local/bin/minio-trace.shBashMake the script executable: 2. Create the systemd service file:#!/bin/bash # Path to the log file LOG_FILE="/var/log/minio-trace.log" # Ensure this path is writable by the service user # Ensure mc is in PATH or provide full path # Ensure the alias 'myminio' is configured for the user running this script /usr/local/bin/mc admin trace -a --json myminio >> "$LOG_FILE" 2>&1File:
/etc/systemd/system/minio-trace.serviceText Only3. Reload systemd and start the service:[Unit] Description=MinIO Trace Logging Service After=network.target minio.service # Ensure MinIO service is up [Service] ExecStart=/usr/local/bin/minio-trace.sh Restart=always RestartSec=5 # Restart every 5 seconds if it fails User=root # Or minio-user if that user has mc configured and permissions Group=root # Or minio-user StandardOutput=append:/var/log/minio-trace-service.log # Service's own logs StandardError=append:/var/log/minio-trace-service.error.log # Service's error logs SyslogIdentifier=minio-trace [Install] WantedBy=multi-user.targetBash4. Verify the service: 5. (Optional) Log Rotation: Prevent the log file from growing indefinitely using logrotate.sudo systemctl daemon-reload sudo systemctl start minio-trace.service sudo systemctl enable minio-trace.serviceFile:
IMPORTANT: This approach will create huge log file with a lot of unnecessary noise./etc/logrotate.d/minio-trace
Prometheus Integration⚓︎
MinIO exposes Prometheus-compatible metrics for detailed monitoring.
-
Generate a bearer token for Prometheus: Run this command on a machine with mc configured to access your MinIO server.
Note: There are different metrics API versions (e.g., v2, v3). Ensure consistency. -
Create Prometheus configuration file (
prometheus.yml): Replaceyour_minio_server_ip:9000with your MinIO server's API address andYOUR_BEARER_TOKEN_HEREwith the token generated above.File:
prometheus/prometheus.yml(e.g., in your docker-compose directory)YAML3. Add Prometheus to docker-compose.yml (if using Docker):global: scrape_interval: 15s rule_files: - /etc/prometheus/minio-alerting.rules.yml # Path inside Prometheus container scrape_configs: - job_name: 'minio-cluster' bearer_token: 'YOUR_BEARER_TOKEN_HERE' metrics_path: /minio/v2/metrics/cluster scheme: http # Or https if MinIO is configured with TLS static_configs: - targets: ['your_minio_server_ip:9000'] # Your MinIO server address - job_name: 'minio-node' bearer_token: 'YOUR_BEARER_TOKEN_HERE' metrics_path: /minio/v2/metrics/node scheme: http static_configs: - targets: ['your_minio_server_ip:9000'] - job_name: 'minio-bucket' bearer_token: 'YOUR_BEARER_TOKEN_HERE' metrics_path: /minio/v2/metrics/bucket scheme: http static_configs: - targets: ['your_minio_server_ip:9000'] # Optional: Add relabeling to filter specific buckets if needed # metric_relabel_configs: # - source_labels: [bucket_name] # regex: 'importantbucket1|importantbucket2' # action: keep - job_name: 'minio-resource' # Added for completeness, may not always be needed bearer_token: 'YOUR_BEARER_TOKEN_HERE' metrics_path: /minio/v2/metrics/resource scheme: http static_configs: - targets: ['your_minio_server_ip:9000']
Update your docker-compose.yml to include Prometheus.YAMLEnsure your prometheus.yml and minio-alerting.rules.yml (see below) are in a directory named prometheus next to your docker-compose.yml.version: '3.7' services: minio: image: quay.io/minio/minio container_name: minio1 # user: "1000:1000" ports: - "9000:9000" - "9001:9001" environment: - MINIO_ROOT_USER=minioadmin - MINIO_ROOT_PASSWORD=minioadmin - MINIO_PROMETHEUS_URL=http://prometheus:9090 # For MinIO Console to link to Prometheus volumes: - /path/to/minio:/data command: server /data --console-address ":9001" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 restart: always prometheus: image: prom/prometheus:latest container_name: prometheus ports: - "9090:9090" volumes: - ./prometheus:/etc/prometheus # Mount prometheus.yml and alert rules # - prometheus_data:/prometheus # Optional: Persistent data for Prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' restart: always
4. Restart Docker Compose:If you added Prometheus or updated its configuration:
Access Prometheus athttp://your_docker_host_ip:9090
Prometheus Alerts⚓︎
Create alert rules for Prometheus to notify you of issues.
-
Create an alert rules file: Refer to MinIO Prometheus Metrics List and Here for available metrics.
File:
prometheus/minio-alerting.rules.ymlYAML2. Ensuregroups: - name: minio-alerts rules: - alert: MinIOTooManyNodesOffline expr: minio_cluster_nodes_offline_total{job="minio-cluster"} > 0 # Adjust threshold as needed for: 5m # Duration for which condition must be true labels: severity: critical annotations: summary: "Node offline in MinIO cluster (instance {{ $labels.instance }})" description: "{{ $value }} node(s) are offline in the MinIO cluster." - alert: MinIOTooManyDrivesOffline expr: minio_cluster_drive_offline_total{job="minio-cluster"} > 1 # Example: alert if more than 1 drive is offline for: 5m labels: severity: critical annotations: summary: "Drive offline in MinIO cluster (instance {{ $labels.instance }})" description: "{{ $value }} drive(s) are offline in the MinIO cluster." - alert: MinIOLowStorageCapacity expr: (minio_cluster_capacity_free_bytes{job="minio-cluster"} / minio_cluster_capacity_total_bytes{job="minio-cluster"}) * 100 < 10 for: 15m labels: severity: warning annotations: summary: "MinIO cluster {{ $labels.instance }} low storage capacity" description: "Cluster {{ $labels.instance }} has less than 10% free storage capacity remaining ({{ $value | printf \"%.2f\" }}%)." # Add more alerts as needed, e.g., for certificate expiry, bucket usage, etc.prometheus.ymlpoints to this rules file:
This was done in the prometheus.yml example:rule_files: - /etc/prometheus/minio-alerting.rules.yml
You'll need to configure Alertmanager separately if you want Prometheus to send notifications (email, Slack, etc.).
Debugging MinIO⚓︎
- Official Debugging Guide: MinIO Debugging Documentation
- Blog Post on Debugging: Debugging MinIO Installs
Common tools include:
mc admin trace
mc admin logs
Server logs (if configured for systemd or viewed via docker logs)
Prometheus metrics
Important Notes⚓︎
MinIO Object Locking
MinIO supports S3 Object Locking (Object Retention), which enforces Write-Once Read-Many (WORM) policies. This is crucial for compliance and data protection.
MinIO Object Locking Documentation
Global mc Options
All mc commands support global options like --config-dir, --quiet, --json, etc. Some can also be set via environment variables.