- Update Quick Start to use HTTPS (no SSH key needed) - Keep SSH instructions for push access - Use actual git.qrty.ink URLs in examples Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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
- Config is code: Your system configuration should be version-controlled and shareable
- Notes deserve versioning: Use git-backed tools (nb) for notes, not just file sync
- Sync ≠ Backup: Syncthing syncs; restic backs up. Use both.
- Self-host when practical: Forgejo, Immich, Jellyfin over proprietary clouds
- 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 configurationmodules/syncthing.nix- Declarative Syncthing setupmodules/neovim.nix- Neovim with nb integrationmodules/backup.nix- restic backup timersmodules/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 manuallyustatus- 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.