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.
Top comments (0)