Готовность к восстановлению
Libre WebUI предоставляет инвентаризацию только для чтения восстановления как первую защитную проверку копирования и восстановления. Она сообщает об известном состоянии и условиях, блокирующих снимок. Она не получает блокировку обслуживания и не копирует, шифрует, загружает, удаляет, исправляет или восстанавливает данные.
libre-webui recovery-check --json > recovery-inventory.json
Из исходников один раз выполните npm run build:backend и замените libre-webui recovery-check на npm run recovery:check --. Установки npx и Homebrew по умолчанию проверяют ~/.libre-webui; DATA_DIR и явные параметры путей переопределяют место.
Команда возвращает 0 без блокировок, 1 при полном отчёте с блокировками и 2 при неверных аргументах или сбое сбора. Используйте --data-dir PATH или --database PATH. Инвентаризация стандартного тома или --data-dir принимает только канонический DATA_DIR/data.sqlite и отклоняет жёсткие/символические ссылки и нерегулярные database/WAL/SHM. Явная --database может быть вне DATA_DIR, но база и сопутствующие файлы должны быть обычными и не символическими ссылками. Без --data-dir родитель базы считается корнем данных, чтобы вместе учесть ключ, bloby и плагины.
Среда также читает исторические плагины из детерминированного каталога plugins пакета бэкенда и, для относительного PLUGINS_DIR, старого пути относительно бэкенда. Активные старые пути инвентаризируются и блокируют снимок только тома при наличии пользовательских определений. Пакетное развёртывание может несколько раз передать --legacy-plugins-dir PATH для перемещённых каталогов совместимости.
Для приватного Compose запускайте проверку в контейнере, чтобы отчёт описывал его том, код и секреты:
docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data
Что проверяет инвентаризация
Версионированный JSON записывает:
- версии приложения, Node.js, ОС и архитектуры;
- размеры SQLite и WAL/SHM,
quick_check, внешние ключи, отпечаток схемы, версию пользователя, отсутствующие таблицы и проверку исходных файлов без следования ссылкам до приватного инспекционного снимка; - чтение, запись, число файлов и байт каталога;
- источник ключа и односторонний 16-символьный отпечаток;
- проверку постоянного
.encryption_keyбез ссылок и с одной жёсткой ссылкой; - наличие, количество, размер и включение в корень пользовательских плагинов, локальных зашифрованных blobов, медиа, голосов, текста документов, старых и платформенных векторов с ACL/фильтрами;
- ограниченную аутентификацию только для чтения каждого канонического локального blob-объекта и обёртки вектора, включая полные фрагменты/checksum и наличие ключа;
- ограниченную аутентификацию распознаваемых старых текстовых AES-GCM-обёрток в чатах, заметках, документах, настройках, секретах, галерее и e-mail, а также AAD-связанных имён голосов, записей и транскрипций;
- числа задач/запусков/предпросмотров Work и ожидаемые Docker-тома, PVC Kubernetes или хешированные пути хоста; том должен иметь управляемую метку и точный ID владельца;
- состояния старых заданий генерации медиа и постоянные задания по состоянию, попытки по исходу, потоки/события и последний глобальный курсор;
- ограниченную аутентификацию зашифрованных содержимого заданий/событий и синтаксис непрозрачных содержимого ссылок; и
- явные блокировки, предупреждения и данные вне каталога приложения.
Отчёт никогда не содержит ключей, секретов JWT/сеансов, учётных данных поставщиков, содержимого плагинов или пользователей и буквальных путей хост-областей. Выводятся только признаки наличия секретов и необратимый отпечаток ключа.
Монтирование только для чтения допустимо для проверки и даёт предупреждение, не блокировку. Готовность приложения требует записи; не запускайте Libre WebUI на read-only снимке инструмента копии.
Блокировки
Любая блокировка означает неудачную проверку. Типичные причины: отсутствующая или повреждённая база, неполная схема, отсутствующий/конфликтующий ключ, повреждённый или неаутентифицированный шифротекст, превышенные лимиты, нечитаемый каталог, связанный или нерегулярный SQLite, активные Work-запуски/предпросмотры, media или durable jobs, отсутствующая/неверно помеченная область Work, несовпадения голов или разрывы последовательностей событий, плагины вне каталога либо управляющая плоскость, неспособная проверить внешние области. Остановите активную работу и исправьте зависимости; не редактируйте отчёт для скрытия.
Зашифрованные payload аутентифицируются по идентичности job/event и как канонический ограниченный JSON. Непрозрачные references только ограничиваются и проверяются синтаксически: нет авторитетного репозитория blob-ссылок для доказательства цели. Отчёт ставит referenceTargetsVerified false и предупреждает, не раскрывая значения.
Старые текстовые поля появились до обязательного маркера, поэтому настоящий открытый текст старых схем остаётся читаемым и не считается аутентифицированным шифротекстом. Канонические обёртки всегда проверяются; трёхчастные значения с IV/tag размера обёртки при порче закрываются. Голосовые поля однозначно бинарны и обязаны аутентифицировать профиль, владельца и поле. encryption.legacyCiphertext сообщает суммы записей/байт без открытого текста.
При наличии users.email_lookup схемы v4 каждый непустой e-mail аутентифицируется и его доменно разделённый ключевой token пересчитывается. Отсутствие, несовпадение или token при null блокирует снимок. Базы до v4 совместимы без колонки.
Текущая граница резервной копии
Инструмент приватного развёртывания останавливает приложение и использует неизменяемый образ контейнера, том и окружение для архива solo. Манифест подписан Ed25519, payload зашифрован операторским AES-256-GCM ключом. Он содержит SQLite, локальные bloby и векторы, селекторы среды и защищённую конфигурацию для расшифровки. До публикации проверяются подпись, checksum шифротекста и расшифрованный payload. libre-webui-restore принимает только новый Docker-том, проверяет инвентарь до копирования и публикует конфигурацию приватными файлами в новом каталоге.
Защищённая конфигурация включает пул PostgreSQL и тайм-ауты подключения, бездействия, SQL-инструкций и блокировки миграции; тайм-аут подключения Redis; обе квоты blob-хранилища; селекторы платформы; префикс S3 и режим адресации. Они находятся в подписанном зашифрованном payload, не открытом манифесте, и публикуются как файлы 0600.
Solo-архив не включает Docker-тома Work, PVC Kubernetes, связанные с хостом каталоги, модели Ollama или внешнее состояние. Сохраняйте исключения видимыми и копируйте Work отдельно. Team использует автономный процесс: экспорт PostgreSQL, точные версионированные S3-объекты, PGVector-инвентарь, конфигурация и ключ запечатываются тем же форматом и проверяются на чистом PostgreSQL/S3. кэш Redis, присутствие, сигналы пробуждения и аренды восстанавливаются из SQL.
Team-копия аутентифицирует каждый ограниченный зашифрованный содержимого заданий/событий в точном экспорте. Защищённый инвентарь считает задания, события, потоки, курсоры, обёртки и ссылки и открытый текст. Каждый поток содержит непрерывное 1..last_sequence, глобальный cursor PostgreSQL не отстаёт от максимума. Восстановление повторяет проверки и требует совпадения с источником. Пропуски между глобальными cursor допустимы из-за нетранзакционного выделения идентификаторов; непрерывность обязательна внутри потока.
Если PLUGINS_DIR вне DATA_DIR, каталог инвентаризируется и исключается из тома. Любые определения блокируют снимок до отдельной копии. То же для старых каталогов. Символические ссылки, нерегулярные или нечитаемые JSON всегда блокируют и не обходятся.
Постоянные задания и упорядоченные события активны в обоих профилях. Проверка блокирует активную попытку или Work, валидирует payload и головы потоков и сохраняет канонический SQL. Solo запускает ограниченного встроенного workera; team — те же обработчики во внешнем, используя Redis только для пробуждения и рассылки.
В продакшене держите ключи и JWT в менеджере секретов, архивы за пределами хоста и зашифрованными, проверяйте восстановление в чистой совместимой среде. Инвентаризация — предварительный снимок, не блокировка и не доказательство восстановления всех внешних ресурсов.
Команды подписанных и зашифрованных копий
Примеры используют установленный libre-webui из npm или Homebrew. Без глобальной установки замените на npx --yes libre-webui@latest. Из исходников соберите бэкенд и замените libre-webui backup на npm run recovery:backup --. Продакшен-образ предоставляет /usr/local/bin/libre-webui. Team требует PostgreSQL 16 pg_dump и pg_restore, включённые в образ и Homebrew; для npm/npx установите совместимый клиент.
Создайте AES-256-GCM ключ архива и пару Ed25519 в приватном каталоге, затем перенесите приватные ключи за хост:
install -d -m 0700 /absolute/private/libre-backup-keys
libre-webui backup keygen \
--directory /absolute/private/libre-backup-keys
Для остановленного solo создайте и независимо проверьте архив:
libre-webui backup create \
--offline \
--data-dir /absolute/path/to/libre-data \
--output /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
libre-webui backup verify \
--archive /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
Сначала выполните preflight, затем применяйте только к новому пустому каталогу:
libre-webui backup restore-preflight \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-apply \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-verify \
--target /absolute/restore/libre-data
Для team остановите все реплики и workеры, оставьте окружение PostgreSQL/S3/keyring источника и создайте архив:
libre-webui backup create-team \
--offline \
--output /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
До восстановления загрузите переменные для отдельной пустой PostgreSQL и пустого версионированного S3. Preflight проверяет подпись, архив, инвентарь и пустоту целей без публикации. Apply восстанавливает, проверяет схему, точные S3 и PGVector и пишет конфигурацию в новый приватный каталог:
libre-webui backup restore-team-preflight \
--archive /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-team-apply \
--archive /absolute/backups/libre-team.lwbackup \
--configuration-output /absolute/restore/libre-team-config \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
Никогда не направляйте восстановление в исходную базу, bucket, существующий каталог данных или непустую конфигурацию. Храните публичный ключ с процедурой; архив и публичный ключ не расшифровывают payload.
Если откат восстановления team неполон, считайте обе цели грязными и не повторяйте сразу. Очистите PostgreSQL, перечислите и удалите все версии объектов и маркеры удаления под точным префиксом S3. Повторите restore-team-preflight; apply безопасен только после чистой проверки.
Запланированные проверенные учения восстановления
Копия, которую не восстанавливали, — надежда, не восстановление. Учение без простоя и оператора выполняет весь процесс:
- Создаёт остановленный снимок каталога — SQLite через API онлайн-копирования, bloby и файлы физически. Ждёт отсутствия durable jobs по правилу
recovery-check. - Превращает копию в подписанный AES-256-GCM архив с временными ключами и полным инвентарём.
- Проверяет архив, восстанавливает в изолированную цель и снова проверяет.
- Записывает длительность как доказанный RTO, интервал успехов как границу RPO и удаляет артефакты. Это проверка, не копия: архив и ключ не сохраняются.
Включите RECOVERY_DRILL_INTERVAL_HOURS (например 24); общая аренда предотвращает двойной запуск реплик. Страница System показывает историю и кнопку "Run drill now", используя GET /api/recovery/drills и POST /api/recovery/drills/run. Автоматический сбой один раз уведомляет всех администраторов и вебхуки; ручной сообщает отказ напрямую. RECOVERY_DRILL_HISTORY ограничивает историю (60 по умолчанию).
Учения покрывают solo (SQLite), где файловый архив авторитетен. Team сохраняет backup create-team; репетиция восстановления пока остаётся шагом оператора.