Files
familienarchiv/docs/infrastructure/s3-migration.md
2026-04-14 23:21:15 +02:00

2.9 KiB

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

# 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=<hetzner-access-key>
S3_SECRET_KEY=<hetzner-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.

# 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.

# 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=<hetzner-access-key>
AWS_SECRET_ACCESS_KEY=<hetzner-secret-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

# 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.