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

Применение изменений

Три класса изменений конфигурации, проверка файла до перезапуска, разница между reload и restart, судьба сессий зрителей и откат к прошлой версии.

Изменение в hastreamer.conf попадает в один из трёх классов. Класс определяет, что произойдёт после systemctl reload: изменение применится немедленно, будет записано в файл, но дождётся systemctl restart, либо перезапустит один поток, не тронув остальные.

Сервер классифицирует каждое изменение сам и пишет вердикт в журнал — угадывать не нужно.

Порядок безопасного изменения#

# 1. Сохраните копию — откат из файла всегда быстрее откатa через API.
sudo cp /etc/hastreamer/hastreamer.conf /root/hastreamer.conf.bak

# 2. Отредактируйте файл.
sudo -e /etc/hastreamer/hastreamer.conf

# 3. Проверьте синтаксис и правила БЕЗ применения.
sudo hastreamer --validate /etc/hastreamer/hastreamer.conf

# 4. Примените горячую часть. Ошибочный файл будет отвергнут,
#    работающая конфигурация останется прежней.
sudo systemctl reload hastreamer

# 5. Прочитайте вердикт: что применилось, что ждёт перезапуска.
sudo journalctl -u hastreamer -n 30 --no-pager

# 6. Только если в вердикте есть строки о перезапуске.
sudo systemctl restart hastreamer
Порядок шагов 4 и 6 не переставляйте

reload при ошибочном файле оставляет сервер работать. restart при ошибочном файле останавливает его: процесс завершится с кодом 1, а Restart=on-failure будет поднимать его каждые 2 секунды — получится цикл перезапусков без видео. Всегда проверяйте файл через --validate и reload.

Три класса изменений#

Класс Что делает systemctl reload Кого затрагивает
Горячее применяет немедленно, на следующем запросе никого: соединения живут
Требует перезапуска записывает в файл и сообщает об этом в журнале; работающий процесс продолжает со старым значением все сессии — при последующем restart
Перезапуск потока пересоздаёт только изменившиеся потоки зрителей этих потоков

Горячие изменения#

Применяются сразу и без разрыва соединений. Политика доступа перечитывается на каждый запрос, даже внутри уже открытого keep-alive-соединения, поэтому включение, отключение и ротация авторизации не требуют перезапуска.

Директива или блок Что меняется
log_level минимальная тяжесть записей в журнале
trusted_proxies список доверенных обратных прокси
allow_origins список источников CORS
public_paths пути, освобождённые от авторизации просмотра
auth { } пароль администратора, статические API-токены, привязка к IP, секрет подписи
auth_backend { } авторизация просмотра: тип, ключи, издатель, список отзыва
principal <имя> { } встроенные учётные записи и их права
session_keys { } срок жизни и привязка билетов сессии
tls { } сертификат и ключ по умолчанию
certificate <имя> { } сертификаты SNI, включая выпуск по ACME
Смена секрета аннулирует выданные билеты

Изменение session_keys { secret } или auth { session_secret } меняет корень, из которого выводится ключ подписи билетов сессии. Все выданные билеты становятся недействительными: зрители получат 401 и переустановят сессию на следующем запросе плейлиста. Разрыва видео при этом нет, если плеер умеет повторить запрос.

Изменения, требующие перезапуска#

Двадцать три параметра привязаны к моменту запуска процесса: порты слушателей, раскладка по ядрам, глобальные параметры приёма и раздачи. Их новое значение попадает в файл сразу, но применяется только на systemctl restart.

Директива Формулировка в журнале
http HLS/API listener (http_port 8080 → 9443)
https HTTPS listener (https_port …)
rtsp RTSP listener (rtsp_port …)
rtsps RTSPS listener (rtsps_port …)
rtmp RTMP listener (rtmp_port …)
rtmps RTMPS listener (rtmps_port …)
webrtc (порт) WebRTC media port (webrtc_udp_port …)
webrtc … public_ip= WebRTC identity (webrtc_public_ip …)
cores worker cores (cores …)
low_latency LL-HLS producer (low_latency …)
rtsp_frame_source ring mode (rtsp_frame_source …)
source_transport puller default (source_transport …)
rtp_max_payload RTP packetizer (rtp_max_payload …)
max_sessions session gate (max_sessions …)
dvr_cleanup_secs DVR evictor (dvr_cleanup_secs …)
media_timeout media-stall watchdog (media_timeout …)
on_demand_grace on-demand grace (on_demand_grace …)
udp_ingest_rcvbuf UDP-ingest buffer (udp_ingest_rcvbuf …)
udp_ingest_shards UDP-ingest routers (udp_ingest_shards …)
udp_ingest_pool_slots UDP-ingest ring (udp_ingest_pool_slots …)
udp_pull_rate UDP pull pacing (udp_pull_rate …)
acme_directory ACME directory (acme_directory …)
acme_contact ACME contact (acme_contact …)
Молчаливое «ничего не изменилось» — самая частая ошибка

Смена порта не действует после reload. Сервер об этом сообщает, но только в журнале. Если вы поменяли http 8080; на http 80;, сделали reload и увидели, что старый порт всё ещё отвечает — это не сбой, а именно этот класс. Нужен systemctl restart.

Блок cluster требует перезапуска, но в вердикт не попадает

Членство в кластере, канал между узлами и его общий ключ строятся один раз при запуске процесса. В таблице выше блока cluster нет, поэтому reload о нём промолчит — и при этом не применит его. Любую правку cluster — ключ, адрес узла, состав узлов, переопределения портов — завершайте systemctl restart. Единственное, что пересчитывается живо, — размещение потоков: директивы host и restream внутри блоков stream.

Перезапуск отдельного потока#

Блоки stream, template, storage и vod сверяются по одному. Перезапускается только тот поток, чей отпечаток изменился; остальные сохраняют аптайм, буферы и сессии.

Отпечаток потока — это весь его блок, кроме labels. Отсюда правила:

Что вы изменили Что перезапустится
input, dvr, segment_seconds, on_demand, caps, любой другой параметр потока только этот поток
только labels ничего; новые метки авторизации действуют сразу
path, segment_secs или identity у storage каждый поток, который в это хранилище пишет
адрес, ключи или tls_verify у storage … s3 каждый поток, который туда копирует
добавили блок stream новый поток запускается, существующие не трогаются
удалили блок stream этот поток останавливается, его сессии закрываются

Тот же перезапуск можно вызвать без правки конфигурации — например, чтобы переподключить зависший источник:

curl -sS -X POST "https://media.example.com/api/v1/streams/cam1/restart" \
  -H "Authorization: Bearer $TOKEN"
{"path":"cam1","restarted":true}
Меняйте метки без перерыва в видео

labels намеренно исключены из отпечатка. Перевод камеры в другую группу доступа не прерывает трансляцию и не сбрасывает зрителей — это единственное изменение внутри stream, которое гарантированно бесплатно. См. Метки потоков.

Проверка файла до применения#

hastreamer --validate разбирает файл, прогоняет все правила и завершается, ничего не запуская и ничего не меняя.

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

При ошибке разбора печатается номер строки:

parse /etc/hastreamer/hastreamer.conf: line 3: unknown directive "cors"

При ошибке правил валидатор накапливает все ошибки и печатает их через ; — чинить файл можно за один проход, а не по одной ошибке за попытку:

invalid config /etc/hastreamer/hastreamer.conf: stream "cam": needs `source` or a non-empty `sources` chain; http_port and rtsp_port must be non-zero; http_port and rtsp_port must differ (both 0); stream "cam" has an empty source

Коды завершения:

Код Значение
0 файл корректен
1 ошибка разбора, ошибка правил или файл не читается
2 путь к файлу не передан (usage: hastreamer --validate <config> [-j])

Флаг -j печатает каноническую JSON-форму конфигурации вместо строки OK. Это ровно то тело, которое принимает PUT /api/v1/config:

sudo hastreamer --validate /etc/hastreamer/hastreamer.conf -j | head -20
Проверка удалась

Команда завершилась кодом 0 и напечатала OK (N streams), где N — число блоков stream в файле. Если число не совпадает с ожидаемым, вы либо забыли блок, либо два блока имеют одинаковый путь — тогда была бы ошибка duplicate stream path "…".

Ту же проверку можно выполнить по сети, не имея доступа к оболочке сервера. POST /api/v1/config/validate разбирает переданный текст и возвращает классификацию, ничего не записывая:

curl -sS -X POST "https://media.example.com/api/v1/config/validate" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(python3 -c 'import json,sys; print(json.dumps({"text": open("/etc/hastreamer/hastreamer.conf").read()}))')"
{
  "classification": {
    "added": ["cam2"],
    "removed": [],
    "respawn": ["cam1"],
    "restart_required": ["HLS/API listener (http_port 8080 → 80)"],
    "untouched": 7
  },
  "ok": true
}
Неверная конфигурация возвращается со статусом 200

POST /api/v1/config/validate отвечает 200 и в успешном, и в неуспешном случае. Признак — поле ok. При "ok": false текст ошибок лежит в поле errors, поля classification нет. Проверяйте ok, а не HTTP-код.

reload против restart#

systemctl reload hastreamer systemctl restart hastreamer
Механизм SIGHUP, процесс не завершается процесс завершается и запускается заново
Файл с ошибкой отвергается, сервер продолжает работу процесс не стартует, цикл перезапусков
Порты слушателей не меняются применяются новые
Сессии зрителей сохраняются, кроме потоков с изменившимся отпечатком все закрываются
Незакрытые записи архива не затрагиваются закрываются корректно, окно слива 5 секунд
Время недоступности нет секунды

Вердикт reload пишется в журнал одной из трёх строк:

