| name | zeabur-object-storage |
| description | Use when deploying object storage (S3-compatible) to Zeabur. Use when user needs MinIO, RustFS, or S3-compatible storage. Use when user says "object storage", "file storage", "S3", "MinIO", "RustFS", "upload files", "store files", "blob storage", or "OSS". Also use when integrating object storage with an existing service. |
Zeabur Object Storage Deployment & Integration
Always use npx zeabur@latest to invoke Zeabur CLI. Never use zeabur directly or any other installation method. If npx is not available, install Node.js first.
Deploy Object Storage
Before deploying, you MUST load the zeabur-template skill first to understand what Zeabur templates are, how they work, and how to deploy them. This skill only covers object storage-specific integration — all template knowledge lives in zeabur-template.
Search for a storage template:
npx zeabur@latest template search minio -i=false --json
Pick the template with the highest deployment count.
- Default to MinIO if the user doesn't specify — most widely supported, built-in web console, auto-creates a default bucket.
- Recommend RustFS if the user wants lightweight/minimal or mentions RustFS specifically.
After Deployment: How to Connect
For object storage, you need: S3 API endpoint (how to connect), access key + secret key (how to authenticate), and a bucket name.
How to connect — service network
npx zeabur@latest service network --id <storage-service-id> -i=false
This shows:
- Private Networking — internal
hostname:port for the S3 API (e.g., minio.zeabur.internal:9000)
- Public Networking — for HTTP ports, it will indicate you need to bind a domain to access externally
MinIO and RustFS ports are HTTP type, so public access is via domain binding, not port forwarding. Bind a domain to the API port via the Dashboard to get an external S3 endpoint (e.g., https://minio-api.zeabur.app).
How to authenticate — variable list
npx zeabur@latest variable list --id <storage-service-id> -i=false
This lists the access key, secret key, and other credentials.
MinIO
Credentials (from variable list)
| Variable | Description |
|---|
MINIO_USERNAME | Access Key ID (default: minio) |
MINIO_PASSWORD | Secret Access Key (auto-generated) |
MINIO_DEFAULT_BUCKET | Default bucket name (default: zeabur) |
MINIO_CONSOLE_URL | Web console URL |
Connect from app (same project)
Set these env vars on your app service:
S3_ENDPOINT=http://minio.zeabur.internal:9000
S3_ACCESS_KEY=${MINIO_USERNAME}
S3_SECRET_KEY=${MINIO_PASSWORD}
S3_BUCKET=zeabur
S3_REGION=us-east-1
S3_FORCE_PATH_STYLE=true
The S3 endpoint is not exposed as a variable — you must hardcode it using the internal hostname from service network.
Connect from local machine
Bind a domain to the API port, then use that domain as endpoint:
mc alias set zeabur https://MINIO_API_DOMAIN MINIO_USERNAME MINIO_PASSWORD
mc ls zeabur/
mc cp local-file.txt zeabur/zeabur/
aws --endpoint-url https://MINIO_API_DOMAIN s3 ls
Web Console
Open MINIO_CONSOLE_URL in a browser, login with MINIO_USERNAME / MINIO_PASSWORD. MinIO auto-creates a zeabur bucket on first boot.
RustFS
Credentials (from variable list)
| Variable | Description |
|---|
RUSTFS_USERNAME | Access Key ID (default: rustfs) |
RUSTFS_PASSWORD | Secret Access Key (auto-generated) |
Connect from app (same project)
Set these env vars on your app service:
S3_ENDPOINT=http://rustfs.zeabur.internal:9000
S3_ACCESS_KEY=${RUSTFS_USERNAME}
S3_SECRET_KEY=${RUSTFS_PASSWORD}
S3_BUCKET=my-bucket
S3_REGION=us-east-1
S3_FORCE_PATH_STYLE=true
The S3 endpoint is not exposed as a variable — you must hardcode it using the internal hostname from service network. Also check service list for the exact service name (may be RustFS not rustfs).
You must create a bucket first — unlike MinIO, RustFS starts with zero buckets.
Connect from local machine
Bind a domain to the API port, then:
mc alias set zeabur https://RUSTFS_API_DOMAIN RUSTFS_USERNAME RUSTFS_PASSWORD
mc mb zeabur/my-bucket
mc ls zeabur/
Web Console
Open the domain bound to port 9001 in a browser, login with RUSTFS_USERNAME / RUSTFS_PASSWORD. Create a bucket before your app can upload files.
SDK Examples
All S3-compatible SDKs need: endpoint, access key, secret key, region, and forcePathStyle: true.
const { S3Client } = require("@aws-sdk/client-s3");
const s3 = new S3Client({
endpoint: process.env.S3_ENDPOINT,
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY,
},
region: "us-east-1",
forcePathStyle: true,
});
import boto3, os
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"],
region_name="us-east-1",
)
cfg, _ := config.LoadDefaultConfig(ctx,
config.WithRegion("us-east-1"),
config.WithCredentialsProvider(
credentials.NewStaticCredentialsProvider(accessKey, secretKey, ""),
),
)
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
o.BaseEndpoint = aws.String(endpoint)
o.UsePathStyle = true
})
Caveats
forcePathStyle is required — Without it, S3 SDKs use virtual-hosted-style URLs (http://bucket.host:9000/key) which won't resolve. This is the #1 cause of "bucket not found" errors.
- Create bucket before uploading (RustFS) — MinIO auto-creates a
zeabur bucket; RustFS does not. Create one via the console or mc mb.
- S3 endpoint is not a template variable — Hardcode it using the hostname from
service network (internal) or the bound domain (external).
- Variable references — Zeabur uses a flat namespace. Set
${MINIO_USERNAME} etc. via the Zeabur Dashboard — the CLI has a known bug with ${} expansion.
- Console vs API ports — MinIO: API
9000, console 9090. RustFS: API 9000, console 9001. Apps connect to the API port.