#!/bin/bash # Скрипт установки F7cloud Talk Recording Server # Этот скрипт устанавливает все необходимые зависимости и настраивает сервер # # Использование: # sudo ./install.sh [OPTIONS] # # Опции: # --hpb-url URL URL сервера HPB (signaling server) # --hpb-secret SECRET Секрет для подключения к HPB (internalsecret) # --f7cloud-url URL URL сервера F7cloud (опционально) # --f7cloud-secret SECRET Секрет для подключения к F7cloud (опционально) # --listen ADDRESS:PORT Адрес и порт для прослушивания (по умолчанию: 127.0.0.1:8000) # # Пример: # sudo ./install.sh --hpb-url https://hpb.example.com --hpb-secret your-secret-here set -e # Цвета для вывода RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Функция для вывода сообщений info() { echo -e "${GREEN}[INFO]${NC} $1" } warn() { echo -e "${YELLOW}[WARN]${NC} $1" } error() { echo -e "${RED}[ERROR]${NC} $1" } # Функция для безопасного копирования с проверками safe_copy() { local source="$1" local dest="$2" if [ ! -e "$source" ]; then error "Источник не существует: $source" return 1 fi # Создаем целевую директорию, если её нет local target_dir=$(dirname "$dest") if [ ! -d "$target_dir" ]; then mkdir -p "$target_dir" fi cp -a "$source" "$dest" # Проверяем успешность копирования if [ ! -e "$dest" ]; then error "Не удалось скопировать $source в $dest" return 1 fi return 0 } # Функция для вывода справки show_help() { echo "Использование: $0 [OPTIONS]" echo "" echo "Опции:" echo " --hpb-url URL URL сервера HPB (signaling server) - ОБЯЗАТЕЛЬНО" echo " --hpb-secret SECRET Секрет для подключения к HPB (internalsecret) - ОБЯЗАТЕЛЬНО" echo " --f7cloud-url URL URL сервера F7cloud (опционально)" echo " --f7cloud-secret SECRET Секрет для подключения к F7cloud (опционально)" echo " --listen ADDRESS:PORT Адрес и порт для прослушивания (по умолчанию: 127.0.0.1:8000)" echo " --help Показать эту справку" echo "" echo "Пример:" echo " sudo $0 --hpb-url https://hpb.example.com --hpb-secret your-secret-here" } # Парсинг аргументов HPB_URL="" HPB_SECRET="" F7CLOUD_URL="" F7CLOUD_SECRET="" LISTEN_ADDRESS="127.0.0.1:8000" while [[ $# -gt 0 ]]; do case $1 in --hpb-url) HPB_URL="$2" shift 2 ;; --hpb-secret) HPB_SECRET="$2" shift 2 ;; --f7cloud-url) F7CLOUD_URL="$2" shift 2 ;; --f7cloud-secret) F7CLOUD_SECRET="$2" shift 2 ;; --listen) LISTEN_ADDRESS="$2" shift 2 ;; --help) show_help exit 0 ;; *) error "Неизвестный параметр: $1" show_help exit 1 ;; esac done # Проверяем обязательные параметры (из аргументов или переменных окружения) if [ -z "$HPB_URL" ]; then # Пробуем получить из переменной окружения HPB_URL="${HPB_URL_ENV:-}" fi if [ -z "$HPB_SECRET" ]; then # Пробуем получить из переменной окружения HPB_SECRET="${HPB_SECRET_ENV:-}" fi if [ -z "$F7CLOUD_URL" ]; then # Пробуем получить из переменной окружения F7CLOUD_URL="${F7CLOUD_URL_ENV:-}" fi if [ -z "$F7CLOUD_SECRET" ]; then # Пробуем получить из переменной окружения F7CLOUD_SECRET="${F7CLOUD_SECRET_ENV:-}" fi if [ -z "$LISTEN_ADDRESS" ] || [ "$LISTEN_ADDRESS" = "127.0.0.1:8000" ]; then # Пробуем получить из переменной окружения, если не задано явно if [ -n "${LISTEN_ADDRESS_ENV:-}" ]; then LISTEN_ADDRESS="${LISTEN_ADDRESS_ENV}" fi fi if [ -z "$HPB_URL" ] || [ -z "$HPB_SECRET" ]; then error "Ошибка: --hpb-url и --hpb-secret являются обязательными параметрами" error "" error "Использование:" error " $0 --hpb-url URL --hpb-secret SECRET [OPTIONS]" error "" error "Или используйте переменные окружения:" error " export HPB_URL_ENV='https://hpb.example.com'" error " export HPB_SECRET_ENV='your-secret'" error " $0" echo "" show_help exit 1 fi # Вывод используемых параметров info "Используемые параметры:" info " HPB URL: $HPB_URL" info " HPB Secret: [скрыт]" if [ -n "$F7CLOUD_URL" ]; then info " F7cloud URL: $F7CLOUD_URL" if [ -n "$F7CLOUD_SECRET" ]; then info " F7cloud Secret: [скрыт]" fi fi info " Listen: $LISTEN_ADDRESS" info "" # Проверка прав root if [ "$EUID" -ne 0 ]; then error "Пожалуйста, запустите скрипт с правами root (sudo)" exit 1 fi info "Начинаем установку F7cloud Talk Recording Server..." # Определение дистрибутива if [ -f /etc/debian_version ]; then DISTRO="debian" PKG_MANAGER="apt-get" elif [ -f /etc/redhat-release ]; then DISTRO="redhat" PKG_MANAGER="yum" else error "Неподдерживаемый дистрибутив Linux" exit 1 fi # Получение директории скрипта SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" # 1. Установка системных зависимостей info "Установка системных зависимостей..." if [ "$DISTRO" = "debian" ]; then $PKG_MANAGER update -y $PKG_MANAGER install -y \ python3 \ python3-pip \ python3-venv \ pulseaudio \ xvfb \ ffmpeg \ libpulse0 \ libpulse-dev \ libx11-dev \ libxext-dev \ libxrender-dev \ libxtst6 \ libxi6 \ libgconf-2-4 \ libasound2-dev \ curl \ wget \ git \ bzip2 \ tar if [ $? -ne 0 ]; then error "Ошибка при установке системных зависимостей" exit 1 fi else error "Установка для RedHat-based дистрибутивов пока не поддерживается автоматически" exit 1 fi # 2. Установка Firefox ESR info "Установка Firefox ESR..." if [ -d "dependencies/firefox-esr" ] && [ -f "dependencies/firefox-esr/firefox" ]; then info "Использование Firefox ESR из dependencies..." # Проверяем существование директории перед копированием if [ ! -d "dependencies/firefox-esr" ]; then error "Директория dependencies/firefox-esr не найдена" exit 1 fi if [ ! -f "dependencies/firefox-esr/firefox" ]; then error "Исполняемый файл Firefox не найден в dependencies/firefox-esr/firefox" exit 1 fi # Создаем целевую директорию, если её нет if [ ! -d "/opt/firefox-esr" ]; then mkdir -p /opt/firefox-esr fi # Копируем с проверкой if ! safe_copy "dependencies/firefox-esr" "/opt/firefox-esr"; then error "Не удалось скопировать Firefox ESR" exit 1 fi ln -sf /opt/firefox-esr/firefox /usr/local/bin/firefox-esr chmod +x /usr/local/bin/firefox-esr # Проверяем успешность установки if [ ! -f "/usr/local/bin/firefox-esr" ] || [ ! -L "/usr/local/bin/firefox-esr" ]; then error "Не удалось создать символьную ссылку на Firefox ESR" exit 1 fi info "Firefox ESR установлен в /opt/firefox-esr" else warn "Firefox ESR не найден в dependencies/, пытаемся скачать..." # Определяем архитектуру ARCH=$(uname -m) if [ "$ARCH" = "x86_64" ]; then FIREFOX_ARCH="linux64" elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then FIREFOX_ARCH="linux-aarch64" else error "Неподдерживаемая архитектура: $ARCH" exit 1 fi info "Скачивание Firefox ESR для $FIREFOX_ARCH..." mkdir -p dependencies cd dependencies # Скачиваем последнюю версию Firefox ESR FIREFOX_URL="https://download.mozilla.org/?product=firefox-esr-latest-ssl&os=${FIREFOX_ARCH}&lang=en-US" if command -v wget &> /dev/null; then wget -q --show-progress -O firefox-esr.tar.bz2 "$FIREFOX_URL" elif command -v curl &> /dev/null; then curl -L -o firefox-esr.tar.bz2 "$FIREFOX_URL" else error "Не найден wget или curl для скачивания Firefox ESR" exit 1 fi if [ -f firefox-esr.tar.bz2 ]; then info "Распаковка Firefox ESR..." if ! tar -xjf firefox-esr.tar.bz2; then error "Не удалось распаковать Firefox ESR" exit 1 fi if [ ! -d firefox ]; then error "Директория firefox не найдена после распаковки" exit 1 fi mv firefox firefox-esr rm firefox-esr.tar.bz2 if [ ! -f firefox-esr/firefox ]; then error "Исполняемый файл Firefox не найден после распаковки" exit 1 fi if ! safe_copy "firefox-esr" "/opt/firefox-esr"; then error "Не удалось скопировать Firefox ESR в /opt" exit 1 fi ln -sf /opt/firefox-esr/firefox /usr/local/bin/firefox-esr chmod +x /usr/local/bin/firefox-esr # Проверяем успешность установки if [ ! -f "/usr/local/bin/firefox-esr" ] || [ ! -L "/usr/local/bin/firefox-esr" ]; then error "Не удалось создать символьную ссылку на Firefox ESR" exit 1 fi info "Firefox ESR установлен в /opt/firefox-esr" else error "Не удалось скачать Firefox ESR" exit 1 fi cd .. fi # 3. Установка Geckodriver info "Установка Geckodriver..." if [ -f "dependencies/geckodriver" ]; then if [ ! -f "dependencies/geckodriver" ]; then error "Файл dependencies/geckodriver не найден" exit 1 fi if ! safe_copy "dependencies/geckodriver" "/usr/local/bin/geckodriver"; then error "Не удалось скопировать Geckodriver" exit 1 fi chmod +x /usr/local/bin/geckodriver # Проверяем успешность установки if [ ! -f "/usr/local/bin/geckodriver" ]; then error "Geckodriver не найден после установки" exit 1 fi info "Geckodriver установлен в /usr/local/bin/geckodriver" elif [ -f "dependencies/geckodriver.tar.gz" ]; then info "Распаковка geckodriver из архива..." cd dependencies if ! tar -xzf geckodriver.tar.gz; then error "Не удалось распаковать Geckodriver" exit 1 fi if [ ! -f geckodriver ]; then error "Файл geckodriver не найден после распаковки" exit 1 fi chmod +x geckodriver if ! safe_copy "geckodriver" "/usr/local/bin/geckodriver"; then error "Не удалось скопировать Geckodriver" exit 1 fi cd .. # Проверяем успешность установки if [ ! -f "/usr/local/bin/geckodriver" ]; then error "Geckodriver не найден после установки" exit 1 fi info "Geckodriver установлен в /usr/local/bin/geckodriver" else warn "Geckodriver не найден в dependencies/, пытаемся скачать..." # Определяем архитектуру ARCH=$(uname -m) if [ "$ARCH" = "x86_64" ]; then GECKODRIVER_ARCH="linux64" elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then GECKODRIVER_ARCH="linux-aarch64" else error "Неподдерживаемая архитектура: $ARCH" exit 1 fi info "Скачивание Geckodriver для $GECKODRIVER_ARCH..." mkdir -p dependencies cd dependencies # Получаем последнюю версию geckodriver из GitHub releases GECKODRIVER_VERSION=$(curl -s https://api.github.com/repos/mozilla/geckodriver/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/' | sed 's/v//') if [ -z "$GECKODRIVER_VERSION" ]; then # Fallback на известную версию GECKODRIVER_VERSION="0.34.0" warn "Не удалось определить версию, используем $GECKODRIVER_VERSION" fi GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/v${GECKODRIVER_VERSION}/geckodriver-v${GECKODRIVER_VERSION}-${GECKODRIVER_ARCH}.tar.gz" if command -v wget &> /dev/null; then wget -q --show-progress -O geckodriver.tar.gz "$GECKODRIVER_URL" elif command -v curl &> /dev/null; then curl -L -o geckodriver.tar.gz "$GECKODRIVER_URL" else error "Не найден wget или curl для скачивания Geckodriver" exit 1 fi if [ -f geckodriver.tar.gz ]; then info "Распаковка Geckodriver..." if ! tar -xzf geckodriver.tar.gz; then error "Не удалось распаковать Geckodriver" exit 1 fi if [ ! -f geckodriver ]; then error "Файл geckodriver не найден после распаковки" exit 1 fi chmod +x geckodriver if ! safe_copy "geckodriver" "/usr/local/bin/geckodriver"; then error "Не удалось скопировать Geckodriver в /usr/local/bin" exit 1 fi rm geckodriver.tar.gz # Проверяем успешность установки if [ ! -f "/usr/local/bin/geckodriver" ]; then error "Geckodriver не найден после установки" exit 1 fi info "Geckodriver установлен в /usr/local/bin/geckodriver" else error "Не удалось скачать Geckodriver" exit 1 fi cd .. fi # 4. Создание виртуального окружения Python info "Создание виртуального окружения Python..." if [ ! -d "venv" ]; then if ! python3 -m venv venv; then error "Не удалось создать виртуальное окружение Python" exit 1 fi # Проверяем успешность создания if [ ! -d "venv" ] || [ ! -f "venv/bin/activate" ]; then error "Виртуальное окружение создано некорректно" exit 1 fi info "Виртуальное окружение создано" else warn "Виртуальное окружение уже существует, пропускаем создание..." # Проверяем, что существующее окружение валидно if [ ! -f "venv/bin/activate" ]; then error "Существующее виртуальное окружение повреждено" exit 1 fi fi # Активация виртуального окружения и установка зависимостей info "Установка Python-зависимостей..." source venv/bin/activate if ! pip install --upgrade pip; then error "Не удалось обновить pip" exit 1 fi if ! pip install -e .; then error "Не удалось установить Python-зависимости" exit 1 fi # Проверяем успешность установки if ! python3 -c "import f7cloud.talk.recording" 2>/dev/null; then error "Модуль f7cloud.talk.recording не найден после установки" exit 1 fi info "Python-зависимости установлены" # 5. Создание пользователя для запуска сервера info "Создание пользователя f7cloud-talk-recording..." if ! id "f7cloud-talk-recording" &>/dev/null; then if ! useradd -r -s /bin/false -d /var/lib/f7cloud-talk-recording f7cloud-talk-recording; then error "Не удалось создать пользователя f7cloud-talk-recording" exit 1 fi # Проверяем успешность создания if ! id "f7cloud-talk-recording" &>/dev/null; then error "Пользователь f7cloud-talk-recording не найден после создания" exit 1 fi info "Пользователь f7cloud-talk-recording создан" else warn "Пользователь f7cloud-talk-recording уже существует" fi # Создание директорий для пользователя if ! mkdir -p /var/lib/f7cloud-talk-recording; then error "Не удалось создать директорию /var/lib/f7cloud-talk-recording" exit 1 fi if ! chown f7cloud-talk-recording:f7cloud-talk-recording /var/lib/f7cloud-talk-recording; then error "Не удалось установить права на /var/lib/f7cloud-talk-recording" exit 1 fi # Проверяем успешность создания директории if [ ! -d "/var/lib/f7cloud-talk-recording" ]; then error "Директория /var/lib/f7cloud-talk-recording не найдена после создания" exit 1 fi # 6. Настройка конфигурации info "Настройка конфигурации..." mkdir -p /etc/f7cloud-talk-recording CONFIG_FILE="/etc/f7cloud-talk-recording/server.conf" if [ ! -f "$CONFIG_FILE" ]; then if [ ! -f "server.conf.in" ]; then error "Шаблон конфигурации server.conf.in не найден" exit 1 fi if ! safe_copy "server.conf.in" "$CONFIG_FILE"; then error "Не удалось создать конфигурационный файл" exit 1 fi # Проверяем успешность создания if [ ! -f "$CONFIG_FILE" ]; then error "Конфигурационный файл не найден после создания" exit 1 fi info "Конфигурационный файл создан в $CONFIG_FILE" # Настройка параметров конфигурации info "Настройка параметров конфигурации..." # Установка адреса прослушивания sed -i "s|#listen = 127.0.0.1:8000|listen = $LISTEN_ADDRESS|" "$CONFIG_FILE" # Настройка HPB (signaling server) if [ -n "$HPB_URL" ] && [ -n "$HPB_SECRET" ]; then info "Настройка HPB (signaling server)..." # Создаем ID для signaling сервера из URL HPB_ID=$(echo "$HPB_URL" | sed 's|https\?://||' | sed 's|/.*||' | sed 's|[^a-zA-Z0-9]|-|g' | sed 's|--*|-|g' | sed 's|^-\||' | sed 's|-$||') if [ -z "$HPB_ID" ]; then HPB_ID="hpb-signaling" fi # Раскомментируем и настраиваем секцию signaling sed -i "s|#signalings = signaling-id, another-signaling|signalings = $HPB_ID|" "$CONFIG_FILE" sed -i "s|#internalsecret = the-shared-secret-for-internal-clients|internalsecret = $HPB_SECRET|" "$CONFIG_FILE" # Добавляем секцию для конкретного signaling сервера if ! grep -q "^\[$HPB_ID\]" "$CONFIG_FILE"; then # Добавляем новую секцию после секции [signaling] cat >> "$CONFIG_FILE" << EOF [$HPB_ID] # URL of the signaling server url = $HPB_URL # Shared secret for authenticating as an internal client of signaling servers. # This must be the same value as configured in the signaling server # configuration file. internalsecret = $HPB_SECRET EOF else # Если секция уже существует, обновляем значения sed -i "/^\[$HPB_ID\]/,/^\[/ { s|^#url = .*|url = $HPB_URL| s|^url = .*|url = $HPB_URL| s|^#internalsecret = .*|internalsecret = $HPB_SECRET| s|^internalsecret = .*|internalsecret = $HPB_SECRET| }" "$CONFIG_FILE" fi info "HPB настроен: URL=$HPB_URL, ID=$HPB_ID" fi # Настройка F7cloud backend (опционально) if [ -n "$F7CLOUD_URL" ] && [ -n "$F7CLOUD_SECRET" ]; then info "Настройка F7cloud backend..." # Создаем ID для backend из URL BACKEND_ID=$(echo "$F7CLOUD_URL" | sed 's|https\?://||' | sed 's|/.*||' | sed 's|[^a-zA-Z0-9]|-|g' | sed 's|--*|-|g' | sed 's|^-\||' | sed 's|-$||') if [ -z "$BACKEND_ID" ]; then BACKEND_ID="f7cloud-backend" fi # Раскомментируем и настраиваем секцию backend sed -i "s|#backends = backend-id, another-backend|backends = $BACKEND_ID|" "$CONFIG_FILE" # Добавляем секцию для конкретного backend if ! grep -q "^\[$BACKEND_ID\]" "$CONFIG_FILE"; then # Добавляем новую секцию после секции [backend] cat >> "$CONFIG_FILE" << EOF [$BACKEND_ID] # URL of the F7cloud instance url = $F7CLOUD_URL # Shared secret for requests from and to the backend servers. This must be the # same value as configured in the F7cloud admin ui. secret = $F7CLOUD_SECRET EOF else # Если секция уже существует, обновляем значения sed -i "/^\[$BACKEND_ID\]/,/^\[/ { s|^#url = .*|url = $F7CLOUD_URL| s|^url = .*|url = $F7CLOUD_URL| s|^#secret = .*|secret = $F7CLOUD_SECRET| s|^secret = .*|secret = $F7CLOUD_SECRET| }" "$CONFIG_FILE" fi info "F7cloud backend настроен: URL=$F7CLOUD_URL, ID=$BACKEND_ID" fi # Настройка путей к браузеру и драйверу sed -i "s|#driverPath =|driverPath = /usr/local/bin/geckodriver|" "$CONFIG_FILE" sed -i "s|#browserPath =|browserPath = /usr/local/bin/firefox-esr|" "$CONFIG_FILE" chown f7cloud-talk-recording:f7cloud-talk-recording "$CONFIG_FILE" chmod 600 "$CONFIG_FILE" info "Конфигурация настроена автоматически" else warn "Конфигурационный файл уже существует, пропускаем создание..." warn "Если нужно обновить конфигурацию, отредактируйте $CONFIG_FILE вручную" fi # 7. Создание systemd service файла info "Создание systemd service..." cat > /etc/systemd/system/f7cloud-talk-recording.service << EOF [Unit] Description=F7cloud Talk Recording Server After=network.target [Service] Type=simple User=f7cloud-talk-recording Group=f7cloud-talk-recording WorkingDirectory=$SCRIPT_DIR Environment="PATH=$SCRIPT_DIR/venv/bin:/usr/local/bin:/usr/bin:/bin" ExecStart=$SCRIPT_DIR/venv/bin/f7cloud-talk-recording --config /etc/f7cloud-talk-recording/server.conf Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload info "Systemd service создан" # Итоговая информация info "" info "==========================================" info "Установка завершена успешно!" info "==========================================" info "" # Проверяем установленные компоненты info "Установленные компоненты:" [ -f "/usr/local/bin/firefox-esr" ] && info " ✓ Firefox ESR" [ -f "/usr/local/bin/geckodriver" ] && info " ✓ Geckodriver" [ -d "venv" ] && [ -f "venv/bin/activate" ] && info " ✓ Виртуальное окружение Python" [ -d "/var/lib/f7cloud-talk-recording" ] && info " ✓ Директория пользователя" [ -f "$CONFIG_FILE" ] && info " ✓ Конфигурационный файл" [ -f "/etc/systemd/system/f7cloud-talk-recording.service" ] && info " ✓ Systemd service" info "" info "Настроенные параметры:" info " HPB URL: $HPB_URL" info " Listen: $LISTEN_ADDRESS" if [ -n "$F7CLOUD_URL" ]; then info " F7cloud URL: $F7CLOUD_URL" fi info "" # Проверяем статус сервиса if systemctl list-unit-files | grep -q "f7cloud-talk-recording.service"; then if systemctl is-enabled --quiet f7cloud-talk-recording 2>/dev/null; then info "✓ Сервис f7cloud-talk-recording включен для автозапуска" else warn "⚠ Сервис f7cloud-talk-recording не включен для автозапуска" fi if systemctl is-active --quiet f7cloud-talk-recording 2>/dev/null; then info "✓ Сервис f7cloud-talk-recording запущен" else warn "⚠ Сервис f7cloud-talk-recording не запущен" fi fi info "" info "Следующие шаги:" if [ -z "$F7CLOUD_URL" ] || [ -z "$F7CLOUD_SECRET" ]; then info "1. Настройте F7cloud backend в конфигурации: $CONFIG_FILE" info " Добавьте секцию [backend-id] с url и secret" fi info "2. Проверьте конфигурацию: $CONFIG_FILE" info "3. Запустите сервис:" info " sudo systemctl start f7cloud-talk-recording" info "4. Включите автозапуск:" info " sudo systemctl enable f7cloud-talk-recording" info "5. Проверьте статус:" info " sudo systemctl status f7cloud-talk-recording" info "" info "Для получения дополнительной информации см. INSTALL.md" info ""