DefangLabs / DefangLabs/defang

S3 / Object Storage Support

Open
#688 1 comment 6 reactions 1 assignee View on GitHub

@lionello is already working on this.

Since Aug 14, 2026.

byoc compose storage
Dominant language
Go
Stars
166
Forks
24
Avg merge
10h 8m
Merged PRs (30d)
33

Description

This is an issue to track provisioning of managed object storage, like AWS S3, DigitalOcean Spaces, GCS, etc.

Please vote on this issue if you would like to express support for this feature.


Design (consolidated from #2212, 2026-09-01)

The extension is x-defang-s3. It attaches to a stub service, in the same way as x-defang-postgres / x-defang-redis: keep a minio:-shaped service block in compose.yaml and tag it. The minio image is a sentinel only — Defang elides it and never runs it, so the archival status of MinIO Community Edition does not apply. Defang provisions real object storage per cloud and injects the env vars the app already reads, so compose.yaml does not change per cloud.

The name says the protocol, not the backend: the app-facing contract is the S3 API on every cloud, the same way x-defang-postgres names Postgres. (Earlier drafts said x-defang-object-store.)

Per cloud
  • AWS — a native S3 bucket. No static keys: Defang scopes an IAM policy for the bucket onto the task role and leaves the access-key/secret-key env vars empty. S3 SDKs that use the AWS default credential chain pick the task role up on their own. provider/defangaws/aws/s3.go already has createPrivateBucket (SSE, public-access block, retain/force-destroy recipes), so provisioning is mostly done.
  • Azure — no native S3 API, so this cloud needs a translation layer: s3proxy with jclouds.provider=azureblob-sdk and empty jclouds.identity/jclouds.credential, which gives DefaultAzureCredential → managed identity with SDK-handled token refresh. (The older azureblob provider cannot refresh — s3proxy issue 352.) The app-to-proxy hop still needs a project-local generated SigV4 key pair, because clients such as rust-s3 always sign; use authorization=aws-v2-or-v4 and path-style addressing. Sidecars are not supported on Azure today, so s3proxy must run as a standalone service first.
  • GCP — a native GCS bucket over its S3-compatible XML/interop API. Auth is HMAC keys minted for a dedicated service account. This is a real static secret, so "no static keys" is best-effort per cloud and does not gate v1.
Decisions locked
  • One bucket per x-defang-s3 service for v1. Multiple buckets per extension is long-term.
  • The bucket name is declared in the extension. DNS cannot carry the endpoint: the name is globally unique, and TLS breaks as well, because no certificate matches objs.project.internal and path style does not help (SNI still carries the private name). So env-var injection is the only route, and the CLI injects env at compose-load time, before provisioning — a generated name is not known yet.
  • Env var convention needs no new code: wireDependentServices in fixup.go already emits <SERVICE>_URL for the model-provider wiring. Reuse it, e.g. OBJS_URL, plus _BUCKET and _REGION.
  • Retain or delete on compose down is a recipe setting, the same as postgres/redis.
  • No manual bucket-collision handling. Pulumi's aws.s3.Bucket already surfaces BucketAlreadyExists / BucketAlreadyOwnedByYou as a normal apply error. Keep only the bucket-name-shape pre-flight check. pulumi.Import is a nice-to-have.
Out of scope for v1
  • Presigned URLs for third-party clients (browsers). SigV4 signs the Host header, so a signature-less or localhost-trust proxy hop breaks them.
  • A local/ephemeral dev storage engine and the split-horizon DNS work that presigned-URL portability needs.
Phases and status
Phase Work Status
1 CLI wiring in defang: extension allowlist, name validation, IsMinioRepo, env injection #2239 open
2 AWS ObjectStore component in pulumi-defang DefangLabs/pulumi-defang#503 (draft)
3 Azure via standalone s3proxy not started
4 GCP via GCS interop + HMAC not started

Provider-side tracking and the full design thread: DefangLabs/pulumi-defang#480. Prior art: the closed WIP PR DefangLabs/defang-mvp#1537 (learnings recorded there) and DefangLabs/defang-mvp#1527.

Forcing function: the Buzz BYOC deploy bundle (DefangLabs/buzz#2) hand-writes S3 endpoint and static-key config today, and has no clean Azure story. With x-defang-s3 that bundle would not need to diverge from deploy/compose/.

Still open
  • GCP: HMAC keys vs. a proxy, and whether "no static keys" is AWS-only.
  • Should Defang warn when a compose file keeps a plain minio on a mounted volume, separately from this extension?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.