private file access.md

Enforce private-file authorization for Next.js

Summary

Enforce private-file authorization in a Next.js app on Ample. The route handler authorizes the request first, records file metadata in a managed PostgreSQL database, stores bytes in a private bucket and streams them back only to authorized callers. The bucket is never published, so objects are reachable only through the app.

Infrastructure requirements

Prerequisites

Exact tested configuration

Steps

  1. Authorize before touching storage. Return 401 for unauthenticated requests; never expose object keys or the bucket endpoint to the browser.

  2. Record metadata in PostgreSQL. Keep the owner, name and object key in a table so authorization decisions come from your data, not from the bucket.

  3. Store and stream through the app. PutObject on upload, GetObject on download, both server-side with the injected credentials.

    ample deploy . --name <app-name> --public --env S3_ENDPOINT=... --env S3_REGION=... --env S3_BUCKET=... --env S3_ACCESS_KEY_ID=... --env S3_SECRET_ACCESS_KEY=... 
    
  4. Test both paths. An unauthenticated request must return 401; an authorized request must return the stored content.

  5. Verify. Fetch the live URL and run the success checks below. On failure read the build log, then the runtime log, fix the cause and deploy again; do not blind-retry.

    ample logs <deployment_id> --kind build
    

Tested examples

Success checks

Limitations

Cost estimate

Estimated 10.00 USD per month (size prices from pricing.toml at build revision a1b8c38919e59cd035ebabaced73cf84ece24371).

Apps and managed databases auto-pause when idle; the estimate is the always-on monthly price of the tested sizes. Plan quotas and budgets apply.

Verification evidence

Last verified: 2026-09-20T01:13:26Z

Execution binding

MCP tool ample_deploy (registry mcp:ample_deploy), schema hash 876465fce906da0c observed 2026-09-20T01:55:48.667900+00:00 at revision 199ff1dfd526, binding state current, required scopes: servers:write, databases:read, buckets:read.