Attach to Apps
Attaching a files service to a hosted app automates the entire credential lifecycle. The platform mints a dedicated access key for the attachment, injects it into the container environment, and revokes it the moment you detach. You never copy a secret into your app's configuration manually.
How It Works
When you attach a files service to an app:
- The platform mints a new access key scoped to the requested permission level and optional prefix.
- The secret is stored in the platform secret store, never returned directly to you.
- On the next deploy, the container receives S3 connection variables derived from the attachment.
- When you detach, the platform revokes the provider-side IAM identity and destroys the stored secret.
The permission and prefix are enforced by the object storage provider's own IAM policy, not by the platform layer. A read-only attachment cannot upload. A prefix-scoped attachment cannot reach objects outside its prefix.
Attach a Files Service
Use POST /app-services/{app-id}/attachments with the files service ID:
curl -u admin:password -X POST \
https://api.foundrydb.com/app-services/{app-id}/attachments \
-H "Content-Type: application/json" \
-d '{
"attached_service_id": "{files-service-id}",
"permission": "read_write",
"prefix": "uploads/"
}'
Attachment Fields
| Field | Required | Description |
|---|---|---|
attached_service_id | Yes | UUID of the files service to attach |
permission | No | read_only or read_write (default: read_write) |
prefix | No | Object key prefix scoping the attachment's key, for example uploads/. Limits the key to objects under this path only. Empty grants the whole bucket |
After attaching, the app redeploys automatically with the new environment variables injected.
Injected Environment Variables
The platform derives an environment variable prefix from the files service name: uppercased, non-alphanumeric characters collapsed to underscores, and prefixed with MDB_. For example, a files service named user-uploads produces the prefix MDB_USER_UPLOADS.
Five variables are injected for every files attachment:
| Variable | Value |
|---|---|
MDB_<NAME>_S3_ENDPOINT | https://eu.files.foundrydb.com |
MDB_<NAME>_S3_BUCKET | The bucket name, for example files-f0e1d2c3 |
MDB_<NAME>_S3_REGION | The bucket region, for example europe-1 |
MDB_<NAME>_S3_ACCESS_KEY_ID | The access key ID |
MDB_<NAME>_S3_SECRET_ACCESS_KEY | The secret access key |
Bare S3 Variables (Single Attachment)
When exactly one files service is attached to an app, the platform also injects a second set of variables with no prefix. These follow the conventional names used by many S3 libraries and tools:
| Variable | Value |
|---|---|
S3_ENDPOINT | https://eu.files.foundrydb.com |
S3_BUCKET | The bucket name |
S3_ACCESS_KEY | The access key ID |
S3_SECRET | The secret access key |
If a second files service is attached, the bare variables are removed and only the prefixed versions remain. This prevents ambiguity.
Reading the Bucket in Your App
TypeScript
import { S3Client } from "@aws-sdk/client-s3";
// Works whether you read the bare variables (single attachment)
// or the prefixed ones (multiple attachments).
const s3 = new S3Client({
region: process.env.S3_ENDPOINT?.includes("eu") ? "europe-1" : "us-1",
endpoint: process.env.S3_ENDPOINT,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY!,
secretAccessKey: process.env.S3_SECRET!,
},
});
const BUCKET = process.env.S3_BUCKET!;
For an app with multiple files attachments, reference the prefixed variables instead:
const s3 = new S3Client({
region: "europe-1",
endpoint: process.env.MDB_USER_UPLOADS_S3_ENDPOINT,
credentials: {
accessKeyId: process.env.MDB_USER_UPLOADS_S3_ACCESS_KEY_ID!,
secretAccessKey: process.env.MDB_USER_UPLOADS_S3_SECRET_ACCESS_KEY!,
},
});
const BUCKET = process.env.MDB_USER_UPLOADS_S3_BUCKET!;
Python
import boto3
import os
s3 = boto3.client(
"s3",
region_name=os.environ.get("S3_ENDPOINT", "").split(".")[0].replace("https://", "") or "europe-1",
endpoint_url=os.environ["S3_ENDPOINT"],
aws_access_key_id=os.environ["S3_ACCESS_KEY"],
aws_secret_access_key=os.environ["S3_SECRET"],
)
BUCKET = os.environ["S3_BUCKET"]
Detach a Files Service
curl -u admin:password -X DELETE \
https://api.foundrydb.com/app-services/{app-id}/attachments/{attachment-id}
The platform revokes the access key on the provider side and destroys the stored secret. On the next deploy, the injected variables are removed from the container.
List Attachments
curl -u admin:password \
https://api.foundrydb.com/app-services/{app-id}
The app_config.attachments field in the app service response lists all current attachments, each with its id, attached_service_id, env_prefix, prefix, permission, and status.
Notes on Attachment Credential Scope
- Each attachment gets its own IAM identity. Revoking one attachment's credential does not affect others.
- The prefix and permission level cannot be changed after attaching. Detach and re-attach with new parameters to change scope.
- Attachment keys are not listed under
GET /file-services/{id}/keys. They are managed by the platform and retired automatically on detach or app deletion. - Key creation is blocked while the files service is over its hard storage quota. Attaching to a quota-exceeded service returns an error.
What's Next
- Using S3 Clients — direct SDK and CLI access with manually minted keys
- Buckets and Keys — create a files service and manage standalone access keys