Storage Configuration
The Kubernetes API uses object storage for app metadata, user content, and execution logs. The Helm chart can wire AWS S3, Azure Blob Storage, Google Cloud Storage, Cloudflare R2, or a generic S3-compatible endpoint, but the checked-in API image does not currently provide the same end-to-end support for every advertised option.
Current Provider Status
Section titled “Current Provider Status”| storage.provider | Backing store | Scoped runtime credentials in the checked-in API | Current guidance |
| --- | --- | --- | --- |
| azure | Azure Blob Storage | Included | Supported by the stock build |
| gcp | Google Cloud Storage | Included | Supported by the stock build |
| r2 | R2 through its S3 API | Included | Use an existing Secret that also supplies R2_API_TOKEN |
| aws | AWS S3 | The chart supports it, but the Kubernetes API target does not enable the aws feature | Rebuild the API with the aws feature before selecting it |
| s3 | Generic S3-compatible endpoint | Resolves to the AWS runtime-credential implementation, which is absent from the stock build | Not an end-to-end stock-image option |
Storage Layout
Section titled “Storage Layout”Configure three logical storage locations:
| Location | Purpose | | --- | --- | | Meta | App and board metadata | | Content | App files, user files, and workflow data | | Logs | Persisted run logs |
Create the buckets or containers before installing the chart; the chart does not provision them. They may be separate locations or the same physical bucket/container referenced by the same name. Meta falls back to content in the shared storage configuration when it is omitted, while the chart emits an explicit meta value. The optional CDN store also falls back to content.
Execution state is configured separately through the execution-state backend. It is not automatically stored in the meta bucket.
Azure Blob Storage
Section titled “Azure Blob Storage”The chart can create the runtime Secret from values:
storage: provider: azure azure: accountName: flowlikestorage accountKey: replace-me metaContainer: meta contentContainer: content logContainer: logsKeep credentials in an uncommitted, access-controlled values file. For a
pre-created Secret, set storage.azure.existingSecret instead. It must expose:
STORAGE_PROVIDER=azureAZURE_STORAGE_ACCOUNT_NAMEAZURE_STORAGE_ACCOUNT_KEYAZURE_META_CONTAINERAZURE_CONTENT_CONTAINERAZURE_LOG_CONTAINER
The account key is also used to mint container-scoped SAS credentials.
Google Cloud Storage
Section titled “Google Cloud Storage”storage: provider: gcp gcp: projectId: my-project serviceAccountKey: |- {"type":"service_account","project_id":"my-project"} metaBucket: flow-like-meta contentBucket: flow-like-content logBucket: flow-like-logsserviceAccountKey is the service-account JSON text consumed by
GOOGLE_APPLICATION_CREDENTIALS_JSON; Kubernetes stringData performs the
Secret's base64 encoding. Do not base64-encode the JSON a second time.
An existing GCP Secret must expose:
STORAGE_PROVIDER=gcpGCP_PROJECT_IDGOOGLE_APPLICATION_CREDENTIALS_JSONwhen the workload cannot use ambient credentialsGCP_META_BUCKETGCP_CONTENT_BUCKETGCP_LOG_BUCKET
Select it with:
storage: provider: gcp gcp: existingSecret: flow-like-storageCloudflare R2
Section titled “Cloudflare R2”R2 uses the AWS-compatible object-store adapter for backing storage and its own temporary-credential API for runtime scoping. Create a private environment file for the Secret:
STORAGE_PROVIDER=awsRUNTIME_CREDENTIALS_PROVIDER=r2R2_ACCOUNT_ID=replace-meR2_API_TOKEN=replace-meR2_ACCESS_KEY_ID=replace-meR2_SECRET_ACCESS_KEY=replace-meAWS_ENDPOINT=https://replace-me.r2.cloudflarestorage.comAWS_REGION=autoAWS_ACCESS_KEY_ID=replace-meAWS_SECRET_ACCESS_KEY=replace-meAWS_USE_PATH_STYLE=trueMETA_BUCKET=flow-like-metaCONTENT_BUCKET=flow-like-contentLOG_BUCKET=flow-like-logsCreate the Secret and select it:
kubectl -n flow-like create secret generic flow-like-storage \ --from-env-file=flow-like-r2.env \ --dry-run=client -o yaml \ | kubectl apply -f -storage: provider: r2 r2: existingSecret: flow-like-storageGrant the API token only the account-level R2 permissions required to create temporary credentials. Keep the S3 access keys and API token out of checked-in values.
AWS S3
Section titled “AWS S3”After rebuilding the Kubernetes API with the flow-like-api/aws feature, AWS
storage requires:
- A workload identity or static AWS credentials that can access the configured buckets
RUNTIME_ROLE_ARN, whose role can be assumed by the API identity- An IAM policy on that runtime role that permits the object operations Flow-Like narrows with per-request session policies
For EKS workload identity, use an existing Secret that omits
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY entirely:
STORAGE_PROVIDER=awsAWS_REGION=eu-central-1META_BUCKET=flow-like-metaCONTENT_BUCKET=flow-like-contentLOG_BUCKET=flow-like-logsRUNTIME_ROLE_ARN=arn:aws:iam::123456789012:role/FlowLikeRuntimeRoleserviceAccount: create: true annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/FlowLikeApiRole
storage: provider: aws aws: existingSecret: flow-like-storageThe chart-generated AWS Secret always writes the static credential keys, even when their values are empty. An explicit empty value is still a configured environment value and can prevent the AWS credential chain from using workload identity. Omitting those keys in an existing Secret avoids that misconfiguration.
Generic S3-Compatible Storage
Section titled “Generic S3-Compatible Storage”The chart's s3 block supplies both S3_* settings for the Kubernetes storage
adapter and AWS_* aliases used by the shared API layer:
storage: provider: s3 s3: endpoint: https://objects.example.com region: us-east-1 accessKeyId: replace-me secretAccessKey: replace-me metaBucket: flow-like-meta contentBucket: flow-like-content logBucket: flow-like-logs usePathStyle: trueThis is enough to describe backing-store access after enabling the API's
aws feature. It is not proof that the service supports Flow-Like's scoped
runtime-credential path: s3 selects the AWS implementation, which calls AWS
STS AssumeRole and requires RUNTIME_ROLE_ARN. Do not treat MinIO or another
S3-compatible service as end-to-end supported without validating that path.
Scoped Credentials
Section titled “Scoped Credentials”Flow-Like loads a master provider from RUNTIME_CREDENTIALS_PROVIDER, falling
back to STORAGE_PROVIDER when the former is absent. Explicit empty values do
not trigger the fallback and are configuration errors.
For app and run operations, the API derives temporary credentials narrowed to paths such as:
apps/{app_id}/users/{user_id}/apps/{app_id}/runs/{app_id}/tmp/user/{user_id}/apps/{app_id}/tmp/global/apps/{app_id}/
AWS uses AssumeRole with an inline session policy, Azure creates SAS tokens,
GCP creates signed or token-based scoped access, and R2 calls its temporary
credentials API. Provider-side IAM remains the outer permission boundary.
Validate the Configuration
Section titled “Validate the Configuration”Render the selected provider before installing:
helm lint apps/backend/kubernetes/helm \ --values flow-like-values.yaml
helm template flow-like apps/backend/kubernetes/helm \ --namespace flow-like \ --values flow-like-values.yamlAfter installation, verify readiness without printing Secret values:
kubectl get deployment flow-like-api -n flow-likekubectl logs deployment/flow-like-api -n flow-likeStartup errors mentioning the provider, master credentials, or a missing bucket/container usually indicate either a missing Secret key, an explicit empty value, a bucket that was not created, or a provider feature that is not present in the API image.