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.
3Setting up your folder
Open crate.naklios.dev in any modern browser. You'll land on Crate's start screen:
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
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.
Create your bucket on Cloudflare R2
Open the dashboard, click Create bucket, name it the same as below.
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.
Create an API token
Scoped to this bucket only — Cloudflare shows the secret once.
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).
- Click Copy CORS JSON.
- 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.
- 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.)
Configure CORS
- Click Copy CORS JSON below.
- Click Open this bucket's CORS settings ↗ — opens the right page in Cloudflare in a new tab.
- Come back here and click Run preflight check.
[
{
"AllowedOrigins": ["https://crate.naklios.dev"],
"AllowedMethods": ["GET","PUT","POST","DELETE","HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]
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.
Pick a passphrase
This unlocks your folder. Crate cannot recover it for you. Aim for at least 70 bits of entropy.
- 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:
Your folder is ready
Bucket connected. Credentials accepted. CORS configured. Passphrase set. Encrypted metadata written to the bucket.
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.
<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:
Your Crate
12 files · 47 MB · encrypted-
📁
photos— ✎ ✕
-
📝
project-notes.mdMay 214.2 KB 👁 ↓ ✎ ⏱ ✕
-
🖼
cover.pngMay 191.3 MB 👁 ↓ ✎ ⏱ ✕
-
📕
contract.pdfMay 12230 KB ↓ ✎ ⏱ ✕
-
🎵
demo-track.mp3Apr 305.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-credsfile 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:
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:
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:
- Run the desktop daemon (recommended).
crate-agentkeeps 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. - 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. - 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
- In your Crate folder UI, click Pair an agent. A modal shows a
CRATE-PAIR-…token + QR code with a 15-minute countdown. - Copy the token to clipboard.
- In a terminal:
crate-agent pair. Paste the token. Type your folder passphrase. crate-agent doctorto verify the install.crate-agent startto run in the foreground, orcrate-agent install-serviceto 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.