Skip to content

Overview

roamd has three parts. Only two of them ever hold keys that can unlock anything: your browser and your computer. Our website sits in the middle and passes along messages it can't read.

   YOUR BROWSER                OUR WEBSITE              YOUR COMPUTER
 +--------------+          +----------------+        +----------------+
 | your vault   |          | your email     |        | roamd program  |
 | (unlocked    |          | locked vault   |        | its own ID key |
 |  only here)  |          | list of your   |        | which browsers |
 |              |          | computers      |        | it trusts      |
 +------+-------+          +-------+--------+        +-------+--------+
        |                          |                         |
        |   locked conversation, end to end                  |
        +==========================+=========================+
                          (passes through, unreadable)

The three big ideas

  1. Your password never leaves your browser. The browser turns it into two separate things: a proof that you know it (sent to us) and a key that stays with you.
  2. Your data is locked before it reaches us. We store it, but only as a locked box.
  3. Your computer decides who gets in, not us. It only accepts browsers you approved while sitting at it, after checking a 6-digit code on both screens.

Why the computer connects out to us

Home internet connections don't let outsiders connect in. So roamd on your computer calls out to our website and keeps that line open, a bit like leaving a phone call connected. When you click Connect, your browser's locked conversation travels down that line.

Read on:

Components

 +------------------ browser --------------------+
 | web app + roamd core compiled to WebAssembly  |
 |  - Argon2id / HKDF / XChaCha20-Poly1305 vault |
 |  - SSH client, host-key pinning               |
 +----------------------+------------------------+
                        | HTTPS + secure WebSockets
 +----------------------v------------------------+
 | hub (Rust)                                    |
 |  - accounts: email, proof hash, sealed vault  |
 |  - device registry: owner, host public key,   |
 |    token hash                                 |
 |  - relays bytes between browser and machine   |
 |  - strict CSP; rate limits                    |
 +----------------------^------------------------+
                        | secure WebSocket, outbound from the machine
 +----------------------+------------------------+
 | roamd agent (Rust) on the user's machine      |
 |  - SSH server: public-key auth only           |
 |  - approved keys = browser keys confirmed     |
 |    on this machine                            |
 |  - terminal only                              |
 +-----------------------------------------------+

Trust boundaries

Party Holds Cannot
Browser Password-derived keys, vault key (tab only), SSH private key, host pins —
Hub Emails, hashed login proofs, sealed vault blobs, device public keys, hashed device tokens Decrypt the vault; log in to a machine; read or alter SSH traffic undetected
Machine Host private key, device token, approved browser public keys Learn the user's password or vault

The hub routes; the machine authorises. A compromised hub can deny service, and can try to impersonate a machine, but it holds no host key, so pinned browsers refuse it. The one exception is the web-delivered code: see What we can and can't see.

Data paths

Path Protection
Browser ↔ hub (API) TLS; the site sits behind Cloudflare, which sees what the hub sees, never SSH plaintext or vault contents
Browser ↔ machine (shell) SSH end to end: post-quantum hybrid or Curve25519 key exchange, ChaCha20-Poly1305 or AES-GCM, Ed25519 keys
Machine ↔ hub (tunnel) TLS WebSocket, device token
Vault at rest (hub) XChaCha20-Poly1305 under a 256-bit vault key the hub never sees
Secrets at rest (machine) DPAPI (Windows), Keychain-held key (macOS), owner-only files (Linux)