Skip to content

Project files in object storage (S3-compatible)

object_storage is a project-file backend (#86) that stores a project's files in an S3-compatible bucket — AWS S3, MinIO, Cloudflare R2, Backblaze B2, Wasabi, or GCS's S3 API — instead of the server's local disk. This fixes agent-written files being stranded on a (possibly multi-instance) server with no retrieval path.

The server brokers every read/write through the same internal interface used for local files, so write_file, the file browser, and the /api/projects/{id}/files API all work unchanged. Objects are keyed under <prefix>companies/<companyId>/projects/<projectId>/files/<path>.

Configure (server)

Var Required Default Meaning
TRIMUS_PROJECT_S3_BUCKET yes bucket name (enabling the backend)
TRIMUS_PROJECT_S3_PREFIX no trimus-project-files/ key prefix (trailing slash added)
TRIMUS_PROJECT_S3_REGION no us-east-1 bucket region
TRIMUS_PROJECT_S3_ENDPOINT no leave empty for AWS S3; set e.g. https://minio.local:9000 or the R2 endpoint
TRIMUS_PROJECT_S3_PATH_STYLE no false true forces path-style addressing (MinIO and most self-hosted gateways)

Credentials come from the standard AWS chain (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN, an instance role, or ~/.aws/credentials) — the same as Trimus's encrypted-backup uploads.

If TRIMUS_PROJECT_S3_BUCKET is unset, the backend is simply unavailable and a project set to object_storage degrades to local-FS with a warning (so a misconfiguration never breaks file access or blocks startup).

Opt a project (or company) in

curl -X PATCH /api/projects/{id} -d '{"file_backend":"object_storage"}'

file_backend lives on projects (and as a per-company default on companies); a project's value overrides its company's. Switching a backend while files still exist on the current one is rejected with 409 (no silent orphaning) — empty or migrate them first.

Notes & limits

  • Remote workers read/write S3 directly using their own TRIMUS_PROJECT_S3_* configuration (AWS default credential chain). The server passes only the backend flag plus the company/project IDs (the object-key prefix) in the task payload — the worker never receives S3 credentials over the wire. Server-side write_file also lands in the same bucket.
  • Per-file size cap is the same 4 MiB ceiling as local files (simple PutObject, no multipart needed).
  • Each project's objects are isolated by the companies/<co>/projects/<proj>/ key prefix; the server is the tenancy authority for which prefix a request hits.