Skip to main content

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:

  1. The platform mints a new access key scoped to the requested permission level and optional prefix.
  2. The secret is stored in the platform secret store, never returned directly to you.
  3. On the next deploy, the container receives S3 connection variables derived from the attachment.
  4. 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

FieldRequiredDescription
attached_service_idYesUUID of the files service to attach
permissionNoread_only or read_write (default: read_write)
prefixNoObject 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:

VariableValue
MDB_<NAME>_S3_ENDPOINThttps://eu.files.foundrydb.com
MDB_<NAME>_S3_BUCKETThe bucket name, for example files-f0e1d2c3
MDB_<NAME>_S3_REGIONThe bucket region, for example europe-1
MDB_<NAME>_S3_ACCESS_KEY_IDThe access key ID
MDB_<NAME>_S3_SECRET_ACCESS_KEYThe 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:

VariableValue
S3_ENDPOINThttps://eu.files.foundrydb.com
S3_BUCKETThe bucket name
S3_ACCESS_KEYThe access key ID
S3_SECRETThe 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