diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..fd7ad0d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,135 @@ +# AGENTS.md + +> для AI агентов, работающих с этим репозиторием + +## what is this + +- **declarative nix config** для нескольких хостов через nix-darwin + home-manager +- активный: **poppy** (MacBook Air M1) +- planned: **muscari** (NixOS server), **rosemary** (backup VM) +- user: `michaotic` (planned: `mikl`) + +## structure + +``` +~/repos/nix-config/ +├── flake.nix # entry point +├── flake.lock # locked deps +├── AGENTS.md # этот файл +├── garden.md # future plans, TODO, миграции +│ +├── hosts/ +│ ├── poppy/ # macbook (active daily driver) +│ │ ├── default.nix # основной конфиг +│ │ ├── apps.nix # brew casks + nix GUI пакеты +│ │ └── system.nix # macOS defaults +│ ├── muscari/ # NixOS server (planned) +│ └── common/ # shared NixOS config +│ +├── home/ # home-manager modules +│ ├── default.nix # imports, sessionVariables +│ ├── cli.nix # CLI tools (universal) +│ ├── git.nix # git config +│ ├── ssh.nix # SSH matchBlocks +│ ├── zsh.nix # shell + aliases +│ ├── kitty.nix # terminal +│ ├── duti.nix # default apps +│ ├── pass.nix # pass + gpg-agent (только для GPG) +│ ├── syncthing.nix # p2p sync +│ ├── zoxide.nix +│ ├── bat.nix +│ ├── eza.nix +│ └── fzf.nix +│ +└── docs/ # документация + ├── structure.md # high-level overview + ├── poppy.md # macbook specifics + ├── muscari.md # server + k3s + ├── shell.md # zsh + pure + ├── terminal.md # kitty + ├── ssh.md # SSH keys, FIDO2, recovery + ├── apps.md # список приложений + ├── cheatsheet.md # quick commands + └── bootstrap.md # manual setup guide +``` + +## commands + +```bash +# rebuild poppy +sudo darwin-rebuild switch --flake .#poppy + +# rebuild muscari +sudo nixos-rebuild switch --flake .#muscari + +# validate before applying +nix flake check + +# update dependencies +nix flake update + +# cleanup old generations +nix-collect-garbage -d +``` + +## важные правила + +### при работе с файлами +- **сначала показывай план**, потом делай +- **никогда** не удаляй user data (GPG, SSH ключи, pass-store) +- новые файлы в `home/` обсуждай перед созданием +- длинные изменения дроби на отдельные коммиты + +### пакеты +- **CLI tools** → `home/cli.nix` (universal) +- **GUI apps** через nix → `hosts/poppy/apps.nix` (use `environment.systemPackages`, NOT `home.packages`) +- **brew casks** → `hosts/poppy/apps.nix` (тот же файл) +- **App Store apps** → ручная установка, в `docs/apps.md` +- **homebrew.onActivation.cleanup = "none"** (по умолчанию, безопаснее) + - `"zap"` удалит всё что не в nix config + +### SSH ключи +- `home/ssh.nix` — matchBlocks для forgejo/github/sol.moe +- **не** добавляй `credential.helper` (мы ходим по SSH, не HTTPS) +- FIDO2 ключи (Ledger) — нужен `nixpkgs#libfido2` и `nixpkgs#openssh` через `nix shell` +- подробности в `docs/ssh.md` + +### git workflow +- основной remote: `forgejo` (ssh://git@git.iscg.dev:2222/mikl/nix-config.git) +- **перед каждым значимым изменением** спрашивай подтверждение +- **не делай** `git push --force` без явного подтверждения + +## backup и recovery + +- **GPG ключ** → https://git.iscg.dev/mikl/gpg (private) +- **pass-store** → https://git.iscg.dev/mikl/pass (синхронизирован) +- **nix-config** → https://git.iscg.dev/mikl/nix-config +- **Obsidian traces** → https://git.iscg.dev/mikl/traces + Syncthing +- **Time Machine** → основной бэкап всего + +## что в работе (TODO) + +- sops-nix для `OPENROUTER_API_KEY` +- rosemary setup (NixOS VM) +- FIDO2 в nix-config постоянно (`libfido2`, `openssh`) +- pass-store remotes (github, git.sol.moe) +- pre-commit с alejandra +- uncomment aseprite в `hosts/poppy/apps.nix` (10-30 мин компиляции) + +## новые хосты + +при добавлении нового хоста: +1. создать `hosts//{default,system}.nix` +2. добавить в `flake.nix` `mkNixos` или `mkDarwin` +3. создать `docs/.md` с описанием +4. обновить `garden.md` + +## контекст для пользователя + +- студент, hse university +- интересы: LLM/AI, it infra, self-hosted, литература +- ADHD, прокрастинация — **не отвлекай** на ненужные темы +- общается на русском и английском +- использует Telegram MCP, Forgejo MCP, SearXNG +- конфиг для macOS, учится nix +- не спеши, показывай план, спрашивай подтверждения diff --git a/docs/apps.md b/docs/apps.md new file mode 100644 index 0000000..c4e4fe9 --- /dev/null +++ b/docs/apps.md @@ -0,0 +1,81 @@ +# apps + +приложения, игры, утилиты на poppy. + +## brew casks (через `hosts/poppy/apps.nix`) + +через Homebrew — для приложений которых **нет** в nixpkgs. + +### основные +- google-chrome, google-drive +- vscodium (редактор) +- github (GitHub Desktop) +- docker-desktop +- ollama-app (LLM) +- obsidian (заметки) +- anki (flashcards) +- calibre (книги) +- telegram (мессенджер) +- element (matrix клиент) +- maccy (clipboard) +- mos (mouse smoothing) +- caffeine (не засыпать) +- marta (файловый менеджер) +- lunacy (дизайн) +- skim (PDF) +- mark-text (markdown) + +### VPN +- amneziavpn + +### игры +- prismlauncher (Minecraft) + +## nix пакеты (через `hosts/poppy/apps.nix`) + +для GUI приложений которые есть в nixpkgs. + +### aseprite +- **в nixpkgs**, но компилируется с нуля (10-30 мин на M1) +- `pkgs.aseprite` 1.3.17.2 +- **раскомментировать** в `hosts/poppy/apps.nix` ПОСЛЕ первой полной сборки +- после первой сборки — кэшируется в `/nix/store/`, больше не компилируется +- пересоберётся только при: + - `nix flake update` (новая версия) + - `nix-collect-garbage -d` (удаление кэша) + +## ручная установка (НЕ через nix) + +### нет в brew/nix +- **Organic Maps** — App Store или скачать .dmg +- **Fermata** — скачать с productdev.me +- **v2rayTun** — App Store +- **Ledger Wallet** — скачать с ledger.com +- **PureRef** — нет для aarch64-darwin (только Intel Mac), скачать вручную + +### App Store apps (Apple ID помнит) +- Affinity, Figma, Aseprite (если через Steam) +- Pages, Numbers, Keynote (Creator Studio) +- Hollow Knight Silksong (на внешнем SSD) +- и т.д. + +## игры + +- **Prism Launcher** (nix) — Minecraft launcher +- **Hollow Knight Silksong** — на внешнем SSD, **бэкапить файлы** +- **Terraria, Slay the Spire 2** — Steam (в `~/Applications/`) + +## brew cleanup ⚠️ + +- `homebrew.onActivation.cleanup = "none"` (безопасный) +- **`"zap"` удалит всё что не в nix config** — опасно +- перед включением `zap` — проверить что все нужные приложения добавлены + +## tasks + +- [ ] **uncomment aseprite** после первой полной сборки +- [ ] установить Organic Maps, Fermata, v2rayTun, Ledger Wallet вручную +- [ ] бэкап Hollow Knight Silksong файлов +- [ ] добавить Terraria, Slay the Spire 2 (если нужно) +- [ ] audit остальных App Store apps +- [ ] вернуть `cleanup = "zap"` после полной инвентаризации diff --git a/docs/muscari.md b/docs/muscari.md index fd0215b..fde638b 100644 --- a/docs/muscari.md +++ b/docs/muscari.md @@ -37,3 +37,8 @@ fetched from `https://git.iscg.dev/mikl.keys` with sha256 pinning. - [ ] k8s aliases (k, kx, kl, kd, etc) - [ ] add nix-specific aliases (switch, update, cleanup with sudo) +- [ ] Anki sync server — self-hosted (https://docs.ankiweb.net/sync-server.html) + - альтернатива AnkiWeb (без лимита 100MB) + - docker-compose с `ankicommunity/anki-sync-server` + - на muscari (k3s) или отдельный контейнер + - клиент: Settings → Sync → Custom server sync URL diff --git a/docs/poppy.md b/docs/poppy.md index bf3ca82..5d4be2d 100644 --- a/docs/poppy.md +++ b/docs/poppy.md @@ -27,8 +27,3 @@ darwin-rebuild switch --flake .#poppy | `switch` | `darwin-rebuild switch --flake .#poppy` | | `update` | `nix flake update && darwin-rebuild switch --flake .#poppy` | | `cleanup` | `nix-collect-garbage -d` | - -## TODO - -- [ ] telegram mcp aliases (tg-login, tg-reset) -- [ ] apple music tools (gamdl) diff --git a/flake.nix b/flake.nix index e11eb5f..91987eb 100644 --- a/flake.nix +++ b/flake.nix @@ -42,7 +42,7 @@ useGlobalPkgs = true; useUserPackages = true; backupFileExtension = "backup"; - users.michaotic = import ./home; + users.mikl = import ./home; }; } ]; @@ -59,7 +59,7 @@ useGlobalPkgs = true; useUserPackages = true; backupFileExtension = "backup"; - users.michaotic = import ./home; + users.mikl = import ./home; }; } ]; diff --git a/garden.md b/garden.md index fe3c455..b0d72a9 100644 --- a/garden.md +++ b/garden.md @@ -91,3 +91,16 @@ currently `flake.nix` has `rosemary` commented out. need to: - сначала создать репы на всех 3 хостах - потом настроить через `pass git remote add` - алиасы в zsh для каждого origin + +### FIDO2 / Ledger Security Key + +Ledger поддерживает FIDO2 через `app-security-key` (open source). SSH-ключ создан +на токене (ed25519-sk), работает локально (sign/verify). Задачи — см. `docs/ssh.md`. + +### sops-nix для секретов + +`flake.nix` уже содержит `sops-nix` в inputs. Нужно: +- создать age ключ (`age-keygen -o ~/.config/sops/age/keys.txt`) +- настроить `secrets/secrets.yaml` с SOPS config +- сконфигурировать `SOPS_AGE_KEY_FILE` (уже в `home/sessionVariables`) +- переместить `OPENROUTER_API_KEY` из plain text в encrypted diff --git a/home/cli.nix b/home/cli.nix index e69de29..046b318 100644 --- a/home/cli.nix +++ b/home/cli.nix @@ -0,0 +1,84 @@ +{ pkgs, ... }: +{ + # Universal CLI tools for all hosts + home.packages = with pkgs; [ + # File navigation & viewing + eza + bat + ripgrep + fd + fzf + tree + wget # download files and recursive sites + + # System info + htop + tldr + fastfetch + tree + + # Editor + micro + + # Node + pnpm # fast node package manager + + # Secrets + (pass.withExtensions (ext: [ ext.pass-otp ])) + gpgme + gnupg + + # Extras + ollama # CLI для LLM + delta # красивый git diff (synonym: git-delta) + alejandra # nix-форматтер + broot # tree с превью + trash-cli # rm с корзиной + texliveFull # LaTeX (~4GB, для математики) + gita # manage multiple git repos + ]; + + # TODO: global npm/pnpm packages not managed by nix for now + # install manually: pnpm i -g @mariozechner/pi-coding-agent + + # GPG agent is configured in home/pass.nix (only for pass) + + # FZF fuzzy finder + programs.fzf = { + enable = true; + enableZshIntegration = true; + defaultCommand = "fd --type f --hidden --exclude .git"; + defaultOptions = [ + "--height 40%" + "--layout=reverse" + "--border" + ]; + }; + + # Zoxide - smarter cd + programs.zoxide = { + enable = true; + enableZshIntegration = true; + options = [ "--cmd cd" ]; + }; + + # Bat - cat with syntax highlighting + programs.bat = { + enable = true; + config = { + theme = "Catppuccin Macchiato"; + italic-text = "always"; + style = "numbers,changes,header"; + }; + }; + + # Eza - modern ls replacement + programs.eza = { + enable = true; + icons = "auto"; + git = true; + }; + + # Fastfetch - system info (using package only, no home-manager module) + # Config is in ~/.config/fastfetch/config.jsonc manually for now +} diff --git a/home/default.nix b/home/default.nix index 33915ee..cf0d005 100644 --- a/home/default.nix +++ b/home/default.nix @@ -1,19 +1,20 @@ -{ pkgs, ... }: +{ pkgs, lib, ... }: { imports = [ ./cli.nix ./git.nix ./ssh.nix ./zsh.nix - ./duti.nix ./pass.nix + ./syncthing.nix + # ./duti.nix - импортируется только в hosts/poppy/default.nix (macOS only) ]; home.stateVersion = "24.11"; home.sessionVariables = { SEARXNG_URL = "https://search.iscg.dev"; - PATH = "/etc/profiles/per-user/michaotic/bin:$HOME/.nix-profile/bin:$HOME/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/Users/michaotic/.opencode/bin:/Users/michaotic/.local/share/pi-node/node-v22.23.1-darwin-arm64/bin"; + PATH = "/etc/profiles/per-user/mikl/bin:$HOME/.nix-profile/bin:$HOME/bin:$HOME/.local/bin:$HOME/.npm-global/bin:/Users/mikl/.opencode/bin:/Users/mikl/.local/share/pi-node/node-v22.23.1-darwin-arm64/bin"; # OPENROUTER_API_KEY = ""; # TODO: move to sops-nix secrets SOPS_AGE_KEY_FILE = "$HOME/.config/sops/age/keys.txt"; EDITOR = "micro"; diff --git a/home/syncthing.nix b/home/syncthing.nix new file mode 100644 index 0000000..6e23142 --- /dev/null +++ b/home/syncthing.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: +{ + # Syncthing - p2p file sync + # Config stored in ~/Library/Application Support/Syncthing/ (default) + # Currently syncs: music, traces + # Devices: poppy (this mac) + remote (UCWTYQI-...) + home.packages = [ pkgs.syncthing ]; + + # Autostart via launchd + # -no-browser: don't open GUI on startup + # KeepAlive: restart if crashes + # RunAtLoad: start at login + launchd.agents.syncthing = { + enable = true; + config = { + ProgramArguments = [ + "${pkgs.syncthing}/bin/syncthing" + "serve" + ]; + RunAtLoad = true; + KeepAlive = true; + ProcessType = "Background"; + }; + }; +} diff --git a/home/zsh.nix b/home/zsh.nix index 9f00444..2a5db39 100644 --- a/home/zsh.nix +++ b/home/zsh.nix @@ -75,7 +75,7 @@ # Init content - uses lib.mkBefore to run before home-manager generated code initContent = lib.mkMerge [ (lib.mkBefore '' - export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin:$HOME/.nix-profile/bin:/etc/profiles/per-user/michaotic/bin:$PATH" + export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin:$HOME/.nix-profile/bin:/etc/profiles/per-user/mikl/bin:$PATH" '') '' # Show fastfetch on shell start diff --git a/hosts/common/default.nix b/hosts/common/default.nix index 2e570d2..0e9b6c6 100644 --- a/hosts/common/default.nix +++ b/hosts/common/default.nix @@ -9,10 +9,10 @@ # Required when using zsh as user shell programs.zsh.enable = true; - users.users.michaotic = { + users.users.mikl = { isNormalUser = true; shell = pkgs.zsh; - home = "/home/michaotic"; + home = "/home/mikl"; }; environment.systemPackages = [ diff --git a/hosts/muscari/default.nix b/hosts/muscari/default.nix index 56cb3b0..342905b 100644 --- a/hosts/muscari/default.nix +++ b/hosts/muscari/default.nix @@ -31,9 +31,9 @@ boot.loader.systemd-boot.enable = lib.mkForce false; boot.loader.efi.canTouchEfiVariables = lib.mkForce false; - # SSH ключи для michaotic: forgejo .keys endpoint с sha256-pinning + # SSH ключи для mikl: forgejo .keys endpoint с sha256-pinning # + hardcoded fallback ключ для восстановления - users.users.michaotic.openssh.authorizedKeys.keyFiles = [ + users.users.mikl.openssh.authorizedKeys.keyFiles = [ (pkgs.fetchurl { url = "https://git.iscg.dev/mikl.keys"; sha256 = "sha256-4n6QLUPozdhHOmsRCuFn7HR9BU3nF0/GR2E7s5Lpz+Q="; diff --git a/hosts/poppy/apps.nix b/hosts/poppy/apps.nix new file mode 100644 index 0000000..02898ff --- /dev/null +++ b/hosts/poppy/apps.nix @@ -0,0 +1,47 @@ +{ pkgs, ... }: +{ + # All poppy apps (brew casks + nix GUI packages) + # импортируется только в hosts/poppy/default.nix + + # Brew casks (приложения которых нет в nixpkgs) + homebrew = { + enable = true; + onActivation.cleanup = "none"; # "none" для безопасности, "zap" после полного аудита + taps = []; + + brews = [ + "kew" + ]; + + casks = [ + "google-chrome" + "google-drive" + "marta" + "vscodium" + "github" + "docker-desktop" + "ollama-app" + "obsidian" + "anki" + "calibre" + "telegram" + "maccy" + "mos" + "caffeine" + "lunacy" + "skim" + "mark-text" + "amneziavpn" + "element" + "prismlauncher" + ]; + }; + + # Nix GUI пакеты (нет в brew) + # pureref — только x86_64-darwin, не работает на M1 + # aseprite — в nixpkgs, но компилируется с нуля (10-30 мин на M1) + # раскомментировать после первой полной сборки (см. docs/apps.md) + environment.systemPackages = with pkgs; [ + # aseprite # пиксельный редактор (uncomment after first build) + ]; +} diff --git a/hosts/poppy/default.nix b/hosts/poppy/default.nix index f601478..2d03646 100644 --- a/hosts/poppy/default.nix +++ b/hosts/poppy/default.nix @@ -1,15 +1,15 @@ { pkgs, ... }: { - imports = [ ./homebrew.nix ./system.nix ]; + imports = [ ./apps.nix ./system.nix ]; networking.hostName = "poppy"; - system.primaryUser = "michaotic"; + system.primaryUser = "mikl"; system.stateVersion = 7; nixpkgs.config.allowUnfree = true; nix.enable = false; - users.users.michaotic = { - home = "/Users/michaotic"; + users.users.mikl = { + home = "/Users/mikl"; shell = pkgs.zsh; }; @@ -17,13 +17,13 @@ # Apply default apps via duti on activation system.activationScripts.defaultApps.text = '' - if [ -f "/Users/michaotic/.config/duti/config" ]; then - ${pkgs.duti}/bin/duti -d /Users/michaotic/.config/duti/config || true + if [ -f "/Users/mikl/.config/duti/config" ]; then + ${pkgs.duti}/bin/duti -d /Users/mikl/.config/duti/config || true fi ''; - home-manager.users.michaotic = { - imports = [ ../../home/kitty.nix ]; + home-manager.users.mikl = { + imports = [ ../../home/kitty.nix ../../home/duti.nix ]; programs.zsh.shellAliases = { switch = "darwin-rebuild switch --flake .#poppy"; update = "nix flake update && darwin-rebuild switch --flake .#poppy"; diff --git a/hosts/poppy/homebrew.nix b/hosts/poppy/homebrew.nix deleted file mode 100644 index 74b7b94..0000000 --- a/hosts/poppy/homebrew.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ - homebrew.enable = true; - homebrew.onActivation.cleanup = "zap"; - - homebrew.taps = []; - - homebrew.brews = [ - "kew" - ]; - - homebrew.casks = [ - "google-chrome" - "google-drive" - "marta" - "vscodium" - "github" - "docker-desktop" - "ollama-app" - "microsoft-word" - "microsoft-excel" - "microsoft-powerpoint" - "obsidian" - "anki" - "calibre" - "telegram" - "maccy" - "mos" - "caffeine" - "lunacy" - "skim" - "markedit" - ]; -} diff --git a/hosts/poppy/system.nix b/hosts/poppy/system.nix index 5962723..6fbbaa7 100644 --- a/hosts/poppy/system.nix +++ b/hosts/poppy/system.nix @@ -132,7 +132,7 @@ "/System/Applications/Calendar.app" "/Applications/Obsidian.app" "/Applications/VSCodium.app" - "/Users/michaotic/Applications/Home Manager Apps/kitty.app" + "/Users/mikl/Applications/Home Manager Apps/kitty.app" "/System/Applications/Books.app" "/System/Applications/QuickTime Player.app" ]; @@ -141,7 +141,7 @@ system.activationScripts.postActivation.text = '' echo "Restarting Dock..." - sudo -u michaotic /usr/bin/killall Dock + sudo -u mikl /usr/bin/killall Dock ''; security.pam.services.sudo_local.touchIdAuth = true; diff --git a/temp.txt b/temp.txt deleted file mode 100644 index 329face..0000000 --- a/temp.txt +++ /dev/null @@ -1 +0,0 @@ -testing this thing