SIRINVIDEO Документация администратора и интегратора На сайт 2026.08

Резервное копирование

Что сохранять, чтобы поднять сервер с нуля за пятнадцать минут, почему архив обычно не бэкапят и как проверить, что восстановление удалось.

Сервер не хранит состояние в базе данных: всё, что делает его этим сервером, лежит в нескольких файлах. Резервная копия небольшая — единицы мегабайт, — и снимается обычным tar. Архив видео (DVR) в неё, как правило, не входит; почему — ниже.

Во всех примерах media.example.com — ваш сервер, $TOKEN — токен доступа к API. Получить токен:

TOKEN=$(curl -sS -X POST https://media.example.com/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"password":"<пароль-администратора>"}' | sed -E 's/.*"token":"([^"]+)".*/\1/')

Что сохранять#

Что Путь Зачем
Конфигурация /etc/hastreamer/hastreamer.conf все потоки, хранилища, авторизация, порты
История конфигурации /etc/hastreamer/hastreamer.conf.history/ последние 32 версии + журнал изменений; из неё возвращаются к предыдущей рабочей конфигурации
Лицензия /etc/hastreamer/license.txt код активации
Сертификаты и состояние TLS /var/lib/hastreamer/tls-state/ загруженные сертификаты, самоподписанная личность, состояние ACME
Юнит systemd /etc/systemd/system/hastreamer.service лимиты дескрипторов и памяти, путь к конфигурации
Параметры ядра /etc/sysctl.d/99-hastreamer.conf настройка хоста под высокую нагрузку
Копия содержит секреты в открытом виде

И hastreamer.conf, и каждый файл в hastreamer.conf.history/ — это полный текст конфигурации: пароль администратора, session_secret, токены API, логины и пароли камер, ключи доступа к S3. На сервере они принадлежат root и закрыты от посторонних (0600/0640), а каталог истории — 0700.

Архив резервной копии обязан быть защищён не слабее: шифруйте его и храните отдельно от сервера. Копия конфигурации, попавшая в общедоступное хранилище, — это компрометация всех камер и всего доступа сразу.

Как выглядит история конфигурации#

Каталог <файл-конфигурации>.history создаётся сервером рядом с самим файлом. В нём лежат пронумерованные версии и журнал:

sudo ls -la /etc/hastreamer/hastreamer.conf.history/
drwx------ 2 root root  120 .
-rw------- 1 root root   93 1.conf
-rw------- 1 root root  202 2.conf
-rw------- 1 root root  224 3.conf
-rw------- 1 root root  373 index.jsonl
sudo cat /etc/hastreamer/hastreamer.conf.history/index.jsonl
{"epoch":1,"hash":"4142a86d9f2192c8","shared_hash":"55e7d03f267ab0a4","ts_ms":1787143146369,"actor":"system","via":"boot"}
{"epoch":2,"hash":"9da3dde1d5ab003a","shared_hash":"e151479b74bed483","ts_ms":1787143426784,"actor":"signal","via":"reload"}
{"epoch":3,"hash":"dcdceb53d14e1d2c","shared_hash":"5286f87464a9b8af","ts_ms":1787143497448,"actor":"signal","via":"reload"}

Журнал только дополняется, хранятся последние 32 версии; более старые удаляются. Поле via говорит, что породило версию (boot, reload, api, apply, rollback, …), actor — кто это сделал.

Тот же журнал доступен через API:

curl -sS https://media.example.com/api/v1/config/history \
  -H "Authorization: Bearer $TOKEN"

Чего в резервной копии обычно нет#

Видеоархив (DVR)/var/lib/hastreamer/dvr или ваш каталог хранилища. Его не бэкапят по трём причинам:

  • Это скользящее окно, а не накопление. Архив ограничен глубиной по времени и объёму: сервер сам удаляет старое. Копия недельной давности содержит записи, которые на боевом сервере уже удалены штатно — восстанавливать их бессмысленно и обычно неправомерно.
  • Объём несопоставим. Архив — это сотни гигабайт и терабайты против мегабайт конфигурации. Копирование такого объёма занимает больше времени, чем допустимый простой.
  • Он и так вытесняется. Сверх ограничений по времени и объёму работает клапан давления на диск: при заполнении файловой системы выше evict_at_percent удаляются самые старые записи по всем потокам.

Если отдельные записи всё-таки нужно сохранить надолго — не копируйте каталог, а выгружайте нужные фрагменты как файлы (экспорт клипа) либо настройте копирование в S3 с собственным сроком хранения. См. Хранилища и S3.

Библиотека VoD — исходные файлы, обычно они уже имеют собственный источник и собственную копию. Сервер их только раздаёт и никогда не изменяет.

Данные в памяти — журнал (4096 записей), аудит (4096), лента событий (512 кадров), ряды метрик и показатели качества сессий. Всё это не переживает даже перезапуск сервиса, копировать нечего. Если нужен долговременный аудит или журнал — снимайте их наружу постоянно, а не в момент бэкапа.

Если вы всё же копируете архив

Копируйте файл записи вместе с его файлом-указателем .idx. Указатель — единственный каталог записей: без него скопированное видео для сервера не существует. И не копируйте каталог, пока сервер пишет: незакрытая текущая запись не имеет суффикса _d<мс> в имени, и её содержимое ещё меняется.

Как снять копию#

Копию можно снимать на работающем сервере: файлы конфигурации пишутся атомарно, полуфабрикат в копию не попадёт.

#!/usr/bin/env bash
# Резервная копия SirinVideo. Запускать от root.
set -euo pipefail
DEST=${1:-/var/backups/sirinvideo}
STAMP=$(date -u +%Y%m%d-%H%M%S)
mkdir -p "$DEST"

# Каталог tls-state появляется только после первого сертификата, поэтому список
# собирается из того, что реально есть, — иначе tar прервёт работу.
ITEMS=()
for p in etc/hastreamer \
         var/lib/hastreamer/tls-state \
         etc/systemd/system/hastreamer.service \
         etc/sysctl.d/99-hastreamer.conf; do
  [[ -e "/$p" ]] && ITEMS+=("$p")
done

tar czf "$DEST/sirinvideo-$STAMP.tar.gz" -C / "${ITEMS[@]}"
chmod 600 "$DEST/sirinvideo-$STAMP.tar.gz"
echo "готово: $DEST/sirinvideo-$STAMP.tar.gz (${#ITEMS[@]} элементов)"
готово: /var/backups/sirinvideo/sirinvideo-20260819-121500.tar.gz (4 элементов)

etc/hastreamer включает и конфигурацию, и каталог истории, и файл лицензии.

Снимайте копию перед каждым изменением

Не полагайтесь только на расписание. Перед правкой конфигурации сохраните текущее состояние — это дешевле, чем разбираться в истории после неудачного изменения. Мелкие правки при этом всегда откатываются через историю, без распаковки архива.

Проверьте, что копия читается, сразу после создания:

tar tzf /var/backups/sirinvideo/sirinvideo-20260819-121500.tar.gz | head
etc/hastreamer/
etc/hastreamer/hastreamer.conf
etc/hastreamer/license.txt
etc/hastreamer/hastreamer.conf.history/
etc/hastreamer/hastreamer.conf.history/index.jsonl

Как восстановить сервер с нуля#

Последовательность рассчитана на чистую машину с тем же дистрибутивом Linux.

1. Установите сервер штатным установщиком. Не восстанавливайте копию поверх пустой системы: установщик заводит каталоги, юнит systemd и параметры ядра. См. Установку с нуля. Дойдя до вопроса о коде активации — пропустите его, код приедет из копии.

2. Остановите сервис.

sudo systemctl stop hastreamer

3. Разверните копию.

sudo tar xzf /path/to/sirinvideo-20260819-121500.tar.gz -C /
sudo systemctl daemon-reload
sudo sysctl --system

4. Проверьте конфигурацию до запуска. Разбор без запуска сервера:

sudo hastreamer --validate /etc/hastreamer/hastreamer.conf
/etc/hastreamer/hastreamer.conf: OK (12 streams)

Ошибка выводится с номером строки, и это штатный способ убедиться, что копия распаковалась целиком.

5. Приведите в соответствие пути. Если на новой машине другие точки монтирования, поправьте в конфигурации пути хранилищ (storage <имя> <путь>) и корни библиотек VoD. Каталог по пути хранилища должен существовать и быть доступен на запись пользователю сервиса.

6. Запустите и прочитайте журнал.

sudo systemctl start hastreamer
sudo journalctl -u hastreamer -n 60 --no-pager

7. Активируйте лицензию. Лицензия привязана к оборудованию: у новой машины другой отпечаток, и он не совпадёт с тем, на котором лицензия активировалась.

sudo hastreamer --print-hwid
<ОТПЕЧАТОК-ОБОРУДОВАНИЯ>

Пока лицензия не действует, панель и API отвечают, а медиа не отдаётся — это штатное поведение. В журнале это видно как hastreamer: NOT LICENSED (enforced) — online activation pending, а запросы к медиа получают 403 license restricted. Порядок активации и что делать при переносе на другое оборудование — Лицензирование.

Сертификаты по ACME после переноса выпускаются заново

Из копии восстановится и состояние ACME, но выданный сертификат привязан к доменному имени. Если новый сервер отвечает на то же имя — сертификат подхватится. Если имя другое, сервер выпустит сертификат заново; на это нужны доступный извне порт 80 и корректная запись DNS. См. TLS и сертификаты.

Проверка восстановления#

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

1. Сервис запущен и не перезапускается по кругу
systemctl is-active hastreamer && systemctl show -p NRestarts --value hastreamer

Ожидается active и 0. Растущее число перезапусков означает, что процесс падает при старте — читайте journalctl -u hastreamer -n 50.

2. Конфигурация принята целиком
curl -sS https://media.example.com/api/v1/config/streams \
  -H "Authorization: Bearer $TOKEN" | head -c 200

В ответе должны быть все потоки, которые были до восстановления, — сравните их число с исходным.

3. Лицензия действует
curl -sS https://media.example.com/api/v1/license -H "Authorization: Bearer $TOKEN"
{"state":"licensed","customer":"example-customer","expires":"2027-01-31","max_streams":50,"hwid":"<ОТПЕЧАТОК>"}

Значение state, отличное от licensed, означает, что медиа отдаваться не будет.

4. Источники поднялись
curl -sS "https://media.example.com/api/v1/streams?fields=id,health,source_error&limit=200" \
  -H "Authorization: Bearer $TOKEN"

У всех потоков ожидается "health":"ok". Значение failing с непустым source_error разбирайте по Диагностике неисправностей.

5. Видео действительно отдаётся
curl -sS -o /dev/null -w '%{http_code}\n' https://media.example.com/cam1/master.m3u8

Ожидается 200. Код 403 license restricted — лицензия; 401/403 — авторизация просмотра (тогда повторите запрос с токеном зрителя). Затем откройте плеер: https://media.example.com/cam1/embed.html.

6. Хранилища архива доступны и на них пишется
curl -sS https://media.example.com/api/v1/storages -H "Authorization: Bearer $TOKEN"
[{"name":"local","path":"/var/lib/hastreamer/dvr","identity_healthy":true,
  "maintenance_healthy":true,"total_bytes":84444717056,"used_bytes":31733628928,
  "avail_bytes":52711088128,"evict_at_percent":90,"streams":[["cam1",21,21012998324]]}]

Оба поля identity_healthy и maintenance_healthy должны быть true, а total_bytes — отличным от нуля. Пустой список или нулевые размеры означают, что каталог хранилища недоступен.

Возврат к предыдущей конфигурации#

Полное восстановление из архива для отката неудачной правки не нужно — для этого есть история.

Посмотрите список версий и выберите номер:

curl -sS https://media.example.com/api/v1/config/history \
  -H "Authorization: Bearer $TOKEN"
[{"epoch":1,"hash":"4142a86d9f2192c8","ts_ms":1787143146369,"actor":"system","via":"boot"},
 {"epoch":2,"hash":"9da3dde1d5ab003a","ts_ms":1787143426784,"actor":"admin","via":"api"}]

Вернитесь к нужной версии:

curl -sS -X POST https://media.example.com/api/v1/config/rollback \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"epoch":1}'
{"epoch":3,"hash":"4142a86d9f2192c8","changed":true,"rolled_from":1}
Возврат — это новая версия, а не удаление

История только дополняется: откат применяет байты старой версии как новую запись. Номер версии никогда не уменьшается, и ни одна правка не пропадает из журнала.

Если сервер не запускается и API недоступен, то же самое делается вручную:

sudo cp /etc/hastreamer/hastreamer.conf.history/1.conf /etc/hastreamer/hastreamer.conf
sudo hastreamer --validate /etc/hastreamer/hastreamer.conf
sudo systemctl restart hastreamer

Куда двигаться дальше#