Для обновления БД и веб-портала центрального сервера необходимо на сервере выполнить следующие команды (заменив ССЫЛКА_НА_ДИСТРИБУТИВ):
cd ~
sudo -i
wget -O preupdateforpost https://fpst.ru/files/utils/preupdateforpost
chmod 755 preupdateforpost
source ./preupdateforpost ССЫЛКА_НА_ДИСТРИБУТИВ
tools/sql-diff --new sql/cctv-db.sql --db cctv | mysql cctv
tools/dbdata --new sql/dbdata.txt --db cctv | mysql cctv
cp -r /var/www/cctv-portal /var/www/cctv-portal.`date '+%Y%m%d-%H%M'`
cp -rf ./cctv-portal /var/www/
rm -rf /var/www/cctv-portal/assets/* && rm -rf /var/www/cctv-portal/assets/.empty-folder
Настроить права доступа к файлам веб-портала (команды зависят от операционной системы):
cd /var/www/cctv-portal/
chgrp -R www-data images assets protected/runtime
chmod -R g+w images assets protected/runtime
find images assets protected/runtime -type d -exec chmod g+w,g+s,+t {} +
chown root:root images/.htaccess && chmod 0444 images/.htaccess
chgrp www-data protected/config/local.php && chmod 640 protected/config/local.php
cd /var/www/cctv-portal/
chgrp -R apache images assets protected/runtime
chmod -R g+w images assets protected/runtime
find images assets protected/runtime -type d -exec chmod g+w,g+s,+t {} +
chown root:root images/.htaccess && chmod 0444 images/.htaccess
chgrp apache protected/config/local.php && chmod 640 protected/config/local.php
restorecon -RF /path/to/webroot
semanage fcontext -a -t httpd_sys_rw_content_t '/path/to/webroot/images(/.*)?'
restorecon -R /path/to/webroot/images
Для обновления мастера и стримера центрального сервера необходимо на сервере выполнить следующие команды:
cd ~
sudo -i
wget https://fpst.ru/files/utils/preupdateforpost
chmod 755 preupdateforpost
source ./preupdateforpost ССЫЛКА_НА_ДИСТРИБУТИВ
mv /usr/local/sbin/cctv-streamer /usr/local/sbin/cctv-streamer.`date '+%Y%m%d-%H%M'`
cp ./sbin/cctv-streamer /usr/local/sbin/cctv-streamer
mv /usr/local/sbin/cctv-master /usr/local/sbin/cctv-master.`date '+%Y%m%d-%H%M'`
cp ./sbin/cctv-master /usr/local/sbin/cctv-master
service cctv-master restart
service cctv-streamer restart
Для обновления выделенного стримера необходимо на сервере выполнить следующие команды (заменив ССЫЛКА_НА_ДИСТРИБУТИВ):
cd ~
sudo -i
wget http://fpst.ru/files/utils/preupdateforpost
chmod 755 preupdateforpost
source ./preupdateforpost ССЫЛКА_НА_ДИСТРИБУТИВ
mv /usr/local/sbin/cctv-streamer /usr/local/sbin/cctv-streamer.`date '+%Y%m%d-%H%M'`
cp ./sbin/cctv-streamer /usr/local/sbin/cctv-streamer
service cctv-streamer restart
Чтобы создать резервную копию Форпост на другом (резервном) сервере, необходимо выполнить следующие действия:
sudo adduser --gecos "" forpost-backup
(Необходимо задать сложный пароль для учётной записи “forpost-backup”. Позднее доступ по паролю будет отключен. )
sudo mkdir -p /var/lib/cctv/forpost-backup
sudo chown forpost-backup:forpost-backup /var/lib/cctv/forpost-backup
ssh-keygen создать пару из публичного и приватного ключа, и содержимое файла публичного ключа id_rsa.pub скопировать на резервный сервер в файл /home/forpost-backup/.ssh/authorized_keys:sudo -i
ssh-keygen
ssh-copy-id forpost-backup@192.168.1.102
где "192.168.1.102" – IP-адрес резервного сервера
(Потребуется ввести пароль от учётной записи “forpost-backup”, придуманный ранее.)
sudo mkdir -p /var/lib/cctv/tools
sudo wget -O /var/lib/cctv/tools/forpost-backup.sh https://fpst.ru/files/utils/forpost-backup.sh
sudo chmod 755 /var/lib/cctv/tools/forpost-backup.sh
sudo mkdir -p /var/log/cctv_backup
/etc/crontab команду для ежедневного создания резервной копии, заменив IP_АДРЕС_РЕЗЕРВНОГО_СЕРВЕРА и ПУТЬ_К_ФАЙЛУ_ПРИВАТНОГО_КЛЮЧА:sudo nano /etc/crontab
3 3 * * * root /var/lib/cctv/tools/forpost-backup.sh forpost-backup IP_АДРЕС_РЕЗЕРВНОГО_СЕРВЕРА ПУТЬ_К_ФАЙЛУ_ПРИВАТНОГО_КЛЮЧА
sudo -i
/var/lib/cctv/tools/forpost-backup.sh forpost-backup 192.168.1.102 /root/.ssh/id_rsa
ls -l /var/lib/cctv/forpost-backup/
sudo passwd -l forpost-backup
(подключение по SSH-ключу будет по-прежнему доступно)
При необходимости создавать резервную копию БД на том же сервере, на котором находится СУБД, следует выполнить команды:
mkdir -p /var/lib/cctv/backups
mkdir -p /var/lib/cctv/tools
wget -O /var/lib/cctv/tools/cctv-db-backup https://fpst.ru/files/utils/cctv-db-backup
chmod 755 /var/lib/cctv/tools/cctv-db-backup
Добавить в файл /etc/crontab команду:
0 5 * * * root /var/lib/cctv/tools/cctv-db-backup
Инструкция предполагает, что восстановление происходит на новом сервере, на котором Форпост установлен не был.
1. Выполняем установку Форпост на новом сервере.
2. Копируем файлы резервной копии на новый сервер, в директорию /var/lib/cctv/forpost-backup/.
3. Выполняем восстановление из резервной копии:
sudo mysql -e "DROP DATABASE cctv;"
sudo mysql -e "DROP USER 'cctv'@'localhost';"
sudo mysql -e "CREATE DATABASE cctv DEFAULT CHARACTER SET utf8;"
sudo gunzip -f /var/lib/cctv/forpost-backup/cctv-20260127-1121.nolock.sql.gz
sudo mysql cctv < /var/lib/cctv/forpost-backup/cctv-20260127-1121.nolock.sql
где “cctv-20260127-1121.nolock.sql” - файл дампа БД из резервной копии.
sudo grep pass /var/lib/cctv/forpost-backup/data/cctv/etc/master.conf
sudo mysql -e "CREATE USER 'cctv'@'localhost' IDENTIFIED BY 'DB_PASSWORD';"
sudo mysql -e "GRANT SELECT, INSERT, UPDATE, DELETE ON cctv.* TO 'cctv'@'localhost';"
sudo mysql -e "ALTER USER 'cctv'@'localhost' IDENTIFIED WITH mysql_native_password BY 'DB_PASSWORD';"
где “DB_PASSWORD” - полученный выше пароль.
sudo systemctl stop cctv-master.service && sudo systemctl stop cctv-streamer.service
sudo cp /var/lib/cctv/forpost-backup/sbin/cctv-master /usr/local/sbin/cctv-master
sudo cp /var/lib/cctv/forpost-backup/sbin/cctv-streamer /usr/local/sbin/cctv-streamer
sudo cp -f /var/lib/cctv/forpost-backup/data/cctv/etc/* /data/cctv/etc/
sudo systemctl start cctv-master.service && sudo systemctl start cctv-streamer.service
sudo cp -rf /var/lib/cctv/forpost-backup/cctv-portal /var/www/
sudo rm -rf /var/www/cctv-portal/assets/* && sudo rm -rf /var/www/cctv-portal/assets/.empty-folder
cd /var/www/cctv-portal
sudo chmod 775 images images/partner images/partner/camera images/screenshot assets protected/runtime
sudo chmod 640 protected/config/local.php
sudo chgrp -R www-data images assets protected/runtime protected/config/local.php
После выполнения всех действий - можно перейти на Портал по IP-адресу нового сервера и выполнить вход под любым пользователем, которые были созданы ранее.
Выполнить на сервере, на котором находится СУБД MySQL, команды:
wget https://fpst.ru/files/cctv-db-clear-202409.tgz
tar xf cctv-db-clear-202409.tgz
cd ./cctv-db-clear-202409
mkdir -p /var/lib/cctv/tools
cp ./cctv-db-clear /var/lib/cctv/tools/
cp ./dbclear.conf /data/cctv/etc/
mkdir -p /data/cctv/sql-backup
mkdir -p /data/cctv/log
Если настройка очистки БД происходит не в процессе установки Форпост, а позже, когда данные в БД уже успели накопиться, рекомендуем первый запуск очистки выполнить вручную:
/var/lib/cctv/tools/cctv-db-clear /data/cctv/etc/dbclear.conf &
Первый запуск может выполняться достаточно продолжительное время. За ходом очистки можно следить по журналу в файле /data/cctv/log/dbclear.log. О завершении очистки скажет строка finished в журнале.
Для регулярного выполнения очистки БД необходимо в файл /etc/crontab добавить запись:
15 2 * * * root /var/lib/cctv/tools/cctv-db-clear /data/cctv/etc/dbclear.conf
По умолчанию скрипт очистки БД создает в папке /data/cctv/sql-backup резервные копии удаляемых данных. Чтобы отключить создание резервных копий (например из-за дефицита дискового пространства), необходимо в конфиге /data/cctv/etc/dbclear.conf закомментировать параметры backup и compress:
{ log: /data/cctv/log/dbclear.log,
# backup: /data/cctv/sql-backup/db-,
days: 45,
# compress: gzip,
}
По умолчанию удаление происходит порциями по 1000 записей. Между удалениями делается пауза продолжительностью (время_удаления_последней_порции x 10). Чтобы ускорить удаление, в конфиг /data/cctv/etc/dbclear.conf необходимо добавить параметры:
event_wait_multiplier: 2,
traffic_wait_multiplier: 2,
translation_wait_multiplier: 2,
record_wait_multiplier: 2,
При таких значениях между удалениями будет делаться пауза продолжительностью (время_удаления_последней_порции x 2).
На сервере, на котором находится веб-портал Форпост, необходимо выполнить команды:
wget https://fpst.ru/files/h265tomp4/h265ToMp4Converter.sh
sudo bash h265ToMp4Converter.sh
Указанные команды предназначены для следующих ОС: Ubuntu, Debian, CentOS.
Если на сервере установлена ОС CentOS с включенным SELinux, то дополнительно к выполнению команд, указанных выше, необходимо сделать попытку скачивания архива через интерфейс пользователя, после чего на сервере выполнить команды:
grep h265tomp4 /var/log/audit/audit.log | audit2allow -M h265tomp4
semodule -i h265tomp4.pp
По умолчанию для подготовки mp4-файлов на сервере используется папка /var/www/cctv-portal/protected/runtime. Чтобы изменить папку, необходимо на сервере в конфиг /var/www/cctv-portal/protected/config/local.php в секцию params добавить строку, заменив PATH_TO_MP4_FOLDER (владельцем папки должен быть пользователь www-data):
'MediaRuntimeFolder' => 'PATH_TO_MP4_FOLDER',
В случае неработоспособности скачивания в формате MP4 необходимо на сервере, на котором находится веб-портал Форпост, в файл /etc/ssl/openssl.cnf внести следующие изменения:
openssl_conf = default_conf
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
CipherString = 'DEFAULT:!DH'
Чтобы Форпост мог отправлять электронные письма, необходимо задать параметры подключения к SMTP-серверу через административную панель в разделе Настройки сайта на вкладке SMTP.
Если SMTP-сервер использует не TLS-шифрование, то на сервере в конфиг /var/www/cctv-portal/protected/config/local.php в секцию components необходимо добавить:
'mail' => array(
'transportOptions' => array(
'encryption'=>'ENCRYPTION',
),
),
ENCRYPTION может принимать значение: ssl, tls, пустое значение (без шифрования).
Чтобы использовать для SMTP-авторизации другой логин, чем email, указанный в поле ”E-mail для сообщений пользователя”, необходимо на сервере добавить в файл /var/www/cctv-portal/protected/config/local.php в секцию params строку, указав нужный логин:
'SMTPUsername' => 'login',
Некоторые типы служебных оповещений, которые отправляются на электронную почту, могут быть отключены, если на сервере, где установлен веб-портал Форпост, в файл /var/www/cctv-portal/protected/config/local.php в секцию params добавить следующие строки:
'DisableCameraMotionDetectorError' => true, // От камер нет уведомлений о движении
'DisableTooHighBitrateNotifications' => true, // Камера превысила допустимую скорость
'NoEmailOnCameraEdit' => true, // Камера отредактирована
Чтобы настроить отправку оповещений о недоступности любой на определенные адреса электронной почты, необходимо на сервере, на котором установлен веб-портал Форпост выполнить:
/var/www/cctv-portal/protected/config/local.php в секцию params добавить строку, указав необходимые адреса электронной почты и заменив на число ПРОДОЛЖИТЕЛЬНОСТЬ_НЕДОСТУПНОСТИ_КАМЕРЫ_В_МИНУТАХ_НЕОБХОДИМАЯ_ДЛЯ_ОПОВЕЩЕНИЯ:'UnavailableCamerasNoticeEmail' => 'EMAIL1;EMAIL2;EMAIL3',
'UnavailableCamerasNoticeTimeoutInMinutes' => ПРОДОЛЖИТЕЛЬНОСТЬ_НЕДОСТУПНОСТИ_КАМЕРЫ_В_МИНУТАХ_НЕОБХОДИМАЯ_ДЛЯ_ОПОВЕЩЕНИЯ,
/etc/crontab добавить строку:*/5 * * * * www-data /usr/bin/php /var/www/cctv-portal/protected/cron.php unavailablecamerasnotice CameraID
Для настройки отправки оповещений пользователей в Telegram необходимо:
/newbot и сохранить значение значение HTTP API токен, которое вернет @BotFather/var/www/cctv-portal/protected/config/local.php в секцию params добавить параметр TelegramBotToken, заменив заменив BOT_TOKEN на значение HTTP API токен:'TelegramBotToken' => 'BOT_TOKEN',
/etc/crontab новую строку:Для ОС Ubuntu/Debian:
*/5 * * * * www-data /usr/bin/php /var/www/cctv-portal/protected/cron.php gettelegrambotupdates
Для ОС CentOS:
*/5 * * * * apache php /var/www/cctv-portal/protected/cron.php gettelegrambotupdates
НастройкиЛичные данные указать значение в поле Username в Telegram, которое скопировать из настроек своего профиля в Telegram (без символа @)Оповещения для камеры, для которой требуется включить оповещения, кликнуть ссылку Настройки и активировать опцию Через TelegramUsername был ранее указан в Личных данных, открыть чат с ботом и нажать кнопку StartВ случае, если push уведомления необходимо отправлять в группу в Telegram, необходимо дополнительно выполнить следующие действия:
BOT_NAME (можно скопировать из профиля бота - значение после символа @):/getchatid @BOT_NAME
CHAT_ID, выполнив в командной строке Linux следующую команду, заменив {BOT_TOKEN} на значение параметра TelegramBotToken из конфига /var/www/cctv-portal/protected/config/local.php:curl -X POST -s https://api.telegram.org/bot{BOT_TOKEN}/getUpdates | grep -Poza '"chat":{"id":-.+?,'
CHAT_ID (вместе со знаком -):"chat":{"id":CHAT_ID,
LOGIN и CHAT_ID:update User set TelegramBotChatID = 'CHAT_ID' where Login = 'LOGIN';
4. В ЛК пользователя в разделе "Настройки -> Личный данные" в поле "MAX (chat_id:ИДЕНТИФИКАТОР)" указать, заменив ИДЕНТИФИКАТОР на идентификатор чата с ботом или идентификатор группового чата: chat_id:ИДЕНТИФИКАТОР
Отправка push уведомлений доступна только для брендированных версий мобильных приложений.
Для настройки отправки push уведомлений в брендированное Android-приложение необходимо через веб-консоль Firebase:
Service accounts создать новый приватный ключ (Generate new private key) и скачать егоНа сервере, на котором установлен веб-портал Форпост, выполнить следующие действия:
/var/www/cctv-portal/protected/config/android_push.jsonchmod 644 /var/www/cctv-portal/protected/config/android_push.json
Для отображения камер на карте необходимо установить OSM (OpenStreetMaps):
apt install docker.io
docker volume create osm-data
РЕГИОН-latest.osm.pbf для нужного регионаИМЯ_ФАЙЛА.osm.pbf, и выполнить импорт карты из скачанного файла:wget -O /var/www/cctv-portal/protected/config/region.osm.pbf http://download.geofabrik.de/russia/ИМЯ_ФАЙЛА.osm.pbf
docker run --name osm_import -v /var/www/cctv-portal/protected/config/region.osm.pbf:/data/region.osm.pbf -v osm-data:/data/database/ overv/openstreetmap-tile-server import
Если на карте требуется отобразить несколько регионов, то необходимо скачать файлы этих регионов, после чего выполнить команду osmium merge. Например:
osmium merge central-fed-district-latest.osm.pbf volga-fed-district-latest.osm.pbf northwestern-fed-district-latest.osm.pbf -o region.osm.pbf
После чего выполнить команду docker run (заменив ПУТЬ_К_ПАПКЕ):
docker run --name osm_import -v ПУТЬ_К_ПАПКЕ/region.osm.pbf:/data/region.osm.pbf -v osm-data:/data/database/ overv/openstreetmap-tile-server import
В зависимости от того, использует веб-портал протокол HTTPS или HTTP, выполнить на сервере действия, указанные ниже.
Запустить docker-контейнер, который будет принимать подключения на 127.0.0.1 (по умолчанию порт 20081):
docker run --name osm --restart always -d -p 127.0.0.1:20081:80 -v osm-data:/data/database/ -d overv/openstreetmap-tile-server run
Настроить веб-сервер Apache:
a2enmod proxy
a2enmod proxy_http
Listen 20080
VirtualHost, который использует SSL-сертификат, полученный от Let's Encrypt для домена WEB_DOMAIN:<VirtualHost *:20080>
ServerName WEB_DOMAIN
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/WEB_DOMAIN/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/WEB_DOMAIN/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:20081/
ProxyPassReverse / http://127.0.0.1:20081/
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
</VirtualHost>
/var/www/cctv-portal/protected/config/local.php в секцию components добавить параметры, заменив WEB_DOMAIN:'geomaps'=>[
'vendor' => 'osm',
'tileHost' => 'https://WEB_DOMAIN:20080/tile/{z}/{x}/{y}.png',
],
service apache2 restart
docker run --name osm --restart always -d -p 20080:80 -v osm-data:/data/database/ -d overv/openstreetmap-tile-server run
http://HOST:20080/tile/0/0/0.png, заменив HOST/var/www/cctv-portal/protected/config/local.php в секцию components добавить параметры, заменив WEB_DOMAIN:'geomaps'=>[
'vendor' => 'osm',
'tileHost' => 'http://WEB_DOMAIN:20080/tile/{z}/{x}/{y}.png',
],
На сервере c OSM выполнить команды:
docker exec -it osm bash -c "sed -i '/ServerAdmin/a\\
<Location /metrics>\\
Require all denied\\
</Location>' /etc/apache2/sites-available/000-default.conf"
docker restart osm
Чтобы разрешить доступ к административной панели и System API только с определенных IP-адресов, необходимо на сервере, на котором установлен веб-портал Форпост, выполнить следующие действия (в примере ниже разрешен доступ только с адресов 192.168.0.100/32 и 10.32.43.0/24):
1. Создать файл /var/www/cctv-portal/protected/config/ip_allowlist.php со следующим содержимым:
<?php
return array(
'AdminIpAllowlist' => array(
'192.168.0.100/32',
'10.32.43.0/24',
),
'SystemApiIpAllowlist' => array(
'192.168.0.100/32',
'10.32.43.0/24',
),
);
?>
При пустом массиве AdminIpAllowlist/SystemApiIpAllowlist доступ к соответствующему разделу не ограничивается.
2. В настройках веб-сервера Apache (инструкция для версии 2.4) в настройке VirtualHost добавить директивы LocationMatch.
<LocationMatch "(?i)^/admin">
Require ip 192.168.0.100/32
Require ip 10.32.43.0/24
</LocationMatch>
<LocationMatch "(?i)^/system-?api">
Require ip 192.168.0.100/32
Require ip 10.32.43.0/24
</LocationMatch>
Для ограничения доступа к веб-порталу только с IP-адресов определённой страны нужно:
sudo apt-get install libapache2-mod-geoip
sudo a2enmod geoip
/etc/apache2/mods-available/geoip.conf<IfModule mod_geoip.c>
GeoIPEnable On
GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
</IfModule>
<Location "/">
SetEnvIf GEOIP_COUNTRY_CODE RU AllowCountry
Deny from all
Allow from env=AllowCountry
</Location>
В этом примере, запросы от пользователей из России будет разрешены, а все остальные запросы будут блокироваться.
Получить доступ к камере по RTSP-ссылке можно одним из следующих способов:
rtsp://HOST:PORT/rtsp/TRANSLATION_ID/TRANSLATION_GUIDTRANSLATION_ID и TRANSLATION_GUID генерируются автоматически случайным образом.rtsp://USER_LOGIN:USER_PASSORD@STREAMER_HOST:STREAMER_PORT/camera/CAMERA_ID/onlineДля постоянных RTSP-ссылок, которые были активированы, можно дополнительно ограничить доступ по IP-адресам пользователей:
1. Ограничить сетевой интерфейс стримера (например, только тем сетевым интерфейсом сервера, который доступен из внутренней сети), через который стример будет транслировать потоки статических RTSP-ссылок. Для ограничения сетевого интерфейса стримера, который будет использоваться для трансляции потоков статических RTSP-ссылок, необходимо в конфиг стримера streamer.conf добавить параметр public_translation_server_address, заменив STREAMER_IP на нужное значение:
public_translation_server_address: "STREAMER_IP",
2. Ограничить список IP-адресов, которые могут подключаться по статической RTSP-ссылке камеры. Для этого необходимо через административную панель Форпост:

