Storage Providers
Flow-Like uses object storage for app metadata, user content, CDN/public content, and execution logs. The Compose stack does not create buckets or containers.
Current Provider Status
Section titled “Current Provider Status”| Configuration | Checked-in Compose images | Notes |
| --- | --- | --- |
| Azure Blob Storage | Supported | API includes Azure runtime credentials |
| Google Cloud Storage | Supported | API includes GCP runtime credentials |
| Cloudflare R2 | Supported with an explicit R2 runtime override | Uses the AWS-compatible backing-store adapter and R2 temporary credentials |
| AWS S3 | Backing-store adapter is present, but the API image omits the flow-like-api/aws feature | Rebuild the API with that feature |
| Other S3-compatible services | Same missing AWS runtime feature, plus unverified STS behavior | Not a stock end-to-end option |
The Docker Compose API target enables azure, gcp, and r2 runtime
credentials. It does not enable aws, even though the Compose file's
interpolation default and .env.example currently select aws.
Explicit Values Required by Compose
Section titled “Explicit Values Required by Compose”The Compose template injects the runtime-provider, CDN, and provider-specific
bucket variables even when their .env values are empty. The Rust
configuration treats an explicit empty value as configured; it does not fall
through to another variable.
For the selected provider:
- set
RUNTIME_CREDENTIALS_PROVIDERto a non-empty provider name; - set
CDN_BUCKET_NAMEto a real bucket/container, commonly the content location; - set all selected provider-specific meta, content, and log names;
- do not expect empty credential fields to activate an ambient credential chain.
The generic logical names should also be set:
META_BUCKET=flow-like-metaCONTENT_BUCKET=flow-like-contentLOG_BUCKET=flow-like-logsCDN_BUCKET_NAME=flow-like-contentMeta and CDN can share the content location by using the same name. Execution
state is configured separately through EXECUTION_STATE_BACKEND; it is not
stored in the meta bucket by default.
Azure Blob Storage
Section titled “Azure Blob Storage”STORAGE_PROVIDER=azureRUNTIME_CREDENTIALS_PROVIDER=azure
AZURE_STORAGE_ACCOUNT_NAME=replace-meAZURE_STORAGE_ACCOUNT_KEY=replace-meAZURE_META_CONTAINER=metaAZURE_CONTENT_CONTAINER=contentAZURE_LOG_CONTAINER=logs
META_BUCKET=metaCONTENT_BUCKET=contentLOG_BUCKET=logsCDN_BUCKET_NAME=contentCreate all three containers before starting the API. The account key is also used to mint short-lived SAS credentials for scoped access.
az storage container create --name meta --account-name replace-meaz storage container create --name content --account-name replace-meaz storage container create --name logs --account-name replace-meGoogle Cloud Storage
Section titled “Google Cloud Storage”STORAGE_PROVIDER=gcpRUNTIME_CREDENTIALS_PROVIDER=gcp
GCP_PROJECT_ID=replace-meGOOGLE_APPLICATION_CREDENTIALS_JSON={"type":"service_account","project_id":"replace-me"}GCP_META_BUCKET=flow-like-metaGCP_CONTENT_BUCKET=flow-like-contentGCP_LOG_BUCKET=flow-like-logs
META_BUCKET=flow-like-metaCONTENT_BUCKET=flow-like-contentLOG_BUCKET=flow-like-logsCDN_BUCKET_NAME=flow-like-contentGOOGLE_APPLICATION_CREDENTIALS_JSON is JSON text, not a path. The Compose
template injects this variable even when it is empty, so provide valid JSON
instead of relying on an empty value to select ambient credentials.
Grant the service account access only to the configured buckets and validate the token-exchange/downscoping path as well as ordinary object access.
Cloudflare R2
Section titled “Cloudflare R2”Keep the backing-store selector on the AWS-compatible adapter and select R2 only for runtime credentials:
STORAGE_PROVIDER=awsRUNTIME_CREDENTIALS_PROVIDER=r2
AWS_ENDPOINT=https://replace-me.r2.cloudflarestorage.comAWS_REGION=autoAWS_USE_PATH_STYLE=trueAWS_ACCESS_KEY_ID=replace-meAWS_SECRET_ACCESS_KEY=replace-meAWS_META_BUCKET=flow-like-metaAWS_CONTENT_BUCKET=flow-like-contentAWS_LOG_BUCKET=flow-like-logs
R2_ENDPOINT=https://replace-me.r2.cloudflarestorage.comR2_ACCOUNT_ID=replace-meR2_ACCESS_KEY_ID=replace-meR2_SECRET_ACCESS_KEY=replace-meR2_API_TOKEN=replace-me
META_BUCKET=flow-like-metaCONTENT_BUCKET=flow-like-contentLOG_BUCKET=flow-like-logsCDN_BUCKET_NAME=flow-like-contentThe R2 API token is separate from the S3-compatible key pair. It is used to mint prefix-scoped temporary credentials, so restrict it to the required account and R2 operations.
AWS S3
Section titled “AWS S3”AWS requires rebuilding docker-compose-api with the flow-like-api/aws
feature. After doing so, configure both backing storage and credential
scoping:
STORAGE_PROVIDER=awsRUNTIME_CREDENTIALS_PROVIDER=aws
AWS_REGION=eu-central-1AWS_USE_PATH_STYLE=falseAWS_ACCESS_KEY_ID=replace-meAWS_SECRET_ACCESS_KEY=replace-meAWS_META_BUCKET=flow-like-metaAWS_CONTENT_BUCKET=flow-like-contentAWS_LOG_BUCKET=flow-like-logs
META_BUCKET=flow-like-metaCONTENT_BUCKET=flow-like-contentLOG_BUCKET=flow-like-logsCDN_BUCKET_NAME=flow-like-contentRUNTIME_ROLE_ARN=arn:aws:iam::123456789012:role/FlowLikeRuntimeRoleThe API identity needs bucket access and permission to assume
RUNTIME_ROLE_ARN. Flow-Like adds per-request inline session policies that
narrow the role to app, user, temporary, and run-log prefixes.
The supplied Compose service always injects the static AWS keys. Empty values remain explicit credentials and can prevent the AWS credential chain from using workload identity. To use an instance or web identity, add a Compose override that removes those environment entries entirely and mounts the identity material required by the platform.
The META_BUCKET_EXPRESS_ZONE, CONTENT_BUCKET_EXPRESS_ZONE, and
LOGS_BUCKET_EXPRESS_ZONE names still appear in the Compose template, but the
current storage code does not read them. They do not enable S3 Express.
Other S3-Compatible Services
Section titled “Other S3-Compatible Services”An endpoint such as MinIO can implement the object operations used by the
backing-store adapter, but STORAGE_PROVIDER=aws also selects the AWS runtime
credential implementation. That implementation calls AWS STS
AssumeRole; basic S3 API compatibility is insufficient.
Do not describe an S3-compatible provider as end-to-end supported until its
scoped runtime-credential path has been implemented and tested. The API does
not read MINIO_* variables.
Validate Before Starting
Section titled “Validate Before Starting”Check interpolation without printing secrets:
docker compose config --quietThen inspect only the non-secret selection and names:
docker compose run --rm --no-deps api sh -lc \ 'printf "storage=%s runtime=%s meta=%s content=%s logs=%s cdn=%s\n" \ "$STORAGE_PROVIDER" "$RUNTIME_CREDENTIALS_PROVIDER" \ "$META_BUCKET" "$CONTENT_BUCKET" "$LOG_BUCKET" "$CDN_BUCKET_NAME"'Start or recreate the API and review its logs:
docker compose up -d --build api api-gatewaydocker compose logs apiTest metadata, content, temporary-file, database, and log operations. A successful bucket listing does not exercise temporary credential scoping.