Crate · user guide

Your personal cloud folder, in a bucket you own.

Crate is a single web page that turns a storage bucket you control into an encrypted cloud folder. Your files are encrypted in this browser before they leave it. Nobody on the way — not Cloudflare, not us — can read them without your passphrase.

This guide walks you through setting up a folder for the first time, using it day-to-day, opening it again on another device, and the design choices that make all of this work.

Live at crate.naklios.dev. Source on GitHub. AGPL-3.0-or-later.

1What you're getting

In one paragraph: a tab in your browser that looks like a file manager, backed by an S3-compatible bucket (Cloudflare R2 by default). Drop files in; they encrypt on your machine; the bucket stores ciphertext. Open the URL on your phone with the same passphrase; the same folder appears. Optionally run a small daemon on your laptop and the same folder lives at ~/crate/ as regular plaintext files.

What makes it different from Dropbox / iCloud / Google Drive:

  • The bucket is yours. You pay Cloudflare directly (free tier covers most users — 10 GB storage, 1 M writes, 10 M reads per month). You can leave Crate at any time; your files stay in your bucket.
  • The encryption is in this browser tab. The bucket owner sees only ciphertext and access patterns. We can prove that — the entire encryption layer is one file: lib/crypto.js.
  • No account with us. There's nothing on a NakliTechie server. The whole app is static HTML; you could host it yourself off any static server tomorrow if our deployment vanished.
  • One credential. Your passphrase is the only thing standing between an attacker with bucket access and your files. No recovery email, no support backdoor. That's the trade-off.

2Before you start

You'll need three things in front of you:

  • A Cloudflare account. Free, takes 60 seconds to create at dash.cloudflare.com/sign-up. No credit card required for the free tier.
  • About 3 minutes. The wizard walks you through everything; the longest step is waiting for CORS to propagate.
  • A passphrase you'll remember. Aim for 4 or more unrelated words (a "passphrase," not a password). Crate's wizard can generate one if you don't want to think one up.
heads up Crate cannot recover your passphrase. If you forget it AND lose your credentials file (you'll get one at the end of setup), the files in your bucket are unreadable random bytes forever. Plan for redundancy — see section 6.

3Setting up your folder

Open crate.naklios.dev in any modern browser. You'll land on Crate's start screen:

crate.naklios.dev
Crate

Your own cloud folder. Files live in storage you control, encrypted on your device before they upload — so the only person who can read them is you.

  • 🔒 End-to-end encryptedAES-256 in this tab. Your passphrase never leaves your device, so nobody else can read your files — not us, not your storage provider.
  • 🪣 Your storage, your keysBring your own bucket — Cloudflare R2, Hetzner, Backblaze, or AWS. We never hold your data and there's nothing to subscribe to.
  • 🚫 No account, no middlemanNo NakliTechie sign-up, no server on the path, no telemetry. Just your browser talking to your bucket.

New here? See how Crate works

You'll need a free Cloudflare account, about 3 minutes, and a passphrase you'll remember.

On your very first visit, a short What is Crate? explainer opens over this screen automatically — the same privacy promise plus how Crate works in three steps, with a Full setup guide button that expands the detailed Cloudflare walk-through. It auto-opens only once; afterwards you can reopen it any time from the New here? See how Crate works link.

For a first-time setup, click Set up a new folder. (If you've onboarded already and you're back, see section 5.) The wizard has five stages: Bucket → Credentials → CORS → Passphrase → Done.

Stage 1 — Bucket

Crate suggests a name like crate-x7k2m9p4. Copy the suggested name, then click the Open Cloudflare R2 ↗ button. In Cloudflare's R2 dashboard, click Create bucket, paste the name, leave region on Automatic, click Create. Come back to the Crate tab. Paste your Cloudflare Account ID (you'll find it in the R2 sidebar) into the second field. Click Verify.

crate.naklios.dev/#bucket
welcome · bucket · credentials · cors · passphrase · done

Create your bucket on Cloudflare R2

Open the dashboard, click Create bucket, name it the same as below.

✓ Bucket reachable

Stage 2 — Credentials

