Production-ready MinIO S3-compatible object storage deployment with declarative JSON-based initialization, optional admin console, and full CI/CD automation.
- S3-Compatible API - Full Amazon S3 API compatibility via MinIO
- Declarative Init Container - JSON-based provisioning of buckets, policies, groups, users, and service accounts
- Admin Console - Optional third-party admin UI (replaces MinIO's removed built-in console)
- Multiple Deployment Modes - Direct port access or Traefik reverse proxy with automatic HTTPS
- DNS-Style Bucket Access - Prepared virtual-host-style routing (e.g.,
bucket.s3.example.com) - CI/CD Automation - Semantic releases, Docker image builds, base image monitoring, auto-merge
-
Clone the repository
git clone https://github.com/bauer-group/CS-MinIO.git cd CS-MinIO -
Create environment file
cp .env.example .env
-
Edit
.env- Set at minimum:MINIO_ROOT_PASSWORD- Admin passwordAPP_SERVICE_SECRET_KEY- Application service account secretADMIN_CONSOLE_PASSWORD- Admin console user password (if using admin console)
-
Edit
config/minio-init.json- Configure buckets, policies, users as needed -
Start MinIO
# Single mode (direct port access) docker compose -f docker-compose-single.yml up -d # Or: Traefik mode (HTTPS via reverse proxy) docker compose -f docker-compose-single-traefik.yml up -d
-
Access MinIO
Mode S3 API Object Browser Single http://localhost:9000http://localhost:9001Traefik https://{S3_HOSTNAME}https://{S3_CONSOLE_HOSTNAME}
┌──────────────────────────────────────────────────────────┐
│ Docker Compose Stack │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ minio-server │◄───│ minio-init │ │ admin- │ │
│ │ │ │ (one-shot) │ │ console │ │
│ │ S3 API │ │ │ │ (optional) │ │
│ │ :9000 │ │ Applies │ │ :9090 │ │
│ │ │ │ JSON config │ │ │ │
│ │ Console │ │ on start │ │ Full │ │
│ │ :9001 │ └──────────────┘ │ admin UI │ │
│ └──────────────┘ └────────────┘ │
│ │ │ │
│ └──────────────────────────────────────┘ │
│ Internal Network │
└──────────────────────────────────────────────────────────┘
| Mode | Compose File | Description |
|---|---|---|
| Single | docker-compose-single.yml |
Direct port binding, no reverse proxy needed |
| Single + Traefik | docker-compose-single-traefik.yml |
HTTPS via Traefik with Let's Encrypt certificates |
Append --profile admin-console to any deployment mode:
docker compose -f docker-compose-single.yml --profile admin-console up -dNote: MinIO removed its built-in admin UI in RELEASE.2025-05-24T17-08-30Z. The built-in console is now an object browser only. The optional admin console service provides full management capabilities (users, policies, buckets, monitoring).
All configuration is done via .env. See .env.example for the full reference with documentation.
Required settings:
| Variable | Description |
|---|---|
MINIO_ROOT_PASSWORD |
MinIO admin password |
APP_SERVICE_SECRET_KEY |
Application service account secret |
Generate secrets:
openssl rand -base64 24The init container reads config/minio-init.json and applies the configuration to MinIO on every start. All operations are idempotent.
Supported resources:
| Resource | Description |
|---|---|
buckets |
Create buckets with versioning, quotas, retention, anonymous policy |
policies |
Custom IAM policy documents (S3 policy JSON) |
groups |
Groups with policy attachments |
users |
Users with group membership and direct policies |
service_accounts |
Service accounts with explicit access key / secret key |
Environment variable resolution: JSON values support ${VAR_NAME} syntax. Variables are resolved from the container's environment at runtime, keeping secrets out of config files.
Example configuration:
{
"buckets": [
{
"name": "documents",
"region": "us-east-1",
"versioning": true,
"policy": "private"
}
],
"policies": [
{
"name": "readwrite-documents",
"statements": [
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
"Resource": ["arn:aws:s3:::documents", "arn:aws:s3:::documents/*"]
}
]
}
],
"users": [
{
"access_key": "app-service",
"secret_key": "${APP_SERVICE_SECRET_KEY}",
"groups": [],
"policies": ["readwrite-documents"]
}
]
}See src/minio-init/README.md for the full JSON schema reference.
This repository builds two Docker images:
| Image | Base | Purpose |
|---|---|---|
ghcr.io/bauer-group/cs-minio/minio |
quay.io/minio/minio |
MinIO server with health check and OCI labels |
ghcr.io/bauer-group/cs-minio/minio-init |
python:3.13-alpine |
Init container with mc client and task framework |
The server image currently uses the base image as-is. The Dockerfile provides a customization section for adding certificates, scripts, or configurations as needed.
The Traefik deployment mode provides:
- Automatic HTTPS via Let's Encrypt certificate resolver
- S3 API endpoint on
${S3_HOSTNAME}(path-style access) - Console endpoint on
${S3_CONSOLE_HOSTNAME} - Admin console endpoint on
${ADMIN_CONSOLE_HOSTNAME}(when enabled) - No-buffering middleware for large S3 uploads
- HTTP to HTTPS redirect on all endpoints
Virtual-host-style bucket access (e.g., bucket.s3.example.com) is prepared but commented out in the Traefik compose file. To enable it:
- Configure wildcard certificates (requires DNS challenge) or explicit SANs
- Uncomment the
HostRegexprules indocker-compose-single-traefik.yml - Set
MINIO_DOMAIN(already configured in the template)
.
├── .github/ # GitHub CI/CD configuration
│ ├── CODEOWNERS # Pull request review assignments
│ ├── dependabot.yml # Automated dependency updates
│ ├── config/
│ │ ├── release/ # Semantic release configuration
│ │ └── docker-base-image-monitor/ # Base image monitoring
│ └── workflows/
│ ├── docker-release.yml # Build, release, push images
│ ├── docker-maintenance.yml # Auto-merge Dependabot PRs
│ ├── check-base-images.yml # Daily base image update check
│ ├── teams-notifications.yml # Microsoft Teams notifications
│ └── ai-issue-summary.yml # AI-powered issue summaries
├── src/
│ ├── minio/ # MinIO server image
│ │ ├── Dockerfile # Server image definition
│ │ └── .dockerignore
│ └── minio-init/ # Init container image
│ ├── Dockerfile # Init image definition
│ ├── main.py # Orchestrator (task discovery, config loading)
│ ├── README.md # Init container documentation
│ ├── config/
│ │ └── default.json # Empty default configuration
│ └── tasks/
│ ├── 01_buckets.py # Bucket creation and configuration
│ ├── 02_policies.py # IAM policy management
│ ├── 03_groups.py # Group creation and policy attachment
│ ├── 04_users.py # User creation and group assignment
│ └── 05_service_accounts.py # Service account provisioning
├── config/
│ └── minio-init.json # Init container configuration (user-facing)
├── docker-compose-single.yml # Single server, direct port access
├── docker-compose-single-traefik.yml # Single server, Traefik HTTPS
├── .env.example # Environment configuration template
├── CHANGELOG.md # Release history (auto-generated)
├── LICENSE # MIT License
└── README.md # This file
The repository uses semantic-release with Conventional Commits:
| Commit Prefix | Version Bump | Example |
|---|---|---|
fix: |
Patch (0.1.0 -> 0.1.1) | fix: correct health check endpoint |
feat: |
Minor (0.1.0 -> 0.2.0) | feat: add bucket lifecycle rules |
BREAKING CHANGE: |
Major (0.1.0 -> 1.0.0) | feat!: change init config format |
Automated pipeline:
- Push to
maintriggers validation (compose files) - Semantic release creates version tag and GitHub release
- Docker images are built and pushed to GHCR and Docker Hub
- Dependabot monitors base images weekly; auto-merges updates
- Daily base image monitor checks for new releases
- Docker Engine 24.0+
- Docker Compose v2.20+
- 512 MB RAM minimum (1 GB+ recommended)
- For Traefik mode: Traefik v2/v3 reverse proxy on the
${PROXY_NETWORK}network
MIT License - BAUER GROUP
Karl Bauer - karl.bauer@bauer-group.com