Post-quantum, end-to-end-encrypted file manager for storage you already own.
Files are sealed in your browser; the relay you self-host never sees a plaintext byte.
Operator handbook → docs.wattcloud.de · Threat model · Protocol spec
Status: personal project, production-shaped packaging, not third-party audited. Run on data you could afford to lose, or keep an independent backup. See Status & licensing.
Point Wattcloud at storage you already run — a Synology / QNAP / TrueNAS / Unraid box over WebDAV or SFTP, a Hetzner Storage Box, an S3-compatible bucket — and you get a browser-accessible vault with end-to-end encryption, multi-device access, and share links. You host the coordinating server yourself, you own the storage, and the server never holds plaintext, key material, or anything that identifies you beyond a per-device enrollment cookie.
All encryption runs in your browser. Files are sealed with AES-256-GCM, and the key exchange combines classical elliptic curves (X25519) with a NIST-standardized post-quantum KEM (ML-KEM-1024). Your passphrase is stretched with Argon2id before it ever contributes to a key. The crypto core runs as a sandboxed WebAssembly module inside a Web Worker; the main UI thread never touches key material.
The server side is a single Rust binary (byo-relay) running under a
hardened systemd unit behind Caddy, which handles TLS via Let's Encrypt
automatically. ~60 MB on disk, single-digit MB of RAM at rest.
SECURITY.md.The on-disk encrypted format is shared across backends, so replicating or migrating between providers is a straight file copy — no re-encrypt pass.
CryptoKey, never on the relay. Forget on
this device drops them locally without touching the remote vault.Full list with screenshots and rationale on docs.wattcloud.de.
Try it on your laptop before touching a VPS. Requires Rust 1.80+, Node 20+, wasm-pack, pnpm 9+.
git clone https://github.com/thewattlabs/wattcloud
cd wattcloud
make dev
That starts byo-relay on 127.0.0.1:8443 and Vite on :5173, with Vite
proxying the relay so the SPA talks to it same-origin. Open
http://localhost:5173/, claim the printed bootstrap token (make claim-token in another shell), connect a WebDAV / SFTP / S3 endpoint, and
you have a working vault. make dev-stop tears the stack down.
One command, on a fresh Ubuntu 22.04+ VPS with DNS pointing at it:
curl -sSLO https://github.com/thewattlabs/wattcloud/releases/latest/download/install.sh
less install.sh # ~150 lines — read before running
sudo bash install.sh cloud.example.com
install.sh cosign-verifies the release tarball against a pinned Sigstore
identity, extracts it, and hands off to deploy-vps.sh from inside the
verified tarball. That provisions Caddy + TLS, generates signing keys,
installs the sandboxed systemd unit, and health-checks /health.
Then claim ownership:
sudo wattcloud status # service + install state
sudo wattcloud claim-token # one-time bootstrap token
Full walkthrough — what lands on disk, non-interactive flags, fork-signer overrides, recovery flow — in docs.wattcloud.de/install/one-command-install/. Access control (invite-only mode, claiming, revoking, recovery) is at /install/access-control/. Upgrades and auto-rollback are at /install/upgrades/.
The full threat model is in SECURITY.md. The five things
worth knowing before you read it:
SECURITY.md.DynamicUser=yes, ProtectSystem=strict,
MemoryDenyWriteExecute=yes, all capabilities dropped, strict seccomp
filter. Every release tarball is keyless cosign-signed via Actions OIDC
and verified before install — install.sh aborts on a swapped asset.VPS hardening (UFW, fail2ban, sshd lockdown, R5 logging, swap, earlyoom,
AIDE, msmtp) is opt-in via sudo wattcloud harden — full walkthrough at
docs.wattcloud.de/operations/hardening/.
The standard install makes no system-wide config changes.
┌──────────────────────────────────────────────────────────────┐
│ Browser SPA (Svelte + Vite) │
│ ├─ Web Worker (sdk-wasm) — all crypto, V7 pipeline │
│ └─ @wattcloud/sdk — StorageProvider dispatcher │
└───────────────┬────────────────────────────────┬─────────────┘
│ │
▼ ▼
┌──────────────────────────┐ ┌─────────────────────────────┐
│ Caddy (TLS + ACME) │ │ User's storage backend │
│ └─ reverse_proxy │ │ (WebDAV, SFTP, S3-compat) │
│ 127.0.0.1:8443 │ │ - opaque V7 ciphertext │
│ │ │ │ - no plaintext ever │
│ ▼ │ └─────────────────────────────┘
│ byo-relay (systemd) │
│ - device enrollment │
│ - SFTP relay │
│ - share storage (V7) │
│ - minimal logs (no IPs) │
└──────────────────────────┘
| Path | Stack | Purpose |
|---|---|---|
sdk/sdk-core |
Rust | Cryptographic core. No I/O, no panics, no unwrap. Feeds sdk-wasm. |
sdk/sdk-wasm |
Rust → wasm-bindgen | Browser crypto kernel loaded by the Web Worker. |
byo-relay |
Rust, Axum | Near-stateless relay (enrollment, SFTP, share storage, stats). Single release binary. |
frontend |
Svelte + Vite | SPA. @wattcloud/sdk at frontend/src/lib/sdk/ — StorageProvider dispatcher, Web Worker client, vault journal. |
docs |
Astro + Starlight | Operator handbook published at docs.wattcloud.de. |
packaging |
Assets | Systemd unit, Caddyfile template, config.json template. Shipped inside the tarball. |
scripts |
Bash | install.sh, deploy-vps.sh, harden-vps.sh, update.sh, uninstall.sh, lib.sh (tarball-shipped); ci.sh, byo-smoke.sh (dev). |
Deeper references: SPEC.md (protocol),
SECURITY.md (threat model), DESIGN.md
(visual + UX system), CLAUDE.md (repo conventions).
make help lists every target. These are contributor and self-builder
tools; operators running a production install never touch Make.
make dev # byo-relay (:8443) + Vite (:5173), foreground
make dev-stop # SIGTERM a running stack (via PID file)
make dev-frontend # Vite only — use when a relay is already running
make dev-relay # byo-relay only — bootstraps .env.dev on first run
make claim-token # dev parity with `sudo wattcloud claim-token`
make build # wasm-pack + Vite build, in order
make test # cargo + npm across the repo
make lint # cargo clippy + eslint
make ci # full local CI (mirrors GitHub Actions)
make dev runs scripts/dev.sh, which generates a gitignored .env.dev
on first run with ephemeral JWT/HMAC signing keys, starts the relay,
waits for /health, then launches Vite. Vite proxies /relay/*,
/health, and /ready so the SPA talks same-origin — no CORS plumbing.
Delete .env.dev to rotate; you'll need to re-enroll.
Packaging and release artifacts (cosign signing happens in CI — it needs Actions OIDC and is not available locally):
make tarball # host-arch tarball → dist/
make tarball-all # cross-compile x86_64 + aarch64 (needs `cross`)
make smoke-tarball # scripts/byo-smoke.sh against the local build
make verify-tarball TARBALL=… SIG=… CERT=… # cosign-verify a downloaded asset
make docker-image # self-builder-only Docker image (not a release artifact)
Real releases flow through a signed v*.*.* tag → release.yml.
Three workflows under .github/workflows/:
ci.yml — push/PR: cargo test + clippy + fmt for the sdk
workspace and byo-relay; npm test + lint + build for the frontend;
wasm-pack build; systemd-analyze verify on the unit; caddy validate on the rendered Caddyfile; scripts/byo-smoke.sh.release.yml — on v*.*.* tag: cross-compile for
x86_64/aarch64-unknown-linux-gnu, build the frontend, assemble
per-arch tarballs, keyless cosign sign-blob each tarball +
install.sh + CHECKSUMS.txt via Actions OIDC, publish the GitHub
Release. Prerelease tags (any - suffix) don't feed
/releases/latest/download.docs.yml — push to main affecting docs/**: build the Astro
Starlight site and deploy to GitHub Pages
(docs.wattcloud.de).All third-party actions are pinned by commit SHA; dependabot.yml keeps
those SHAs current. The release trust chain is in SECURITY.md §13:
install.sh and wattcloud-update run cosign verify-blob against
TRUSTED_SIGNER_IDENTITY before extraction. A swapped GitHub release
asset fails verification and the scripts abort.
scripts/ci.sh mirrors the Actions ci.yml command set for local runs.
Status. Personal project. The encrypted on-disk format and the zero-knowledge invariants are stable — changes would make existing vaults undecryptable, so they're treated as protocol version bumps, not refactors. Install flow and packaging are production-shaped and exercised in CI. The codebase has not had a third-party security audit; run it on data you could afford to lose, or keep an independent backup.
Roadmap. WebDAV and SFTP are shipping. S3-compatible is in active development. OAuth-based providers (Google Drive, Dropbox, OneDrive, Box, pCloud) are gated behind a feature flag and not currently exposed in the SPA. The full operator handbook — install, access control, hardening, backups, troubleshooting, recovery, security model, sharing, multi-device, identity, FAQ — lives on docs.wattcloud.de.
Development style. Wattcloud is developed with extensive AI pair-programming ("vibe coding"). Design-level decisions — protocol, cryptographic choices, threat model, license — are the maintainer's. Implementation-level diffs are reviewed for behavior and spot-checked before they land, but are not line-by-line hand-audited. The label is used honestly; weight the codebase accordingly and treat the lack of a third-party security audit as load-bearing.
License. AGPL-3.0-or-later — see LICENSE. You are free
to use, study, modify, and distribute Wattcloud under the GNU Affero GPL
v3. The notable wrinkle versus plain GPL: if you run a modified version
as a network-accessible service, you must make your modifications
available to the users of that service under the same license. Running
unmodified signed releases on your own infrastructure for your own use
triggers no extra obligations.
The Wattcloud name and wordmark are not covered by the AGPL and are reserved by the project — forks must be renamed.
This is a personal project and patches are not being actively solicited
yet. Security findings are welcome — please open a GitHub security
advisory rather than a public issue;
SECURITY.md documents the intake process. When the
project opens up further, contributions that improve security, the BYO
protocol, or provider coverage will be most welcome. All contributions
are accepted under the project's AGPL-3.0 license; by opening a PR you
agree your work is licensed on the same terms. See
CONTRIBUTING.md.