afreidah/s3-orchestrator

Storage orchestration layer presenting many S3/blob providers as a single S3 endpoint, keeping a configurable number of copies across them with read failover, plus optional per-backend byte, request, ingress and egress limits, zstd compression and envelope encryption

Go

40

946 commits

updated Oct 5, 2026

See the code

See what people are saying

README

s3-orchestrator

s3-orchestrator

CI Coverage Quality Gate License: MIT

Project Website · Documentation · Maximizing Free-Tier Storage

Most applications talk to one S3 backend, which ties them to that provider's uptime, pricing, and limits. s3-orchestrator puts a single S3 endpoint in front of any number of S3-compatible backends — OCI Object Storage, Backblaze B2, AWS S3, MinIO, Wasabi, Cloudflare R2, anything that speaks S3 — and presents them as one or more virtual buckets. It tracks where every object lives in its own database, which is what lets it enforce per-backend byte quotas, keep N copies across providers, fail reads over when one goes dark, and take a backend out of the fleet without downtime.

Clients see one endpoint and one namespace. The backends never learn the orchestrator exists — they see ordinary S3 calls, so any provider the AWS SDK can talk to works.

The terminal browser's Backends view: twelve backends listed with health, quota used against limit, object count, API requests, ingress, egress and bytes saved by compression

The web dashboard — storage summary, integrity and compression coverage, monthly usage against each provider's limits, object browser and live logs The web dashboard, showing total used against capacity, a per-backend table of quota and usage, integrity coverage with the oldest unverified copy, encryption and compression coverage, monthly usage against each backend's request and transfer budgets, the object browser, the effective configuration, and a live log tail

Who this is for

AudienceUse case
HomelabbersStack free-tier allocations from multiple providers into usable storage without paying for a single plan.
Self-hosters running MinIOAdd automatic cloud backups to a local MinIO instance with one config change — no sync scripts or extra tooling.
Small teams and startupsMulti-cloud redundancy and encryption without the cost or complexity of enterprise storage platforms.
Anyone wanting provider independenceApplications talk S3 to one endpoint — swap, add, or remove backends without touching a line of code.

What it does

  • Backend quotas. Each backend carries a byte limit and writes overflow to the next when it fills, so a 20 GB allocation and a 10 GB one become one 30 GB bucket. Monthly API-request, egress and ingress caps work the same way.
  • Replication. Set a factor and every object lands on that many distinct backends. A background replicator makes the copies, or write_path.parallel_copies has the write claim its targets and upload to all of them at once, answering the client on the first copy committed — which spares the replicator a full GET of the object and the source backend's egress for every copy it would have made. Reads fail over to a surviving copy, a scrubber checks stored bytes against recorded hashes, and an over-replication worker trims the set when a recovered backend brings its copies back.
  • Access control. A credential resolves to a user, and that user holds a grant on each resource it may reach: a virtual bucket for object access, a backend or the instance itself for the control plane. SigV4 and presigned URLs.
  • Object tagging. Key/value labels stored with the object, always on. Inline on PutObject and CreateMultipartUpload, the three ?tagging operations, and x-amz-tagging-directive on a server-side copy. Lifecycle rules can filter on a tag.
  • Encryption and compression. Envelope encryption (AES-256-GCM; master key inline, in a file, or in Vault Transit) and chunked zstd compression. Both optional and transparent to clients; sizes, ETags and content hashes stay those of the object the client wrote. With both on, compression runs first, because ciphertext does not compress.
  • Terraform provider. Published to the Terraform and OpenTofu registries. Manages the buckets, users, credentials and grants a deployment serves.
  • Database. Embedded SQLite with no external dependencies, single-node PostgreSQL, or many instances with Redis-backed shared counters so quotas hold across the fleet.
  • Operator tooling. Online drain, rebalance, import of an existing bucket, integrity scrub, a cleanup queue with a dead-letter table, hot config reload, an admin API, a web dashboard and a terminal object browser.

Moving providers without downtime

Point the orchestrator at the bucket you already have and import its objects into the metadata layer — nothing moves. Add the new provider and raise the replication factor, and the workers copy everything across while traffic keeps flowing. Once the copies are in place, drain the old backend and delete it from the config. No step takes the application down.

What else is out there

If you've gone looking for a tool that does something similar, there don't appear to be many options:

ProjectWhat it isWhy it's not the same
rclone union remoteClient-side multi-remote stackingPer-client config, no server endpoint, no central drain/rebalance/quota enforcement
MinIO GatewayWas a multi-backend S3 proxyDeprecated in 2022
Flexify.IOCommercial multi-cloud S3 SaaSClosed source; $0.03/GiB SaaS or $0.09/hr self-hosted
gaul/s3proxy, oxyno-zeta/s3-proxyS3 API translation / routing proxiesSingle backend at a time, or multi-bucket routing without quotas, replication, or a metadata layer

