UNRUIN
документация · v1.0

Авария

Восстановление без Unruin

Как вернуть данные, когда потерян сам оркестратор.

Июльская чистка 2026 года поменяла устройство секретов и хранилищ; причины и порядок переезда — в SIMPLIFICATION.md.

Самый быстрый путь — встроенные помощники

Для обычного восстановления, когда Unruin жив, ничего из написанного ниже писать руками не надо. У каждого задания есть готовый лист восстановления:

  • Из командной строки: unruin restore-guide <config.yaml> <job> печатает команды для копирования, где уже подставлены адрес хранилища, метка точек восстановления этого задания и шаги, специфичные для типа источника — строка rsync … /var/lib/docker/volumes/<том>/_data/ для docker-тома или psql <база> < /restore/stdin для потока из Postgres.
  • Сделай за меня, на стороне сервера: unruin restore <config.yaml> <job> [snapshot] [--dest name] [--to dir] раскладывает точку восстановления в папку на сервере (внутри <состояние>/restores или UNRUIN_RESTORE_DIR) и печатает путь. Открытый текст никуда не скачивается.
  • Из панели: открыть задание → вкладка Восстановление → выбрать точку → «Развернуть на сервере», либо скопировать тот же лист команд. Восстановление из браузера всегда пишет только по пути на сервере — расшифрованные данные в браузер не скачиваются, — и закрыто ключом API или loopback, как любое другое действие, что-то меняющее.

Дальше — лист восстановления без Unruin: как достать данные, имея только git, один офлайновый секрет и restic.


Весь смысл Unruin в том, что для возврата ваших данных Unruin не нужен. Этот лист разворачивает любую копию, включая самые важные данные, при помощи только:

  1. jobs.yaml из репозитория с конфигурацией — там названы хранилища и бэкенды, но нет ни одного секрета;
  2. секрета аварийного конверта — ключа хранилища аварийной копии, который лежит офлайн: в вашем менеджере паролей, распечатанным, ключом age в сейфе. Это единственный секрет, которого НЕТ во встроенном хранилище kr://;
  3. бинарника restic.

Ни работающего оркестратора, ни UNRUIN_MASTER_PASSPHRASE, ни хранилища kr://.

Порядок раскрутки важен

Обычные ключи хранилищ и доступы к бэкендам лежат в kr://, зашифрованные мастер-фразой. Ключ аварийного задания — нет: это ссылка env://, подаваемая снаружи Unruin, и именно она разрывает круговую зависимость. Поэтому восстановление идёт так:

секрет аварийного конверта (офлайн)
   └─> развернуть точку с важными данными из аварийного хранилища   [restic, ключ из пункта 2]
        └─> поднять обратно эту службу или эти данные
             └─> оттуда достать хранилище kr:// (или ввести секреты заново); все остальные
                 ключи хранилищ и доступы снова доступны
                  └─> разворачивать что угодно ещё — Unruin или restic напрямую

Аварийное хранилище намеренно разворачивается без kr:// и без мастер-фразы: оно зависит только от трёх вещей из списка наверху. Все остальные хранилища зависят от kr://, поэтому его тоже надо сохранять — см. последний раздел.

Шаг 1 — развернуть аварийное хранилище (оркестратор не нужен)

Найдите в jobs.yaml аварийное задание — то, у которого repo_password это ссылка env://, например critical-breakglass. Посмотрите, какой бэкенд у его хранилища.

Задайте адрес хранилища и офлайновый ключ, затем разворачивайте:

sh
# Пример: аварийное хранилище — SFTP на другой площадке или S3 из jobs.yaml.
export RESTIC_REPOSITORY="sftp:bk@offsite.example.com:/backups/critical"
export RESTIC_PASSWORD="<тот самый офлайновый ключ>"

# Для аварийного хранилища в S3/MinIO подставьте и доступы, которые вы держали офлайн:
# export AWS_ACCESS_KEY_ID=...  AWS_SECRET_ACCESS_KEY=...

restic snapshots                       # убедиться, что хранилище читается
restic restore latest --target /restore/critical

Поднимите восстановленную службу, указав ей на /restore/critical — её каталог данных и вложения. Если аварийное задание — это, скажем, обычная копия файлов какого-нибудь менеджера паролей, то здесь вы поднимаете его обратно и входите своим мастер-паролем. Но это просто приложение, которое вы копируете, а не часть Unruin.

Шаг 2 — всё остальное

