alawadi.cloudDocs
Guides

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_KEY

Buckets 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=path is set, the endpoint is exactly https://basin.alawadi.cloud, and the region is me-central-1.

Full reference: Basin overview · limits and errors.

On this page