MinIO Deploy Role¶
Deploys MinIO object storage server as a hardened systemd service with optional TLS and bucket/policy bootstrap.
Features¶
Version Pinned: Reproducible deployments with mandatory checksum validation
Secure by Default: Systemd hardening, loopback binding, credential validation
Single-Node Ready: LUKS-encrypted data directory support
Optional Bootstrap: mc client, buckets, versioning, policies, service accounts
Idempotent: Safe to run multiple times
Verification Built-in: Automatic health checks after deployment
Quick Start¶
Minimal Deployment (Internal Only)¶
- hosts: server
become: true
vars:
sops_secrets: "{{ lookup('community.sops.sops', 'secrets/prod/minio.yml') | from_yaml }}"
roles:
- role: local.ops_library.minio_deploy
vars:
minio_root_user: "{{ sops_secrets.root_user }}"
minio_root_password: "{{ sops_secrets.root_password }}"
minio_version: "RELEASE.2024-10-02T17-50-41Z"
minio_checksum: "sha256:abc123..."
With Bootstrap (Buckets + Service Accounts)¶
- hosts: server
become: true
vars:
sops_secrets: "{{ lookup('community.sops.sops', 'secrets/prod/minio.yml') | from_yaml }}"
roles:
- role: local.ops_library.minio_deploy
vars:
# Credentials
minio_root_user: "{{ sops_secrets.root_user }}"
minio_root_password: "{{ sops_secrets.root_password }}"
# Version pinning (REQUIRED)
minio_version: "RELEASE.2024-10-02T17-50-41Z"
minio_checksum: "sha256:abc123..."
# Data directory
minio_data_dirs:
- /mnt/cryptdata/minio/data
# Bootstrap
minio_bootstrap_with_mc: true
minio_mc_version: "RELEASE.2024-10-02T17-50-41Z"
minio_mc_checksum: "sha256:def456..."
minio_buckets:
- name: backups
versioning: true
policy: private
minio_service_accounts:
- name: app
access_key: "{{ sops_secrets.app_access_key }}"
secret_key: "{{ sops_secrets.app_secret_key }}"
policy: readonly
allowed_buckets: [backups]
Architecture¶
┌─────────────────┐
│ Application │
│ (echoport) │
└────────┬────────┘
│ S3 API
▼
┌─────────────────┐ ┌──────────────────┐
│ MinIO Service │◄────►│ Web Console │
│ 127.0.0.1:9001 │ │ 127.0.0.1:9002 │
└────────┬────────┘ └──────────────────┘
│
▼
┌─────────────────┐
│ LUKS Encrypted │
│ Data Directory │
│ /mnt/cryptdata │
└─────────────────┘
Role Variables¶
Required Variables¶
Variable |
Example |
Description |
|---|---|---|
|
|
Root username (from SOPS) |
|
|
Root password (from SOPS) |
|
|
Explicit MinIO version |
|
|
SHA256 checksum for binary |
Bootstrap Variables (if minio_bootstrap_with_mc: true)¶
Variable |
Example |
Description |
|---|---|---|
|
|
mc client version |
|
|
SHA256 checksum for mc |
Optional Variables¶
Variable |
Default |
Description |
|---|---|---|
|
|
Bind address (loopback by default) |
|
|
S3 API port |
|
|
Web console port |
|
|
Console host when exposed via Traefik |
|
|
S3 API host when exposed via Traefik |
|
|
Data directory paths |
|
|
Enable TLS |
|
|
Enable bucket/policy bootstrap |
See defaults/main.yml for the complete list.
Version Pinning & Checksums¶
SECURITY REQUIREMENT: Version pinning is mandatory for reproducible and secure deployments.
Get MinIO Checksums¶
# List available release builds
curl -s https://dl.min.io/server/minio/release/linux-amd64/archive/ | grep RELEASE
# List available hotfix builds
curl -s https://dl.min.io/server/minio/hotfixes/linux-amd64/archive/archive/ | grep RELEASE
# Get checksum for a release build
VERSION="RELEASE.2024-10-02T17-50-41Z"
curl -s "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.${VERSION}.sha256sum"
# Get checksum for a hotfix build
HOTFIX_VERSION="RELEASE.2025-10-15T17-29-55Z.hotfix.c392ab039"
curl -s "https://dl.min.io/server/minio/hotfixes/linux-amd64/archive/archive/minio.${HOTFIX_VERSION}.sha256sum"
Get mc Client Checksums¶
# Get mc checksum
VERSION="RELEASE.2024-10-02T17-50-41Z"
curl -s "https://dl.min.io/client/mc/release/linux-amd64/archive/mc.${VERSION}.sha256sum"
Bootstrap Features¶
Buckets¶
minio_buckets:
- name: backups
versioning: true
policy: private
- name: public-data
versioning: false
policy: public
Policies: private, readonly, writeonly, public
Service Accounts¶
minio_service_accounts:
- name: echoport
access_key: "{{ sops_secrets.echoport_access_key }}"
secret_key: "{{ sops_secrets.echoport_secret_key }}"
policy: readonly
allowed_buckets:
- backups
TLS Configuration¶
To enable TLS, provide certificate content via SOPS:
# In SOPS secrets file
tls_cert: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
tls_key: |
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
# In playbook
minio_tls_enable: true
minio_tls_cert_content: "{{ sops_secrets.tls_cert }}"
minio_tls_key_content: "{{ sops_secrets.tls_key }}"
Verification¶
The role automatically verifies:
✓ API endpoint reachable
✓ Console endpoint reachable
✓ Health check passes
✓ mc alias works (if bootstrap enabled)
✓ Buckets exist (if bootstrap enabled)
Manual Verification¶
# On target host
mc alias set local http://127.0.0.1:9001 <ROOT_USER> <ROOT_PASS>
mc admin info local
mc ls local/
Security Considerations¶
Loopback Binding: Default binds to 127.0.0.1 (internal only)
Systemd Hardening: NoNewPrivileges, PrivateTmp, ProtectSystem, etc.
Credential Validation: Deployment fails with “CHANGEME” placeholders
Checksum Validation: Binary integrity verified before installation
No Secrets in Logs:
no_log: truefor sensitive operations
Upgrades¶
To upgrade MinIO:
Check latest release: https://github.com/minio/minio/releases
Get new checksum (see Version Pinning section)
Update playbook variables:
minio_version: "RELEASE.2025-10-15T17-29-55Z.hotfix.c392ab039" minio_checksum: "sha256:newchecksum..."
Rerun deployment - role will download new binary and restart service
Troubleshooting¶
Service won’t start¶
# Check logs
journalctl -u minio -f
# Check systemd status
systemctl status minio
# Verify ports not in use
sudo lsof -i :9001
sudo lsof -i :9002
Checksum validation fails¶
# Verify checksum format
echo "sha256:abc123..." | grep -E '^sha256:[a-f0-9]{64}$'
# Get correct checksum
curl -s "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.RELEASE.xxx.sha256sum"
# or hotfix stream:
curl -s "https://dl.min.io/server/minio/hotfixes/linux-amd64/archive/archive/minio.RELEASE.xxx.hotfix.yyyyyyyyy.sha256sum"
Bootstrap fails¶
# Test mc connectivity
mc alias set test http://127.0.0.1:9001 <USER> <PASS>
mc admin info test
# Check credentials
mc admin user list test
Examples¶
Basic Internal-Only Deployment¶
- role: local.ops_library.minio_deploy
vars:
minio_root_user: "{{ vault_minio_user }}"
minio_root_password: "{{ vault_minio_password }}"
minio_version: "RELEASE.2024-10-02T17-50-41Z"
minio_checksum: "sha256:abc123..."
Production with Bootstrap¶
See “With Bootstrap” example in Quick Start section.
Multi-Disk Setup¶
minio_data_dirs:
- /mnt/disk1/minio
- /mnt/disk2/minio
- /mnt/disk3/minio
- /mnt/disk4/minio
Note: MinIO requires at least 4 drives for erasure coding.
Dependencies¶
Target OS: Debian/Ubuntu with systemd
Ansible: >= 2.9
Root/sudo access on target
License¶
MIT