Connect an app to object storage
Wire a deployed container to an S3 bucket with environment variables and the AWS SDK, for JavaScript (v3) and Python (boto3).
Your apps on alawadi.cloud read and write objects with the same S3 credentials you create alongside a bucket. Store the endpoint, region, bucket name, and keys as environment variables on your container, then use any S3 SDK. This page walks the end-to-end wiring for a JavaScript (AWS SDK for JavaScript v3) and a Python (boto3) app.
1. Create a bucket and copy its keys
In Cloud Studio, pick Basin, name the bucket, set a capacity, and click Create. See buckets for the options.
Copy the Access Key and Secret Key (the secret is
shown once) and the full bucket name (prefixed, for
example t1a2b3c4-media).
2. Set environment variables on your app
Open your app in the dashboard and add these environment variables. Set the secret as a secret value, do not bake it into your image or commit it:
S3_ENDPOINT=https://basin.alawadi.cloud
S3_REGION=me-central-1
S3_BUCKET=YOUR_BUCKET
S3_ACCESS_KEY=YOUR_ACCESS_KEY
S3_SECRET_KEY=YOUR_SECRET_KEYBuckets created before the region was renamed show damm-1 in their saved
config; it's a permanent alias for me-central-1, so an older .env keeps
working unchanged.
Keep the secret out of your image
Set S3_SECRET_KEY as an environment variable (or secret) in the dashboard,
never in your Dockerfile, your source, or a committed .env. A leaked key can
read and write your buckets, billed to your balance. If it leaks,
regenerate it.
Running on alawadi.cloud? Attach the bucket to your app
When you attach a bucket to an app, the platform injects all five
variables for you and points S3_ENDPOINT at the bucket's in-cluster
address, so your app reaches storage over the platform's private network
instead of going out to the public internet and back. An attached value always
wins over a hand-set S3_ENDPOINT. Set S3_ENDPOINT=https://basin.alawadi.cloud
by hand only for tools that run outside the platform — your laptop, CI, or
another host.
3. Use the SDK
Point the SDK at S3_ENDPOINT, set the me-central-1 region, and enable
path-style addressing. Then read and write objects as usual.
// npm install @aws-sdk/client-s3
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, // required: path-style addressing
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY,
secretAccessKey: process.env.S3_SECRET_KEY,
},
});
const Bucket = process.env.S3_BUCKET;
// Write an object.
await s3.send(
new PutObjectCommand({ Bucket, Key: "hello.txt", Body: "hello alawadi" }),
);
// Read it back.
const res = await s3.send(new GetObjectCommand({ Bucket, Key: "hello.txt" }));
console.log(await res.Body.transformToString());# pip install boto3
import os
import boto3
from botocore.config import Config
s3 = boto3.client(
"s3",
endpoint_url=os.environ["S3_ENDPOINT"],
region_name=os.environ["S3_REGION"],
aws_access_key_id=os.environ["S3_ACCESS_KEY"],
aws_secret_access_key=os.environ["S3_SECRET_KEY"],
config=Config(s3={"addressing_style": "path"}), # required
)
bucket = os.environ["S3_BUCKET"]
# Write an object.
s3.put_object(Bucket=bucket, Key="hello.txt", Body=b"hello alawadi")
# Read it back.
obj = s3.get_object(Bucket=bucket, Key="hello.txt")
print(obj["Body"].read().decode())Large files upload in parts automatically
Both SDKs switch to a multipart upload for large objects, keeping each
part under the 95 MB per-request limit. For very large files prefer the
managed helpers (@aws-sdk/lib-storage's Upload, or boto3's upload_file /
upload_fileobj), which handle the parts for you. See
limits and errors.
What to check if it fails
403 AccessDenied: wrong or regenerated key, or the wrong bucket, credentials reach only your own buckets. See access keys.404 NoSuchBucket: you used the short name; use the full prefixed name from the dashboard.- Timeouts or signature errors: confirm
forcePathStyle/addressing_style=pathis set, the endpoint is exactlyhttps://basin.alawadi.cloud, and the region isme-central-1.
Full reference: Basin overview · limits and errors.
Connect a container registry
Create a private registry on alawadi.cloud, push images from GitHub Actions over OIDC, and deploy them to a container.
Add managed Postgres, MySQL, or Redis
Add a managed database to a project from the dashboard and link it into a container so the connection URL is injected automatically.