Когда важные данные вернулись, восстановите хранилище kr://: положите secrets.kr обратно в UNRUIN_STATE_DIR (из точки восстановления шага 1 или из своей офлайновой копии) и задайте UNRUIN_MASTER_PASSPHRASE. Дальше быстрее всего поднять оркестратор и дать unruin разворачивать обычным способом: он сам разрешает все ключи хранилищ и доступы, и вы не держите в руках ни одного значения.

Если разворачивать хранилище руками всё-таки приходится (оркестратор ещё не поднят), помните: kr:// по устройству работает только на запись, команды, которая напечатала бы сохранённый секрет, не существует. Значит, для полностью ручного восстановления нужны ключ хранилища и доступы из ваших собственных записей — те же значения, которые вы когда-то сохраняли. Хранилище, ключ которого у вас точно есть офлайн, — аварийное (это тот самый секрет env:// из шага 1):

sh
# Ручное восстановление аварийного хранилища — его ключ env:// у вас уже есть.
export RESTIC_REPOSITORY="sftp:bk@offsite.example.com:/backups/breakglass"
export RESTIC_PASSWORD="$BREAKGLASS_RESTIC_PW"          # офлайновый секрет env://
restic snapshots --tag job:critical-data-breakglass
restic restore latest --tag job:critical-data-breakglass --target /restore/critical
# Для дампа базы (источник-поток) в точке восстановления один файл — сам дамп:
#   psql app < /restore/app-db/dump      # или: mysql shop < /restore/app-db/dump

Для остальных хранилищ, чьи ключи есть только в kr://, поднимайте unruin — это и есть задуманный, не ручной путь.

Каждое хранилище — это хранилище restic

Любое хранилище Unruin — репозиторий restic; зеркал мимо restic, для которых нужен был бы отдельный случай, не существует. Вторая копия на другой площадке — это ещё одно хранилище restic, которое Unruin наполняет через restic copy: зашифровано, дедуплицировано, разворачивается напрямую. Чтобы развернуть из второго, когда первого больше нет, направьте restic прямо на бэкенд этого хранилища: копия, сделанная restic copy, разделяет с основным ключ и параметры нарезки, поэтому один и тот же ключ читает обе. Подавайте его так же, как выше — через unruin или из своих офлайновых записей.

Проверьте этот лист (не пропускайте)

План восстановления, который вы ни разу не прогоняли, — это догадка. Хотя бы один раз:

  1. Разверните аварийную точку восстановления на пустой машине, пользуясь ТОЛЬКО офлайновым секретом, restic и этим файлом. Убедитесь, что открывается.
  2. Разверните одну настоящую точку с базой и залейте её в одноразовую базу.

Если хоть на одном шаге понадобилось что-то, чего нет в трёх пунктах наверху, план восстановления сломан — чините до того, как он понадобится.

Как хранить секрет аварийного конверта

  • Держите его СНАРУЖИ хранилища kr://: в менеджере паролей, которым распоряжаетесь вы, распечатанным в сейфе или в файле под age, ключ от которого офлайн. Он остаётся ссылкой env:// именно затем, чтобы никогда не зависеть ни от kr://, ни от мастер-фразы.
  • Сменить его — значит перевыпустить ключ аварийного хранилища restic (restic key add / key remove) и обновить офлайновую копию.
  • Аварийное хранилище стоит сделать доступным только на дозапись и со стороны копирования тоже: взломанный оркестратор не должен уметь стереть ваш последний рубеж.

Как сохранить возможность восстановить kr://

Хранилище kr:// — один зашифрованный файл secrets.kr в каталоге состояния (UNRUIN_STATE_DIR), зашифрованный мастер-фразой. В нём лежат все ключи хранилищ и доступы, кроме аварийного. Чтобы развернуть эти хранилища после потери Unruin, нужен либо этот файл вместе с фразой, либо ручной ввод каждого секрета заново.

  • Сохраняйте secrets.kr офлайн и впишите UNRUIN_MASTER_PASSPHRASE в свой лист восстановления: потерять оба — значит вводить заново каждый секрет kr://.
  • Аварийное хранилище намеренно обходит эту зависимость, держа свой ключ в env://, — чтобы последнему рубежу для открытия никогда не требовалось хранилище kr://.

Бесплатно, целиком ваше, наружу ничего не уходит. Сайт статический: ни аналитики, ни куки, ни внешних запросов.