Files
n_os_tr/README.md

239 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# n_OS_tr
**A privacy-preserving, ephemeral operating system whose identity and configuration live on [Nostr](https://nostr.com).**
You boot n_OS_tr. It asks for a 12-word mnemonic (or generates one for you). From that mnemonic it deterministically derives every key the system needs — your personal identity, your relay keys, your blob-store keys, your mesh identity — using the standard [NIP-06](https://github.com/nostr-protocol/nips/blob/master/06.md) derivation scheme. Your preferences, dotfiles, bookmarks, and personal configuration are then loaded from Nostr relays, decrypted with your own key, and projected into your home directory on a RAM-backed filesystem. Nothing is saved to disk. You don't even need storage on your computer, and part of the intention of this project is that you don't have any.
When you power off, **everything disappears**. There is no local trace that you were ever on this machine.
The next time you boot — on the same machine, a different machine, a Pi in your pocket — you type the same 12 words and your environment materializes again.
---
## Status
- **Phase 2 Slice B+C: live.** Base ISO with [`fips`](https://github.com/) mesh daemon, [`c-relay`](https://github.com/) Nostr relay, [`ginxsom`](https://github.com/) Blossom blob server, nginx reverse proxy, first-boot provisioning, and smoke test are all green. See [`plans/slice_bc_fips_crelay.md`](plans/slice_bc_fips_crelay.md).
- **Phase 3 (identity + config): planned.** Mnemonic-driven identity subsystem and Nostr-as-home-directory are in design. See [`plans/identity_subsystem.md`](plans/identity_subsystem.md) and [`plans/nostr_config_projection.md`](plans/nostr_config_projection.md).
- **Phase 4 (Pi flavor and GUI): scoped.** Pi Zero 2 W live image and an optional amd64 GUI flavor come after the identity/config work stabilizes.
---
## The core idea in three sentences
1. **One mnemonic = your whole identity.** A single BIP-39 seed phrase deterministically generates every key the OS and its apps need, via [NIP-06](https://github.com/nostr-protocol/nips/blob/master/06.md) (`m/44'/1237'/{index}'/0/0`).
2. **All config lives on Nostr.** Replaceable events signed by your main key hold your dotfiles, preferences, and per-app state, encrypted to yourself with [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md).
3. **The OS is ephemeral.** Root filesystem is an overlay on tmpfs. Shutdown wipes memory. No persistent local state by default — not even `machine-id`, Wi-Fi credentials, or shell history.
---
## The key tree
Every key in the system is deterministically derived from your single 12-word mnemonic. Each role gets its own index on the NIP-06 derivation path:
| Index | Role | Used by |
|-------|----------------------|------------------------------------------------------------|
| `0` | Main account | Your public Nostr identity (profile, posts, social graph) |
| `1` | Throwaway / test | Experimental account, scratch work, testing |
| `2` | c-relay admin | Admin key for your local [`c-relay`](includes/c-relay/) personal Nostr relay |
| `3` | ginxsom server | Server key for your local [`ginxsom`](includes/ginxsom/) Blossom blob store |
| `4` | fips node | Mesh node identity for the [`fips`](includes/fips/) daemon (also yields your fips IPv6) |
| `5`+ | Reserved future uses | New apps request an index from the identity agent at install time |
An app never sees the mnemonic or the seed. It asks the local **identity agent** for "the key assigned to role X", and the agent derives and returns it (or signs on its behalf via [NIP-46](https://github.com/nostr-protocol/nips/blob/master/46.md)). Details in [`plans/identity_subsystem.md`](plans/identity_subsystem.md).
The derivation method itself is not invented — it's standard NIP-06 and matches the reference implementation in [`/home/user/lt/client/www/tools.html`](../client/www/tools.html) (`nostr-tools.nip06.privateKeyFromSeedWords(mnemonic, "", index, 0, 0)`).
**Crypto core.** All mnemonic handling, key derivation, event signing, NIP-44 encryption, and NIP-46 signer/bunker flows are implemented by the vendored [`includes/nostr_core_lib`](includes/nostr_core_lib/) library — a C implementation of the relevant NIPs already unit-tested in [`includes/nostr_core_lib/tests`](includes/nostr_core_lib/tests/). The identity agent and config projection services are thin wrappers around its API; n_OS_tr does not reimplement any Nostr crypto itself.
**Language and toolchain.** Every n_OS_tr binary we ship (identity-agent, TUI, config-loader, config-writer, smoketest helpers) is **C99, statically linked against musl libc**, built inside Alpine Docker — the same pattern [`includes/nostr_core_lib`](includes/nostr_core_lib/), [`includes/ginxsom`](includes/ginxsom/), and [`includes/c-relay`](includes/c-relay/) already use. Output is self-contained static ELFs (`ldd` reports "not a dynamic executable"), identical toolchain across amd64 and arm64, no Python or Node.js at runtime. Details in [`plans/tui_login.md §0.1`](plans/tui_login.md#01-toolchain-alpine--musl-dev-built-in-docker).
```mermaid
flowchart LR
M[12-word BIP-39 mnemonic<br/>user enters or generates at boot]
M --> S[BIP-32 seed]
S --> D0[Index 0<br/>main account]
S --> D1[Index 1<br/>throwaway]
S --> D2[Index 2<br/>c-relay admin]
S --> D3[Index 3<br/>ginxsom]
S --> D4[Index 4<br/>fips node]
S --> DN[Index 5..N<br/>future roles]
```
---
## The privacy contract
n_OS_tr makes a small number of hard promises to the user. These are non-negotiable; they're enforced by the image build and audited by the smoke test. The full list is in [`plans/threat_model.md`](plans/threat_model.md).
The short version:
- **Your mnemonic never touches disk.** Not swap, not logs, not journal, not `~/.bash_history`, not crash dumps.
- **The root filesystem is ephemeral.** Every boot is a clean slate; shutdown leaves no recoverable trace on the boot media.
- **No cross-boot fingerprint.** `machine-id`, MAC address, hostname, and Wi-Fi credentials do not persist by default.
- **No on-disk logs.** systemd-journald runs in volatile mode. User app caches are tmpfs-backed.
- **Your config is encrypted on Nostr to yourself.** Relay operators see ciphertext and metadata only. Run your own [`c-relay`](includes/c-relay/) to keep even the metadata local.
- **Identity can be walked away from.** Power off, remove the USB/SD, destroy it if you want — the only recoverable identity is the one you carry in your head or on paper.
---
## Architecture at a glance
```mermaid
flowchart TB
subgraph boot[Boot sequence]
direction TB
B1[Kernel + initramfs]
B2[tmpfs overlay root<br/>= ephemeral]
B3[privacy-hardener<br/>MAC rand, swap off,<br/>volatile journald,<br/>fresh machine-id]
B4[identity-agent<br/>prompt for 12 words<br/>or generate new]
B5[network-bootstrap<br/>Wi-Fi / Ethernet /<br/>fips mesh]
B6[config-loader<br/>Nostr replaceable events<br/>projected to ~/]
B7[user shell or GUI]
B1 --> B2 --> B3 --> B4 --> B5 --> B6 --> B7
end
subgraph core[Core subsystems]
ID[identity-agent<br/>NIP-06 derivation<br/>NIP-46 signer]
CFG[config projection<br/>NIP-44 encrypted]
HARD[privacy-hardener<br/>+ shutdown-wiper]
end
subgraph opt[Optional user services]
FIPS[fips mesh daemon]
CREL[c-relay personal relay]
GINX[ginxsom + nginx blob store]
end
B4 --- ID
B6 --- CFG
B3 --- HARD
B7 -.optional.-> FIPS
B7 -.optional.-> CREL
B7 -.optional.-> GINX
```
The "core subsystems" (identity, config, hardening) define the product. Everything else — fips, c-relay, ginxsom, nginx, the GUI, the Pi HAT drivers — is optional user-facing infrastructure layered on top.
---
## Form factors
n_OS_tr is one product, delivered as multiple image flavors that all share the same core subsystems.
| Flavor | Status | Use case |
|-------------------------------------|-----------------|------------------------------------------------------------------------------------------|
| **amd64 live ISO (text console)** | Live (Phase 2) | Boot any x86_64 laptop/desktop from USB, get a privacy-preserving session. |
| **amd64 live ISO with GUI** | Planned | Adds a minimal window manager for users who want graphical apps on the same session. |
| **Raspberry Pi Zero 2 W live image**| Planned | Pocket-sized hardware token + mesh node; Waveshare LCD HAT as the mnemonic-entry UI. |
| **Other Pi models (Pi 4, CM4)** | Possible later | Same stack, larger form factor with HDMI-GUI capable. |
The design goal is that a user who knows their 12 words can sit down in front of any of these, boot, type their phrase, and have the same configuration materialize. See [`plans/iso_architecture.md`](plans/iso_architecture.md) for the amd64 build details today and the companion project [`raspberry_pi_zero_nostr`](../raspberry_pi_zero_nostr) for current Pi exploration work that will fold into the monorepo later.
---
## Current service stack (Phase 2)
The live Phase 2 Slice B+C ISO ships these services and components out of the box. They are *infrastructure for advanced users*, not the core product — the core product is identity + config, which is Phase 3.
All first-party components are organized under [`includes/`](includes/) as git submodules and are pulled with `git submodule update --init --recursive`.
| Service / Component | Role |
|--------------------------------------------------------------------------------|--------------------------------------------------------------------------|
| [`n_OS_tr-firstboot`](iso/config/includes.chroot/usr/local/sbin/n_OS_tr-firstboot) | Generates ephemeral service keypairs, issues self-signed TLS, configures fips interface |
| [`fips`](includes/fips/) | Nostr-addressed mesh networking daemon (virtual IPv6, mesh routing) |
| [`c-relay`](includes/c-relay/) | High-performance C Nostr relay running locally |
| [`ginxsom`](includes/ginxsom/) | Blossom blob server, served via nginx reverse proxy |
| [`nt`](includes/nostr_terminal/) | Nostr Terminal (TUI) client for reading/writing notes, DMs, and follows |
| [`otp`](includes/otp/) | One-time pad encryption tool with hardware RNG support |
| [`didactyl`](includes/didactyl/) | Nostr-native AI agent with a skill-based architecture |
| [`nginx`](iso/config/includes.chroot/etc/nginx/sites-available/n_OS_tr.conf) | TLS-terminating reverse proxy for relay and blob endpoints |
| [`n_OS_tr-smoketest`](iso/config/includes.chroot/usr/local/bin/n_OS_tr-smoketest) | End-to-end health check (21 checks, currently all green) |
When Phase 3 lands, these services become **opt-in keys at NIP-06 indices 2, 3, 4** — they inherit deterministic identities from the user's mnemonic instead of generating fresh keys on first boot.
---
## Planning documents
Read these in order for the full picture:
1. [`README.md`](README.md) — this file. Vision and structure.
2. [`plans/threat_model.md`](plans/threat_model.md) — the privacy contract. What we defend, what we don't, forbidden behaviors.
3. [`plans/identity_subsystem.md`](plans/identity_subsystem.md) — how the 12-word mnemonic becomes every key in the system.
4. [`plans/nostr_config_projection.md`](plans/nostr_config_projection.md) — how Nostr events become your home directory.
5. [`plans/iso_architecture.md`](plans/iso_architecture.md) — the current amd64 live-build architecture.
6. [`plans/slice_bc_fips_crelay.md`](plans/slice_bc_fips_crelay.md) — Phase 2 Slice B+C implementation notes (shipped).
7. [`plans/network_boot.md`](plans/network_boot.md) — research and notes on network-boot delivery options.
---
## Running the current ISO
For practical "how do I build and boot it" instructions see [`docs/RUNNING.md`](docs/RUNNING.md).
TL;DR:
```bash
# Build
./build.sh --clean
# Run locally in a VM (headless serial)
HEADLESS=1 ./scripts/run-iso.sh
# Or flash to USB and boot real hardware
sudo dd if=iso/live-image-amd64.hybrid.iso of=/dev/sdX bs=4M status=progress
```
Once booted, run [`n_OS_tr-smoketest`](iso/config/includes.chroot/usr/local/bin/n_OS_tr-smoketest) for an end-to-end health check.
---
## Developer notes
- Historical Debian live-build reference material (tutorials, package discovery, GUI/splash options, minimization, persistence) has been moved to [`docs/debian_live_notes.md`](docs/debian_live_notes.md). Nothing in there is authoritative for the product — it's a cheatsheet we built up while bootstrapping the ISO.
- The amd64 live image is built with [`live-build`](live-build/) via [`build.sh`](build.sh). The ISO itself is produced at `iso/live-image-amd64.hybrid.iso`.
- Service artifacts staged into the ISO come from submodules under [`includes/`](includes/): [`fips`](includes/fips/) (mesh daemon), [`c-relay`](includes/c-relay/) (Nostr relay), [`ginxsom`](includes/ginxsom/) (Blossom server), and [`nostr_core_lib`](includes/nostr_core_lib/) (the C Nostr library used as the crypto core for identity and config projection).
---
## Licensing and contributing
TBD. The product principle is: **you should always be able to build and run this from source, verify it matches the shipped image, and run it on your own hardware with no external dependencies.** Anything that violates that principle does not belong in the product.
---
## Why this exists
Operating systems today are identity sinks. They remember your SSIDs, your login history, your hostnames, your keys, your clipboard, your browsing state. When a machine changes hands — sold, seized, borrowed, stolen — those traces go with it.
At the same time, Nostr gives us something new: **a place to keep identity and preferences that is not tied to any particular computer, account, server, or company**. Your keys are just math. Your preferences are just signed events. Any machine that can do elliptic-curve crypto can reconstitute your setup.
n_OS_tr puts those two facts together. The computer is disposable. The identity and configuration are portable. And the glue between them — the mnemonic, the derivation scheme, the config projection — is open, standard, and auditable.
That's the product.
## Virtual Consoles (Multi-Terminal)
n_OS_tr uses Linux virtual consoles to provide multiple independent terminals without a GUI:
| TTY | Keystroke | Purpose |
|-----|-----------|---------|
| tty1 | `Ctrl+Alt+F1` | 🔐 **Signer** — mnemonic entry, status display, signing approval prompts |
| tty2 | `Ctrl+Alt+F2` | ⚙️ **Services** — post-unlock service selection menu |
| tty3tty6 | `Ctrl+Alt+F3`..`F6` | **Shell** — standard login prompts for admin commands |
Each terminal has a distinct background color tint and banner so you always know where you are:
- **tty1** (red tint): `🔐 n_OS_tr SIGNER · TTY1`
- **tty2** (blue tint): `⚙️ n_OS_tr SERVICES · TTY2`
- **tty3tty6** (default): login banner shows `n_OS_tr · SHELL · ttyN`
### Boot flow
1. Boot lands on **tty1** with the `nsigner` mnemonic prompt
2. Enter or generate your 12-word BIP-39 mnemonic on tty1
3. Switch to **tty2** (`Ctrl+Alt+F2`) — it auto-detects the signer is ready and shows the service menu
4. Toggle services (c-relay, ginxsom, fips, nginx) and apply
5. Switch to **tty3** (`Ctrl+Alt+F3`) for a working shell at any time
Signing approval prompts appear on tty1. When a service requests a signature, switch back to tty1 to approve or deny.