|
| 1 | +# Architecture |
| 2 | + |
| 3 | +## Core Components |
| 4 | + |
| 5 | +### The Daemon |
| 6 | + |
| 7 | +A long-running daemon process manages each Litterbox. It is started automatically when entering a Litterbox and persists until the container is stopped. |
| 8 | + |
| 9 | +**Responsibilities:** |
| 10 | + |
| 11 | +- Manages the SSH agent server for key access |
| 12 | +- Monitors active sessions via lockfiles |
| 13 | +- Automatically stops the container when all sessions close |
| 14 | + |
| 15 | +**Lockfiles** in `~/Litterbox/`: |
| 16 | + |
| 17 | +- `.daemon-{LBX_NAME}.lock` - Contains the daemon's PID. Prevents multiple daemons from running simultaneously. |
| 18 | +- `.session-{LBX_NAME}.lock` - Contains PIDs of all active terminal sessions. The daemon periodically cleans stale PIDs and stops the container when this file becomes empty. |
| 19 | + |
| 20 | +### SSH Key Architecture |
| 21 | + |
| 22 | +Litterbox implements a custom SSH agent to control key access. |
| 23 | + |
| 24 | +**Components:** |
| 25 | + |
| 26 | +1. **Key Storage** - Keys are stored in `~/Litterbox/keys.ron`, encrypted with a user-provided password. |
| 27 | + |
| 28 | +2. **SSH Agent Server** - A custom agent implementation built on russh that: |
| 29 | + - Runs inside the daemon as an async task |
| 30 | + - Listens on a Unix socket mounted into the container |
| 31 | + - Decrypts keys only when needed and registers them with the agent |
| 32 | + |
| 33 | +3. **Confirmation System** - Before any key operation (sign, list, add, remove), the agent spawns a GUI confirmation dialog using. Users can: |
| 34 | + - Approve the single request |
| 35 | + - Approve for the entire session (subsequent requests of the same type are auto-approved) |
| 36 | + - Decline the request |
| 37 | + |
| 38 | +A new short-livived process is spawned for each confirmation dialog. This is mainly to work around threading issues with the GUI system. |
| 39 | + |
| 40 | +### Container Lifecycle |
| 41 | + |
| 42 | +**Building:** |
| 43 | + |
| 44 | +- Litterbox uses Dockerfile templates to build images |
| 45 | +- Images are tagged with `work.litterbox.name` label for discovery |
| 46 | +- Each Litterbox has both an image and a container |
| 47 | + |
| 48 | +**Starting:** |
| 49 | + |
| 50 | +- The container entrypoint is `/litterbox wait`, which blocks until the session lock file is empty |
| 51 | +- This is detected using inotify for efficient watching |
| 52 | + |
| 53 | +**Stopping:** |
| 54 | + |
| 55 | +- When the daemon detects no active sessions, it exits |
| 56 | +- This triggers the container's entrypoint to return |
| 57 | +- Podman automatically stops the container |
| 58 | + |
| 59 | +### File System Isolation |
| 60 | + |
| 61 | +The isolation model restricts what the container can access: |
| 62 | + |
| 63 | +**Mounted Paths:** |
| 64 | + |
| 65 | +- `~/Litterbox/homes/{name}` → `/home/user` (user's home inside container) |
| 66 | +- `/litterbox` (binary, read-only) → Container entrypoint |
| 67 | +- `/session.lock` (host's session lock, read-only) → Used for waiting |
| 68 | +- `/tmp/ssh-agent.sock` → SSH agent socket for key access |
| 69 | +- `/tmp/pipewire-0` (optional) → PipeWire socket for audio |
| 70 | +- Wayland socket → Host's Wayland display |
| 71 | + |
| 72 | +**Isolation Boundaries:** |
| 73 | + |
| 74 | +- User namespace is set to `keep-id` to match host user |
| 75 | +- Root filesystem is fully isolated (no access to host except mounted paths) |
| 76 | +- Network mode defaults to `pasta` (user-mode networking stack) |
| 77 | + |
| 78 | +### Session Tracking |
| 79 | + |
| 80 | +Each terminal session is tracked via PID: |
| 81 | + |
| 82 | +1. When `litterbox enter` runs, it adds the terminal's PID to the session lockfile |
| 83 | +2. When the terminal exits, the PID is removed from the lockfile |
| 84 | +3. The daemon periodically checks and cleans up PIDs for dead processes |
| 85 | +4. When the lockfile is empty, the container stops |
| 86 | + |
| 87 | +This allows multiple concurrent sessions (e.g., multiple terminals) to share one container. |
| 88 | + |
| 89 | +### Entry Flow |
| 90 | + |
| 91 | +When a user runs `litterbox enter NAME`: |
| 92 | + |
| 93 | +1. **Container Check** - Verify container exists; start if not running |
| 94 | +2. **Daemon Start** - If daemon not running, spawn it with the key password via stdin |
| 95 | +3. **Session Registration** - Add terminal PID to session lockfile |
| 96 | +4. **Home Setup** - Run `/litterbox setup-home` to initialize user's home directory (only on first entry) |
| 97 | +5. **Shell Launch** - Start user's shell inside the container |
0 commit comments