A single Go binary that fronts multiple S3-compatible storage backends (Cloudflare R2, DigitalOcean Spaces, IDrive e2, MinIO, ...) behind one S3-compatible endpoint. It issues its own credentials to clients, verifies their SigV4 signatures itself, then re-signs each request with the real backend's credentials before forwarding it — real backend credentials never reach clients. Modeled on 9router, which does the same job for LLM providers.
export ROUTER_MASTER_KEY=$(head -c32 /dev/urandom | base64) # generate once, back it up separately from the DB
export ADMIN_PASSWORD=change-me
export DB_PATH=./s3router.db # default shown
export PORT=8080 # default shown
go run .Then open http://localhost:8080/admin/login to add a backend, map a
client-facing bucket name to a real bucket on it, and create a router
credential. The credential's secret is shown exactly once at creation time.
Point any S3 SDK at http://<router-host>:<port> using the router-issued
access key/secret, with path-style addressing and non-chunked body
signing (both are common SDK flags — e.g. s3ForcePathStyle /
use_path_style_endpoint, and disabling aws-chunked streaming signatures
in favor of UNSIGNED-PAYLOAD or single-shot signing). aws-chunked
streaming signatures are not supported in this version.
docker build -t s3router .
docker run -p 8080:8080 \
-e ROUTER_MASTER_KEY=... -e ADMIN_PASSWORD=... \
-v s3router-data:/data -e DB_PATH=/data/s3router.db \
s3routerROUTER_MASTER_KEY and the SQLite file must both survive a redeploy, but
should be backed up separately — losing the master key alone makes
every encrypted secret in the database unrecoverable even if the DB file is
intact. The 9router-backup project's rclone-sidecar pattern (periodic
.backup snapshot pushed to S3-compatible storage, with auto-restore on a
fresh volume) can be adapted directly for the SQLite file.
go test ./... # unit tests
go test -tags=integration ./test/integration/... # real MinIO container (requires Docker)See docs/superpowers/specs/2026-09-06-s3-router-design.md for the full
design rationale, data model, and request-flow details.