Quickstart

Prerequisites: Go 1.27+, Docker, Make.

git clone https://github.com/afreidah/s3-orchestrator.git
cd s3-orchestrator
make run

Starts three MinIO backends via Docker Compose, embedded SQLite as the metadata store, and the orchestrator on localhost:9000.

aws --endpoint-url http://localhost:9000 s3 cp /etc/hostname s3://photos/test.txt
aws --endpoint-url http://localhost:9000 s3 ls s3://photos/

Default credentials: access key photoskey, secret photossecret. Web dashboard at localhost:9000/ui/ (login admin / admin).

Full credentials and troubleshooting: docs/quickstart.md.

Install

ChannelSource
Containerdocker pull ghcr.io/afreidah/s3-orchestrator:<version>
Debian / Ubuntu.deb from GitHub Releases
Static binaryLinux / macOS / Windows from GitHub Releases
From sourcegit clone && make build
Terraform providerafreidah/s3-orchestrator on the Terraform Registry, or the OpenTofu Registry

Database: SQLite is embedded — no external dependencies for single-instance use. PostgreSQL 14+ is also an option and is required for multi-instance deployments (database.driver: postgres); the schema migrates on boot.

Generate a config interactively: s3-orchestrator init.

Verify release artifacts

Container images and release checksums are signed with cosign (keyless / Sigstore):

# Container image
cosign verify ghcr.io/afreidah/s3-orchestrator:<version> \
  --certificate-identity-regexp='github\.com/afreidah/s3-orchestrator' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

# Release checksums
cosign verify-blob checksums.txt --bundle checksums.txt.bundle \
  --certificate-identity-regexp='github\.com/afreidah/s3-orchestrator' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

Architecture in 30 seconds

              S3 clients (aws cli, rclone, etc.)
                          |
                          v
                    +-----------+
                    | S3 Orch.  |  <-- SigV4 auth, rate limiting, quota routing
                    +-----------+
                     |         |
            +--------+         +------------------+------------------+
            v                  v                  v                  v
       PostgreSQL        OCI Object         Backblaze B2          AWS S3
       (metadata)       Storage (20 GB)       (10 GB)             (5 GB)
                              \                  |                  /
                               '------------ 35 GB total ---------'

Metadata (object locations, quota counters, multipart state, cleanup queue) lives in PostgreSQL or SQLite. Backends only ever see plain S3 calls — no orchestrator-specific protocol, no schema requirements. Any provider that speaks the AWS SDK works.

Deeper details: docs/architecture.md.

Documentation

TopicDoc
First-run / demoQuickstart
S3 client setupUser Guide
Architecturedocs/architecture.md
Configuration walkthrough + hot-reloaddocs/configuration.md
Authentication (SigV4, tokens, multi-bucket)docs/authentication.md
Backends, quotas, routing strategiesdocs/backends.md
Database engines, schema, migrationsdocs/database.md
Replication, over-replication, orphan reconciliationdocs/replication.md
Cleanup queue, lifecycle expiry, pending intentsdocs/cleanup-and-lifecycle.md
Envelope encryption, Vault Transitdocs/encryption.md
At-rest compression (chunked zstd)docs/compression.md
Object tagging (key/value labels)docs/tagging.md
Operations (drain, rebalance, scrub, cache, trace)docs/operations.md
Monitoring (Prometheus, OTel, audit log)docs/monitoring.md
Background services referencedocs/background-services.md
Webhook notificationsdocs/notifications.md
CLI subcommandsdocs/cli.md
Provisioning buckets and identities with TerraformGuide · Terraform Registry · OpenTofu Registry
UI + Admin API JSON endpointsdocs/api-reference.md
Deployment (Nomad, Kubernetes, Docker)docs/deployment.md
Security hardeningdocs/security-hardening.md
Performance tuningdocs/performance-tuning.md
Disaster recoverydocs/disaster-recovery.md
Version migrationdocs/version-migration.md
Benchmark trendsLive charts · scheduled runs
Coding conventionsdocs/style-guide.md
Build / test / contributeCONTRIBUTING.md

Contributing

Contributions welcome. Start with CONTRIBUTING.md for the build / test / submit workflow, and docs/style-guide.md for the codebase's conventions.

License

MIT

aws-s3
backblaze-b2
backup-tool
cloud-storage
data-replication
devops
distributed-systems
failover
golang
homelab
minio
multi-cloud
object-storage
postgres
quota-management
reverse-proxy
s3
self-hosted
sqlite
storage-orchestrator

Significant stargazers

Achille

258 followers · starred Apr 2026

Daenney

157 followers · starred Apr 2026

afreidah/s3-orchestrator

