NC

Naijacloud

Docs

DashboardStart free

Storage

/

Access control & keys

Access control & keys

One set of workspace credentials authenticates the S3 API. Whether an object is readable without them depends on the bucket, and on whether you signed a link for it.

4 min read

Workspace credentials

Your workspace has an Access Key ID and a Secret Access Key, shown under Settings → Storage access keys. They authenticate every S3 API call.

They authenticate nothing else. Email, deploys and the platform API use a scoped API key from the card below them, which is a different credential with a different lifetime.

One key covers every region. Storing in a second region does not issue a second key: the same credentials work against each region's endpoint, so only the endpoint and region in your client config change. A bucket shows the endpoint and region to pair them with on its own page.

Workspace settings showing the storage access keys card with a revealed access key ID, a masked secret and a rotate keys action
The secret is masked until an admin reveals it.

Treat the secret like a database password:

  • Keep it in environment variables, not in the repository.
  • Do not ship it to a browser or a mobile app. Anything a client can read, a user can extract. Sign a URL instead.
  • Rotate it if it may have been exposed.

Rotating keys

Rotate keys issues a new pair. Any client still using the old secret stops working, so plan the change:

  1. Rotate.
  2. Update the variables on every service that uses storage.
  3. Redeploy those services so they pick up the new values.
!

Rotation affects the whole workspace, not one bucket or one service. Check which services hold the credentials before rotating in production, including cron jobs, which are easy to forget because they are not serving traffic.

Public and private buckets

Access is set per bucket, on its Permissions tab.

Private means objects require credentials, or a signed link. This is the default, and the right setting for anything belonging to a user.

Public read means every object in the bucket is readable by anyone with its URL, with no credentials. Suitable for assets that are already public.

!

Public read is not per object. Turning it on exposes everything in the bucket, including anything uploaded there earlier. Keep public assets in a bucket that has never held anything private.

A signed URL grants time-limited access to one object in a private bucket. That is how you let a user download their own invoice without making the bucket public:

A short-lived download link

import { GetObjectCommand } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { s3 } from './storage.js'; export const downloadUrl = (key) => getSignedUrl(s3, new GetObjectCommand({ Bucket: 'my-bucket', Key: key }), { expiresIn: 300, });

Two rules:

  • Authorise before you sign. The signature proves the link came from you, not that the requester is allowed the file. Check ownership first.
  • Keep expiry short. A signed URL works for anyone holding it until it expires, so minutes rather than days.

CORS for browser uploads

A browser uploading straight to a bucket makes a cross-origin request, which the bucket must allow. Without it the browser blocks the preflight and the upload fails before any bytes are sent. That usually shows up as a network error with nothing in your server logs, because the request never reached your server.

On the bucket's Permissions tab, allow:

  • your site's origin,
  • the methods you use (PUT for uploads, GET for reads),
  • the headers your client sends, such as Content-Type.
i

List your real origins explicitly, including the local one you develop against. A wildcard origin on a bucket that accepts uploads lets any site on the internet use your signed URLs.

Lifecycle rules

For objects that should not live forever, the bucket's Management tab takes rules such as expiring anything under a tmp/ prefix after a number of days. That keeps temporary uploads from accumulating without a cleanup job.

Next steps