Как я перешёл на NixOS и настроил там OpenClaw

от автора

Переход на NixOS

Полгода я сидел на Арче, и в конце июня одно обновление остановило моё сердце на вечер. Что вообще случилось? Сидел я, значит, вечером, решил апдейтнуть систему, и после обновления перестала подниматься Амнезия. Это произошло из-за того, что обновилось ядро, несовместимое с версией amneziawg.

Решил поставить чистый WireGuard, но не смог его нормально настроить, вследствие чего сломал инет. Пришлось откатиться. У меня был настроенный snapper, но уже не помню, по какой причине не получилось откатиться. Решил восстановиться с бэкапа (на флешке у меня были zstd-архивы корня и хомяка). Получилось распаковать только корень. У хомяка повредилась структура при записи на флешку, поэтому через утилиту распаковать не удалось. Забросил.

Начал думать, какой выбрать надёжный дистрибутив. Хотел Федору, но не захотел с Арча переходить на что-то простое. Стал выбирать из сложных… т.к. я девопс (сторонник декларативного подхода), мне приглянулся Никс. Запал тот факт, что можно управлять системой одним конфигом. Поставил. Решил разобраться с тем хомяком. Вытащил оттуда ~9,5 ГБ, но все конфиги Hyprland были написаны только наполовину (вторая половина содержимого стёрлась). Удалил хомяка, чтобы не занимал место. Конфиги Hyprland решил написать сам, не брать с инета.

В общем, получилось по красоте настроить весь визуал:

Амнезию настроил с первого раза за несколько минут. На Арче я настраивал Амнезию далеко не с первого раза + у меня ещё тогда не было опыта. В Никсе это просто строчек 10-15 в один конфиг и всё:

  systemd.services.amneziawg = {    description = "AmneziaWG VPN Tunnel";    after = ["network.target"];    wantedBy = ["multi-user.target"];    path = with pkgs; [amneziawg-tools amneziawg-go iproute2 bash iptables];    environment = {      WG_QUICK_USERSPACE_IMPLEMENTATION = "amneziawg-go";    };    serviceConfig = {      Type = "oneshot";      RemainAfterExit = "yes";      ExecStart = "${pkgs.amneziawg-tools}/bin/awg-quick up awg0";      ExecStop = "${pkgs.amneziawg-tools}/bin/awg-quick down awg0";    };  };

Настройка OpenClaw

Сначала решил попробовать локально через ollama. У меня Ryzen 5 1400, RX560 (4 ГБ) и ОЗУ (16 ГБ). Начал с лёгкой модели llama3.2:1b — отвечает почти без задержки, но несёт всякую чушь (просто поздоровался с ней на русском языке, а она мне прислала какой-то огромный китайский текст), потом протестировал qwen2.5:7b — но там уже комп просто завис. Так что от локального решения пришлось отказаться.

Начал искать бесплатную апишку. Нашёл через одного ютубера и вышел на сайт Z.ai. Там увидел две бесплатные модельки: GLM-4.7-Flash и вроде GLM-4.5-Flash. Выбрал которую посовременнее. Контекста 200к токенов, для коротких диалогов вполне достаточно. Минус только в очереди, в пиковые часы иногда приходится ждать ответа минут 10-15.

На Арче настроить OpenClaw было проще простого. У меня тогда это занимало примерно полчаса, а здесь… подольше. Ну, на самом деле я на Никсе хотел сделать не просто рабочего ассистента, а модернизированного. Начал искать в инете, как можно улучшить OpenClaw. И нашел, что можно внедрить в него долгосрочную память, чем я и занялся.

На Никсе через nix-openclaw всё описывается одним конфигом:

