Compare commits

..

11 commits

17 changed files with 411 additions and 59 deletions

135
AGENTS.md Normal file
View file

@ -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/<name>/{default,system}.nix`
2. добавить в `flake.nix` `mkNixos` или `mkDarwin`
3. создать `docs/<name>.md` с описанием
4. обновить `garden.md`
## контекст для пользователя
- студент, hse university
- интересы: LLM/AI, it infra, self-hosted, литература
- ADHD, прокрастинация — **не отвлекай** на ненужные темы
- общается на русском и английском
- использует Telegram MCP, Forgejo MCP, SearXNG
- конфиг для macOS, учится nix
- не спеши, показывай план, спрашивай подтверждения

81
docs/apps.md Normal file
View file

@ -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"` после полной инвентаризации

View file

@ -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

View file

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

View file

@ -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;
};
}
];

View file

@ -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

View file

@ -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
}

View file

@ -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";

25
home/syncthing.nix Normal file
View file

@ -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";
};
};
}

View file

@ -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

View file

@ -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 = [

View file

@ -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=";

47
hosts/poppy/apps.nix Normal file
View file

@ -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)
];
}

View file

@ -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";

View file

@ -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"
];
}

View file

@ -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;

View file

@ -1 +0,0 @@
testing this thing