Brandon Lucas afe7826d58 Complete self-contained grapho CLI with all 8 phases
Phase 5 (Server):
- grapho server setup/mount/unmount/ls commands
- SSHFS/NFS mount instructions

Phase 6 (SQLite):
- State database for event tracking
- grapho history command
- Events logged for sync/backup operations

Phase 7 (Export):
- grapho export creates tar.zst archive
- grapho import restores from archive
- Full data portability between machines

Phase 8 (Dashboard):
- grapho dashboard generates HTML status page
- Dark theme, mobile-friendly
- Can be served with python http.server

Self-contained improvements:
- grapho setup now auto-initializes Syncthing
- grapho backup init <repo> runs restic init directly
- grapho backup runs restic backup directly
- grapho backup list shows snapshots directly
- All configs saved to ~/.config/grapho/

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-16 06:56:24 -05:00
2026-02-16 01:06:55 -05:00

Ultimate Notetaking, Sync & Backup System

A NixOS-based system for managing the three types of data in a computer:

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

# One-command setup (public repo, no SSH key needed)
nix run 'git+https://git.qrty.ink/blu/grapho.git'

# Or clone first, then run
git clone https://git.qrty.ink/blu/grapho.git
cd grapho
nix run .

Full Setup Guide

First Computer (Initial Setup)

# 1. Clone the repo
git clone https://git.qrty.ink/blu/grapho.git
cd grapho

# 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/grapho.git

Additional Computers (Joining)

# One command (no SSH key needed for public repo)
nix run 'git+https://git.qrty.ink/blu/grapho.git'
# Choose option [2], enter your config git URL and age key

# Or clone first:
git clone https://git.qrty.ink/blu/grapho.git && cd grapho
nix run . -- <config-git-url> <your-age-key>

Mobile Device (Phone/Tablet)

# 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)

nix develop
# Provides: nb, syncthing, restic, rclone, age, sops, etc.

Apply as NixOS Module

Add to your flake.nix inputs, then import the module:

{
  inputs.grapho.url = "git+https://git.qrty.ink/blu/grapho.git";

  # In your configuration:
  imports = [ inputs.grapho.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

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.

# Rebuild your system
sudo nixos-rebuild switch --flake .#your-hostname

# Update flake inputs
nix flake update

Tier 2: Notes with nb

# 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:

nb remote set git@your-forgejo:you/notes.git

Tier 2: Documents with Syncthing

Documents in ~/Documents/ sync automatically via Syncthing.

# 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:

# 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:

{
  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:

{
  services.syncthing.settings.folders = {
    "documents" = {
      path = "~/Documents";
      devices = [ "laptop" "desktop" ];
    };
    "music" = {
      path = "~/Music";
      devices = [ "laptop" "desktop" "server" ];
    };
  };
}

Backup Paths

Edit modules/backup.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. 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.

Directory Structure

.
├── flake.nix                 # Entry point
├── flake.lock
├── README.md
├── docs/
│   ├── research/
│   │   └── sync-tools-comparison.md
│   ├── ARCHITECTURE.md
│   └── LLM-CONTEXT.md        # For AI assistants
├── modules/
│   ├── 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

Contributing

PRs welcome! Please read ARCHITECTURE.md first.

License

MIT


Built with Nix, because reproducibility matters.

Description
No description provided
Readme 496 KiB
Languages
Nix 58.7%
Shell 41.3%