Architecture

BuddyDrive uses peer-to-peer networking with encrypted backup, relay fallback, and relay-backed config recovery.

┌─────────────────┐                    ┌─────────────────┐
│  Your Machine   │                    │ Buddy's Machine │
│                 │                    │                 │
│  ┌───────────┐  │   direct/relay     │  ┌───────────┐  │
│  │ BuddyDrive│◄─┼───────────────────┼──►│ BuddyDrive│  │
│  └───────────┘  │                    │  └───────────┘  │
│       │         │                    │       │         │
│       ▼         │                    │       ▼         │
│  ┌───────────┐  │                    │  ┌───────────┐  │
│  │  Files    │  │                    │  │ Encrypted │  │
│  │ (plain)   │  │                    │  │  Blobs    │  │
│  └───────────┘  │                    │  └───────────┘  │
└─────────────────┘                    └─────────────────┘

Components

Daemon

The daemon runs in the foreground today and contains:

GUI

The GTK4 app shows:

CLI

The CLI handles:

Networking

libp2p Stack

Layer Protocol Purpose
Transport TCP Direct connection
Security Noise Direct transport encryption
Muxer Yamux Multiplexing
Discovery Relay API Find buddy addresses via pairing-code-derived keys

Peer Discovery

How two buddies find each other:

  1. Each daemon publishes its address record to the relay API at /discovery/<derived-key>, where the key is derived from the pairing code (HMAC-authenticated)
  2. The daemon looks up configured buddies using the same derived key (every 10 minutes)
  3. It reads the peer ID, advertised multiaddrs, reachability flag, and sync time from the record
  4. Deterministic initiator selection: the side without a public address initiates; if both same reachability, lower buddy UUID initiates
  5. It dials a public TCP address directly, or falls back to a relay when configured
  6. Cached addresses in state.db allow reconnection when the relay is temporarily unavailable

NAT Traversal

File Sync

Change Detection

The sync manager monitors configured folders:

  1. Scan files in the folder using streaming blake2b hash (64KB chunks, never full file in memory)
  2. Capture path, encrypted path, size, mtime, content hash, mode, and symlink target
  3. Compare against the previous index
  4. Detect added, modified, deleted, and moved files (move detection via content hash matching)

Transfer Protocol

File transfer uses a chunked protocol with encryption:

File list exchange → Delta computation (moves, deletes, missing) → Chunked transfer → Hash verification

Chunks are sent in 64KB blocks. LZ4 compression is used when it helps. When folder encryption is enabled, chunks are encrypted with random nonces (XSalsa20-Poly1305). Paths are encrypted with deterministic nonces so the same filename always encrypts the same way.

Restored files are hash-verified after write.

Restore Behavior

Restore is just sync in the opposite direction:

  1. One side advertises a file in its folder list
  2. The other side sees the file is missing locally
  3. The sync session requests the missing file
  4. The file is recreated locally and hash-verified

If the destination folder is append-only and already has a file with that name, the local file is kept.

SQLite State

BuddyDrive keeps runtime and file state in SQLite under ~/.buddydrive/.

Recovery Flow

Setup Recovery

  1. buddydrive setup-recovery generates a 12-word phrase
  2. BuddyDrive derives a 32-byte master key from the phrase
  3. Recovery metadata is stored in [recovery] in config.toml
  4. The serialized config is encrypted with the master key and uploaded to the relay

Recover On A New Machine

  1. buddydrive recover asks for the 12-word phrase
  2. BuddyDrive derives the same master key again
  3. It fetches the encrypted config blob from the relay
  4. The config is decrypted and saved locally
  5. Starting the daemon lets normal sync restore missing files

Control API

Local HTTP server (default port 17521) for GUI communication. Localhost connections require no authentication; LAN connections must use a secret path prefix /w/<secret>/.

Endpoint Purpose
GET /statusRuntime status
GET /buddiesBuddy list with connection state
GET /foldersFolder list with sync status
GET /configCurrent saved configuration
GET /logsRecent log entries
GET /recoveryExport recovery metadata
POST /foldersAdd folder
DELETE /folders/:nameRemove folder
POST /buddies/pairPair buddy through the local API
POST /buddies/pairing-codeGenerate pairing code
DELETE /buddies/:idRemove buddy
POST /sync/:folderTrigger sync
POST /configUpdate selected config fields
POST /config/reloadReload config from disk
POST /recovery/setupGenerate recovery phrase
POST /recovery/verify-wordVerify recovery word
POST /recovery/recoverRecover from mnemonic
POST /recovery/exportExport recovery metadata
POST /recovery/sync-configSync config to relay
POST /daemon/stopRequest daemon stop

Limitations

Current

Planned

See Features for user-facing capabilities or Security for current security scope.