From 9e44cb4c99431db313da4c2be3283437748b95b2 Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 16 Oct 2026 21:43:45 +0300 Subject: [PATCH] feat(ThinkPad): Added sops and 1-st key Also have an instruktion for sops --- .sops.yaml | 7 ++ host/ThinkPad/configuration.nix | 1 + host/ThinkPad/secrets/secrets.nix | 14 +++ host/ThinkPad/secrets/wallhaven.pem | 14 +++ secret.md | 170 ++++++++++++++++++++++++++++ 5 files changed, 206 insertions(+) create mode 100644 .sops.yaml create mode 100644 host/ThinkPad/secrets/secrets.nix create mode 100644 host/ThinkPad/secrets/wallhaven.pem create mode 100644 secret.md diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..c993f72 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,7 @@ +keys: + - &kirill age1tx6jdr6535xxeygpwkkgvdwc24tulr420cm7gk56xzfp0slzeqks2nwpyg +creation_rules: + - path_regex: host/[^/]+/secrets/.+$ + key_groups: + - age: + - *kirill diff --git a/host/ThinkPad/configuration.nix b/host/ThinkPad/configuration.nix index 54c697e..5af7b24 100644 --- a/host/ThinkPad/configuration.nix +++ b/host/ThinkPad/configuration.nix @@ -11,6 +11,7 @@ ./modules/grab.nix ./modules/thinkpad.nix ./modules/fingerprint.nix + ./secrets/secrets.nix (import ../modules/common.nix { inherit lib; diff --git a/host/ThinkPad/secrets/secrets.nix b/host/ThinkPad/secrets/secrets.nix new file mode 100644 index 0000000..b1d5ecc --- /dev/null +++ b/host/ThinkPad/secrets/secrets.nix @@ -0,0 +1,14 @@ +{ + sops = { + age.keyFile = "/root/age.key"; + + secrets = { + wallhaven = { + format = "binary"; + sopsFile = ./wallhaven.pem; + owner = "kirill"; + mode = "0400"; + }; + }; + }; +} diff --git a/host/ThinkPad/secrets/wallhaven.pem b/host/ThinkPad/secrets/wallhaven.pem new file mode 100644 index 0000000..8a33be6 --- /dev/null +++ b/host/ThinkPad/secrets/wallhaven.pem @@ -0,0 +1,14 @@ +{ + "data": "ENC[AES256_GCM,data:0Dw6uMFnVNZKg2ANaHRcMicOPQ7U+mi5V6dia47GDUMM,iv:ScI+ESgBXXcu5hlDkP6m50FL8lp7S3E2cLbf1M9ZAbQ=,tag:VBwdRDyWV3unNUhSVguu2g==,type:str]", + "sops": { + "age": [ + { + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3bWFwMUlwMmxJenZib2Qy\nRk5TMkVtQS9kLzgyWlFNbFVFbzJmUVNXZFRBCkVKQldtcTd5ZElzcVpienhDM3dh\nTmFQZTN0KytZVnZQMmNZNGFQSUlIbXMKLS0tIERBVmhGMmgwZmNwTHB6eEZ0bFJX\nWFN2cVE0WmFna2V5UWE2NXJ6OU9YM2cKWitmQY994raC3Kz/QYXVmiONTomW/JYB\n0PADqEp32xsw/gFnTwi7zbfFPD63ME2PYJ4I9wNKcgR/cFoW2Sv8Jg==\n-----END AGE ENCRYPTED FILE-----\n", + "recipient": "age1tx6jdr6535xxeygpwkkgvdwc24tulr420cm7gk56xzfp0slzeqks2nwpyg" + } + ], + "lastmodified": "2026-10-16T17:19:39Z", + "mac": "ENC[AES256_GCM,data:+CSe7gGwiSANibzDJ4DVTq1OXykiR1vv49szqlxCZyAeKqnxbEjaNFCdslxPAa8SGttDqDxM9aO59DSO3AKxzR9J4kfKqZ7eA8/cNC0DKltzS4AkLkPcGjFpctdUiYENXaPrtk1tV8e/GeW1//f3R61hzAEama8jjkoeAYaDZIM=,iv:aD4c8y2a8whXyG0ig05bryZPfh/NrETeth+O5D4/bPE=,tag:r1EbYa0lsr/u2Rw6ZFjYsQ==,type:str]", + "version": "3.13.3" + } +} diff --git a/secret.md b/secret.md new file mode 100644 index 0000000..a3b6987 --- /dev/null +++ b/secret.md @@ -0,0 +1,170 @@ +# Секреты (sops-nix) + +Кратко: как всё устроено, как добавить новый секрет и как поднять рабочий sops на новом устройстве. + +## Как устроено + +- `.sops.yaml` в корне репозитория — список age-реципиентов и правила выбора ключа по пути файла. +- Зашифрованные секреты хоста: `host//secrets/<файл>`. +- Метаданные секретов: `host//secrets/secrets.nix`, подключается из `host//configuration.nix` через `imports`. +- При активации sops-nix расшифровывает секреты в `/run/secrets/<имя>` (runtime, в `/nix/store` ничего не попадает). +- age-ключ выводится из существующего SSH-ключа. + +Текущее правило в `.sops.yaml`: + +```yaml +creation_rules: + - path_regex: host/[^/]+/secrets/.+$ +``` + +То есть правило выбирается по пути файла: всё, что лежит в `host//secrets/`, шифруется на перечисленных реципиентов. + +## Добавить новый секрет + +1. Придумай имя, дальше для примера — `mysecret`. + +2. Положи открытое значение во временный файл **внутри** `host//secrets/` (путь важен — см. `path_regex`): + + ```bash + printf '%s' 'СЕКРЕТНОЕ_ЗНАЧЕНИЕ' > host/ThinkPad/secrets/mysecret.plain + ``` + +3. Зашифруй (приватный ключ не нужен — sops берёт публичного реципиента из `.sops.yaml`): + + ```bash + nix-shell -p sops --run \ + "sops --input-type binary --output-type binary \ + --encrypt host/ThinkPad/secrets/mysecret.plain \ + --output host/ThinkPad/secrets/mysecret.enc" + rm host/ThinkPad/secrets/mysecret.plain + ``` + + `--input-type`/`--output-type` обязательны для бинарных данных, иначе sops пытается определить тип по расширению. + +4. Опиши секрет в `host//secrets/secrets.nix`: + + ```nix + { + sops = { + age.keyFile = "/root/age.key"; + + secrets = { + mysecret = { + format = "binary"; # yaml | json | binary | dotenv | ini + sopsFile = ./mysecret.enc; + owner = "kirill"; # владелец расшифрованного файла + mode = "0400"; + }; + }; + }; + } + ``` + + `format = "binary"` — для произвольных байтов (`.pem`, токены). Для структурированных данных используй `yaml`/`json`. + `owner`/`mode` нужны, если секрет читает пользовательский процесс (а не root-сервис). + +5. `git add` — **Nix видит только файлы, добавленные в git** — и ребилд: + + ```bash + git add host/ThinkPad/secrets/ + sudo nixos-rebuild switch --flake .#ThinkPad + ``` + +6. Проверка: + + ```bash + sudo ls -l /run/secrets/mysecret + ``` + +## Изменить или посмотреть существующий секрет + +Используется приватный ключ (`/root/age.key`), поэтому нужен root: + +```bash +sudo SOPS_AGE_KEY_FILE=/root/age.key nix-shell -p sops --run \ + "sops host/ThinkPad/secrets/wallhaven.pem" +``` + +`sops` сам не ищет `/root/age.key`, путь передаётся через `SOPS_AGE_KEY_FILE`. + +## Новое устройство + +1. Убедись, что на устройстве есть приватный SSH-ключ, из которого выводится age-ключ. Ключ должен быть **без пароля** — иначе расшифровка при активации будет требовать ввода. + +2. Создай age-ключ: + + ```bash + sudo nix-shell -p ssh-to-age --run \ + "ssh-to-age -private-key -i /home/kirill/.ssh/<ваш_ключ> -o /root/age.key" + sudo chmod 600 /root/age.key + ``` + +3. Проверь, что публичный age-реципиент устройства совпадает с тем, что в `.sops.yaml`: + + ```bash + nix-shell -p ssh-to-age --run \ + "ssh-to-age -i /home/kirill/.ssh/<ваш_ключ>.pub" + ``` + + Должно вывести: + + ``` + age1tx6jdr6535xxeygpwkkgvdwc24tulr420cm7gk56xzfp0slzeqks2nwpyg + ``` + + Если вывод другой — добавь новый реципиент (см. следующий раздел). + +4. Создай структуру секретов хоста: + + ``` + host//secrets/secrets.nix + host//secrets/<файлы секретов> + ``` + + Минимальный `secrets.nix`: + + ```nix + { + sops.age.keyFile = "/root/age.key"; + secrets = { + # ... + }; + } + ``` + + И добавь `./secrets/secrets.nix` в `imports` в `host//configuration.nix`. + +5. `git add` + ребилд: + + ```bash + git add host//secrets/ + sudo nixos-rebuild switch --flake .# + ``` + +## Добавить устройство к существующим секретам + +1. Получи age-реципиент устройства (шаг 3 выше). + +2. Добавь его в `.sops.yaml`: + + ```yaml + keys: + - &kirill age1tx6jdr6535xxeygpwkkgvdwc24tulr420cm7gk56xzfp0slzeqks2nwpyg + - &newdevice age1...новый_реципиент... # замени на реальный + + creation_rules: + - path_regex: host/[^/]+/secrets/.+$ + key_groups: + - age: + - *kirill + - *newdevice + ``` + +3. Перешифруй существующие секреты под новый список реципиентов (нужен приватный ключ, значит root): + + ```bash + sudo SOPS_AGE_KEY_FILE=/root/age.key nix-shell -p sops --run \ + "sops updatekeys host/ThinkPad/secrets/wallhaven.pem" + ``` + +4. `git add` + ребилд на этом устройстве.