S3 object storage
A hosted, S3-compatible object store for your project: 100 GB on an encrypted volume, powered by SeaweedFS (Apache-2.0), speaking the same protocol as AWS S3 — every S3 SDK, the AWS CLI, and presigned URLs work.
Provision it
bootload database install s3 --project production
# → s3://<ACCESS_KEY>:<SECRET_KEY>@s3.internal:8333
One command creates the store with two generated keys (shown once here,
kept in the project secret store). It starts private: reachable only by
your project's other services at s3.internal:8333. Pass --name assets
for a different service name.
Use it from your apps (private)
Point any S3 SDK at the internal endpoint with path-style addressing;
use no-aws as the region (any name works — this one says what it means). Create buckets from
your code (CreateBucket) — no console needed.
import { S3Client } from "@aws-sdk/client-s3";
const s3 = new S3Client({
endpoint: "http://s3.internal:8333",
region: "no-aws",
forcePathStyle: true,
credentials: { accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY },
});
Make it public
For browser uploads/downloads and presigned URLs, expose it:
bootload exposure s3 public --wait
# ✅ s3 is now public and reachable at https://s3-a1b2c3.fr1.apps.bootload.io
You get an https address immediately (platform certificate). The keys are still required — anonymous requests are refused.
export AWS_ACCESS_KEY_ID=<ACCESS_KEY>
export AWS_SECRET_ACCESS_KEY=<SECRET_KEY>
export AWS_DEFAULT_REGION=no-aws
E=https://s3-a1b2c3.fr1.apps.bootload.io
aws --endpoint-url $E s3 mb s3://media # create a bucket
aws --endpoint-url $E s3 cp video.mp4 s3://media/ # upload
aws --endpoint-url $E s3 presign s3://media/video.mp4 --expires-in 3600
# → a link anyone can open for an hour
Sign requests (and generate presigned URLs) against the public endpoint. Single requests are capped at 50 MB — larger objects upload via multipart, which every SDK and the AWS CLI do automatically.
Your own domain
bootload domain add example.com # verify ownership once
bootload domain attach assets.example.com s3
The certificate for assets.example.com is issued automatically once the
name resolves to the platform edge (the attach command prints the exact
CNAME/A record if you host DNS elsewhere). Presigned URLs then carry your
domain. bootload domain detach assets.example.com s3 removes it.
Backups, rotation, going private again
bootload backup create --service s3 # manifest + the 100 GB volume, online
bootload backup restore-service <id> # runs in the background; the CLI follows it
To rotate the keys, set new values for the service's S3_ACCESS_KEY and
S3_SECRET_KEY secrets and bootload restart s3 — the store re-reads them
at boot. To go private again, detach any custom domains, remove the public
route, and run bootload exposure s3 internal --port 8333.
Limits
- One identity with full access to its own store (per-bucket users are on the roadmap).
- 50 MB per single request on the public endpoint — use multipart beyond that (automatic in SDKs).
- Storage bills at the standard volume rate; the store is a singleton service (no horizontal scaling).