N Nightship
Guides / Storage
// storage

Connect object storage for Tide

Tide stores build chunks in your own S3-compatible bucket — you own the data, and nightshipd never proxies bytes. Point it at Cloudflare R2, AWS S3, or a self-hosted store.

How credentials are split

Tide deliberately keeps three parties apart, so no single leaked secret is catastrophic:

Let Nightship set up Cloudflare R2 for you

On Cloudflare R2, nightship storage init does the whole setup: it creates the bucket, mints the scoped credentials, hands CI its key and connects your server — no clicking through the dashboard for each piece. Three things only you can do first, because they need your account and your card:

  1. Create a Cloudflare account (free).
  2. Open R2 in the dashboard and enable it — R2 asks for a payment method even though the free tier covers a lot of build traffic.
  3. Create one API token: Manage Account → API Tokens → Create Token → Create Custom Token, with two permissions — User → API Tokens → Edit and Account → Workers R2 Storage → Edit — scoped to your account. Copy the token value; Cloudflare shows it once.

That token is powerful (it can create further credentials), so Nightship uses it for this one setup and never stores it. Give it to the CLI through the environment rather than the command line, where it would land in shell history:

export CLOUDFLARE_API_TOKEN=<the token you just copied>
nightship storage init            # reports what it would do, creates nothing
nightship storage init --yes      # creates the bucket and credentials

The preview names the account it found (you never have to look up your account id), suggests a bucket name you can override with --bucket, and shows the endpoint your server will use. With --yes it creates:

CI's credential is printed once, as the TIDE_S3_* block you paste into your CI secrets — or written to a file with --ci-secret-file <path> if you'd rather not have it in scrollback. Nightship keeps no copy. If anything fails part way, the run undoes what it created, so you can fix the cause and run it again.

If your token lacks API Tokens → Edit, Nightship cannot mint the R2 credentials for you — it will say so, and you can create them by hand with the Cloudflare R2 recipe below and connect them with storage set.

Connect the server to the bucket

As an admin, open Admin → Storage in the desktop app and click Connect Cloudflare R2… or Connect S3-compatible storage… (presets for AWS, Hetzner, Backblaze and MinIO fill in endpoint and region). The server probes the bucket with the credential you paste and only saves it when the probe passes; the page then names the provider and bucket it is connected to, and Test re-probes at any time. The same from a terminal:

nightship storage set --endpoint https://<account>.r2.cloudflarestorage.com \
  --region auto --bucket my-builds --access-key <KEY> --secret-key <SECRET>
nightship storage test      # probe the saved credential
nightship storage show      # provider + bucket, never the secret
nightship storage forget    # disconnect

On Nightship Cloud this is the only way to connect storage — the hosted server has no disk you could edit. Self-hosters can also write the file the server keeps it in, <data-dir>/tide.json (endpoint, region, bucket, access_key, secret_key), which is what the Drydock demo does. The Tide sync endpoint returns 503 until storage is connected.

A read-only key is the smallest credential the server needs to serve builds. If you later want backups in the same bucket, the server writes them under backups/ with this credential — so either give it a read/write key, or keep the read-only key and put backups in a separate bucket.

Configure the push side (environment)

nightship-tide reads the bucket and a write key from the environment, so CI can supply them as secrets:

TIDE_S3_ENDPOINT=https://<account>.r2.cloudflarestorage.com
TIDE_S3_REGION=auto
TIDE_S3_BUCKET=my-builds
TIDE_S3_KEY=<write-key-id>
TIDE_S3_SECRET=<write-key-secret>

Provider recipes

Cloudflare R2 (recommended)

Endpoint https://<account-id>.r2.cloudflarestorage.com (or the …eu.r2.cloudflarestorage.com jurisdiction endpoint for EU data residency), region auto. Create one bucket, then two scoped R2 API tokens: Object Read & Write locked to that bucket for CI, and Object Read for the server — which is exactly the pair storage init creates for you above. R2 has no per-request egress fees, which suits build distribution.

AWS S3

Standard S3 endpoint and a real region (e.g. eu-central-1). Create an IAM user (or role) with write access to the bucket for CI and a read-only one for the server; both use SigV4, which Tide speaks natively.

Self-hosted (Garage)

For on-prem or air-gapped studios — builds that must never leave the building — point Tide at a self-hosted S3 server. Garage is a single binary with no dependencies and is what Drydock bundles, so you can try the whole delta path locally first. Because Tide only needs the S3 API, any compliant server is a drop-in.

With storage connected, publish to a Tide channel in Push a build from the command line.

← All guides