Skip to content

[FEATURE] Local S3-compatible storage for dev, plus server S3 endpoint override and AWS_ENABLED flag #108

Open

Description

@IanCou

Problem

Contributors cannot test anything that uploads a file (resume upload, avatars) on their own machine:

  1. The local dev stack (peopleportal/dev-stack, added in Add one-command local dev stack (authentik, Gitea, Mongo, Redis, Mailpit) and update local dev docs #105) has no S3-compatible service. MinIO was removed because its upstream repository was archived on 2026-04-25 and its community images are no longer reliably available.
  2. The server cannot talk to a non-AWS S3 server anyway. peopleportal/server/src/clients/AWSClient/S3Client.ts creates the client with only region and credentials (no endpoint, no forcePathStyle). S3_BUCKET_NAME is the only bucket setting.
  3. Some AWS features (Organizations, Budgets, STS for team AWS accounts) cannot work locally, and there is no flag to switch them off.

So S3_ENDPOINT, path-style and AWS_ENABLED appear in .env.example as placeholders but the server ignores them. Adding a storage container alone will not wire uploads.

Proposed work

A. Server (small PR)

  • Honor S3_ENDPOINT and S3_FORCE_PATH_STYLE in S3Client.ts. Defaults must keep production behavior identical.
  • Add an AWS_ENABLED flag (default true). When false, the Organizations, Budgets and STS provisioning features return a clear "disabled in this environment" result instead of calling AWS.
  • Make sure presigned POST and presigned GET URLs use a host the browser can reach (localhost, not the compose service name).
  • Consider requestChecksumCalculation: "WHEN_REQUIRED", since newer AWS SDK versions add checksums that some S3-compatible servers handle unevenly.

B. Dev stack

  • Add one local S3-compatible service to peopleportal/dev-stack/docker-compose.yml, with a scripted bootstrap that creates the bucket, an access key and CORS for browser uploads.
  • Add S3 checks to verify.sh and update the dev-stack README and the local development wiki page.

Candidates (from research, not tested yet)

The portal uses @aws-sdk/s3-presigned-post (browser POST uploads with policy conditions), so the server must enforce POST policies like AWS does.

Option Notes
Garage (first choice) Strict presigned POST policy checks confirmed in source (eq, starts-with, content-length-range, expiry). Small multi-arch image. Needs a dev garage.toml. AGPL, fine unmodified.
SeaweedFS (weed mini) Apache-2.0, env-only bootstrap, POST policy checks confirmed in source. Larger image. Always set access keys, or the S3 gateway allows everything.
versitygw Apache-2.0 and small, but its POST support is only about 6 months old.
Not suitable moto (no POST policy checks), Adobe S3Mock (no signature validation or CORS), Zenko (no PostObject), LocalStack (auth token required since 2026.03), MinIO (archived).

Acceptance

  • ./scripts/up.sh --write-env brings up S3 along with the rest of the stack, and verify.sh passes.
  • Uploading a resume and an avatar through the local portal works, and files exceeding the allowed size or type are rejected.
  • Production behavior is unchanged when the new variables are unset.

Notes

Activity

  1. self-assigned this
    on Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

InfraCI/CD, AWS, build, deployenhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions