Резервное копирование
Что сохранять, чтобы поднять сервер с нуля за пятнадцать минут, почему архив обычно не бэкапят и как проверить, что восстановление удалось.
Сервер не хранит состояние в базе данных: всё, что делает его этим сервером, лежит в нескольких
файлах. Резервная копия небольшая — единицы мегабайт, — и снимается обычным 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, но выданный сертификат привязан к доменному имени. Если новый сервер отвечает на то же имя — сертификат подхватится. Если имя другое, сервер выпустит сертификат заново; на это нужны доступный извне порт 80 и корректная запись DNS. См. TLS и сертификаты.
Проверка восстановления#
Восстановление считается успешным, когда проходят все шесть проверок. Выполняйте их по порядку: каждая следующая имеет смысл только после предыдущей.
systemctl is-active hastreamer && systemctl show -p NRestarts --value hastreamer
Ожидается active и 0. Растущее число перезапусков означает, что процесс падает при старте —
читайте journalctl -u hastreamer -n 50.
curl -sS https://media.example.com/api/v1/config/streams \ -H "Authorization: Bearer $TOKEN" | head -c 200
В ответе должны быть все потоки, которые были до восстановления, — сравните их число с исходным.
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, означает, что медиа отдаваться не будет.
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 разбирайте
по Диагностике неисправностей.
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.
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
Куда двигаться дальше#
- Применение изменений — как безопасно править конфигурацию и что требует перезапуска.
- Диагностика неисправностей — если после восстановления что-то не поднялось.
- Лицензирование — активация на новом оборудовании.
- Хранилища и S3 — долговременное хранение записей вместо копирования каталога.