MinIO is a high-performance, S3-compatible object storage server you can run on your own infrastructure. This guide deploys MinIO using Docker Compose with Traefik handling automatic HTTPS on two separate domains — one for the web console, one for the S3 API. By the end, you'll have MinIO serving S3-compatible object storage securely at your domains.
Set Up the Directory Structure
1. Create the project directory structure:
$mkdir -p ~/minio/{data,letsencrypt}
$cd ~/minio
2. Create the environment file:
$nano .env
MINIO_ROOT_USER=admin
MINIO_ROOT_PASSWORD=STRONG_PASSWORD
DOMAIN_CONSOLE=console.example.com
DOMAIN_API=s3.example.com
LETSENCRYPT_EMAIL=admin@example.com
Point DNS A records for both DOMAIN_CONSOLE and DOMAIN_API at the server.
Deploy with Docker Compose
1. Add your user to the Docker group:
$sudo usermod -aG docker $USER
$newgrp docker
2. Create the Docker Compose manifest:
$nano docker-compose.yml
services:
traefik:
image: traefik:latest
container_name: traefik
restart: unless-stopped
environment:
DOCKER_API_VERSION: "1.44"
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--certificatesresolvers.le.acme.httpchallenge=true"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL}"
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./letsencrypt:/letsencrypt
minio:
image: minio/minio:latest
container_name: minio
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
MINIO_BROWSER_REDIRECT_URL: https://${DOMAIN_CONSOLE}
volumes:
- ./data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
labels:
- "traefik.enable=true"
- "traefik.http.routers.minio-api.rule=Host(`${DOMAIN_API}`)"
- "traefik.http.routers.minio-api.entrypoints=websecure"
- "traefik.http.routers.minio-api.tls=true"
- "traefik.http.routers.minio-api.tls.certresolver=le"
- "traefik.http.routers.minio-api.service=minio-api-svc"
- "traefik.http.services.minio-api-svc.loadbalancer.server.port=9000"
- "traefik.http.routers.minio-console.rule=Host(`${DOMAIN_CONSOLE}`)"
- "traefik.http.routers.minio-console.entrypoints=websecure"
- "traefik.http.routers.minio-console.tls=true"
- "traefik.http.routers.minio-console.tls.certresolver=le"
- "traefik.http.routers.minio-console.service=minio-console-svc"
- "traefik.http.services.minio-console-svc.loadbalancer.server.port=9001"
3. Start the services:
$docker compose up -d
4. Verify the services are running:
$docker compose ps
Access MinIO
-
Web console:
https://console.example.com— sign in withMINIO_ROOT_USER/MINIO_ROOT_PASSWORD. -
S3 API:
https://s3.example.com— point S3 SDKs and CLIs at this endpoint with the same credentials.
Next Steps
MinIO is running with separate console and API endpoints over HTTPS. From here you can:
- Create buckets, users, and access policies from the console
- Generate non-root access keys for application use
- Configure server-side encryption and bucket versioning for durability
For the full guide with additional tips, visit the original article on Vultr Docs.
For further actions, you may consider blocking this person and/or reporting abuse
