feat: S3-compatible object storage backend

BACKEND_STORAGE_DRIVER=s3 swaps LocalStore for a stdlib-only SigV4
implementation — PutObject/GetObject/DeleteObject/CopyObject/ListObjectsV2
against any S3-compatible API (AWS, MinIO, Garage, R2). Storage becomes a
Store interface; storage_path records s3://bucket/key. Content-Length is
resolved by seeking or temp-file spooling — chunked uploads are rejected
by real S3 servers. Bucket auto-created on startup.

Verified live against zenko/cloudserver: bucket, put, get, copy, delete.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-24 19:38:50 +02:00
1 parent f747b33b46
commit 3aca5bd1e0
11 files changed
+810 -17

No files matched your search

+11
View File
@@ -50,6 +50,17 @@ BACKEND_PUBLIC_URL=http://localhost/api/v1
BACKEND_INTERNAL_URL=http://backend:8080
BACKEND_STORAGE_ROOT=/data/storage
# Object storage driver: "local" (default, uses BACKEND_STORAGE_ROOT) or "s3".
# For s3, point S3_ENDPOINT at any S3-compatible API (AWS, MinIO, Garage, R2).
BACKEND_STORAGE_DRIVER=local
#S3_ENDPOINT=http://minio:9000
#S3_REGION=us-east-1
#S3_BUCKET=primora-objects
#S3_ACCESS_KEY_ID=
#S3_SECRET_ACCESS_KEY=
#S3_PREFIX=
#S3_PATH_STYLE=true
# Mail defaults — each is overridable in-app (Settings → Instance). In-app
# values win over these env vars; deleting the in-app value reverts here.
RESEND_API_KEY=