# MinIO to Hetzner Object Storage Migration This document covers the migration from MinIO (used in development and CI) to Hetzner Object Storage in production. --- ## Why Zero Application Code Changes Are Needed The app uses the S3 API. MinIO implements the S3 API. Hetzner Object Storage implements the S3 API. The only change is in environment variables. Zero application code changes. Zero Spring Boot changes. One `.env` swap. --- ## Environment Variable Swaps ### Application S3 Configuration ```bash # Development / CI — MinIO S3_ENDPOINT=http://minio:9000 S3_ACCESS_KEY=${MINIO_ROOT_USER} S3_SECRET_KEY=${MINIO_ROOT_PASSWORD} S3_BUCKET_NAME=archive-documents S3_REGION=us-east-1 # Production — Hetzner Object Storage S3_ENDPOINT=https://fsn1.your-objectstorage.com # Hetzner S3 endpoint S3_ACCESS_KEY= S3_SECRET_KEY= S3_BUCKET_NAME=archive-documents S3_REGION=eu-central ``` --- ## MinIO in the Production Compose File Once on Hetzner Object Storage, remove the `minio`, `create-buckets` services from the production Compose file entirely. The backend talks to Hetzner directly. Mailpit is already dev-only. MinIO becomes dev-only by the same pattern. ```yaml # docker-compose.prod.yml — production overrides services: minio: profiles: ["dev"] # only starts when --profile dev is passed create-buckets: profiles: ["dev"] mailpit: profiles: ["dev"] ``` --- ## WAL-G Backup Target Configuration The same environment-variable swap applies to WAL-G database backups. Same scripts, same WAL-G binary, different endpoint and credentials. ```bash # Development (WAL-G → MinIO) WALG_S3_PREFIX=s3://backups/wal AWS_ENDPOINT=http://minio:9000 AWS_ACCESS_KEY_ID=${MINIO_ROOT_USER} AWS_SECRET_ACCESS_KEY=${MINIO_ROOT_PASSWORD} # Production (WAL-G → Hetzner Object Storage) WALG_S3_PREFIX=s3://archive-db-wal/wal AWS_ENDPOINT=https://fsn1.your-objectstorage.com AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= ``` --- ## Bucket Setup on Hetzner Hetzner Object Storage buckets are created via the Hetzner Cloud Console or API -- there is no `mc` client equivalent needed, unlike MinIO's `create-buckets` init container. Create the bucket once, set credentials, done. ### Hetzner Object Storage Configuration ```bash # Hetzner S3-compatible endpoint (Frankfurt region) S3_ENDPOINT=https://fsn1.your-objectstorage.com S3_REGION=eu-central # Bucket names — create once in Hetzner Console # archive-documents — application documents # archive-db-backups — pg_dump logical backups # archive-db-wal — WAL-G continuous archiving ``` --- ## Production Credentials In development, using MinIO root credentials for application access is acceptable. In production, create a dedicated Hetzner S3 service account with bucket-scoped permissions. The app should never use root/admin credentials.