{ openclaw-workspace, ... }: {  programs.openclaw = {    enable = true;    workspace.bootstrapFiles = {      agents = "${openclaw-workspace}/AGENTS.md";      soul = "${openclaw-workspace}/SOUL.md";      tools = "${openclaw-workspace}/TOOLS.md";      identity = "${openclaw-workspace}/IDENTITY.md";      user = "${openclaw-workspace}/USER.md";    };    environment = {      ZHIPU_API_KEY = "/run/agenix/openclaw-zhipu-key";      OPENCLAW_GATEWAY_TOKEN = "/run/agenix/openclaw-gateway-token";    };    config = {      gateway = { mode = "local"; };      tools.elevated = {        enabled = true;        allowFrom = { telegram = [5748618304]; };      };      channels.telegram = {        tokenFile = "/run/agenix/openclaw-telegram-token";        allowFrom = [5748618304];      };      models.providers.openai = {        baseUrl = "https://open.bigmodel.cn/api/paas/v4";        apiKey = { source = "env"; provider = "default"; id = "ZHIPU_API_KEY"; };        models = [{          name = "glm-4.7-flash";          id = "glm-4.7-flash";          api = "openai-completions";          contextWindow = 200000;        }];      };

А память и настройки самого агента отдельно:

      memory.backend = "qmd";      agents.defaults = {        model.primary = "openai/glm-4.7-flash";        thinkingDefault = "low";        compaction.reserveTokensFloor = 20000;      };    };  };}

На Арче это собиралось руками: ставил пакет, создавал конфиги, руками писал systemd-юнит для gateway, настраивал переменные окружения. Тут просто включил модуль и готово. Когда первый раз увидел конфиг модуля — не понял, куда смотреть. Оказалось, он состоит из трёх частей: overlay, home-manager module и systemd user service. Из полезных плагинов: summarize (сжимает историю) и peekaboo (показывает, что агент видит в браузере).

Самое первое, что я проверил после настройки — телеграм-бота. Гейтвей подключился к Bot API. Написал задачу, агент выполнил на сервере, прислал результат. Elevated tools — файловая система и команды.

Но перед тем, как телеграм-бот заработал, надо было решить, где хранить токен (не в гите же). Наткнулся на agenix. Теперь ключи у меня зашифрованы прямо в гите и никаких .env, которые можно было случайно запушить (проходил это на Арче). agenix шифрует age-ключом, расшифровывается только при сборке. Выглядит как список файлов, привязанных к системе:

"secrets/openclaw-telegram-token.age".publicKeys = [ system ];"secrets/openclaw-zhipu-key.age".publicKeys = [ system ];"secrets/openclaw-gateway-token.age".publicKeys = [ system ];"secrets/amneziawg-awg0.age".publicKeys = [ system ];

В users.nix для каждого прописывается owner, group, mode. На системе файлы лежат в /run/agenix/. Read-only, только владелец, подправить на лету нельзя — только пересобрать. Дальше я задумался: ассистент должен знать, кто он и что может. Для этого придумали bootstrap-файлы. Пять файлов в ~/.config/openclaw/, загружаются в контекст при старте gateway. Вот как это выглядит по файлам:

  • AGENTS.md (инструкции) — общайся со мной на русском языке, перемещайся по файлам и запускай команды. PolKit у меня настроен для управления питанием;

  • SOUL.md (характер) — неформальный и технический;

  • TOOLS.md (список доступного) — bash, read/write, glob/grep. Модель сама решает, что из этого применить;

  • IDENTITY.md (кто он) — персональный ассистент;

  • USER.md (мои данные) — имя, страна, город…

В итоге получилось настроить OpenClaw на Никсе лучше, чем на Арче. На Арче не хватало рук обновить конфиги. А тут всё в репозитории, сделал nixos-rebuild switch и готово. Теперь вся моя система крутится вокруг gateway. Режим local означает, что всё на локальной машине. Гейтвей запускается через systemd user service (сообщество советует, хоть и не хотел сначала, т.к. не люблю, когда в фоне запущено то, что тебе не нужно сейчас):

Память — qmd (маркдаун-файлы с метаданными: дата, модель, токены). При старте gateway подгружает историю, ну и контекст не теряется:

В общем, сравнивать Арч и Никс не совсем честно, т.к. на Арче я всё делал впервые, а на Никсе уже был опыт. Но факт есть факт. Амнезия убила вечер из-за ядра, тут 15 строк. OpenClaw настраивал полчаса руками, а тут programs.openclaw.enable.

Мой конфиг

ссылка на оригинал статьи https://habr.com/ru/articles/1076294/