Managed S3 / RustFS
Managed S3 is S3-compatible object storage, backed by RustFS, that Temps runs as a container on your own server: you create the service, link it to a project, and Temps injects S3_ENDPOINT, the access keys and AWS-style aliases into that project's environment. There are no per-GB, request or bandwidth fees, and scheduled backups mirror the bucket to an off-server S3 source.
Provision and manage object storage three ways: the dashboard, the @temps-sdk/cli command-line tool (Manage from the CLI), or the REST API. If you use an AI coding agent (Claude Code, Cursor, Windsurf), install the temps-cli skill and just describe what you want.
Creating S3 storage
Create S3 / RustFS storage
- 1
Navigate to Services then click Create Service.
- 2
Select S3 / RustFS as the service type.
- 3
Choose the storage engine: RustFS (the Rust-native default) for anything new, MinIO only for legacy services, or a custom image. Note: the CLI -t s3 flow defaults to RustFS and does not support an engine flag — use the dashboard to select a different engine.
- 4
Click Create Service. Temps auto-assigns an API port from 9000 (and a console port from 9001 for RustFS), sets the region to us-east-1, and generates an access key and secret key.
Checkpoint: Run bunx @temps-sdk/cli services list and confirm the new service appears with status running.
Via Dashboard:
- Navigate to Services → Create Service.
- Select S3 / RustFS.
- Choose the storage engine:
- RustFS — the Rust-native default (
rustfs/rustfs:1.0.0-beta.6). - MinIO — kept for legacy services (
minio/minio:RELEASE.2025-09-07T16-13-09Z). Deprecated — use RustFS for anything new. - Custom image — bring your own.
- RustFS — the Rust-native default (
- Click Create Service.
On creation Temps auto-assigns an API port starting from 9000 (and a console port from 9001 for RustFS), sets the region to us-east-1, and generates an access key (AKIA…) and secret key.
MinIO is deprecated. Existing MinIO services keep working, but provision RustFS for new object storage — it is the default, supported engine going forward.
Manage from the CLI
Provision and manage object storage two ways — hand it to a coding agent, or run the @temps-sdk/cli commands yourself.
Drive it through an AI agent
Most clients never type these commands by hand. A coding agent — Claude Code, Codex, or Opencode — runs the @temps-sdk/cli calls (shown below) against the Temps API for you. Install the CLI skill once so the agent knows every command and flag:
npx skills add gotempsh/temps --skill temps-cli
Then describe the goal in plain language — "create an S3 bucket and link it to my project" — and the agent issues the commands — or call the skill directly by typing /temps-cli. New to AI agents? See how to call a skill for the step-by-step. Browse every skill on the AI Skills page.
The underlying commands
Whether the agent runs them or you do, these are the @temps-sdk/cli calls. The same services create -t <type> flow covers every managed service — see Managed PostgreSQL for the fully worked, parameter-by-parameter example.
Create
# Log in once (stores credentials in ~/.temps)
bunx @temps-sdk/cli login
# Create the service. Set parameters with repeatable -s key=value flags;
# if a required one is missing the CLI fails fast and names it, so you
# can add it and re-run.
bunx @temps-sdk/cli services create -t s3 -n my-storage -y
Inspect, link & manage
# List services and grab the numeric ID
bunx @temps-sdk/cli services list
# Full details, including endpoint and access keys
bunx @temps-sdk/cli services show --id 10
# Link to a project so S3_ENDPOINT / S3_ACCESS_KEY (and friends) are injected
bunx @temps-sdk/cli services link --id 10 --project my-app
bunx @temps-sdk/cli services env --id 10 --project my-app # see injected vars
bunx @temps-sdk/cli services unlink --id 10 --project my-app
# Lifecycle
bunx @temps-sdk/cli services stop --id 10
bunx @temps-sdk/cli services start --id 10
bunx @temps-sdk/cli services upgrade --id 10 -v rustfs/rustfs:1.0.0-beta.6
bunx @temps-sdk/cli services remove --id 10 -f # removes container and data volume
Connecting to S3
When linked to a project, Temps injects S3_ENDPOINT, S3_HOST, S3_PORT, S3_ACCESS_KEY, S3_SECRET_KEY, S3_REGION, and S3_BUCKET, along with AWS-style aliases (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION, AWS_ENDPOINT_URL) so standard AWS SDKs work unchanged:
Link S3 storage to a project
- 1
Open Services and select your S3 / RustFS service.
- 2
Link it to the target project so the S3_* and AWS_* environment variables are injected.
- 3
Redeploy or restart the linked app so it picks up the injected variables.
Checkpoint: Confirm the project now lists S3_ENDPOINT, S3_ACCESS_KEY, and the AWS-style aliases in its environment variables.
Node.js with AWS SDK v3
import { S3Client, PutObjectCommand, GetObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({
endpoint: process.env.S3_ENDPOINT,
region: process.env.S3_REGION,
forcePathStyle: true,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY,
},
});
await s3.send(new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: 'uploads/image.jpg',
Body: fileBuffer,
ContentType: 'image/jpeg',
}));
Python with boto3
import os
import boto3
# boto3 reads AWS_* automatically, or pass them explicitly:
s3 = boto3.client(
's3',
endpoint_url=os.environ['S3_ENDPOINT'],
aws_access_key_id=os.environ['S3_ACCESS_KEY'],
aws_secret_access_key=os.environ['S3_SECRET_KEY'],
)
s3.upload_file('local-file.jpg', os.environ['S3_BUCKET'], 'uploads/image.jpg')
Pre-signed URLs
Generate pre-signed URLs for temporary access without exposing credentials:
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: 'uploads/private-document.pdf',
});
// URL expires in 1 hour
const url = await getSignedUrl(s3, command, { expiresIn: 3600 });
Backups & durability
Objects are stored on the server's disk in a dedicated Docker volume, so a single disk failure loses them unless you back them up. On the backup schedule you set, Temps mirrors the service's buckets to your S3 backup source; point that source at a different provider or region than the server. Restore in place or into a new service from any backup; there is no point-in-time recovery, so objects written after the last backup are not covered. See Restore & Recovery for the restore API.
Back up and restore via the Temps CLI
# Back up this service now to S3 source 3
bunx @temps-sdk/cli backups run-service --id 10 --s3-source-id 3
# List backups on that source, then restore one into a new service
bunx @temps-sdk/cli services list-backups --s3-source-id 3
bunx @temps-sdk/cli services restore --id 10 --backup-id 42 --new-service auto -y
Monitoring
View live metrics and health in the dashboard's Services section — CPU & memory usage, disk usage, and uptime. Service-level monitoring is not yet exposed through the CLI.
Resource limits
You can cap how much memory, swap, and CPU the service's container is allowed to use, and inspect what it's actually consuming. A service with no limits set runs unconstrained (the default). The same controls apply to every managed service type — PostgreSQL (standalone and cluster), MongoDB, Redis, RustFS, and S3.
The service detail page shows a Resources card that polls runtime status every 30 seconds and live usage every 5 seconds, plus an Edit limits dialog.
Editing limits
Open Services → select the service → Resources card → Edit limits. The dialog has independent Memory and CPU toggles:
| Field | Meaning | Empty / off |
|---|---|---|
| Memory | Hard memory cap, in MiB | Unlimited |
| Swap | Extra swap above the memory cap, in MiB | No extra swap |
| CPU | CPU cap, in cores | Unlimited |
The Swap input means swap in addition to the memory limit — Memory = 512 and Swap = 256 lets the container use 512 MiB of RAM plus 256 MiB of swap. Internally Temps submits memory + swap to Docker. When a memory cap is set and the working set exceeds it, the kernel OOM killer terminates the container — that kill never reaches the app's own logs, so the oom_killed flag on the runtime endpoint is often the only signal.
Endpoints
All served under the /api prefix:
GET /api/external-services/{id}/runtime
GET /api/external-services/{id}/stats
PATCH /api/external-services/{id}/resources
GET …/runtime(ExternalServicesRead) — a per-containerdocker inspectsnapshot:status,restart_count(a steady climb signals a crash loop),oom_killed, lastexit_code, image, and the limits actually applied (so you can detect drift between configured and live caps).GET …/stats(ExternalServicesRead) — a one-shot CPU/memory usage sample per container, cheap enough to poll every 5–10s.memory_percentis measured against the memory limit when one is set, or against host RAM otherwise.PATCH …/resources(ExternalServicesWrite) — persists the caps to the service's encrypted config and live-applies them via Docker's update API (no restart needed). A request where every field isnullremoves all limits.
Security
- Name
Network Isolation- Description
- Reachable only from containers on the same Temps internal network — the port is never exposed to the public internet
- Apps connect using the container name as the host, over private networking
- Access keys are auto-generated at creation; you never have to choose one
- Name
Credential Handling- Description
- Temps injects the endpoint and keys as environment variables when the service is linked — never hard-code them
- Credentials are stored encrypted at rest (see Encryption below)
- Passwords and keys are fixed at creation; there is no credential rotation for managed services yet
Encryption
Credentials (access keys, secret keys) are encrypted with AES-256-GCM before being written to the Temps database. The key lives at ~/.temps/encryption_key — protect this file and back it up separately from the database.
Stored objects are not encrypted at the application layer by default. For encryption at rest, enable it at the infrastructure level — encrypted volumes or LUKS on bare metal; Temps does not manage disk encryption. In transit, traffic stays on the internal Docker network and is never exposed to the public internet.
Deleting the service
Delete the S3 / RustFS service
- 1
Take a fresh backup first: open Services, select the service, click Trigger backup and wait for it to finish.
- 2
Unlink all projects so no running app still holds a reference to the credentials.
Checkpoint: Confirm the service shows no linked projects before deleting.
- 3
Delete the service from its settings page and confirm. This removes the container, data volume and backup records and cannot be undone.
Deleting removes the container, volume and backup records; backup objects remain in your S3 backup bucket and can be recovered with orphan restore. The live objects on the volume cannot be recovered.
- Take a fresh backup — Services → select the service → Trigger backup, and wait for it to finish. The backup file stays in your S3 bucket after the service is deleted; open the backup to copy its S3 path.
- Unlink all projects so no running app still holds a reference to the credentials.
- Delete the service from its settings page and confirm.
Pricing & ownership
Because the service runs on your own infrastructure, there are no per-GB storage charges, request fees, or metered bandwidth costs. A recommended starting allocation:
| Tier | Storage |
|---|---|
| Small | 10 GB |
| Medium | 100 GB |
| Large | 500 GB+ |
Object storage is built in. For comparison (checked October 2026): Vercel Blob bills for storage, operations and data transfer; Netlify Blobs is built into Netlify; Railway Buckets are S3-compatible at $0.015 per GB-month with free egress. All three run on the vendor's infrastructure, while a Temps bucket runs on your own disk with no per-GB fees. Your data never leaves your server; Temps (the company) has no access to it. See Data Ownership & Privacy for the full policy, including GDPR.
Related
- Set Up Managed Services — every service type, import and per-project isolation
- Managed PostgreSQL, Managed MariaDB, Managed Redis and Managed MongoDB — the other managed engines
- Backups and Restore & Recovery — schedules, S3 sources and restore modes
- Self-hosted S3 storage after MinIO: RustFS and Garage — background guide to choosing an S3-compatible server