Crate now needs an API token scoped to only this bucket. Click Open R2 API Tokens ↗Create API Token:

  • Permission: Object Read & Write
  • Specify bucket: pick the one you just made (don't leave it at "All buckets")
  • TTL: leave blank, or pick a long horizon

Cloudflare shows you the Access Key ID + Secret Access Key ONCE. Copy both before you close the page — Cloudflare will not show the secret again. Paste them into the wizard. Click Verify.

crate.naklios.dev/#credentials
welcome · bucket · credentials · cors · passphrase · done

Create an API token

Scoped to this bucket only — Cloudflare shows the secret once.

✓ Credentials accepted

Stage 3 — CORS

Your browser needs explicit permission to talk to your bucket. Crate generates the exact JSON you need and gives you a direct deep-link to the right Cloudflare page (the bucket's CORS settings — not the generic R2 overview).

  1. Click Copy CORS JSON.
  2. Click Open this bucket's CORS settings ↗. A new tab opens at exactly the right page in Cloudflare. Scroll to CORS Policy, click Add CORS policy, paste, save.
  3. Come back to the Crate tab and click Run preflight check. (If it fails immediately, wait 30 seconds — CORS changes take time to propagate — then retry.)
crate.naklios.dev/#cors
welcome · bucket · credentials · cors · passphrase · done

Configure CORS

  1. Click Copy CORS JSON below.
  2. Click Open this bucket's CORS settings ↗ — opens the right page in Cloudflare in a new tab.
  3. Come back here and click Run preflight check.
[
  {
    "AllowedOrigins": ["https://crate.naklios.dev"],
    "AllowedMethods": ["GET","PUT","POST","DELETE","HEAD"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }
]
✓ Preflight succeeded
why we ask The CORS JSON tells Cloudflare which web origin is allowed to talk to your bucket from a browser. It does not give Crate or anyone else read access to your files — it only controls headers Cloudflare sends back. The actual files are still encrypted before they ever leave your tab.

Stage 4 — Passphrase

Pick a passphrase. Crate measures strength with zxcvbn and only lets you advance once you clear 70 bits of entropy. The hint card on this stage spells out exactly how to hit that bar:

  • Easiest: hit Generate. 7 random dictionary words, ~77 bits. Write them down.
  • Memorable: 5 or more unrelated common words — correct-horse-battery-staple-seven.
  • Compact: 12+ random characters mixing case, digits, symbols — 7zL!q4Mn$ePr.
  • What doesn't work: single dictionary words (any length), Password123!-style, birthdays, song lyrics.
crate.naklios.dev/#passphrase
welcome · bucket · credentials · cors · passphrase · done

Pick a passphrase

This unlocks your folder. Crate cannot recover it for you. Aim for at least 70 bits of entropy.

How to clear 70 bits — pick one:
  • Easiest: hit Generate below. 7 random dictionary words, ~77 bits.
  • Memorable: 4+ unrelated common words — pick at least 5 for safety.
  • Compact: 12+ random chars mixing case/digits/symbols.

Strength: strong (78 bits)

✓ Match — strong enough

Stage 5 — Done

Crate now writes a small .crate/crate.json + an empty manifest to your bucket. When that finishes you see:

crate.naklios.dev/#done
welcome · bucket · credentials · cors · passphrase · done

Your folder is ready

Bucket connected. Credentials accepted. CORS configured. Passphrase set. Encrypted metadata written to the bucket.

Make future unlocks one step

Download a small encrypted credentials file. With this file + your passphrase, you can unlock from any device in two clicks instead of typing five strings. The file is useless without your passphrase. Keep it like a backup credential.

do this now Click ↓ Download credentials file (recommended) before opening your folder. You'll get a small file named <bucket-name>.crate-creds. Save it the same way you'd save a backup password — 1Password, password manager, encrypted USB. Anyone with this file and your passphrase can read your folder; either alone is useless. Future unlocks become drop-file + type-passphrase.

4Using your folder

Click Open your folder and the wizard hands off to the folder UI:

crate.naklios.dev

Your Crate

12 files · 47 MB · encrypted
Home notes 2026
  • 📁
    photos
    ✎ ✕
  • 📝
    project-notes.md
    May 21
    4.2 KB 👁 ↓ ✎ ⏱ ✕
  • 🖼
    cover.png
    May 19
    1.3 MB 👁 ↓ ✎ ⏱ ✕
  • 📕
    contract.pdf
    May 12
    230 KB ↓ ✎ ⏱ ✕
  • 🎵
    demo-track.mp3
    Apr 30
    5.8 MB ↓ ✎ ⏱ ✕

The toolbar

  • ⬆ Upload — open a file picker, or drag files directly onto the page. They encrypt + upload one at a time.
  • 📁 New folder — empty folders are recorded as explicit events in the manifest so they survive across devices.
  • ⟳ Refresh — pulls the latest manifest from the bucket. (Sync is automatic every ~15 s; this is for impatient checks.)
  • 🔐 Credentials — re-download the encrypted .crate-creds file at any time. Use this if you skipped the download at setup.
  • Pair an agent — issue a one-time pairing token to set up the desktop daemon. See section 7.
  • Export — download all your files as a single zip (or stream to a folder on disk for larger Crates). Useful as a one-shot backup or migration tool.
  • 🔒 Lock — zero the master key, clear in-tab session state, return to the start screen. Use before leaving the laptop unattended.

Per-file actions

Hover any file row. The buttons on the right reveal:

  • 👁 Preview — open text or image files inline without downloading. Files larger than 50 MB show a "too large to preview, use Download" message.
  • ↓ Download — decrypt + save to your Downloads folder. Large files stream straight to a destination you pick on disk.
  • ✎ Rename — pure manifest event; the underlying ciphertext is unchanged on the bucket.
  • ⏱ History — see every change to that file: when it was created, every update + size delta, any rename, the delete if present. Read from the manifest already in memory; no network call.
  • ✕ Delete — DELETEs the object and appends a delete event. There is no trash bin in v1.

Search

The search box under the toolbar filters the current folder by basename substring, case-insensitive. Clears when you click any breadcrumb to navigate.

Drag-and-drop

Drag files from your desktop / Finder / Files app onto the folder area. The whole UI lights up with a "Drop to upload" overlay; release to upload. Each file is encrypted in this tab, then PUT to your bucket.

Mobile

The same URL works on a phone. The folder UI is responsive; actions are always visible (no hover-to-reveal on touch devices). Upload from your phone's photo picker works for images and most file types.

5Coming back later

You closed the tab, came back tomorrow (or on your phone, or on a different laptop). Open crate.naklios.dev, click Unlock an existing folder.

The default path — credentials file + passphrase

If you downloaded the .crate-creds file at first-time setup, this is two clicks:

crate.naklios.dev/#unlock
welcome · unlock

Unlock an existing folder

Pick the credentials file you downloaded at first setup, then enter your folder passphrase. The file is useless without the passphrase.

🔐 Drop your .crate-creds file here, or click to pick it.

No file? Enter the 5 details manually.

Drag the file onto the dropzone (or click to pick it). The bucket name from the file's encrypted hint surfaces immediately:

crate.naklios.dev/#unlock

Welcome back to crate-x7k2m9p4

Enter your passphrase to reopen it.

✓ Loaded crate-x7k2m9p4 from file.

The fallback — five fields, no file

If you lost the credentials file (or you're on a brand-new device and haven't transferred it yet), click No file? Enter the 5 details manually. The unlock screen reveals the original 5-input form:

  • Bucket name
  • Cloudflare Account ID (32 hex characters)
  • Access Key (~32 chars)
  • Secret Access Key (~64 chars)
  • Folder passphrase

Tedious but viable — and you can re-download a fresh .crate-creds file from the folder UI's 🔐 Credentials button once you're back in.

Refresh keeps you logged in

If you accidentally hit ⌘R / F5 mid-session, you don't go back to square one. The encrypted credentials blob lives in your tab's sessionStorage (passphrase-encrypted; useless without your passphrase). On reload, the wizard sees the blob and goes straight to "Welcome back to name. Enter your passphrase to reopen it." One field instead of five (or two).

The blob dies when you close the tab or click 🔒 Lock. So a hard quit + relaunch goes back to the full unlock screen.

6Backup & recovery

Your bucket is your only copy of the files by default. If you lose access to it (account closed, accidentally deleted, ransomware on your Cloudflare account), the files are gone unless you've made a copy somewhere else. The encryption that keeps Cloudflare from reading your files also means Cloudflare can't restore them for you.

Three independent redundancy options:

  1. Run the desktop daemon (recommended). crate-agent keeps a plaintext mirror at ~/crate/ on macOS or Linux. Point Time Machine, restic, rsync, or whatever you already use at that folder. The plaintext lives on hardware you control.
  2. Mirror the bucket. rclone sync r2:bucket-A r2:bucket-B, or use Cloudflare's R2 → R2 replication. Ciphertext-preserving; restore = swap creds in the wizard.
  3. Export from the browser. The folder UI's Export button gives you a zip of everything. One-shot — use the daemon for recurring backups.

Three disaster scenarios

You lost the passphrase + the creds file

Files are gone. There is no reset, no support email, no recovery flow. Plan ahead: write the passphrase down, store the creds file somewhere safe.

You lost the passphrase, but have the creds file

Still gone — the file is encrypted with the passphrase. Same outcome as above.

You lost the creds file, but have the passphrase

Fine. Use the 5-input manual unlock to get back in, then click 🔐 Credentials in the folder UI to download a fresh file.

You lost the bucket

Restore from whichever redundancy you set up: daemon's local folder, rclone mirror, or exported zip. Create a new bucket; same passphrase; you're back.

Full runbook: docs/backup.md.

7The desktop daemon

crate-agent is a small Go binary that keeps a folder on your laptop in sync with your Crate. It runs as a background service; you edit files in ~/crate/ with any tool (vim, VS Code, drag-drop in Finder), the daemon encrypts + uploads them. Browser-side changes download + decrypt to the same folder.

The daemon never holds your bucket credentials — it pairs with the browser via a one-time token and talks to a transport (the Hub bucket-proxy), not directly to R2.

Install

# macOS (Apple Silicon)
curl -L -o crate-agent https://github.com/NakliTechie/crate-agent/releases/latest/download/crate-agent-darwin-arm64
chmod +x crate-agent && sudo mv crate-agent /usr/local/bin/

# macOS (Intel)
curl -L -o crate-agent https://github.com/NakliTechie/crate-agent/releases/latest/download/crate-agent-darwin-amd64
chmod +x crate-agent && sudo mv crate-agent /usr/local/bin/

# Linux (x86_64)
curl -L -o crate-agent https://github.com/NakliTechie/crate-agent/releases/latest/download/crate-agent-linux-amd64
chmod +x crate-agent && sudo mv crate-agent /usr/local/bin/

# Linux (ARM64)
curl -L -o crate-agent https://github.com/NakliTechie/crate-agent/releases/latest/download/crate-agent-linux-arm64
chmod +x crate-agent && sudo mv crate-agent /usr/local/bin/

(Windows: v1.x roadmap.)

Pair + start

  1. In your Crate folder UI, click Pair an agent. A modal shows a CRATE-PAIR-… token + QR code with a 15-minute countdown.
  2. Copy the token to clipboard.
  3. In a terminal: crate-agent pair. Paste the token. Type your folder passphrase.
  4. crate-agent doctor to verify the install.
  5. crate-agent start to run in the foreground, or crate-agent install-service to install as a launchd / systemd-user unit that starts at login.

Once running, ~/crate/ is bidirectional with the browser within ~15 seconds. Full daemon docs in the crate-agent repo.

8Security model

The short version of the full crypto design:

  • Master key = PBKDF2-SHA256 of your passphrase + a 16-byte random salt stored in .crate/crate.json. 600,000 iterations (OWASP 2023 recommendation). Lives only in this browser tab's memory.
  • Per-file data keys = fresh 32 random bytes per file, wrapped by AES-256-GCM under the master key. Sealed with the file's UUID as additional-authenticated-data so a row-swap attack on the bucket fails authentication.
  • Payload sealing = AES-256-GCM with the per-file data key + a fresh 12-byte IV per write.
  • Signed manifest = JSONL log of every event (create, update, delete, move, mkdir), each event HMAC-SHA256-signed with the master key; each event carries the previous event's signature → tamper-evident chain. The entire manifest is then encrypted at rest.
  • Credentials file = the four bucket strings (name, account ID, access key, secret key) bundled into a JSON envelope encrypted with AES-256-GCM under a key derived by PBKDF2-SHA256(passphrase, salt). Independent salt from the bucket's salt; useless without the passphrase.
  • Concurrent-write safety = ETag-conditional PUT (If-Match) with replay-on-412. Two tabs PUTting at the same time → second one gets 412 → re-GET, splice pending events on top, retry up to 3 times.

What we explicitly don't protect against

  • Compromise of your browser tab while it's unlocked. If a Chrome extension can read your tab's memory, it can read your master key + every file you touch. Same as 1Password and other client-side crypto apps. Use a clean profile if this matters.
  • Side-channel access patterns. Cloudflare sees the number of objects you have, their sizes, and when you touch them. They cannot see the content.
  • Future cryptanalytic breaks of AES-256-GCM or PBKDF2-SHA256. If either falls, every app using them falls together. We'd migrate via a v2 wire format.

Crate is AGPL-3.0-or-later. The entire encryption layer is lib/crypto.js. Every network call lives in lib/bucket.js. The credentials-file format is lib/credsfile.js. There is no telemetry, no analytics, no backend.