2026-03-22 03:30:21 +00:00
# Archipelago — Architecture
2026-01-24 22:01:51 +00:00
2026-03-22 03:30:21 +00:00
> **Bitcoin Node OS** — Flash to USB, install on hardware, manage via web UI.
2026-01-24 22:01:51 +00:00
2026-07-08 17:09:24 -04:00
**Stack**: Rust backend + Vue 3 + TypeScript (strict) + Vite + Tailwind CSS + Pinia + rootless Podman (Quadlet)
2026-04-09 21:32:08 +02:00
**Target OS**: Debian 13 (Trixie) — x86_64 and ARM64
2026-07-08 17:09:24 -04:00
**Status**: 1.8.0-alpha — single-node production gate green; multinode pass + release hardening in progress (see [`ROADMAP.md` ](ROADMAP.md ))
2026-03-22 03:30:21 +00:00
---
## System Layers
2026-01-24 22:01:51 +00:00
```
2026-03-22 03:30:21 +00:00
┌──────────────────────────────────────────────────────┐
│ YOUR BROWSER │
│ Vue 3 SPA (Composition API + Pinia) │
└──────────────────────┬───────────────────────────────┘
│ HTTP / WebSocket
┌──────────────────────┴───────────────────────────────┐
│ NGINX │
2026-07-08 17:09:24 -04:00
│ /rpc/v1 → backend /app/{id}/ → container │
2026-03-22 03:30:21 +00:00
└──────────────────────┬───────────────────────────────┘
2026-07-08 17:09:24 -04:00
│ port 5678 (127.0.0.1)
2026-03-22 03:30:21 +00:00
┌──────────────────────┴───────────────────────────────┐
│ RUST BACKEND (core/) │
2026-07-08 17:09:24 -04:00
│ Auth, ~380 RPC methods, orchestrator + reconciler, │
│ federation, mesh, identity, wallet, updates │
2026-03-22 03:30:21 +00:00
└──────────────────────┬───────────────────────────────┘
2026-07-08 17:09:24 -04:00
│ Podman REST API socket + systemd Quadlet units
2026-03-22 03:30:21 +00:00
┌──────────────────────┴───────────────────────────────┐
│ ROOTLESS PODMAN CONTAINERS │
2026-07-08 17:09:24 -04:00
│ 50+ manifest-driven apps as user.slice Quadlet │
│ units — survive backend restarts, self-heal │
2026-03-22 03:30:21 +00:00
└──────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
2026-07-08 17:09:24 -04:00
│ DEBIAN 13 (Trixie) │
│ systemd, UFW, Tor, AppArmor, Reticulum daemon │
2026-03-22 03:30:21 +00:00
└──────────────────────────────────────────────────────┘
2026-01-24 22:01:51 +00:00
```
2026-03-22 03:30:21 +00:00
## Codebase Stats
2026-01-24 22:01:51 +00:00
2026-03-22 03:30:21 +00:00
| Component | Lines | Files |
|-----------|-------|-------|
2026-07-08 17:09:24 -04:00
| Rust backend (`core/` ) | ~117,000 | ~334 |
| TypeScript/Vue (`neode-ui/src/` ) | ~69,000 | ~325 |
| Shell scripts (`scripts/` ) | — | ~51 |
| Packaged apps (`apps/*/manifest.yml` ) | — | 51 |
2026-03-22 03:30:21 +00:00
## Backend Crates (`core/`)
2026-07-08 17:09:24 -04:00
Workspace members (root `core/Cargo.toml` ):
2026-03-22 03:30:21 +00:00
| Crate | Purpose |
|-------|---------|
2026-07-08 17:09:24 -04:00
| `archipelago` | Main binary — API (~380 RPC methods), container orchestrator + boot reconciler, mesh, identity/federation, wallet, updates, marketplace |
| `container` (`archipelago-container` ) | Podman REST client, canonical manifest schema, Quadlet compiler, health monitor, signed app catalog, image verification |
| `security` (`archipelago-security` ) | AppArmor/seccomp container policy generation, secrets manager |
| `openwrt` (`archipelago-openwrt` ) | TollGate gateway provisioning over SSH/UCI |
| `performance` (`archipelago-performance` ) | Resource limits |
Also on disk but **not** workspace members (standalone/legacy, cleanup tracked in the hardening plan §G): `models` , `helpers` , `js-engine` , `container-init` .
### Key Backend Modules
2026-03-22 03:30:21 +00:00
```
core/archipelago/src/
2026-07-08 17:09:24 -04:00
├── api/handler/ — HTTP routing (/rpc, /health, /dwn, /ws)
├── api/rpc/dispatcher.rs — RPC dispatch (~380 method arms)
├── api/rpc/package/ — App install/lifecycle/stacks (multi-container)
├── container/ — prod_orchestrator, boot_reconciler, quadlet,
│ app_catalog (signed, embedded manifests),
│ version_config, crash_recovery, secrets
├── trust/ — release-root anchor (pinned Ed25519 pubkey),
│ detached-signature verify, did:key
├── mesh/ — Meshtastic + MeshCore + Reticulum transports,
│ X3DH/double-ratchet crypto, outbox/scheduler,
│ mesh AI assistant, bitcoin relay
├── federation/ — multi-node federation over Tor, state sync
├── identity.rs / identity_manager.rs — Ed25519 did:key, multi-identity
├── credentials/ — W3C Verifiable Credentials
├── nostr_discovery.rs — Nostr presence (NIP-33 kind 30078)
2026-03-22 03:30:21 +00:00
├── nostr_handshake.rs — NIP-44 encrypted peer comms
2026-07-08 17:09:24 -04:00
├── marketplace.rs — decentralized app marketplace (Nostr NIP-78,
│ DID-signed manifests, trust scoring)
├── wallet/ — LND integration, ecash (Fedimint/Cashu)
├── update.rs — signed OTA: resumable download, rollback,
│ post-update self-verify window
├── session.rs / auth.rs — sessions (persisted), Argon2id, TOTP
├── transport/ / network/ — Tor transport, DWN store/sync
└── fips/ / swarm/ / streaming/ — federation IPS anchor, P2P swarm (gated), streaming (WIP)
2026-03-22 03:30:21 +00:00
```
2026-01-24 22:01:51 +00:00
2026-07-08 17:09:24 -04:00
## App Platform (as built)
An app is a directory `apps/<id>/manifest.yml` parsed by the canonical schema
in `core/container/src/manifest.rs` . A manifest declares identity, a container
source (**image XOR build**), and runtime shape: ports, volumes (confined to
`/var/lib/archipelago` ), generated config files, environment, devices,
resources, health checks, and the launch interface. Ergonomics are declarative
too: `derived_env` (host-fact templating), `secret_env` (podman secrets — values
never appear in `podman inspect` or unit files), `generated_secrets` /
`generated_certs` (self-healing), `network_aliases` , `data_uid` , and
allow-listed `post_install` hooks that run inside the app's own sandbox.
**Install** compiles the manifest to a rootless **Quadlet unit under
`user.slice` ** — containers survive backend restarts and reboots.
Multi-container apps (BTCPay, Mempool, Immich, NetBird, IndeeHub) are sets of
per-member manifests installed via the stack orchestrator on an app-local
network with readiness gates and generated cross-service secrets. A
level-triggered **boot reconciler** converges actual state to desired state
every 30 seconds.
**Distribution**: the signed catalog (`releases/app-catalog.json` , Ed25519
detached signature over canonical JSON, verified against the pinned
release-root anchor in `trust/anchor.rs` ) embeds the full manifest per app;
nodes overlay catalog manifests over disk files (catalog wins), so apps can
ship without OTA disk files. A curated subset (27 apps) powers the store UI
(`app-catalog/catalog.json` ). A parallel **decentralized marketplace**
(Nostr NIP-78 discovery, DID-signed manifests, federation-weighted trust
scoring, Lightning purchase invoices) is implemented as a second,
community-distribution channel.
**Security invariants** enforced at manifest validation: read-only root and
no-new-privileges by default, capability allow-list, `network_policy ∈
{isolated, bridge, host}`, bind mounts confined to ` /var/lib/archipelago`, no
privileged containers, rootless only.
2026-03-22 03:30:21 +00:00
## Frontend (`neode-ui/src/`)
```
├── api/ — RPC client, WebSocket, container client
2026-07-08 17:09:24 -04:00
├── views/ — Dashboard, Apps, Marketplace, Cloud, Server,
│ Mesh, Web5, Settings, Monitoring, Fleet, Chat,
│ onboarding flow (11 screens), kiosk, recovery
├── components/ — EasyHome, ModeSwitcher, BootScreen, SpotlightSearch, …
├── stores/ — Pinia: app, install, mesh, cloud, goals, uiMode,
│ controller (gamepad), aiPermissions, …
├── composables/ — useControllerNav, useToast, useNavSounds, …
├── router/ — ~51 routes
└── style.css — global glassmorphism theme
2026-03-22 03:30:21 +00:00
```
2026-07-08 17:09:24 -04:00
Three UI modes (Pro/Easy/Chat), gamepad navigation, i18n, PWA. Tested with
Vitest + Playwright. AIUI is a separate external app surfaced via nginx.
## Mesh Networking
2026-03-22 03:30:21 +00:00
2026-07-08 17:09:24 -04:00
Three LoRa transports behind one chat UI and a common `MeshRadioDevice`
surface:
- **Meshtastic** — in-process async serial driver (protobuf over SLIP)
- **MeshCore** — framed-serial protocol; phone companion apps speak this
- **Reticulum (RNS/LXMF)** — host-supervised Python daemon
(`reticulum-daemon/` , PyInstaller-packaged, one per RNode radio) speaking
Unix-socket JSON-RPC to the backend; `archy-rnodeconf` ships as an OS-level
radio config tool
End-to-end encryption uses X3DH key agreement + double-ratchet. Extras: image
and voice attachments, mesh AI assistant (`!ai` ), Bitcoin balance relay over
mesh, steganography, store-and-forward outbox.
2026-01-24 22:01:51 +00:00
## Networking
2026-07-08 17:09:24 -04:00
- **Container DNS**: app-local Podman networks with `network_aliases` ; aardvark-dns resolution
- **Tor**: system daemon, SOCKS5 on 9050, hidden services per node; all inter-node federation traffic
- **Federation**: invite-based joining, DID-based trust levels, state sync, cross-node app deploy
2026-03-22 03:30:21 +00:00
- **UFW**: `DEFAULT_FORWARD_POLICY="ACCEPT"` required for LAN container access
2026-07-08 17:09:24 -04:00
- **OpenWrt/TollGate**: gateway provisioning via the `openwrt` crate
2026-03-22 03:30:21 +00:00
## Security Model
| Layer | Measures |
|-------|----------|
| OS | Debian hardening, AppArmor, minimal packages |
| Nginx | CSP headers, rate limiting, auth_request, session validation |
| Backend | Input validation, CSRF, session auth, bind 127.0.0.1 only |
2026-07-08 17:09:24 -04:00
| Containers | Rootless Podman, cap-drop ALL + reviewed allow-list, readonly root, no-new-privileges, memory limits |
| Supply chain | Ed25519-signed release manifests + app catalog against a pinned release-root anchor; auto-apply refuses unsigned |
| Crypto | Ed25519 signatures, ChaCha20-Poly1305 encryption, Argon2id password hashing (transparent bcrypt upgrade), constant-time comparisons |
2026-03-22 03:30:21 +00:00
| Network | Tor hidden services, UFW firewall, SSRF prevention |
## Data Paths
| Data | Path |
|------|------|
| App data | `/var/lib/archipelago/{app-id}/` |
| Identity | `/var/lib/archipelago/identity/` |
| Multi-identity | `/var/lib/archipelago/identities/` |
| Federation | `/var/lib/archipelago/federation/` |
| DWN messages | `/var/lib/archipelago/dwn/messages/` |
| Credentials | `/var/lib/archipelago/credentials/` |
| Backups | `/var/lib/archipelago/backups/` (ChaCha20-Poly1305) |
2026-07-08 17:09:24 -04:00
| Secrets | `/var/lib/archipelago/secrets/{app-id}/` (0600, service-user-owned) |
2026-03-22 03:30:21 +00:00
| Sessions | `/var/lib/archipelago/sessions.json` |
2026-07-08 17:09:24 -04:00
| Marketplace cache | `/var/lib/archipelago/marketplace/` |
2026-03-22 03:30:21 +00:00
| Frontend | `/opt/archipelago/web-ui/` |
| Backend binary | `/usr/local/bin/archipelago` |
## Key Features (Working)
2026-07-08 17:09:24 -04:00
- 50+ containerized apps with one-click install/manage; full lifecycle matrix repeatedly green on real hardware
- Bitcoin Core **and** Knots with per-app version pinning and safe switching; LND + Core Lightning
2026-03-22 03:30:21 +00:00
- Multi-node federation with invite-based joining and trust levels
- W3C DID identity (did:key, DID Documents, Verifiable Credentials)
docs(app-platform): sync the platform docs with the shipped code
- app-manifest-spec.md: full rewrite from the real schema in
core/container/src/manifest.rs — it was 5 months stale and missing the
entire modern feature set (build, network/network_aliases, derived_env,
secret_env, generated_secrets/certs, data_uid, files, interfaces, hooks,
extensions flatten) and documented wrong network_policy values.
- app-developer-guide.md: add generated_secrets/generated_certs/
network_aliases/hooks to the field table.
- APP-PACKAGING-MIGRATION-PLAN.md: phase status stamped (1-3 done, 5 mostly,
4+6 open); deleted meshtastic app removed from regression-proof lists.
- registry-manifest-design.md: status design → implemented (phases 1-3),
stale manifest_dir:Option line fixed.
- marketplace-protocol.md: reframed proposal → as-built (marketplace.rs +
RPCs + UI shipped; create-invoice noted; schema disambiguated).
- manifest-hooks-design.md: phase 3 (indeedhub) done, phase 4 resolved via
orchestrator+generated_secrets instead of hooks.
- README/architecture: restore the NIP-07 signer-bridge claim — it is real
(neode-ui/public/nostr-provider.js), the earlier audit only grepped Rust.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:24:22 -04:00
- Nostr: NIP-33 node discovery, NIP-44/NIP-04 encryption, NIP-07 signer bridge for iframe apps, relay hosting
2026-07-08 17:09:24 -04:00
- Decentralized marketplace (NIP-78 discovery, trust scoring, Lightning purchases)
- File sharing with access controls (free/peers-only/paid via LN, on-chain, ecash)
2026-03-22 03:30:21 +00:00
- Encrypted backups (Argon2 + ChaCha20-Poly1305)
2026-07-08 17:09:24 -04:00
- Health monitoring + level-triggered reconciler with tiered auto-restart
- Tri-protocol LoRa mesh (Meshtastic / MeshCore / Reticulum) with E2E crypto
- Signed OTA updates with rollback and post-update self-verification
- Three-mode UI (Pro/Easy/Chat), gamepad navigation, real-time WebSocket updates
- Bootable ISO installer (`image-recipe/` ), Android companion app
2026-03-22 03:30:21 +00:00
## Further Documentation
| Doc | Purpose |
|-----|---------|
2026-07-08 17:09:24 -04:00
| [`ROADMAP.md` ](ROADMAP.md ) | Shipped / in-progress / planned |
2026-03-22 03:30:21 +00:00
| [`developer-guide.md` ](developer-guide.md ) | Dev setup, workflow, code conventions |
2026-07-08 17:09:24 -04:00
| [`api-reference.md` ](api-reference.md ) | RPC endpoint reference |
2026-03-22 03:30:21 +00:00
| [`app-developer-guide.md` ](app-developer-guide.md ) | Building and publishing apps |
2026-07-08 17:09:24 -04:00
| [`app-manifest-spec.md` ](app-manifest-spec.md ) | The `manifest.yml` schema |
2026-03-22 03:30:21 +00:00
| [`user-walkthrough.md` ](user-walkthrough.md ) | End-user installation and usage guide |
| [`troubleshooting.md` ](troubleshooting.md ) | Diagnostic scenarios and solutions |
| [`operations-runbook.md` ](operations-runbook.md ) | Ops commands and emergency recovery |
| [`multi-node-architecture.md` ](multi-node-architecture.md ) | Federation protocol design |
| [`marketplace-protocol.md` ](marketplace-protocol.md ) | Decentralized app discovery via Nostr |
2026-07-08 17:09:24 -04:00
| [`PRODUCTION-MASTER-PLAN.md` ](PRODUCTION-MASTER-PLAN.md ) | North star and workstream narrative |
| [`UNIFIED-TASK-TRACKER.md` ](UNIFIED-TASK-TRACKER.md ) | Live, priority-ordered open items |
| [`archive/` ](archive/ ) | Historical audits, session logs, shipped designs |