Introduction
Building a highly available object storage solution requires distributed storage that can survive node failures while maintaining data integrity. MinIO provides enterprise-grade object storage with S3 compatibility, making it an excellent self-hosted alternative to cloud storage services.
In this comprehensive tutorial, you’ll learn how to deploy a production-ready MinIO cluster across four Ubuntu 24.04 VPS instances using Docker Compose. We’ll implement erasure coding for data redundancy, configure TLS encryption, and establish a fully distributed object storage cluster that can tolerate multiple node failures.
By the end of this guide, you’ll have a robust, S3-compatible storage cluster suitable for VPS backups, application data, and enterprise workloads.
Prerequisites
Before starting this deployment, ensure you have:
- Four VPS instances running Ubuntu 24.04 LTS with minimum 4GB RAM and 50GB storage each
- Root or sudo access on all servers
- Docker and Docker Compose installed on all nodes
- Network connectivity between all nodes on ports 9000 and 9001
- Domain name or static IPs for cluster access
- SSL certificates (Let’s Encrypt or your CA)
Resource Requirements:
- CPU: 2+ cores per node
- RAM: 4GB minimum, 8GB recommended per node
- Storage: 50GB+ per node for data drives
- Network: 1Gbps interconnect preferred
Step-by-Step Tutorial
Step 1: Install Docker on All Nodes
Execute these commands on each of your four Ubuntu 24.04 servers:
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Docker
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Enable Docker service
sudo systemctl enable --now docker
sudo usermod -aG docker $USER
Step 2: Configure Cluster Networking
Set hostnames and configure /etc/hosts
on all nodes. Replace IPs with your actual server addresses:
# Configure /etc/hosts on all nodes
sudo tee -a /etc/hosts << 'EOF'
10.0.1.10 minio-01
10.0.1.11 minio-02
10.0.1.12 minio-03
10.0.1.13 minio-04
EOF
Step 3: Create Directory Structure
Create the necessary directories on each node:
# Create MinIO directories
sudo mkdir -p /opt/minio/{data1,data2,config,certs}
sudo chown -R 1001:1001 /opt/minio
sudo chmod -R 755 /opt/minio
Step 4: Generate TLS Certificates
For production environments, use proper certificates. For testing, generate self-signed certificates:
# Generate self-signed certificates (replace with your domain)
sudo openssl req -new -x509 -days 365 -nodes \
-out /opt/minio/certs/public.crt \
-keyout /opt/minio/certs/private.key \
-subj "/C=US/ST=CA/L=SF/O=MinIO/OU=IT/CN=minio.example.com"
# Set proper permissions
sudo chmod 644 /opt/minio/certs/public.crt
sudo chmod 600 /opt/minio/certs/private.key
sudo chown -R 1001:1001 /opt/minio/certs
Step 5: Create Docker Compose Configuration
Create the following Docker Compose file on each node, adjusting the server addresses:
# /opt/minio/docker-compose.yml
version: '3.8'
services:
minio:
image: quay.io/minio/minio:RELEASE.2024-12-13T22-19-12Z
hostname: minio-01 # Change per node: minio-01, minio-02, etc.
container_name: minio
command: >
server --console-address ':9001'
http://minio-01/opt/minio/data1 http://minio-01/opt/minio/data2
http://minio-02/opt/minio/data1 http://minio-02/opt/minio/data2
http://minio-03/opt/minio/data1 http://minio-03/opt/minio/data2
http://minio-04/opt/minio/data1 http://minio-04/opt/minio/data2
environment:
- MINIO_ROOT_USER=minioadmin
- MINIO_ROOT_PASSWORD=your_secure_password_here
- MINIO_SERVER_URL=https://minio.example.com:9000
- MINIO_BROWSER_REDIRECT_URL=https://minio.example.com:9001
volumes:
- /opt/minio/data1:/opt/minio/data1
- /opt/minio/data2:/opt/minio/data2
- /opt/minio/certs:/root/.minio/certs
ports:
- "9000:9000"
- "9001:9001"
networks:
- minio-cluster
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
networks:
minio-cluster:
driver: bridge
Step 6: Configure Firewall Rules
Configure UFW to allow cluster communication:
# Enable UFW and allow SSH
sudo ufw --force enable
sudo ufw allow ssh
# Allow MinIO ports from cluster nodes
sudo ufw allow from 10.0.1.0/24 to any port 9000
sudo ufw allow from 10.0.1.0/24 to any port 9001
# Allow public access (adjust as needed)
sudo ufw allow 9000/tcp
sudo ufw allow 9001/tcp
Step 7: Deploy the MinIO Cluster
Start the cluster on all nodes simultaneously:
# Start MinIO on all nodes (run on each server)
cd /opt/minio
sudo docker compose up -d
# Verify cluster status
sudo docker compose logs -f
Step 8: Verify Cluster Health
Check cluster connectivity and health:
# Check container status
sudo docker compose ps
# Test cluster health
curl -k https://minio-01:9000/minio/health/cluster
# Access MinIO Console
echo "MinIO Console: https://your-domain:9001"
echo "Username: minioadmin"
echo "Password: your_secure_password_here"
Best Practices
Security Hardening
- Change default credentials: Always use strong, unique passwords for MinIO root user
- Use proper TLS certificates: Deploy Let’s Encrypt or CA-signed certificates for production
- Network segmentation: Place MinIO nodes in a private network when possible
- Access policies: Implement least-privilege IAM policies for applications
Performance Optimization
- Storage backend: Use NVMe SSDs for optimal performance
- Network bandwidth: Ensure adequate inter-node connectivity
- Memory allocation: Allocate sufficient RAM for caching and metadata operations
- Monitoring: Implement Prometheus metrics for cluster monitoring
Backup and Disaster Recovery
# Install MinIO Client for backup operations
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc && sudo mv mc /usr/local/bin/
# Configure backup destination
mc alias set local https://minio.example.com:9000 minioadmin your_password
mc alias set remote https://backup-location.com access_key secret_key
# Create backup script
mc mirror local/bucket-name remote/backup-bucket
Conclusion
You’ve successfully deployed a highly available MinIO cluster with erasure coding across four Ubuntu 24.04 servers. This configuration provides excellent data durability, S3 compatibility, and can survive multiple node failures while maintaining service availability.
The cluster offers enterprise-grade features including TLS encryption, distributed storage, and automatic healing capabilities. Consider integrating this setup with your existing backup strategies or as a cost-effective alternative to commercial object storage services.
For production deployments requiring high-performance infrastructure, explore our Singapore VPS or Amsterdam VPS solutions with NVMe storage and high-availability features that complement your MinIO cluster deployment.