Files
grapho/README.md
Brandon Lucas d30d2efa4e Rename grapho to pal, add onboard command, fix interactive input
- Rename grapho → pal across entire codebase (CLI, NixOS module,
  flake, docs, config paths)
- Add `pal onboard` interactive setup wizard with 4 steps:
  device, config repo, sync, backups
- Shows current setup summary when re-running onboard on an
  existing installation with warnings about what will change
- Fix askConfirm/askInput to read from /dev/tty so interactive
  prompts work correctly
- Remove || operator usage in askConfirm (not reliable in Lux)
- Add pal package to nix develop shell
- Document ~/.config/pal/ directory structure in README

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 22:38:37 -05:00

400 lines
13 KiB
Markdown

# Ultimate Notetaking, Sync & Backup System
A NixOS-based system for managing the three types of data across devices:
| Tier | Type | Examples | Sync Model |
|------|------|----------|------------|
| **1** | Configuration | flake.nix, dotfiles | Git (public, shareable) |
| **2** | Syncable Data | Notes, documents | Git (nb) + Syncthing |
| **3** | Large Data | Photos, videos, repos | Central backup, on-demand |
## Quick Start
```bash
# One-command setup (public repo, no SSH key needed)
nix run 'git+https://git.qrty.ink/blu/pal.git'
# Or clone first, then run
git clone https://git.qrty.ink/blu/pal.git
cd pal
nix run .
```
## Full Setup Guide
### First Computer (Initial Setup)
```bash
# 1. Clone the repo
git clone https://git.qrty.ink/blu/pal.git
cd pal
# 2. Run setup (one command - includes all dependencies)
nix run .
# Or: nix develop && ./setup
# 3. Choose option [1] "New setup (first device)"
# This generates an age encryption key - SAVE IT!
# 4. (Optional) Set up SSH for push access
# Add your SSH key to Gitea: https://git.qrty.ink/user/settings/keys
# Then switch to SSH remote:
git remote set-url origin ssh://git@git.qrty.ink:2222/blu/pal.git
```
### Additional Computers (Joining)
```bash
# One command (no SSH key needed for public repo)
nix run 'git+https://git.qrty.ink/blu/pal.git'
# Choose option [2], enter your config git URL and age key
# Or clone first:
git clone https://git.qrty.ink/blu/pal.git && cd pal
nix run . -- <config-git-url> <your-age-key>
```
### Mobile Device (Phone/Tablet)
```bash
# On any computer that's already set up:
nix run . -- mobile
# Or: ./setup mobile
```
This shows a QR code for Syncthing pairing. You can also manually paste device IDs.
### Just Try the Tools (No Setup)
```bash
nix develop
# Provides: nb, syncthing, restic, rclone, age, sops, etc.
```
### Apply as NixOS Module
Add to your flake.nix inputs, then import the module:
```nix
{
inputs.pal.url = "git+https://git.qrty.ink/blu/pal.git";
# In your configuration:
imports = [ inputs.pal.nixosModules.default ];
}
```
## Philosophy
1. **Config is code**: Your system configuration should be version-controlled and shareable
2. **Notes deserve versioning**: Use git-backed tools (nb) for notes, not just file sync
3. **Sync ≠ Backup**: Syncthing syncs; restic backs up. Use both.
4. **Self-host when practical**: Forgejo, Immich, Jellyfin over proprietary clouds
5. **Open source only**: Every tool in this stack is FOSS
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ YOUR MACHINES │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Desktop │ │ Laptop │ │ Phone │ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ TIER 2 │ │
│ │ nb (notes) │◄── git push/pull │
│ │ Syncthing │◄── P2P sync (optional) │
│ └───────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ YOUR SERVER │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Forgejo │ │ Immich │ │ Jellyfin │ │
│ │ (git/nb) │ │ (photos) │ │ (media) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ └────────────────┼────────────────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ restic │ │
│ │ (backup) │ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────▼──────┐ │
│ │ B2 / NAS │ │
│ │ (offsite) │ │
│ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
## What's Included
### NixOS Modules
- `modules/nb.nix` - nb notebook CLI installation and configuration
- `modules/syncthing.nix` - Declarative Syncthing setup
- `modules/neovim.nix` - Neovim with nb integration
- `modules/backup.nix` - restic backup timers
- `modules/server/` - Forgejo, Immich, Jellyfin configurations
### Development Shell
```bash
nix develop
```
Provides: `nb`, `syncthing`, `restic`, `rclone`, `jq`, and helper scripts.
### Helper Scripts
- `usync` - Unified sync command (syncs nb + triggers Syncthing scan)
- `ubackup` - Run restic backup manually
- `ustatus` - Show sync/backup status across all tiers
## Usage
### Tier 1: Configuration
Your system config lives in this repo. Fork it, customize it, push to your own GitHub.
```bash
# Rebuild your system
sudo nixos-rebuild switch --flake .#your-hostname
# Update flake inputs
nix flake update
```
### Tier 2: Notes with nb
```bash
# Create a note
nb add "My note title"
# Edit with neovim
nb edit 1
# Sync to remote
nb sync
# Search notes
nb search "keyword"
# List notebooks
nb notebooks
```
Set up git remote for nb:
```bash
nb remote set git@your-forgejo:you/notes.git
```
### Tier 2: Documents with Syncthing
Documents in `~/Documents/` sync automatically via Syncthing.
```bash
# Check Syncthing status
syncthing cli show system
# Force rescan
syncthing cli scan --folder documents
```
### Tier 3: Large Data
Photos upload to Immich (mobile app or web).
Media is served via Jellyfin.
Manual files can be uploaded with rclone:
```bash
# Upload to your server
rclone copy ~/Videos/project server:archive/videos/
# List remote files
rclone ls server:archive/
```
## Customization
### Adding Your Own Notebooks
Edit `modules/nb.nix`:
```nix
{
programs.nb = {
notebooks = {
personal = {
remote = "git@forgejo:you/personal-notes.git";
};
work = {
remote = "git@forgejo:you/work-notes.git";
};
};
};
}
```
### Syncthing Folders
Edit `modules/syncthing.nix`:
```nix
{
services.syncthing.settings.folders = {
"documents" = {
path = "~/Documents";
devices = [ "laptop" "desktop" ];
};
"music" = {
path = "~/Music";
devices = [ "laptop" "desktop" "server" ];
};
};
}
```
### Backup Paths
Edit `modules/backup.nix`:
```nix
{
services.restic.backups.default = {
paths = [
"/home/you/Documents"
"/home/you/notes"
"/var/lib/important"
];
};
}
```
## FAQ
### Why nb instead of Obsidian/Notion/etc?
- **Git-native**: Full version history, proper merges
- **Plain text**: Markdown files, no vendor lock-in
- **CLI-first**: Works over SSH, in tmux, everywhere
- **Scriptable**: Integrates with shell workflows
- **Encrypted option**: Built-in GPG encryption
### Why not just Syncthing for everything?
Syncthing is great for binary files but poor for text conflicts. When you edit notes on multiple devices, you want git-style merges, not `.sync-conflict` files scattered everywhere.
### Is Syncthing buggy?
No. See [our research](./docs/research/sync-tools-comparison.md). Common issues are:
- Treating it as a backup (it's not)
- Android battery killing the app (use Syncthing-Fork)
- Expecting cloud-style behavior from P2P sync
### Why self-host?
- **Control**: Your data on your hardware
- **Privacy**: No third-party access
- **Cost**: One-time hardware vs. monthly subscriptions
- **Learning**: Valuable sysadmin experience
But cloud is fine too. This system works with GitHub, Backblaze B2, etc.
## Repository Structure
```
.
├── flake.nix # Entry point
├── flake.lock
├── README.md
├── cli/
│ └── pal.lux # CLI source (Lux language)
├── docs/
│ ├── research/
│ │ └── sync-tools-comparison.md
│ ├── ARCHITECTURE.md
│ └── LLM-CONTEXT.md # For AI assistants
├── modules/
│ ├── pal.nix # Core pal NixOS module
│ ├── nb.nix
│ ├── syncthing.nix
│ ├── neovim.nix
│ ├── backup.nix
│ └── server/
│ ├── forgejo.nix
│ ├── immich.nix
│ └── jellyfin.nix
├── hosts/
│ ├── desktop/
│ │ └── configuration.nix
│ ├── laptop/
│ │ └── configuration.nix
│ └── server/
│ └── configuration.nix
├── home/
│ └── default.nix # home-manager config
└── scripts/
├── usync
├── ubackup
└── ustatus
```
## Data Directory (`~/.config/pal/`)
When you run `pal onboard` or `pal setup`, this directory is created to hold all your data and configuration. Everything is human-readable unless noted.
```
~/.config/pal/
├── pal.toml # Main config (TOML) — device name, ports, schedule
├── age-key.txt # Age encryption private key
├── state.db # Event history (SQLite)
├── config-repo/ # Your system config (git-managed)
│ └── .git/
├── sync/ # Syncthing-managed data (syncs across devices)
│ ├── notes/ # Your notes
│ ├── documents/ # Your documents
│ └── dotfiles/ # Your dotfiles
├── syncthing/ # Syncthing runtime (auto-generated)
│ ├── config/ # config.xml, TLS certs, keys
│ └── db/ # Syncthing index database
├── restic/ # Backup settings
│ ├── password # Repository password (auto-generated, plaintext)
│ ├── repository # Repository URL/path (plaintext)
│ └── cache/ # Local cache for faster operations
├── backups/ # Restic repository (if backing up locally)
│ ├── config # ⚠ Encrypted — restic internal, not human-readable
│ ├── data/ # Encrypted, deduplicated backup chunks
│ ├── index/ # Backup index
│ ├── keys/ # Repository encryption keys
│ ├── locks/ # Lock files
│ └── snapshots/ # Snapshot metadata
└── server/ # Mount point for remote server storage
```
**What's human-readable?** `pal.toml`, `restic/password`, `restic/repository`, and everything in `sync/` and `config-repo/`. The `syncthing/config/` directory is auto-generated XML. The `backups/` directory is a restic repository where everything is encrypted by design — use `pal backup list` to inspect snapshots.
## Contributing
PRs welcome! Please read [ARCHITECTURE.md](./docs/ARCHITECTURE.md) first.
## License
MIT
---
*Built with Nix, because reproducibility matters.*