File storage
Files are encrypted before they reach the API, so wherever they are stored only ever holds ciphertext. There are two drivers:
BLOB_DRIVER |
Files live in |
|---|---|
fs |
The data volume, /srv/skillpouch/blobs (default) |
s3 |
Any S3-compatible bucket: Cloudflare R2, AWS S3, MinIO, Garage |
With s3, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY_ID and
S3_SECRET_ACCESS_KEY are all required; the API refuses to start without
them. S3_REGION defaults for R2 (auto), and S3_PREFIX puts the files
in a folder inside the bucket, e.g. prod/ to share one bucket.
Cloudflare R2
Section titled “Cloudflare R2”| In Cloudflare | Setting | Credentials |
|---|---|---|
| R2 → Create bucket | e.g. skillpouch-blobs, location automatic, no public access |
S3_BUCKET |
| R2 → Overview → Account details | S3 API URL https://<account id>.r2.cloudflarestorage.com (without the bucket) |
S3_ENDPOINT |
| R2 → Manage API tokens → Create Account API token | Permission Object Read & Write, only this bucket | S3_ACCESS_KEY_ID, and S3_SECRET_ACCESS_KEY or secrets/s3_secret_access_key |
Moving a running server to a bucket
Section titled “Moving a running server to a bucket”The live API keeps using the volume until the last step, so users notice nothing.
-
Add the four
S3_settings toenv/api.env(or the secret tosecrets/s3_secret_access_key), keepBLOB_DRIVER=fs, and deploy, so the API container has the settings. -
Copy the files:
docker exec -e API_ROLE=copy-blobs -e BLOB_DRIVER=s3 <live api container> node dist/main.mjsdocker ps --filter name=apishows the container. It logsblobs copiedwith counts. -
Set
BLOB_DRIVER=s3and deploy again. -
Run step 2 once more. It copies only what was uploaded in between and skips the rest.
Keep the volume until you’ve checked a few pouches.
With a bucket, back it up with the provider’s own tools or rclone:
backup.sh covers only the volume (Backups).