Object storage
S3-compatible object storage that works with any S3 client.
Managed S3-compatible object storage, powered by Tigris in production. Works with any S3 SDK or tool.
service "api" {
build = build.api
command = "./api"
endpoint {
public = true
}
env = {
S3_ENDPOINT = storage.uploads.endpoint
S3_ACCESS_KEY = storage.uploads.access_key
S3_SECRET_KEY = storage.uploads.secret_key
S3_BUCKET = storage.uploads.bucket
}
}
storage "uploads" {}
You can declare multiple buckets; each storage block is its own bucket with its own credentials.
Connection attributes
| Attribute | Description |
|---|---|
endpoint |
S3-compatible endpoint URL (for example, http://127.0.0.1:5000 in dev). |
access_key |
Access key for authentication. |
secret_key |
Secret key for authentication. |
bucket |
Bucket name. |
public_url |
HTTPS origin for anonymous reads. Available only when public = true. |
Public buckets
Public buckets are opt-in:
storage "assets" {
public = true
}
service "web" {
build = build.web
env = {
ASSETS_PUBLIC_URL = storage.assets.public_url
}
}
public_url has no trailing slash. Append the object key to it, for example
${ASSETS_PUBLIC_URL}/images/logo.png.
Public access allows anonymous object reads. Uploads and deletes still require credentials, and directory listing is disabled. CORS headers, cache-control metadata, and custom domains are separate concerns.
Removing public = true makes an existing bucket private again on the next
deployment. Preview buckets are forked from their parent, so making a preview
bucket public can expose copied parent data.
Example: AWS SDK (JavaScript)
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
const s3 = new S3Client({
endpoint: process.env.S3_ENDPOINT,
region: "us-east-1", // Required but ignored locally
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY,
},
forcePathStyle: true, // Required for local S3-compatible servers
});
await s3.send(
new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: "myfile.txt",
Body: "Hello, world!",
})
);
Local development
During specific dev, a local S3-compatible server runs automatically, and the same storage.* references resolve to it. Public bucket URLs use the local server and support anonymous reads. Browse bucket contents from the local dashboard.
Production
Browse bucket contents and manage stored files from the dashboard.
If a service outside of Specific needs to read from or write to a bucket, generate direct S3-compatible credentials (read/write or read-only) from the storage resource’s Access tab in the dashboard.
In preview environments, object storage is forked from the parent environment.