Storage Providers
A new Compose installation includes RustFS, three private buckets and bootstrap for separate API and temporary-credential issuer identities. The API uses S3-compatible object operations and prefix-scoped STS credentials. Basic bucket access alone does not validate execution isolation.
The checked-in RustFS image is pinned by digest to 1.0.0-rc.5, a release
candidate. Qualify the exact image, gateway and policies together before
admitting tenants, and repeat that qualification when changing the pin.
Bundled storage settings
Section titled “Bundled storage settings”| Variable | Default or source | Purpose |
|---|---|---|
OBJECT_STORE_MODE | bundled | Enables the bundled topology |
STORAGE_PROVIDER, RUNTIME_CREDENTIALS_PROVIDER | aws | S3 backing adapter and runtime credential implementation |
S3_STS_PROVIDER | rustfs | RustFS session issuance |
S3_PUBLIC_ENDPOINT | http://s3.localhost:9000 | Signed origin reachable by clients and execution services |
S3_INTERNAL_ENDPOINT | http://object-store:9000 | Direct internal storage access |
STS_ENDPOINT_URL | http://object-store:9000 | Private credential issuance |
AWS_USE_PATH_STYLE | true | Bucket names appear in object paths |
META_BUCKET | flow-like-meta | App and Flow metadata |
CONTENT_BUCKET | flow-like-content | App and user content |
LOG_BUCKET | flow-like-logs | Execution logs |
STS_SESSION_TTL_SECONDS | 7200 | Requested session lifetime |
The default mode requires three distinct bucket names. CDN_BUCKET_NAME
defaults to the content bucket in the S3 adapter; this does not make that bucket
public.
Setup generates three independent identities:
RUSTFS_ROOT_USERandRUSTFS_ROOT_PASSWORDreach the store and bootstrap only.AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEYidentify the API storage user.STS_ISSUER_ACCESS_KEYandSTS_ISSUER_SECRET_KEYidentify the restricted issuer.
The API and issuer are regular IAM users because RustFS service accounts cannot
issue STS sessions. Both users are denied administration; the API user is also
denied AssumeRole. Bootstrap uses the pinned release’s native
/rustfs/admin/v3 API with S3 SigV4.
Storage secrets support _FILE inputs. Unreadable or empty files fail, and
readers remove only trailing line endings. The API requires exactly one of a
value and its _FILE setting. Bootstrap and standalone storage readers give the
file precedence, but configure only one form when sharing settings with the API.
The library accepts STS_SESSION_TTL_SECONDS from 900 to 43,200 seconds and
defaults to 3,600; Compose and Helm request 7,200 for hour-long runs plus margins.
The API uses the expiration actually returned by STS. RustFS rejects AWS SSE-KMS
and S3 Express settings and omits AWS KMS policy clauses. Static API credentials
do not require a fabricated session token.
Runners receive temporary credentials in their signed dispatch payloads. Session policies limit access to the required buckets and app, user, temporary or run-log prefixes. Killing a runner ends its processes; it does not instantly revoke credentials that were copied elsewhere. Provider expiration remains relevant.
Initialization and drift
Section titled “Initialization and drift”Bootstrap requires distinct bucket names and exact, comma-separated browser
origins in S3_CORS_ALLOWED_ORIGINS; wildcard origins fail. Existing bucket
policies stop initialization for review. CORS and lifecycle rules expire
incomplete multipart uploads after one day and content under tmp/ after two.
Existing IAM policies must match the expected definitions. Users must have only their expected policy and no group membership. Bootstrap verifies existing user passwords without replacing them. Changing a configured secret therefore needs an explicit IAM rotation or a new identity. Preserve the working identities and investigate drift before changing existing policies.
Keep the signing origin reachable
Section titled “Keep the signing origin reachable”The API, compiler, browser/desktop clients and per-run gateways must all reach
the exact S3_PUBLIC_ENDPOINT used for signatures. Changing a signed URL’s
host, port or path breaks its signature.
For the local default, s3.localhost resolves to the data gateway inside
Compose and to loopback on the client machine. Add a client hosts entry when
needed. A client on another machine cannot use the operator’s loopback address.
The data gateway forwards only configured bucket paths. Root listing, STS and administration routes are denied. The private RustFS endpoint remains separate; do not publish it in place of the data gateway.
S3_INTERNAL_ENDPOINT serves API LanceDB access; AWS_ENDPOINT remains a
legacy fallback. META_BUCKET_ENDPOINT, CONTENT_BUCKET_ENDPOINT and
LOGS_BUCKET_ENDPOINT override exported per-bucket endpoints. Shared credentials
carry the region, path-style and explicit HTTP settings. HTTPS certificate
verification remains enabled. Install private CAs in each caller’s trust store;
CA files are not carried in the credentials.
Public TLS storage
Section titled “Public TLS storage”For https://storage.example.com, route your TLS proxy to the data gateway and
configure:
S3_PUBLIC_ENDPOINT=https://storage.example.comS3_GATEWAY_ALIAS=object-gatewayCOMPILER_ALLOWED_STORAGE_HOSTS=https://storage.example.com,http://object-store:9000EXECUTION_OBJECT_STORE_TLS_GATEWAY=trueThe alias prevents Compose from resolving the public HTTPS hostname directly to a plaintext internal listener. Preserve the signed host and request path through the TLS proxy.
Enable EXECUTION_OBJECT_STORE_TLS_GATEWAY only after verifying that this TLS
origin denies STS and administration. A sandbox’s HTTPS CONNECT tunnel hides
request paths from its execution proxy, so that proxy relies on the TLS
endpoint’s bucket-only contract.
Verify prefix authorization
Section titled “Verify prefix authorization”After bootstrap, run the included conformance command against a disposable or backed-up store:
docker compose build object-store-initdocker compose up -d object-store object-gatewaydocker compose run --rm object-store-initdocker compose run --rm --entrypoint python object-store-init /opt/object-store/conformance.pyThe script uses unique test prefixes and removes its objects afterward. It checks permitted reads/writes, denied sibling prefixes and other buckets, list-prefix restrictions, copy-source authorization, multipart initiation and abort, missing/invalid session tokens, STS/admin denial and presigned GET/PUT.
The probes also check confusable prefixes, empty-prefix listing, explicit deny,
nested STS issuance and API-user STS denial. A valid result must include both
successful authorized operations and rejected unauthorized operations. Repeat
the suite when changing the store digest, policies, public endpoint or issuer
identity. Kubernetes runs the same contract through
helm test <release> -n <namespace> --logs.
Complete additional tests for actual expiration, multipart completion and copy, application operations, restored IAM state and host failure. A passing smoke test does not cover those paths.
Include an hour-long workflow that can read and write near its deadline and operations that fail after real session expiry. Recheck old credentials after restore and rotation, and retain the store digest and probe results with the deployment release.
Back up both object data and RustFS IAM metadata. Restore them together with
matching deployment identities on a clean host, then rerun authorization checks.
Do not treat the named object_store_data volume as an off-host backup.
To check bootstrap logic without starting a store, run from the repository root:
python3 -m venv /tmp/flow-like-store-tests/tmp/flow-like-store-tests/bin/pip install -r apps/backend/docker-compose/object-store/requirements.txtPYTHONDONTWRITEBYTECODE=1 /tmp/flow-like-store-tests/bin/python -m unittest discover -s apps/backend/docker-compose/object-store -p 'test_*.py'These offline tests do not validate a deployed storage provider.
Retain or adopt external S3/STS
Section titled “Retain or adopt external S3/STS”Use the supplied overlay:
OBJECT_STORE_MODE=externalCOMPOSE_FILE=docker-compose.yml:docker-compose.external-store.ymlS3_STS_PROVIDER=awsS3_INTERNAL_ENDPOINT=https://your-storage-originS3_PUBLIC_ENDPOINT=https://your-storage-originSTS_ENDPOINT_URL=https://your-sts-originCOMPILER_ALLOWED_STORAGE_HOSTS=https://your-storage-originProvide the external API and issuer credentials, existing bucket names and
provider-appropriate path-style settings. Use S3_STS_PROVIDER=rustfs for a
separately hosted qualified RustFS installation.
The overlay removes bundled storage and bootstrap from the active graph. It does not create buckets or migrate data. The per-run TLS gateway restriction still applies: an unrestricted S3/administration endpoint does not satisfy the bucket-only contract.
AWS S3
Section titled “AWS S3”The stock API already includes AWS runtime credentials. Set
RUNTIME_ROLE_ARN to the execution role and configure the issuer’s permission
to assume it. Flow-Like supplies an inline session policy that narrows the
role’s access. Verify role and bucket policies as well as ordinary API access.
For hour-long executions, the role’s maximum session duration must cover the requested session and all execution budgets. AWS role chaining is limited to one hour, which cannot cover a full hour of execution plus queueing and grace. See the AWS AssumeRole duration contract. Automatic credential renewal is not implemented.
For customer-managed KMS encryption, the role also needs the relevant KMS
permissions. Configure S3_KMS_KEY_ARN or the per-bucket KMS variables; details
are in Storage Providers.
The Compose API includes explicit AWS credential environment entries. To use workload identity, supply a reviewed override that removes those entries and provides the platform’s identity material. Empty static keys are not a workload-identity configuration.
Other providers
Section titled “Other providers”The API also includes Azure, GCP and R2 implementations. Their variables remain
in .env.example; Storage Providers describes the
provider contracts.
For R2, retain STORAGE_PROVIDER=aws for the backing adapter and select
RUNTIME_CREDENTIALS_PROVIDER=r2 for scoped credentials. Configure the R2
account, API token and S3 keys. For Azure/GCP, set the provider-specific names
explicitly where the Compose file injects empty overrides.
An alternative provider still needs the execution gateway, compiler, reachable signing endpoint and lifetime checks validated together. Generic S3 API support does not establish support for inline STS prefix policies.