storage/docker-compose.yml
Sergei Poljanski bdfc028ca1
All checks were successful
Deploy storage stack / deploy (push) Successful in 20s
Route s3.asxp.io to Garage
The data is copied and verified and both apps sign with their Garage
keys, so send s3.asxp.io to Garage's S3 API. MinIO loses its route and
stays up, unrouted, as the way back.

Garage answers no anonymous S3 request. Unsigned GET and HEAD of
/public/<key> go to its web endpoint instead, with the Host header the
endpoint picks the bucket by, so the links handed out so far keep
working. Signed requests for that bucket still reach the S3 API.

Assisted-by: Claude:fable-5-2
2026-11-11 03:44:37 +04:00

114 lines
3.8 KiB
YAML

services:
postgres:
image: postgres:17-alpine
container_name: storage-postgres
restart: unless-stopped
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: postgres
volumes:
- pg_data:/var/lib/postgresql/data
networks:
- storage
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 10
postgres-init:
image: postgres:17-alpine
container_name: storage-postgres-init
depends_on:
postgres:
condition: service_healthy
environment:
PGHOST: postgres
PGUSER: postgres
PGPASSWORD: ${POSTGRES_PASSWORD}
ASXPIO_DB_PASSWORD: ${ASXPIO_DB_PASSWORD}
BINGO_DB_PASSWORD: ${BINGO_DB_PASSWORD}
volumes:
- ./init/postgres-init.sh:/init.sh:ro
entrypoint: ["/bin/sh", "/init.sh"]
networks:
- storage
restart: "no"
# Kept only as the way back until Garage has proven itself: not routed,
# not bootstrapped, its data frozen as of the switch.
minio:
image: minio/minio:latest
container_name: storage-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://s3.asxp.io
volumes:
- minio_data:/data
networks:
- storage
healthcheck:
test: ["CMD", "mc", "ready", "local"]
interval: 5s
timeout: 5s
retries: 10
labels:
- "traefik.enable=false"
garage:
image: dxflrs/garage:v2.5.0
container_name: storage-garage
restart: unless-stopped
command: ["/garage", "server", "--single-node"]
volumes:
- ./garage.toml:/etc/garage.toml:ro
- ./secrets/garage_rpc_secret:/run/secrets/garage_rpc_secret:ro
- garage_meta:/var/lib/garage/meta
- garage_data:/var/lib/garage/data
networks:
- storage
- traefik
healthcheck:
test: ["CMD", "/garage", "status"]
interval: 10s
timeout: 5s
retries: 10
labels:
- "traefik.enable=true"
- "traefik.docker.network=traefik"
# The S3 API.
- "traefik.http.routers.garage-s3.rule=Host(`s3.asxp.io`)"
- "traefik.http.routers.garage-s3.entrypoints=websecure"
- "traefik.http.routers.garage-s3.tls=true"
- "traefik.http.routers.garage-s3.tls.certresolver=letsencrypt"
- "traefik.http.routers.garage-s3.service=garage-s3"
- "traefik.http.services.garage-s3.loadbalancer.server.port=3900"
# Anonymous reads of the public bucket: unsigned GET/HEAD of
# /public/<key> goes to the web endpoint as Host public.web.garage,
# path /<key>. Signed requests still reach the S3 API above.
- "traefik.http.routers.garage-public.rule=Host(`s3.asxp.io`) && PathPrefix(`/public/`) && (Method(`GET`) || Method(`HEAD`)) && !HeaderRegexp(`Authorization`, `.+`) && !QueryRegexp(`X-Amz-Signature`, `.+`)"
- "traefik.http.routers.garage-public.priority=1000"
- "traefik.http.routers.garage-public.entrypoints=websecure"
- "traefik.http.routers.garage-public.tls=true"
- "traefik.http.routers.garage-public.tls.certresolver=letsencrypt"
- "traefik.http.routers.garage-public.service=garage-web"
- "traefik.http.routers.garage-public.middlewares=garage-public-strip,garage-public-host"
- "traefik.http.middlewares.garage-public-strip.stripprefix.prefixes=/public"
- "traefik.http.middlewares.garage-public-host.headers.customrequestheaders.Host=public.web.garage"
- "traefik.http.services.garage-web.loadbalancer.server.port=3902"
volumes:
pg_data:
minio_data:
garage_meta:
garage_data:
networks:
storage:
name: storage
traefik:
external: true