config reload: applied epoch 9 (hash 4a186afe976f6ef3)
config reload: no change
config reload REJECTED: <текст ошибок> (running config unchanged)
reload — это и есть проверка на боевом сервере

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

Что происходит с сессиями зрителей#

Событие HLS, LL-HLS, DASH MSE-WS, HTTP-TS RTSP WebRTC (WHEP) Архив и VoD
Горячее изменение ничего ничего ничего ничего ничего
Перезапуск одного потока перерыв на время пересоздания, живое окно строится заново соединение закрывается сессия закрывается сессия закрывается чтение записанного не прерывается
systemctl restart перерыв на время перезапуска закрывается закрывается закрывается закрывается
Смена источника внутри потока (резервирование) не прерывается не прерывается не прерывается не прерывается
Переподключение источника по media_timeout не прерывается не прерывается не прерывается не прерывается

Различие принципиальное. Опросные протоколы (HLS, LL-HLS, DASH) не держат соединения: после перезапуска потока плеер, который повторяет запрос плейлиста, продолжит воспроизведение с нового живого края сам. Постоянные соединения (MSE-WS, HTTP-TS, RTSP, WebRTC) закрываются, и повторное подключение — задача плеера; встроенный плеер это делает, сторонний может не делать.

Чтение уже записанного архива и файлов VoD от перезапуска потока не зависит: запись на диск и её раздача — независимые пути.

Переподключение источника сессий не рвёт

Обрыв связи с камерой, переход на резервный источник и срабатывание сторожевого таймера media_timeout не закрывают ни одной сессии зрителя: кольцевые буферы, сессии и запись потока в каталоге сохраняются. В HLS появляется отметка разрыва, но плеер не получает 404. См. Резервирование источников.

История конфигурации и откат#

Каждое принятое изменение записывается в журнал версий рядом с файлом конфигурации:

/etc/hastreamer/hastreamer.conf
/etc/hastreamer/hastreamer.conf.history/
    index.jsonl     — по строке на версию
    1.conf          — точные байты версии 1
    2.conf
    …
Свойство Значение
Глубина последние 32 версии
Права каталог 0700, файлы 0600 — в конфигурации лежат пароли и учётные данные камер
Номер версии (epoch) монотонно растёт и никогда не уменьшается, в том числе при откате
Что записывается точные байты применённой конфигурации плюс автор и способ изменения

Журнал пополняется при любом принятом применении. Поле via называет источник изменения, поле actor — кто его сделал:

via Источник изменения
boot запуск процесса
reload systemctl reloadactor при этом всегда signal
api PUT /api/v1/config — применение текста конфигурации целиком
globals PATCH /api/v1/config/globals — точечная правка глобальных директив
apply создание, изменение или удаление потока либо хранилища через API
rollback POST /api/v1/config/rollback
cert-upload, cert-delete, cert-acme загрузка, удаление и автоматический выпуск сертификата
template-save, template-delete изменение шаблонов
vod-lib-save, vod-lib-delete изменение библиотек VoD

Прочитать историю:

curl -sS "https://media.example.com/api/v1/config/history" \
  -H "Authorization: Bearer $TOKEN"
[{"epoch":1,"hash":"d9b4d2d2a819ff24","shared_hash":"85851d2f59d9e592",
  "ts_ms":1786787600937,"actor":"system","via":"boot"}]

Откатиться к записанной версии:

curl -sS -X POST "https://media.example.com/api/v1/config/rollback" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"epoch": 7}'
{"epoch":10,"hash":"85851d2f59d9e592","changed":true,"rolled_from":7}

Версии старше 32 последних в журнале уже нет — откат к ней вернёт 404 {"title":"version not found"}. Если вам нужен долгий архив конфигураций, копируйте файл во внешнее хранилище: см. Резервное копирование.

Откат — это новая версия, а не возврат назад

Байты версии 7 применяются как версия 10. История только дополняется, номер версии не уменьшается. Поэтому откат можно откатить.

Откат не возвращает порты

rollback проходит ту же классификацию, что и обычное применение. Если откатываемая версия отличается портом или другим параметром из таблицы выше, откат вернёт файл, но не работающее значение — нужен systemctl restart. Ответ на откат этого не показывает: смотрите журнал.

Та же история доступна в панели управления: Конфигурация → История, с кнопкой отката у каждой записи. См. Веб-интерфейс.

Запрет изменений через API#

Создайте файл .locked рядом с конфигурацией — и любой изменяющий вызов API вернёт 423 Locked:

sudo touch /etc/hastreamer/hastreamer.conf.locked
{"type":"about:blank","title":"config locked","status":423,
 "detail":"the config is locked (/etc/hastreamer/hastreamer.conf.locked exists) — remove that file to enable edits via the API/UI"}

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

Блокировка не защищает файл

.locked — это защита от случайного изменения через панель, а не права доступа. Кто может писать в /etc/hastreamer/, тот может удалить и сам файл блокировки. Разграничивайте доступ правами файловой системы.

Что дальше#