Storage orchestration layer presenting many S3/blob providers as a single S3 endpoint, keeping a configurable number of copies across them with read failover, plus optional per-backend byte, request, ingress and egress limits, zstd compression and envelope encryption

Go

40

946 commits

updated Oct 5, 2026

See the code

See what people are saying

README

s3-orchestrator

s3-orchestrator

CI Coverage Quality Gate License: MIT

Project Website · Documentation · Maximizing Free-Tier Storage

Most applications talk to one S3 backend, which ties them to that provider's uptime, pricing, and limits. s3-orchestrator puts a single S3 endpoint in front of any number of S3-compatible backends — OCI Object Storage, Backblaze B2, AWS S3, MinIO, Wasabi, Cloudflare R2, anything that speaks S3 — and presents them as one or more virtual buckets. It tracks where every object lives in its own database, which is what lets it enforce per-backend byte quotas, keep N copies across providers, fail reads over when one goes dark, and take a backend out of the fleet without downtime.

Clients see one endpoint and one namespace. The backends never learn the orchestrator exists — they see ordinary S3 calls, so any provider the AWS SDK can talk to works.

The terminal browser's Backends view: twelve backends listed with health, quota used against limit, object count, API requests, ingress, egress and bytes saved by compression

The web dashboard — storage summary, integrity and compression coverage, monthly usage against each provider's limits, object browser and live logs The web dashboard, showing total used against capacity, a per-backend table of quota and usage, integrity coverage with the oldest unverified copy, encryption and compression coverage, monthly usage against each backend's request and transfer budgets, the object browser, the effective configuration, and a live log tail

Who this is for

AudienceUse case
HomelabbersStack free-tier allocations from multiple providers into usable storage without paying for a single plan.
Self-hosters running MinIOAdd automatic cloud backups to a local MinIO instance with one config change — no sync scripts or extra tooling.
Small teams and startupsMulti-cloud redundancy and encryption without the cost or complexity of enterprise storage platforms.
Anyone wanting provider independenceApplications talk S3 to one endpoint — swap, add, or remove backends without touching a line of code.

What it does

  • Backend quotas. Each backend carries a byte limit and writes overflow to the next when it fills, so a 20 GB allocation and a 10 GB one become one 30 GB bucket. Monthly API-request, egress and ingress caps work the same way.
  • Replication. Set a factor and every object lands on that many distinct backends. A background replicator makes the copies, or write_path.parallel_copies has the write claim its targets and upload to all of them at once, answering the client on the first copy committed — which spares the replicator a full GET of the object and the source backend's egress for every copy it would have made. Reads fail over to a surviving copy, a scrubber checks stored bytes against recorded hashes, and an over-replication worker trims the set when a recovered backend brings its copies back.
  • Access control. A credential resolves to a user, and that user holds a grant on each resource it may reach: a virtual bucket for object access, a backend or the instance itself for the control plane. SigV4 and presigned URLs.
  • Object tagging. Key/value labels stored with the object, always on. Inline on PutObject and CreateMultipartUpload, the three ?tagging operations, and x-amz-tagging-directive on a server-side copy. Lifecycle rules can filter on a tag.
  • Encryption and compression. Envelope encryption (AES-256-GCM; master key inline, in a file, or in Vault Transit) and chunked zstd compression. Both optional and transparent to clients; sizes, ETags and content hashes stay those of the object the client wrote. With both on, compression runs first, because ciphertext does not compress.
  • Terraform provider. Published to the Terraform and OpenTofu registries. Manages the buckets, users, credentials and grants a deployment serves.
  • Database. Embedded SQLite with no external dependencies, single-node PostgreSQL, or many instances with Redis-backed shared counters so quotas hold across the fleet.
  • Operator tooling. Online drain, rebalance, import of an existing bucket, integrity scrub, a cleanup queue with a dead-letter table, hot config reload, an admin API, a web dashboard and a terminal object browser.

Moving providers without downtime

Point the orchestrator at the bucket you already have and import its objects into the metadata layer — nothing moves. Add the new provider and raise the replication factor, and the workers copy everything across while traffic keeps flowing. Once the copies are in place, drain the old backend and delete it from the config. No step takes the application down.

What else is out there

If you've gone looking for a tool that does something similar, there don't appear to be many options:

ProjectWhat it isWhy it's not the same
rclone union remoteClient-side multi-remote stackingPer-client config, no server endpoint, no central drain/rebalance/quota enforcement
MinIO GatewayWas a multi-backend S3 proxyDeprecated in 2022
Flexify.IOCommercial multi-cloud S3 SaaSClosed source; $0.03/GiB SaaS or $0.09/hr self-hosted
gaul/s3proxy, oxyno-zeta/s3-proxyS3 API translation / routing proxiesSingle backend at a time, or multi-bucket routing without quotas, replication, or a metadata layer