Квота камеры - это объем дискового пространства, который потребуется для хранения архива камеры. Квота рассчитывается для каждой камеры как произведение битрейта камеры и длительности архива, выбранной в настройках камеры в Форпост.
При добавлении/редактировании камеры квота камеры сравнивается с доступным дисковым пространством. Доступное дисковое пространство рассчитывается как разница между общим дисковым пространством и суммой квот уже существующих камер.
Чтобы открыть список камер с информацией об их квотах, необходимо в административной панели на странице "Обзор" нажать ссылку "Статистика по всем камерам".
По умолчанию используется статический расчет квот. При таком способе в расчете квоты используется битрейт, указанный в настройках камер со стороны Форпост:
Динамический расчет квот позволяет рассчитывать квоты таким образом, чтобы при определении дискового пространства, которое требуется для записи камер, использовался фактический битрейт, с которым каждая камера выполняла запись за предыдущие 24 часа.
Чтобы изменить способ расчета квот со статического на динамический, необходимо на сервере, где установлен веб-портал Форпост, в файл /etc/crontab добавить строку:
Для ОС Ubuntu/Debian:
15 2 * * * www-data /usr/bin/php /var/www/cctv-portal/protected/cron.php QuotaRatio
Для ОС CentOS:
15 2 * * * apache php /var/www/cctv-portal/protected/cron.php QuotaRatio
После строки необходимо обязательно добавить пустую строку (перевод строки).
Изменения вступят в силу после 02:15 следующего дня.
Отключить проверку дискового пространства при добавлении/редактировании камер можно следующим образом:
Streamer в поле ReservedSpace указать отрицательное значение -43980465111040. Указанное значение – это 40 ТБ, на которые система при валидации будет увеличивать доступное пространство, и проверка будет гарантированно успешной:mysql cctv
update Streamer set ReservedSpace = -43980465111040;
service cctv-master restart
Для настройки отправки push уведомлений в Telegram необходимо:
/newbot и сохранить значение значение HTTP API токен, которое вернет @BotFather/var/www/cctv-portal/protected/config/local.php в секцию params добавить параметр TelegramBotToken, заменив заменив BOT_TOKEN на значение HTTP API токен:'TelegramBotToken' => 'BOT_TOKEN',
/etc/crontab новую строку:Для ОС Ubuntu/Debian:
*/5 * * * * www-data /usr/bin/php /var/www/cctv-portal/protected/cron.php gettelegrambotupdates
Для ОС CentOS:
*/5 * * * * apache php /var/www/cctv-portal/protected/cron.php gettelegrambotupdates
НастройкиЛичные данные указать значение в поле Username в Telegram, которое скопировать из настроек своего профиля в Telegram (без символа @)Оповещения для камеры, для которой требуется включить оповещения, кликнуть ссылку Настройки и активировать опцию Через TelegramUsername был ранее указан в Личных данных, открыть чат с ботом и нажать кнопку StartВ случае, если push уведомления необходимо отправлять в группу в Telegram, необходимо дополнительно выполнить следующие действия:
BOT_NAME (можно скопировать из профиля бота - значение после символа @):/getchatid @BOT_NAME
CHAT_ID, выполнив в командной строке Linux следующую команду, заменив {BOT_TOKEN} на значение параметра TelegramBotToken из конфига /var/www/cctv-portal/protected/config/local.php:curl -X POST -s https://api.telegram.org/bot{BOT_TOKEN}/getUpdates | grep -Poza '"chat":{"id":-.+?,'
CHAT_ID (вместе со знаком -):"chat":{"id":CHAT_ID,
LOGIN и CHAT_ID:update User set TelegramBotChatID = 'CHAT_ID' where Login = 'LOGIN';
Отправка push уведомлений доступна только для брендированных версий мобильных приложений.
Для настройки отправки push уведомлений в брендированное Android-приложение необходимо через веб-консоль Firebase:
Service accounts создать новый приватный ключ (Generate new private key) и скачать егоНа сервере, на котором установлен веб-портал Форпост, выполнить следующие действия:
/var/www/cctv-portal/protected/config/android_push.jsonchmod 644 /var/www/cctv-portal/protected/config/android_push.json
Для отправки push уведомлений в брендированное iOS-приоложение необходимо:
Apple Push Notification service SSL (Sandbox & Production)/var/www/cctv-portal/protected/config/push.pem/var/www/cctv-portal/protected/config/local.php в секцию params добавить, заменив IOS_APP_BUNDLE_ID:'IosBundleID' => 'IOS_APP_BUNDLE_ID',Если используется несколько брендированных приложений, для отправки push уведомлений в эти приложения необходимо выполнить на сервере, на которому установлен веб-портал Форпост, следующие действия, заменив {ClientType} на идентификатор приложения:
/var/www/cctv-portal/protected/config/{ClientType}android_push.json/var/www/cctv-portal/protected/config/local.php в секцию params добавить:'{ClientType}GoogleAPICredentials' => 'ПУТЬ_К_ФАЙЛУ_ПРИВАТНОГО_КЛЮЧА_ПРИЛОЖЕНИЯ',/var/www/cctv-portal/protected/config/{ClientType}push.pem/var/www/cctv-portal/protected/config/local.php в секцию params добавить, заменив IOS_APP_BUNDLE_ID:'{ClientType}IosBundleID' => 'IOS_APP_BUNDLE_ID',HTML код для встраивания онлайн видео на сайт можно получить либо через административную панель: страница камеры → вкладка Общий доступ. В HTML коде для страницы embed.html можно использовать следующие параметры:
Чтобы для пользователей, включая администраторов, появилась возможность при входе в приложения Форпост проверять пароль с помощью внешнего сервера, доступного по протоколу LDAP, на сервере, на котором установлен веб-портал Форпост, необходимо выполнить следующие действия:
/var/www/cctv-portal/protected/config/local.php в секцию params добавить строку:'EnableUserAuthProviders' => true,INSERT INTO `AuthProvider` (`TypeID`, `Params`, `Name`, `IsDefault`) VALUES (6, NULL, 'LDAP', 0);apt-get install php-ldapservice apache2 restartНастройки сайта на вкладке LDAP указать параметры подключения к LDAP-серверу. В зависимости от того, указан или нет параметр Атрибут поиска пользователя, будет по-разному через LDAP-сервер выполняться проверка пользователя, который выполняет вход:Атрибут поиска пользователя указан:Атрибут поиска пользователя=Логин пользователя,Базовое имя для каталогаАтрибут поиска пользователя=Логин пользователяАтрибут поиска пользователя не указан:Логин пользователя@Доменное имя сервера(&(sAMAccountName=Логин пользователя))Способ проверки пароля и выбрать вариант LDAPПодготовить к репликации первый сервер MySQL:
/etc/mysql/my.cnf первого сервера добавить, заменив SERVER_IP:[mysqld]
server_id = 1
log_bin = /var/log/mysql/mysql-bin.log
log_bin_index = /var/log/mysql/mysql-bin.log.index
relay_log = /var/log/mysql/mysql-relay-bin
relay_log_index = /var/log/mysql/mysql-relay-bin.index
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
log_slave_updates = 1
auto-increment-increment = 2
auto-increment-offset = 1
expire_logs_days = 7
bind-address = SERVER_IP
PASSWORD:create user 'replication1'@'%' identified by 'PASSWORD';
grant replication slave on *.* to 'replication1'@'%';
flush privileges;
mkdir /var/log/mysql
chown mysql:mysql /var/log/mysql
service mysql restart
Подготовить к репликации второй сервер MySQL:
/etc/mysql/my.cnf второго сервера добавить, заменив SERVER_IP:[mysqld]
server_id = 2
log_bin = /var/log/mysql/mysql-bin.log
log_bin_index = /var/log/mysql/mysql-bin.log.index
relay_log = /var/log/mysql/mysql-relay-bin
relay_log_index = /var/log/mysql/mysql-relay-bin.index
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
log_slave_updates = 1
auto-increment-increment = 2
auto-increment-offset = 1
expire_logs_days = 7
bind-address = SERVER_IP
PASSWORD:create user 'replication2'@'%' identified by 'PASSWORD';
grant replication slave on *.* to 'replication2'@'%';
flush privileges;
mkdir /var/log/mysql
chown mysql:mysql /var/log/mysql
service mysql restart
Запустить репликацию с первого на второй сервер MySQL:
mysql -e "show master status;"
SERVER_1_IP, PASSWORD, SERVER_1_STATUS_LOG_FILE_NAME, SERVER_1_STATUS_LOG_POSITION:STOP SLAVE;
CHANGE MASTER TO MASTER_HOST = 'SERVER_1_IP', MASTER_USER = 'replication1', MASTER_PASSWORD = 'PASSWORD', MASTER_LOG_FILE = 'SERVER_1_STATUS_LOG_FILE_NAME', MASTER_LOG_POS = SERVER_1_STATUS_LOG_POSITION;
START SLAVE;
SHOW SLAVE STATUS \G;
Запустить репликацию с второго на первый сервер MySQL:
mysql -e "show master status;"
SERVER_2_IP, PASSWORD, SERVER_2_STATUS_LOG_FILE_NAME, SERVER_2_STATUS_LOG_POSITION:STOP SLAVE;
CHANGE MASTER TO MASTER_HOST = 'SERVER_2_IP', MASTER_USER = 'replication2', MASTER_PASSWORD = 'PASSWORD', MASTER_LOG_FILE = 'SERVER_2_STATUS_LOG_FILE_NAME', MASTER_LOG_POS = SERVER_2_STATUS_LOG_POSITION;
START SLAVE;
SHOW SLAVE STATUS \G;
Для Debian/Ubuntu:
sudo apt update
sudo apt install fail2ban
Для современных систем c systemd:
sudo systemctl enable --now fail2ban
Для устаревших систем с init.d
sudo update-rc.d fail2ban defaults
Для CentOS:
sudo yum install epel-release
sudo yum install fail2ban
Для современных систем c systemd:
sudo systemctl enable --now fail2ban
Для устаревших систем с init.d
sudo chkconfig fail2ban on
Создать файл /etc/fail2ban/filter.d/forpost-security.conf со следющим содержанием:
[Definition]
_pfx = ^\s*\[(?:error|warning)\] \[security\.[a-z]+\] \[ip=
_uri = %(_pfx)s[^\]]*\] \[uri=
failregex = %(_pfx)s<HOST>\]
ignoreregex = %(_uri)s/account/camera/[^/]+/StopTranslation\.html
%(_uri)s/api/StopTranslation
datepattern = ^%%Y/%%m/%%d %%H:%%M:%%S
Создать файл /etc/fail2ban/filter.d/forpost-http.conf со следющим содержанием:
[Definition]
_pfx = ^\s*\[(?:error|warning)\] \[exception\.CHttpException\.(?:400|404|500)\] \[ip=
_uri = %(_pfx)s[^\]]*\] \[uri=
failregex = %(_pfx)s<HOST>\]
ignoreregex = %(_uri)s/(?:robots\.txt|favicon\.ico|sitemap\.xml|apple-touch-icon[^\]]*|browserconfig\.xml|\.well-known/)\]
%(_uri)s/account/camera/[^/]+/StopTranslation\.html
%(_uri)s/api/StopTranslation
datepattern = ^%%Y/%%m/%%d %%H:%%M:%%S
Создать файл /etc/fail2ban/jail.d/forpost.conf со следющим содержанием:
[forpost-security]
enabled = true
filter = forpost-security
port = http,https
logpath = /var/www/cctv-portal/protected/runtime/security.log
findtime = 3600
maxretry = 20
bantime = 3600
backend = polling
[forpost-404]
enabled = true
filter = forpost-http
port = http,https
logpath = /var/www/cctv-portal/protected/runtime/http_404.log
findtime = 1200
maxretry = 25
bantime = 3600
backend = polling
[forpost-400]
enabled = true
filter = forpost-http
port = http,https
logpath = /var/www/cctv-portal/protected/runtime/http_400.log
findtime = 1200
maxretry = 10
bantime = 3600
backend = polling
[forpost-500]
enabled = true
filter = forpost-http
port = http,https
logpath = /var/www/cctv-portal/protected/runtime/http_500.log
findtime = 1200
maxretry = 25
bantime = 3600
backend = polling
Создать не существующие лог файлы:
systemctl edit fail2banДля Ubuntu/Debian
[Service]
ExecStartPre=/usr/bin/touch /var/www/cctv-portal/protected/runtime/security.log /var/www/cctv-portal/protected/runtime/http_400.log /var/www/cctv-portal/protected/runtime/http_404.log /var/www/cctv-portal/protected/runtime/http_500.log
ExecStartPre=/usr/bin/chown www-data:www-data /var/www/cctv-portal/protected/runtime/security.log /var/www/cctv-portal/protected/runtime/http_400.log /var/www/cctv-portal/protected/runtime/http_404.log /var/www/cctv-portal/protected/runtime/http_500.log
Для CentOS
[Service]
ExecStartPre=/usr/bin/touch /var/www/cctv-portal/protected/runtime/security.log /var/www/cctv-portal/protected/runtime/http_400.log /var/www/cctv-portal/protected/runtime/http_404.log /var/www/cctv-portal/protected/runtime/http_500.log
ExecStartPre=/usr/bin/chown apache:apache /var/www/cctv-portal/protected/runtime/security.log /var/www/cctv-portal/protected/runtime/http_400.log /var/www/cctv-portal/protected/runtime/http_404.log /var/www/cctv-portal/protected/runtime/http_500.log
Перезапустить fail2ban командой:
systemctl restart fail2ban
for jail in forpost-security forpost-404 forpost-400 forpost-500; do echo -e "\n=== Статус $jail ==="; fail2ban-client status $jail; done
=== Статус forpost-security ===
Status for the jail: forpost-security
|- Filter
| |- Currently failed: 12
| |- Total failed: 1043
| `- File list:
`- Actions
|- Currently banned: 0
|- Total banned: 4
`- Banned IP list:
=== Статус forpost-404 ===
Status for the jail: forpost-404
|- Filter
| |- Currently failed: 4
| |- Total failed: 6039
| `- File list:
`- Actions
|- Currently banned: 0
|- Total banned: 121
`- Banned IP list:
=== Статус forpost-400 ===
Status for the jail: forpost-400
|- Filter
| |- Currently failed: 3
| |- Total failed: 7
| `- File list:
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
for jail in forpost-security forpost-404 forpost-400 forpost-500; do echo "Очистка jail: $jail"; fail2ban-client unban --all $jail; done
Очистка jail: forpost-security
0
Очистка jail: forpost-404
0
Очистка jail: forpost-400
0
Пример перехода на московское время (Europe/Moscow).
Установить часовой пояс ОС:
timedatectl set-timezone Europe/Moscow
В двух файлах указать одинаковое значение timeZone:
runuser -u www-data -- nano /var/www/cctv-portal/protected/config/local.php
runuser -u www-data -- nano /var/www/cctv-portal/protected/runtime/config.php
Перезапустить службы, чтобы они применили новый часовой пояс:
systemctl restart mysql
systemctl restart apache2
systemctl restart cctv-master
systemctl restart cctv-streamer
Названия могут отличаться: например, mariadb вместо mysql.
Проверить время сервера
date
Чт 10 сен 2026 08:00:07 MSK
Проверить время MySQL
mysql -u root -p -e \
"SELECT NOW(), UTC_TIMESTAMP(), @@global.time_zone, @@session.time_zone;"
| NOW() | UTC_TIMESTAMP() | @@global.time_zone | @@session.time_zone |
|---|---|---|---|
| 2026-09-10 08:00:17 | 2026-09-10 05:00:17 | SYSTEM | SYSTEM |
Проверить время последних 5 событий
mysql -u root -p -D cctv -e \
"SELECT ID, CreationDate, EventTypeID, EventSubjectID FROM Event ORDER BY ID DESC LIMIT 5;"
| ID | CreationDate | EventTypeID | EventSubjectID |
|---|---|---|---|
| 101009 | 2026-09-10 08:00:02 | 1 | 120 |
| 101008 | 2026-09-10 08:00:00 | 1 | 127 |
| 101007 | 2026-09-10 08:00:00 | 1 | 127 |
| 101006 | 2026-09-10 08:00:00 | 1 | 127 |
| 101005 | 2026-09-10 08:00:00 | 1 | 127 |
Модуль "Таймлапс" собирает видеоролики из кадров камеры. Ролики бывают двух видов:
Кадры и ролики хранятся в MinIO. Готовые ролики пользователь смотрит и скачивает в личном кабинете, в отчете "Таймлапс". Настраивает модуль только администратор в административной панели.
Все задачи выполняет портал: съемку, очередь, сборку и удаление устаревших роликов.
Ролики находятся в разделе «Отчеты», пункт «Таймлапс». Пункт виден пользователю, у которого есть право на видеоаналитику хотя бы одной камеры с включенным модулем. Кнопка «Смотреть» открывает ролик в окне просмотра, «Скачать» сохраняет файл MP4.
Для работы модуля "Таймлапс" требуется соответствующая лицензия.
Требуется установить на сервер ffmpeg с кодеком libx264. Вызов должен быть доступен из командной строки по команде ffmpeg.
Для работы модуля “Таймлапс” требуется установить на сервер Minio. Для размещения файлов хранения Minio рекомендуется использовать файловую систему XFS. Вариант установки Minio с использованием Docker на том же сервере, на котором установлен веб-портал Форпост:
<root-пароль> - сгенерировать
sudo tee /root/minio.env >/dev/null <<'EOF'
MINIO_ROOT_USER=minioadmin-forpost
MINIO_ROOT_PASSWORD=<root-пароль>
EOF
sudo chmod 600 /root/minio.env
</path/to/minio-data-folder> - заменить
sudo mkdir -p </path/to/minio-data-folder>
sudo docker run -d --name fpst_minio --restart unless-stopped \
--env-file /root/minio.env \
-v </path/to/minio-data-folder>:/data \
-p 127.0.0.1:19000:9000 \
-p 127.0.0.1:19001:9001 \
quay.io/minio/minio server /data --console-address ":9001"
curl -fsS http://127.0.0.1:19000/minio/health/live && echo OK
mc к серверу (внутри контейнера MinIO слушает порт 9000):<root-пароль> - заменить на ранее сгененированный
sudo docker exec fpst_minio mc alias set local http://127.0.0.1:9000 minioadmin-forpost '<root-пароль>'
sudo docker exec fpst_minio mc mb local/forpost
<пароль-портала> - сгенерировать
sudo docker exec -i fpst_minio sh -c 'cat > /tmp/forpost-portal.json' <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{"Effect": "Allow", "Action": ["s3:ListBucket", "s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::forpost"]},
{"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:GetObjectVersion",
"s3:DeleteObject", "s3:DeleteObjectVersion"],
"Resource": ["arn:aws:s3:::forpost/*"]}
]
}
EOF
sudo docker exec fpst_minio mc admin policy create local forpost-portal /tmp/forpost-portal.json
sudo docker exec fpst_minio mc admin user add local forpost-portal '<пароль-портала>'
sudo docker exec fpst_minio mc admin policy attach local forpost-portal --user forpost-portal
<пароль-портала> - заменить на ранее сгенерированный
'storage' => array(
'class' => 'Storage',
'type' => 'minio',
'address' => 'http://127.0.0.1:19000',
'username' => 'forpost-portal', // access key
'password' => '<пароль-портала>', // secret key
'bucket' => 'forpost',
'region' => 'ru',
'objectUrlEnabled' => false,
),
Требуется в /etc/crontab добавить задачи, которые будут снимать кадры и собирать ролики:
<пользователь> - заменить на:
* * * * * <пользователь> php <корень портала>/protected/cron.php Timelapse capture
* * * * * <пользователь> php <корень портала>/protected/cron.php Timelapse plan
* * * * * <пользователь> php <корень портала>/protected/cron.php Timelapse run
30 3 * * * <пользователь> php <корень портала>/protected/cron.php Timelapse clean
Настройка модуля для каждой камеры выполняется индивидуально через административную панель на странице камеры (Управление камерой → Видеоаналитика → Таймлапс).
Все даты и время в окне настройки модуля указаны в часовом поясе камеры. Если у камеры часовой пояс не задан, используется часовой пояс веб-портала.
В окне настроек модуля расположены две вкладки:
Ролики по расписанию задаются профилями. Профиль описывает, как часто снимать кадры и за какой период собирать ролик. На одной камере может быть несколько профилей, например ролик за каждые сутки и ролик за месяц. Кадры профили снимают общие, если их расписания совпадают.
Профиль добавляется кнопкой «Добавить профиль», удаляется ссылкой «Удалить» в его заголовке. Изменения вступают в силу после кнопки «Сохранить».
Кадры снимаются по расписанию, которое отсчитывается от времени первого кадра. При частоте 60 минут и первом кадре в 09:00 кадры будут в 10:00, 11:00, 12:00 и так далее. При частоте 1 сут и первом кадре в 12:00 будет один кадр в день, ровно в 12:00.
При частоте меньше часа камеры автоматически разносятся по разным минутам, чтобы не нагружать стример одновременно. Камера с частотой 5 минут может снимать в 09:02, 09:07, 09:12, а соседняя в 09:03, 09:08. На ролик это не влияет.
Первый кадр снимается в ближайшую минуту по расписанию после сохранения профиля.
Итоговый ролик собирается сразу после окончания периода:
| Период | Ролик за | Итоговый ролик собирается |
|---|---|---|
| Час | прошедший час, например 13:00-14:00 | в начале следующего часа |
| Сутки | сутки с 00:00 до 00:00 | в 00:00 следующих суток |
| Неделя | с понедельника 00:00 до следующего понедельника | в понедельник в 00:00 |
| Месяц | с 1-го числа до 1-го числа следующего месяца | 1-го числа в 00:00 |
| Год | с 1 января до 1 января следующего года | 1 января в 00:00 |
За каждый период получается свой ролик, прежние ролики остаются до конца срока хранения.
Чтобы видеть ролик до конца периода, включите обновление. Например, при периоде «Сутки» и обновлении «Раз в час» в 01:00 соберется ролик за 00:00-01:00, в 02:00 за 00:00-02:00 и так далее. Это одна и та же карточка в личном кабинете, она обновляется, а после итоговой сборки получает отметку «завершен».
Каждое обновление собирает ролик заново из всех кадров периода. Частые обновления длинных роликов нагружают сервер: годовой ролик с кадром раз в минуту лучше обновлять раз в месяц.
Разовая задача собирает один ролик за выбранный интервал из архива камеры. Задача ставится в очередь сразу, кнопкой «Сохранить» на вкладке «По расписанию» ее сохранять не нужно, поток камеры не перезапускается. Поставить задачу можно, только когда модуль на камере включен и сохранен.
Для разовых задач нужна постоянная запись. Если у камеры другой тип записи, окно предупредит: в ролике будут пропуски.
После нажатия «Поставить в очередь» окно сообщает, когда начнется сборка и сколько примерно она займет. Ниже формы список последних задач камеры с состоянием: в очереди, собирается N %, готово или ошибка с причиной. Задачу в очереди и задачу с ошибкой можно удалить.