Quickstart

Prerequisites: Go 1.27+, Docker, Make.

git clone https://github.com/afreidah/s3-orchestrator.git
cd s3-orchestrator
make run

Starts three MinIO backends via Docker Compose, embedded SQLite as the metadata store, and the orchestrator on localhost:9000.

aws --endpoint-url http://localhost:9000 s3 cp /etc/hostname s3://photos/test.txt
aws --endpoint-url http://localhost:9000 s3 ls s3://photos/

Default credentials: access key photoskey, secret photossecret. Web dashboard at localhost:9000/ui/ (login admin / admin).

Full credentials and troubleshooting: docs/quickstart.md.

Install

ChannelSource
Containerdocker pull ghcr.io/afreidah/s3-orchestrator:<version>
Debian / Ubuntu.deb from GitHub Releases
Static binaryLinux / macOS / Windows from GitHub Releases
From sourcegit clone && make build
Terraform providerafreidah/s3-orchestrator on the Terraform Registry, or the OpenTofu Registry

Database: SQLite is embedded — no external dependencies for single-instance use. PostgreSQL 14+ is also an option and is required for multi-instance deployments (database.driver: postgres); the schema migrates on boot.

Generate a config interactively: s3-orchestrator init.

Verify release artifacts

Container images and release checksums are signed with cosign (keyless / Sigstore):

# Container image
cosign verify ghcr.io/afreidah/s3-orchestrator:<version> \
  --certificate-identity-regexp='github\.com/afreidah/s3-orchestrator' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

# Release checksums
cosign verify-blob checksums.txt --bundle checksums.txt.bundle \
  --certificate-identity-regexp='github\.com/afreidah/s3-orchestrator' \
  --certificate-oidc-issuer='https://token.actions.githubusercontent.com'

Architecture in 30 seconds

              S3 clients (aws cli, rclone, etc.)
                          |
                          v
                    +-----------+
                    | S3 Orch.  |  <-- SigV4 auth, rate limiting, quota routing
                    +-----------+
                     |         |
            +--------+         +------------------+------------------+
            v                  v                  v                  v
       PostgreSQL        OCI Object         Backblaze B2          AWS S3
       (metadata)       Storage (20 GB)       (10 GB)             (5 GB)
                              \                  |                  /
                               '------------ 35 GB total ---------'

Metadata (object locations, quota counters, multipart state, cleanup queue) lives in PostgreSQL or SQLite. Backends only ever see plain S3 calls — no orchestrator-specific protocol, no schema requirements. Any provider that speaks the AWS SDK works.

Deeper details: docs/architecture.md.

Documentation

TopicDoc
First-run / demoQuickstart
S3 client setupUser Guide
Architecturedocs/architecture.md
Configuration walkthrough + hot-reloaddocs/configuration.md
Authentication (SigV4, tokens, multi-bucket)docs/authentication.md
Backends, quotas, routing strategiesdocs/backends.md
Database engines, schema, migrationsdocs/database.md
Replication, over-replication, orphan reconciliationdocs/replication.md
Cleanup queue, lifecycle expiry, pending intentsdocs/cleanup-and-lifecycle.md
Envelope encryption, Vault Transitdocs/encryption.md
At-rest compression (chunked zstd)docs/compression.md
Object tagging (key/value labels)docs/tagging.md
Operations (drain, rebalance, scrub, cache, trace)docs/operations.md
Monitoring (Prometheus, OTel, audit log)docs/monitoring.md
Background services referencedocs/background-services.md
Webhook notificationsdocs/notifications.md
CLI subcommandsdocs/cli.md
Provisioning buckets and identities with TerraformGuide · Terraform Registry · OpenTofu Registry
UI + Admin API JSON endpointsdocs/api-reference.md
Deployment (Nomad, Kubernetes, Docker)docs/deployment.md
Security hardeningdocs/security-hardening.md
Performance tuningdocs/performance-tuning.md
Disaster recoverydocs/disaster-recovery.md
Version migrationdocs/version-migration.md
Benchmark trendsLive charts · scheduled runs
Coding conventionsdocs/style-guide.md
Build / test / contributeCONTRIBUTING.md

Contributing

Contributions welcome. Start with CONTRIBUTING.md for the build / test / submit workflow, and docs/style-guide.md for the codebase's conventions.

License

MIT

aws-s3
backblaze-b2
backup-tool
cloud-storage
data-replication
devops
distributed-systems
failover
golang
homelab
minio
multi-cloud
object-storage
postgres
quota-management
reverse-proxy
s3
self-hosted
sqlite
storage-orchestrator

Significant stargazers

Achille

258 followers · starred Apr 2026

Daenney

157 followers · starred Apr 2026