From ca7b2da587df36863f65af6f60346512aff347f1 Mon Sep 17 00:00:00 2001 From: hosh1 Date: Mon, 11 Aug 2025 04:38:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install.sh | 2219 +++++++++++++++++++++++++++------------------------- 1 file changed, 1158 insertions(+), 1061 deletions(-) diff --git a/install.sh b/install.sh index 9684432..8ad22dd 100644 --- a/install.sh +++ b/install.sh @@ -1,19 +1,26 @@ #!/bin/bash clear - set -e +# Переменные UNINSTALL=false REINSTALL=false +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOG_FILE="/tmp/altcor_install_$(date +%Y%m%d_%H%M%S).log" +# Цвета для вывода +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' + +# Обработка параметров командной строки while getopts ":ur" opt; do case $opt in - u) - UNINSTALL=true - ;; - r) - REINSTALL=true - ;; + u) UNINSTALL=true ;; + r) REINSTALL=true ;; \?) echo -e "${RED}[Ошибка]${NC} Неизвестный параметр: -$OPTARG" >&2 echo "Использование: $0 [-u] [-r]" @@ -24,134 +31,170 @@ while getopts ":ur" opt; do esac done -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -NC='\033[0m' - -log_success() { echo -e "${GREEN}[Успех]${NC} $1"; } -log_error() { echo -e "${RED}[Ошибка]${NC} $1"; } -log_info() { echo -e "${BLUE}[Инфо]${NC} $1"; } -log_warning() { echo -e "${YELLOW}[Предупреждение]${NC} $1"; } -log_step() { echo -e "${CYAN}[Шаг]${NC} $1"; } +# Функции логирования +log_to_file() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"; } +log_success() { echo -e "${GREEN}[Успех]${NC} $1"; log_to_file "SUCCESS: $1"; } +log_error() { echo -e "${RED}[Ошибка]${NC} $1"; log_to_file "ERROR: $1"; } +log_info() { echo -e "${BLUE}[Инфо]${NC} $1"; log_to_file "INFO: $1"; } +log_warning() { echo -e "${YELLOW}[Предупреждение]${NC} $1"; log_to_file "WARNING: $1"; } +log_step() { echo -e "${CYAN}[Шаг]${NC} $1"; log_to_file "STEP: $1"; } +# Генерация безопасного пароля generate_password() { - openssl rand -base64 32 | tr -d "=+/" | cut -c1-16 + if command -v openssl >/dev/null 2>&1; then + openssl rand -base64 32 | tr -d "=+/" | cut -c1-16 + else + # Fallback для систем без openssl + head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16 + fi } -check_component() { +# Проверка прав администратора +check_root() { + if [[ $EUID -ne 0 ]]; then + log_error "Запустите этот скрипт с правами администратора (sudo)." + exit 1 + fi +} + +# Определение дистрибутива +detect_distro() { + if [ -f /etc/os-release ]; then + source /etc/os-release + DISTRO="$ID" + FAMILY="$ID_LIKE" + VERSION_ID="${VERSION_ID}" + else + log_error "Не удалось определить дистрибутив." + exit 1 + fi + + if echo "$DISTRO $FAMILY" | grep -qi "debian\|ubuntu"; then + PKG_MANAGER="apt" + DISTRO_FAMILY="debian" + WEBSERVER_SERVICE="apache2" + WEBROOT="/var/www/html" + APACHE_CONF="/etc/apache2/sites-available/000-default.conf" + WEBSERVER_USER="www-data" + PHP_INI_PATH="/etc/php/8.3/apache2/php.ini" + DB_SOCKET="/var/run/mysqld/mysqld.sock" + elif echo "$DISTRO $FAMILY" | grep -qi "rhel\|centos\|fedora\|rocky\|almalinux"; then + DISTRO_FAMILY="rhel" + WEBSERVER_SERVICE="httpd" + WEBROOT="/var/www/html" + APACHE_CONF="/etc/httpd/conf.d/altcor.conf" + WEBSERVER_USER="apache" + DB_SOCKET="/var/lib/mysql/mysql.sock" + + if command -v dnf >/dev/null 2>&1; then + PKG_MANAGER="dnf" + else + PKG_MANAGER="yum" + fi + + # Определяем путь к PHP INI для RHEL семейства + if [ -f "/etc/opt/remi/php83/php.ini" ]; then + PHP_INI_PATH="/etc/opt/remi/php83/php.ini" + PHP_FPM_CONF="/etc/opt/remi/php83/php-fpm.d/www.conf" + PHP_FPM_SERVICE="php83-php-fpm" + SOCKET_PATH="/var/opt/remi/php83/run/php-fpm/www.sock" + elif [ -f "/etc/php.ini" ]; then + PHP_INI_PATH="/etc/php.ini" + PHP_FPM_CONF="/etc/php-fpm.d/www.conf" + PHP_FPM_SERVICE="php-fpm" + SOCKET_PATH="/run/php-fpm/www.sock" + fi + else + log_error "Дистрибутив '$DISTRO' не поддерживается." + log_info "Поддерживаются: Debian, Ubuntu, CentOS, RHEL, Fedora, Rocky Linux, AlmaLinux" + exit 1 + fi + + log_info "Обнаружен дистрибутив: $DISTRO ($DISTRO_FAMILY)" +} + +# Функция для безопасного выполнения команд +safe_execute() { + local description="$1" + shift + log_info "$description..." + + if "$@" >/dev/null 2>&1; then + log_success "$description - выполнено" + return 0 + else + log_error "$description - не удалось выполнить" + log_to_file "FAILED COMMAND: $*" + return 1 + fi +} + +# Проверка статуса компонента +check_component_status() { local component=$1 local command_check=$2 local service_check=$3 - if [[ -n "$command_check" && $(command -v "$command_check" 2>/dev/null) ]]; then + if command -v "$command_check" >/dev/null 2>&1; then if [[ -n "$service_check" ]]; then if systemctl is-active --quiet "$service_check" 2>/dev/null; then - return 0 + return 0 # Установлен и работает else - return 1 + return 1 # Установлен, но не работает fi else - return 0 + return 0 # Установлен fi else - return 2 + return 2 # Не установлен fi } +# Проверка существующей установки check_existing_installation() { log_step "Проверка существующей установки..." - local apache_status=2 php_status=2 mariadb_status=2 redis_status=2 + local apache_status php_status mariadb_status redis_status local need_reinstall=false + # Проверка Apache log_info "Проверка Apache..." if [ "$DISTRO_FAMILY" = "debian" ]; then - if command -v apache2 >/dev/null 2>&1; then - if systemctl is-active --quiet apache2 2>/dev/null; then - apache_status=0 - else - apache_status=1 - fi - else - apache_status=2 - fi + check_component_status "Apache" "apache2" "apache2" + apache_status=$? else - if command -v httpd >/dev/null 2>&1; then - if systemctl is-active --quiet httpd 2>/dev/null; then - apache_status=0 - else - apache_status=1 - fi - else - apache_status=2 - fi + check_component_status "Apache" "httpd" "httpd" + apache_status=$? fi + # Проверка PHP log_info "Проверка PHP..." - if command -v php >/dev/null 2>&1; then - php_status=0 - else - php_status=2 - fi + check_component_status "PHP" "php" "" + php_status=$? + # Проверка MariaDB log_info "Проверка MariaDB..." - if command -v mysql >/dev/null 2>&1; then - if systemctl is-active --quiet mariadb 2>/dev/null; then - mariadb_status=0 - else - mariadb_status=1 - fi - else - mariadb_status=2 - fi + check_component_status "MariaDB" "mysql" "mariadb" + mariadb_status=$? + # Проверка Redis log_info "Проверка Redis..." - if command -v redis-cli >/dev/null 2>&1; then - if systemctl is-active --quiet redis-server 2>/dev/null || systemctl is-active --quiet redis 2>/dev/null; then - redis_status=0 - else - redis_status=1 - fi + if systemctl is-active --quiet redis-server 2>/dev/null || systemctl is-active --quiet redis 2>/dev/null; then + redis_status=0 + elif command -v redis-cli >/dev/null 2>&1; then + redis_status=1 else redis_status=2 fi + # Вывод статуса компонентов echo "" + display_component_status "Apache" $apache_status + display_php_status $php_status + display_component_status "MariaDB" $mariadb_status + display_component_status "Redis" $redis_status - case $apache_status in - 0) echo -e "Apache: ${GREEN}Установлен и работает${NC}" ;; - 1) echo -e "Apache: ${YELLOW}Установлен, но не работает${NC}"; need_reinstall=true ;; - 2) echo -e "Apache: ${RED}Не установлен${NC}"; need_reinstall=true ;; - esac - - case $php_status in - 0) - php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно") - if [[ "$php_version" == "8.3" ]]; then - echo -e "PHP: ${GREEN}Установлен (версия $php_version)${NC}" - else - echo -e "PHP: ${YELLOW}Установлен (версия $php_version, требуется 8.3)${NC}" - need_reinstall=true - fi - ;; - 2) echo -e "PHP: ${RED}Не установлен${NC}"; need_reinstall=true ;; - esac - - case $mariadb_status in - 0) echo -e "MariaDB: ${GREEN}Установлен и работает${NC}" ;; - 1) echo -e "MariaDB: ${YELLOW}Установлен, но не работает${NC}"; need_reinstall=true ;; - 2) echo -e "MariaDB: ${RED}Не установлен${NC}"; need_reinstall=true ;; - esac - - case $redis_status in - 0) echo -e "Redis: ${GREEN}Установлен и работает${NC}" ;; - 1) echo -e "Redis: ${YELLOW}Установлен, но не работает${NC}"; need_reinstall=true ;; - 2) echo -e "Redis: ${RED}Не установлен${NC}"; need_reinstall=true ;; - esac - + # Проверка конфигурации БД if [ -f "/var/www/html/db_config.php" ]; then echo -e "Конфигурация БД: ${GREEN}Найдена${NC}" else @@ -161,84 +204,80 @@ check_existing_installation() { echo "" - if [ "$need_reinstall" = false ] && [ "$apache_status" -eq 0 ] && [ "$php_status" -eq 0 ] && [ "$mariadb_status" -eq 0 ]; then - if [ "$REINSTALL" = true ]; then - log_warning "Обнаружена существующая установка. Начинаем переустановку..." - return 1 - else - log_success "Все компоненты уже установлены и работают корректно" - echo "" - echo -e "${YELLOW}Altcor уже полностью установлен и функционирует.${NC}" - echo "" - read -p "Хотите переустановить систему? [y/n]: " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Yy]$ ]]; then - log_info "Начинаем переустановку по запросу пользователя..." - REINSTALL=true - return 1 - else - echo "" - log_info "Переустановка отменена. Система остается без изменений." - echo "" - echo "Для принудительной переустановки используйте: $0 -r" - echo "" - exit 0 - fi - fi - else - if [ "$need_reinstall" = true ]; then - log_warning "Обнаружены проблемы с установленными компонентами." - echo "" - read -p "Хотите переустановить всю систему? [y/n]: " -n 1 -r - echo "" - if [[ $REPLY =~ ^[Yy]$ ]]; then - log_info "Начинаем полную переустановку..." - REINSTALL=true - return 1 - else - log_info "Продолжаем обычную установку/обновление компонентов..." - return 0 - fi - else - log_info "Обнаружены отсутствующие компоненты. Продолжаем установку..." - return 0 - fi + # Определяем необходимость переустановки + if [[ $apache_status -ne 0 ]] || [[ $php_status -ne 0 ]] || [[ $mariadb_status -ne 0 ]]; then + need_reinstall=true fi + + return $([ "$need_reinstall" = "true" ] && echo 1 || echo 0) } +# Отображение статуса компонента +display_component_status() { + local name=$1 + local status=$2 + + case $status in + 0) echo -e "$name: ${GREEN}Установлен и работает${NC}" ;; + 1) echo -e "$name: ${YELLOW}Установлен, но не работает${NC}" ;; + 2) echo -e "$name: ${RED}Не установлен${NC}" ;; + esac +} + +# Отображение статуса PHP с проверкой версии +display_php_status() { + local status=$1 + + case $status in + 0) + local php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно") + if [[ "$php_version" == "8.3" ]]; then + echo -e "PHP: ${GREEN}Установлен (версия $php_version)${NC}" + else + echo -e "PHP: ${YELLOW}Установлен (версия $php_version, требуется 8.3)${NC}" + return 1 + fi + ;; + 2) echo -e "PHP: ${RED}Не установлен${NC}"; return 1 ;; + esac + return 0 +} + +# Полное удаление системы full_uninstall() { log_step "Начинаем полное удаление Altcor..." + # Остановка сервисов log_info "Остановка сервисов..." - systemctl stop nginx apache2 httpd php*-fpm mariadb mysql redis redis-server 2>/dev/null || true + for service in nginx apache2 httpd php*-fpm mariadb mysql redis redis-server php83-php-fpm; do + systemctl stop "$service" 2>/dev/null || true + done + # Удаление пакетов log_info "Удаление пакетов..." if [ "$DISTRO_FAMILY" = "debian" ]; then - export DEBIAN_FRONTEND=noninteractive - echo "mariadb-server mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mariadb-server-10.* mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mysql-server-* mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true + # Подготавливаем автоматические ответы для удаления MariaDB/MySQL + for db_package in mariadb-server mysql-server; do + for version in "" "-10.3" "-10.5" "-10.6" "-10.11" "-5.7" "-8.0"; do + echo "${db_package}${version} mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true + done + done - apt purge -y nginx* apache2* php* mariadb* mysql* redis* 2>/dev/null || true - apt autoremove -y 2>/dev/null || true + safe_execute "Удаление пакетов (Debian/Ubuntu)" \ + apt purge -y nginx* apache2* php* mariadb* mysql* redis* + safe_execute "Очистка неиспользуемых пакетов" apt autoremove -y else - $PKG_MANAGER remove -y nginx httpd php* mariadb* mysql* redis* 2>/dev/null || true + safe_execute "Удаление пакетов (RHEL/CentOS/Fedora)" \ + $PKG_MANAGER remove -y nginx httpd php* mariadb* mysql* redis* fi + # Удаление файлов и директорий log_info "Удаление файлов конфигурации и данных..." - rm -rf \ - /etc/nginx \ - /etc/apache2 \ - /etc/httpd \ - /etc/php* \ - /var/www/html/* \ - /var/lib/mysql* \ - /var/lib/redis* \ - ~/.mysql_history \ - /root/.mysql_history \ - /root/.db_password 2>/dev/null || true + rm -rf /etc/nginx /etc/apache2 /etc/httpd /etc/php* /var/www/html/* \ + /var/lib/mysql* /var/lib/redis* ~/.mysql_history /root/.mysql_history \ + /root/.db_password /etc/opt/remi/php83 /opt/remi/php83 2>/dev/null || true log_success "Полное удаление завершено." @@ -250,426 +289,389 @@ full_uninstall() { fi } -proceed_with_installation() { - DB_PASSWORD=$(generate_password) - - log_step "Остановка конфликтующих сервисов..." - systemctl stop nginx httpd apache2 php*-fpm mariadb mysql 2>/dev/null || true - systemctl disable nginx httpd 2>/dev/null || true - - log_info "Ожидание полной остановки служб..." - sleep 3 - - echo "" - echo "Начинаем установку Altcor..." - echo "" - - log_step "Удаление старых версий пакетов..." +# Обновление системы и установка базовых пакетов +update_system() { + log_step "Обновление системы и установка базовых пакетов..." + if [ "$DISTRO_FAMILY" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive - - echo "mariadb-server mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mariadb-server-10.3 mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mariadb-server-10.5 mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mariadb-server-10.6 mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mariadb-server-10.11 mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mysql-server-5.7 mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - echo "mysql-server-8.0 mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true - - apt remove -y nginx nginx-common nginx-core >/dev/null 2>&1 || true - apt remove -y php7.* php8.0* php8.1* php8.2* libapache2-mod-php7.* libapache2-mod-php8.0* libapache2-mod-php8.1* libapache2-mod-php8.2* >/dev/null 2>&1 || true - - apt remove --purge -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" mariadb* mysql* /dev/null 2>&1 || true - apt autoremove -y >/dev/null 2>&1 || true - rm -rf /var/lib/mysql* /etc/mysql* /var/log/mysql* 2>/dev/null || true - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - $PKG_MANAGER remove -y nginx >/dev/null 2>&1 || true - $PKG_MANAGER remove -y php php7* php80* php81* php82* >/dev/null 2>&1 || true - $PKG_MANAGER remove -y mariadb* mysql* >/dev/null 2>&1 || true - rm -rf /var/lib/mysql* /etc/my.cnf* /var/log/mysql* 2>/dev/null || true + safe_execute "Обновление списка пакетов" apt update -y + safe_execute "Установка базовых пакетов" \ + apt install -y software-properties-common lsb-release ca-certificates \ + curl wget gnupg2 apt-transport-https unzip + else + safe_execute "Обновление системы" $PKG_MANAGER update -y + safe_execute "Установка EPEL репозитория" $PKG_MANAGER install -y epel-release || true + safe_execute "Установка базовых пакетов" \ + $PKG_MANAGER install -y curl wget gnupg2 unzip fi - log_success "Старые пакеты удалены" +} - log_step "Обновление списка пакетов..." - if [ "$DISTRO_FAMILY" = "debian" ]; then - export DEBIAN_FRONTEND=noninteractive - apt update -y >/dev/null 2>&1 - apt install -y software-properties-common lsb-release ca-certificates curl wget gnupg2 apt-transport-https unzip >/dev/null 2>&1 - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - $PKG_MANAGER update -y >/dev/null 2>&1 - $PKG_MANAGER install -y epel-release >/dev/null 2>&1 || true - $PKG_MANAGER install -y curl wget gnupg2 unzip >/dev/null 2>&1 - fi - log_success "Система обновлена, базовые пакеты установлены" - - log_step "Добавление репозиториев для PHP 8.3..." +# Настройка репозиториев PHP 8.3 +setup_php_repositories() { + log_step "Настройка репозиториев для PHP 8.3..." + if [ "$DISTRO_FAMILY" = "debian" ]; then if ! apt-cache show php8.3 &>/dev/null; then - log_info "Добавление PPA ondrej/php..." - if ! add-apt-repository ppa:ondrej/php -y >/dev/null 2>&1; then - log_error "Не удалось добавить PPA ondrej/php." - exit 1 + log_info "Добавление репозитория Sury для PHP 8.3..." + + # Добавляем ключ GPG + if ! curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/php-archive-keyring.gpg 2>/dev/null; then + log_warning "Не удалось добавить ключ Sury, пробуем PPA..." + safe_execute "Добавление PPA ondrej/php" add-apt-repository ppa:ondrej/php -y + else + # Добавляем репозиторий Sury + CODENAME=$(lsb_release -cs) + echo "deb [signed-by=/usr/share/keyrings/php-archive-keyring.gpg] https://packages.sury.org/php/ $CODENAME main" > /etc/apt/sources.list.d/php.list fi - apt update -y >/dev/null 2>&1 + safe_execute "Обновление списка пакетов после добавления репозитория PHP" apt update -y if ! apt-cache show php8.3 &>/dev/null; then - log_error "PHP 8.3 все еще недоступен после добавления PPA." + log_error "PHP 8.3 недоступен после добавления репозиториев" exit 1 fi - log_success "PPA добавлен успешно" - else - log_success "PHP 8.3 уже доступен в репозиториях" fi + log_success "Репозиторий PHP 8.3 настроен" + + else + log_info "Настройка репозиториев Remi для RHEL-семейства..." + + local version_id=$(echo "$VERSION_ID" | cut -d'.' -f1) - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - log_info "Добавление репозитория Remi..." if [ "$DISTRO" = "fedora" ]; then - $PKG_MANAGER install -y https://rpms.remirepo.net/fedora/remi-release-$(rpm -E %fedora).rpm >/dev/null 2>&1 || true + local fedora_version=$(rpm -E %fedora) + safe_execute "Установка Remi репозитория для Fedora" \ + $PKG_MANAGER install -y "https://rpms.remirepo.net/fedora/remi-release-${fedora_version}.rpm" else - $PKG_MANAGER install -y https://rpms.remirepo.net/enterprise/remi-release-$(rpm -E %rhel).rpm >/dev/null 2>&1 || true + safe_execute "Установка Remi репозитория для RHEL/CentOS" \ + $PKG_MANAGER install -y "https://rpms.remirepo.net/enterprise/remi-release-${version_id}.rpm" fi + # Включаем модуль PHP 8.3 если доступен DNF if command -v dnf >/dev/null 2>&1; then - dnf module reset php -y >/dev/null 2>&1 || true - dnf module enable php:remi-8.3 -y >/dev/null 2>&1 || true + safe_execute "Сброс модуля PHP" dnf module reset php -y || true + safe_execute "Включение модуля PHP 8.3" dnf module enable php:remi-8.3 -y || true fi - if ! $PKG_MANAGER list available php83* php8.3* >/dev/null 2>&1; then - log_error "PHP 8.3 недоступен в репозиториях." - exit 1 - fi - log_success "Репозиторий Remi добавлен успешно" + log_success "Репозиторий Remi настроен" fi +} - log_step "Установка Apache..." +# Установка компонентов системы +install_components() { + log_step "Установка основных компонентов..." + + # Остановка конфликтующих сервисов + log_info "Остановка конфликтующих сервисов..." + for service in nginx httpd apache2 php*-fpm mariadb mysql; do + systemctl stop "$service" 2>/dev/null || true + done + systemctl disable nginx httpd 2>/dev/null || true + + sleep 3 + + # Удаление старых версий + remove_old_packages + + # Установка Apache if [ "$DISTRO_FAMILY" = "debian" ]; then - export DEBIAN_FRONTEND=noninteractive - apt install -y apache2 >/dev/null 2>&1 - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - $PKG_MANAGER install -y httpd >/dev/null 2>&1 + safe_execute "Установка Apache" apt install -y apache2 + else + safe_execute "Установка Apache (httpd)" $PKG_MANAGER install -y httpd fi - log_success "Apache установлен" + + # Установка MariaDB + install_mariadb + + # Установка PHP 8.3 + install_php83 + + # Установка дополнительных компонентов + install_additional_components +} - log_step "Установка MariaDB..." +# Удаление старых пакетов +remove_old_packages() { + log_info "Удаление старых версий пакетов..." + if [ "$DISTRO_FAMILY" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive + # Настройка автоматических ответов для MySQL/MariaDB + for db_package in mariadb-server mysql-server; do + for version in "" "-10.3" "-10.5" "-10.6" "-10.11" "-5.7" "-8.0"; do + echo "${db_package}${version} mysql-server/remove-data-dir boolean true" | debconf-set-selections 2>/dev/null || true + done + done + + apt remove -y nginx nginx-common nginx-core 2>/dev/null || true + apt remove -y php7.* php8.0* php8.1* php8.2* libapache2-mod-php7.* libapache2-mod-php8.0* libapache2-mod-php8.1* libapache2-mod-php8.2* 2>/dev/null || true + apt remove --purge -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" mariadb* mysql* 2>/dev/null || true + apt autoremove -y 2>/dev/null || true + else + $PKG_MANAGER remove -y nginx php php7* php80* php81* php82* mariadb* mysql* 2>/dev/null || true + fi + + # Удаление файлов данных MySQL/MariaDB + rm -rf /var/lib/mysql* /etc/mysql* /var/log/mysql* /etc/my.cnf* 2>/dev/null || true +} + +# Установка MariaDB +install_mariadb() { + log_info "Установка MariaDB..." + + if [ "$DISTRO_FAMILY" = "debian" ]; then + export DEBIAN_FRONTEND=noninteractive echo "mariadb-server mysql-server/root_password password ''" | debconf-set-selections 2>/dev/null || true echo "mariadb-server mysql-server/root_password_again password ''" | debconf-set-selections 2>/dev/null || true - - apt install -y mariadb-server >/dev/null 2>&1 - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - $PKG_MANAGER install -y mariadb-server >/dev/null 2>&1 + safe_execute "Установка MariaDB" apt install -y mariadb-server + else + safe_execute "Установка MariaDB" $PKG_MANAGER install -y mariadb-server fi - - log_info "Запуск MariaDB..." - systemctl start mariadb >/dev/null 2>&1 - systemctl enable mariadb >/dev/null 2>&1 - + + # Запуск и включение MariaDB + safe_execute "Запуск MariaDB" systemctl start mariadb + safe_execute "Включение MariaDB в автозагрузку" systemctl enable mariadb + + # Ожидание полного запуска log_info "Ожидание полного запуска MariaDB..." - sleep 5 - + local retry_count=0 + while ! systemctl is-active --quiet mariadb && [ $retry_count -lt 10 ]; do + sleep 2 + ((retry_count++)) + done + if ! systemctl is-active --quiet mariadb; then - log_error "MariaDB не смог запуститься" + log_error "MariaDB не удалось запустить" exit 1 fi +} - log_success "MariaDB установлен и запущен" - - log_step "Установка дополнительных компонентов (Redis, LibreOffice, Java)..." +# Установка PHP 8.3 +install_php83() { + log_info "Установка PHP 8.3 и расширений..." + if [ "$DISTRO_FAMILY" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive - apt install -y redis-server libreoffice default-jre >/dev/null 2>&1 - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - $PKG_MANAGER install -y redis libreoffice java-11-openjdk >/dev/null 2>&1 - fi - log_success "Дополнительные компоненты установлены" - - log_step "Добавление репозиториев для PHP 8.3..." - if [ "$DISTRO_FAMILY" = "debian" ]; then - # Для Ubuntu/Debian - if ! apt-cache show php8.3 &>/dev/null; then - log_info "Добавление PPA ondrej/php для Ubuntu/Debian..." - - # Устанавливаем необходимые пакеты для PPA - apt update -y >/dev/null 2>&1 - apt install -y software-properties-common gnupg2 lsb-release >/dev/null 2>&1 - - # Добавляем ключ GPG для PPA ondrej/php - curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/php-archive-keyring.gpg 2>/dev/null - - # Определяем кодовое имя дистрибутива - CODENAME=$(lsb_release -cs) - - # Добавляем репозиторий - echo "deb [signed-by=/usr/share/keyrings/php-archive-keyring.gpg] https://packages.sury.org/php/ $CODENAME main" > /etc/apt/sources.list.d/php.list - - # Обновляем списки пакетов - apt update -y >/dev/null 2>&1 - - # Проверяем доступность PHP 8.3 - if ! apt-cache show php8.3 &>/dev/null; then - log_error "PHP 8.3 все еще недоступен после добавления репозитория Sury." - log_info "Попытка добавления через PPA..." - - if add-apt-repository ppa:ondrej/php -y >/dev/null 2>&1; then - apt update -y >/dev/null 2>&1 - if ! apt-cache show php8.3 &>/dev/null; then - log_error "PHP 8.3 недоступен ни через Sury, ни через PPA ondrej/php" - exit 1 - fi - else - log_error "Не удалось добавить ни один репозиторий для PHP 8.3" - exit 1 - fi - fi - log_success "Репозиторий PHP добавлен успешно" - else - log_success "PHP 8.3 уже доступен в репозиториях" - fi - - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - log_info "Настройка репозиториев для RHEL-семейства..." - - # Определяем версию системы - if [ -f /etc/os-release ]; then - VERSION_ID=$(grep VERSION_ID /etc/os-release | cut -d'"' -f2 | cut -d'.' -f1) - fi - - if [ "$DISTRO" = "fedora" ]; then - log_info "Добавление репозитория Remi для Fedora..." - FEDORA_VERSION=$(rpm -E %fedora) - - # Устанавливаем EPEL и Remi для Fedora - $PKG_MANAGER install -y https://rpms.remirepo.net/fedora/remi-release-${FEDORA_VERSION}.rpm >/dev/null 2>&1 || true - - # Включаем модуль PHP 8.3 - if command -v dnf >/dev/null 2>&1; then - dnf module reset php -y >/dev/null 2>&1 || true - dnf module enable php:remi-8.3 -y >/dev/null 2>&1 || true - fi - - elif echo "$DISTRO" | grep -qi "rocky\|rhel\|centos\|almalinux"; then - log_info "Добавление репозитория Remi для RHEL/Rocky/CentOS..." - - # Устанавливаем EPEL - $PKG_MANAGER install -y epel-release >/dev/null 2>&1 || true - - # Добавляем Remi репозиторий в зависимости от версии - if [ "$VERSION_ID" = "8" ]; then - $PKG_MANAGER install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm >/dev/null 2>&1 || true - elif [ "$VERSION_ID" = "9" ]; then - $PKG_MANAGER install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm >/dev/null 2>&1 || true - else - log_warning "Неизвестная версия RHEL ($VERSION_ID), пробуем универсальный подход" - $PKG_MANAGER install -y https://rpms.remirepo.net/enterprise/remi-release-${VERSION_ID}.rpm >/dev/null 2>&1 || true - fi - - # Включаем модуль PHP 8.3 если доступен DNF - if command -v dnf >/dev/null 2>&1; then - dnf module reset php -y >/dev/null 2>&1 || true - dnf module enable php:remi-8.3 -y >/dev/null 2>&1 || true - fi - fi - - # Обновляем кэш пакетов - $PKG_MANAGER makecache >/dev/null 2>&1 || true - - # Проверяем доступность PHP пакетов - if ! $PKG_MANAGER list available | grep -E "php8[0-9].*8\.3|php-8\.3|php.*remi.*8\.3" >/dev/null 2>&1; then - log_error "PHP 8.3 недоступен в репозиториях после добавления Remi" - log_info "Доступные PHP пакеты:" - $PKG_MANAGER list available | grep php | head -10 - exit 1 - fi - log_success "Репозиторий Remi добавлен успешно" - fi - - log_step "Установка PHP 8.3 и расширений..." - if [ "$DISTRO_FAMILY" = "debian" ]; then - export DEBIAN_FRONTEND=noninteractive - - # Список пакетов для Debian/Ubuntu - PHP_PACKAGES="php8.3 php8.3-cli php8.3-common php8.3-mysql php8.3-curl php8.3-gd \ - php8.3-mbstring php8.3-xml php8.3-zip php8.3-opcache php8.3-intl \ - php8.3-bcmath php8.3-json php8.3-readline libapache2-mod-php8.3" - - log_info "Устанавливаем пакеты: $PHP_PACKAGES" - - if ! apt install -y $PHP_PACKAGES >/dev/null 2>&1; then - log_error "Не удалось установить базовые PHP пакеты. Подробности:" - apt install -y $PHP_PACKAGES 2>&1 | tail -20 - - log_info "Попытка установки по одному пакету для выявления проблемного..." - for pkg in $PHP_PACKAGES; do - if apt install -y $pkg >/dev/null 2>&1; then - log_success "Установлен: $pkg" - else - log_error "Не удалось установить: $pkg" - fi - done - exit 1 - fi - - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - # Определяем, какие пакеты PHP нужно установить + local php_packages="php8.3 php8.3-cli php8.3-common php8.3-mysql php8.3-curl php8.3-gd php8.3-mbstring php8.3-xml php8.3-zip php8.3-opcache php8.3-intl php8.3-bcmath php8.3-json php8.3-readline libapache2-mod-php8.3" + else + # Определяем доступные пакеты PHP для RHEL семейства if $PKG_MANAGER list available | grep -q "php83-php\b"; then - # Remi PHP 8.3 пакеты (Rocky/CentOS/RHEL) - log_info "Используем пакеты php83-* из Remi репозитория" - PHP_PACKAGES="php83-php php83-php-cli php83-php-common php83-php-mysqlnd php83-php-curl php83-php-gd \ - php83-php-mbstring php83-php-xml php83-php-zip php83-php-opcache php83-php-intl \ - php83-php-bcmath php83-php-json php83-php-fpm" - - elif $PKG_MANAGER list available | grep -E "php-8\.3|php.*remi.*8\.3" >/dev/null 2>&1; then - # Альтернативный формат пакетов Remi - log_info "Используем пакеты php-* версии 8.3 из Remi репозитория" - PHP_PACKAGES="php php-cli php-common php-mysqlnd php-curl php-gd \ - php-mbstring php-xml php-zip php-opcache php-intl \ - php-bcmath php-json php-fpm" + local php_packages="php83-php php83-php-cli php83-php-common php83-php-mysqlnd php83-php-curl php83-php-gd php83-php-mbstring php83-php-xml php83-php-zip php83-php-opcache php83-php-intl php83-php-bcmath php83-php-json php83-php-fpm" else - # Стандартные пакеты (Fedora) - log_info "Используем стандартные пакеты php-*" - PHP_PACKAGES="php php-cli php-common php-mysqlnd php-curl php-gd \ - php-mbstring php-xml php-zip php-opcache php-intl \ - php-bcmath php-json php-fpm" - fi - - log_info "Устанавливаем пакеты: $PHP_PACKAGES" - - if ! $PKG_MANAGER install -y $PHP_PACKAGES >/dev/null 2>&1; then - log_error "Не удалось установить PHP пакеты. Подробности:" - $PKG_MANAGER install -y $PHP_PACKAGES 2>&1 | tail -20 - - log_info "Попытка установки по одному пакету для выявления проблемного..." - for pkg in $PHP_PACKAGES; do - if $PKG_MANAGER install -y $pkg >/dev/null 2>&1; then - log_success "Установлен: $pkg" - else - log_error "Не удалось установить: $pkg" - fi - done - exit 1 - fi - - # Создаем символические ссылки для PHP83 если нужно - if command -v php83 >/dev/null 2>&1 && [ ! -f /usr/bin/php ]; then - log_info "Создание символических ссылок для php83..." - ln -sf /opt/remi/php83/root/usr/bin/php /usr/bin/php >/dev/null 2>&1 || true - ln -sf /opt/remi/php83/root/usr/bin/php-fpm /usr/bin/php-fpm >/dev/null 2>&1 || true - - # Добавляем путь в PATH - echo 'export PATH=/opt/remi/php83/root/usr/bin:$PATH' > /etc/profile.d/php83.sh - source /etc/profile.d/php83.sh >/dev/null 2>&1 || true + local php_packages="php php-cli php-common php-mysqlnd php-curl php-gd php-mbstring php-xml php-zip php-opcache php-intl php-bcmath php-json php-fpm" fi fi - # Проверяем успешность установки PHP + if ! $PKG_MANAGER install -y $php_packages >/dev/null 2>&1; then + log_error "Не удалось установить PHP пакеты. Подробности в логе: $LOG_FILE" + $PKG_MANAGER install -y $php_packages 2>&1 | tee -a "$LOG_FILE" + exit 1 + fi + + # Создание символических ссылок для php83 (если нужно) + if command -v php83 >/dev/null 2>&1 && [ ! -f /usr/bin/php ]; then + ln -sf /opt/remi/php83/root/usr/bin/php /usr/bin/php 2>/dev/null || true + echo 'export PATH=/opt/remi/php83/root/usr/bin:$PATH' > /etc/profile.d/php83.sh + fi + + # Проверка установки PHP + verify_php_installation +} + +# Проверка установки PHP +verify_php_installation() { log_info "Проверка установки PHP..." - if command -v php >/dev/null 2>&1; then - PHP_VERSION=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно") - if [[ "$PHP_VERSION" == "8.3" ]]; then - log_success "PHP 8.3 успешно установлен (версия: $(php -v | head -1))" - else - log_warning "PHP установлен, но версия $PHP_VERSION (ожидалась 8.3)" - log_info "Попытка исправления версии PHP..." - - # Для Debian попробуем переключить версию - if [ "$DISTRO_FAMILY" = "debian" ] && command -v update-alternatives >/dev/null 2>&1; then - if [ -f /usr/bin/php8.3 ]; then - update-alternatives --set php /usr/bin/php8.3 >/dev/null 2>&1 || true - PHP_VERSION=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно") - if [[ "$PHP_VERSION" == "8.3" ]]; then - log_success "Версия PHP исправлена на 8.3" - fi - fi - fi - fi - else + if ! command -v php >/dev/null 2>&1; then log_error "PHP не найден после установки" exit 1 fi - # Проверяем установку основных расширений - log_info "Проверка PHP расширений..." - REQUIRED_EXTENSIONS="mysqli pdo_mysql curl gd mbstring xml zip opcache intl bcmath json" - MISSING_EXTENSIONS="" - - for ext in $REQUIRED_EXTENSIONS; do - if php -m | grep -q "^$ext$" 2>/dev/null; then - log_success "Расширение $ext: установлено" - else - log_warning "Расширение $ext: НЕ найдено" - MISSING_EXTENSIONS="$MISSING_EXTENSIONS $ext" - fi - done - - if [ -n "$MISSING_EXTENSIONS" ]; then - log_warning "Отсутствующие расширения:$MISSING_EXTENSIONS" - log_info "Попытка дополнительной установки расширений..." + local php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно") + if [[ "$php_version" != "8.3" ]]; then + log_warning "PHP версия $php_version (ожидалась 8.3)" - if [ "$DISTRO_FAMILY" = "debian" ]; then - for ext in $MISSING_EXTENSIONS; do - if [ "$ext" = "mysqli" ] || [ "$ext" = "pdo_mysql" ]; then - apt install -y php8.3-mysql >/dev/null 2>&1 || true - else - apt install -y php8.3-$ext >/dev/null 2>&1 || true - fi - done - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - for ext in $MISSING_EXTENSIONS; do - if [ "$ext" = "mysqli" ] || [ "$ext" = "pdo_mysql" ]; then - $PKG_MANAGER install -y php*-mysqlnd >/dev/null 2>&1 || true - else - $PKG_MANAGER install -y php*-$ext >/dev/null 2>&1 || true - fi - done + # Попытка исправления версии для Debian + if [ "$DISTRO_FAMILY" = "debian" ] && [ -f /usr/bin/php8.3 ]; then + update-alternatives --set php /usr/bin/php8.3 2>/dev/null || true + php_version=$(php -v 2>/dev/null | head -1 | cut -d' ' -f2 | cut -d'.' -f1,2 2>/dev/null || echo "неизвестно") fi fi - log_success "PHP 8.3 и расширения установлены" + if [[ "$php_version" == "8.3" ]]; then + log_success "PHP 8.3 успешно установлен" + else + log_error "Не удалось установить PHP 8.3 (текущая версия: $php_version)" + exit 1 + fi + + # Проверка расширений PHP + verify_php_extensions +} - log_step "Настройка Apache и модулей..." - if [ "$DISTRO_FAMILY" = "debian" ]; then - a2enmod php8.3 rewrite ssl headers expires deflate >/dev/null 2>&1 - - for php_ver in 7.4 8.0 8.1 8.2; do - a2dismod php$php_ver >/dev/null 2>&1 || true - done - - WEBROOT="/var/www/html" - APACHE_CONF="/etc/apache2/sites-available/000-default.conf" - WEBSERVER_USER="www-data" - - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - WEBROOT="/var/www/html" - APACHE_CONF="/etc/httpd/conf.d/altcor.conf" - WEBSERVER_USER="apache" - - # Отключаем старые конфигурации PHP и mod_php - rm -f /etc/httpd/conf.d/php.conf /etc/httpd/conf.modules.d/*php*.conf - - # Определяем, какой PHP-FPM сервис и путь к конфигурации использовать - if [ -f "/etc/opt/remi/php83/php-fpm.d/www.conf" ]; then - PHP_FPM_CONF="/etc/opt/remi/php83/php-fpm.d/www.conf" - PHP_FPM_SERVICE="php83-php-fpm" - SOCKET_PATH="/var/opt/remi/php83/run/php-fpm/www.sock" - elif [ -f "/etc/php-fpm.d/www.conf" ]; then - PHP_FPM_CONF="/etc/php-fpm.d/www.conf" - PHP_FPM_SERVICE="php-fpm" - SOCKET_PATH="/run/php-fpm/www.sock" +# Проверка расширений PHP +verify_php_extensions() { + log_info "Проверка PHP расширений..." + + local required_extensions="mysqli pdo_mysql curl gd mbstring xml zip opcache intl bcmath json" + local missing_extensions="" + + for ext in $required_extensions; do + if php -m 2>/dev/null | grep -q "^$ext$"; then + log_success "Расширение $ext: установлено" else - log_error "Не найден конфигурационный файл PHP-FPM" - exit 1 + log_warning "Расширение $ext: НЕ найдено" + missing_extensions="$missing_extensions $ext" fi + done + + if [ -n "$missing_extensions" ]; then + log_warning "Попытка установки отсутствующих расширений:$missing_extensions" + install_missing_php_extensions "$missing_extensions" + fi +} - # Создаем конфигурацию только для PHP-FPM (без mod_php) - cat > "/etc/httpd/conf.d/php-fpm.conf" << 'EOF' +# Установка недостающих расширений PHP +install_missing_php_extensions() { + local missing_extensions="$1" + + if [ "$DISTRO_FAMILY" = "debian" ]; then + for ext in $missing_extensions; do + if [[ "$ext" =~ ^(mysqli|pdo_mysql)$ ]]; then + apt install -y php8.3-mysql 2>/dev/null || true + else + apt install -y "php8.3-$ext" 2>/dev/null || true + fi + done + else + for ext in $missing_extensions; do + if [[ "$ext" =~ ^(mysqli|pdo_mysql)$ ]]; then + $PKG_MANAGER install -y php*-mysqlnd 2>/dev/null || true + else + $PKG_MANAGER install -y "php*-$ext" 2>/dev/null || true + fi + done + fi +} + +# Установка дополнительных компонентов +install_additional_components() { + log_info "Установка дополнительных компонентов (Redis, LibreOffice, Java)..." + + if [ "$DISTRO_FAMILY" = "debian" ]; then + export DEBIAN_FRONTEND=noninteractive + safe_execute "Установка дополнительных компонентов" \ + apt install -y redis-server libreoffice default-jre + else + safe_execute "Установка дополнительных компонентов" \ + $PKG_MANAGER install -y redis libreoffice java-11-openjdk + fi +} + +# Настройка Apache и PHP +configure_apache_php() { + log_step "Настройка Apache и PHP..." + + if [ "$DISTRO_FAMILY" = "debian" ]; then + configure_apache_debian + else + configure_apache_rhel + fi + + # Настройка PHP.ini + configure_php_ini + + # Создание виртуального хоста + create_virtual_host + + # Проверка конфигурации Apache + verify_apache_config +} + +# Настройка Apache для Debian/Ubuntu +configure_apache_debian() { + log_info "Настройка Apache для Debian/Ubuntu..." + + # Включение модулей + a2enmod php8.3 rewrite ssl headers expires deflate 2>/dev/null || true + + # Отключение старых версий PHP + for php_ver in 7.4 8.0 8.1 8.2; do + a2dismod "php$php_ver" 2>/dev/null || true + done +} + +# Настройка Apache для RHEL семейства +configure_apache_rhel() { + log_info "Настройка Apache для RHEL семейства..." + + # Удаление старых конфигураций PHP + rm -f /etc/httpd/conf.d/php.conf /etc/httpd/conf.modules.d/*php*.conf 2>/dev/null || true + + # Настройка PHP-FPM + configure_php_fpm + + # Создание конфигурации PHP-FPM для Apache + create_php_fpm_config + + # Создание общей конфигурации Altcor + create_altcor_config +} + +# Настройка PHP-FPM +configure_php_fpm() { + log_info "Настройка PHP-FPM..." + + if [ -z "$PHP_FPM_CONF" ] || [ ! -f "$PHP_FPM_CONF" ]; then + log_error "Файл конфигурации PHP-FPM не найден: $PHP_FPM_CONF" + exit 1 + fi + + # Создание резервной копии + cp "$PHP_FPM_CONF" "${PHP_FPM_CONF}.backup.$(date +%Y%m%d_%H%M%S)" + + # Настройка параметров PHP-FPM pool + sed -i "s|;*listen = .*|listen = $SOCKET_PATH|" "$PHP_FPM_CONF" + sed -i 's/;*listen.owner = .*/listen.owner = apache/' "$PHP_FPM_CONF" + sed -i 's/;*listen.group = .*/listen.group = apache/' "$PHP_FPM_CONF" + sed -i 's/;*listen.mode = .*/listen.mode = 0660/' "$PHP_FPM_CONF" + sed -i 's/;*user = .*/user = apache/' "$PHP_FPM_CONF" + sed -i 's/;*group = .*/group = apache/' "$PHP_FPM_CONF" + + # Настройка производительности + sed -i 's/;*pm = .*/pm = dynamic/' "$PHP_FPM_CONF" + sed -i 's/;*pm.max_children = .*/pm.max_children = 50/' "$PHP_FPM_CONF" + sed -i 's/;*pm.start_servers = .*/pm.start_servers = 5/' "$PHP_FPM_CONF" + sed -i 's/;*pm.min_spare_servers = .*/pm.min_spare_servers = 5/' "$PHP_FPM_CONF" + sed -i 's/;*pm.max_spare_servers = .*/pm.max_spare_servers = 35/' "$PHP_FPM_CONF" + + # Создание директории для socket + local socket_dir=$(dirname "$SOCKET_PATH") + mkdir -p "$socket_dir" + chown apache:apache "$socket_dir" + + # Запуск PHP-FPM + safe_execute "Запуск PHP-FPM" systemctl start "$PHP_FPM_SERVICE" + safe_execute "Включение PHP-FPM в автозагрузку" systemctl enable "$PHP_FPM_SERVICE" + + if ! systemctl is-active --quiet "$PHP_FPM_SERVICE"; then + log_error "PHP-FPM не удалось запустить" + systemctl status "$PHP_FPM_SERVICE" --no-pager -l | tee -a "$LOG_FILE" + exit 1 + fi +} + +# Создание конфигурации PHP-FPM для Apache +create_php_fpm_config() { + log_info "Создание конфигурации PHP-FPM для Apache..." + + cat > "/etc/httpd/conf.d/php-fpm.conf" << EOF # PHP-FPM configuration for Apache -# ВАЖНО: НЕ загружаем mod_php - используем только PHP-FPM +# Использование только PHP-FPM, без mod_php -# Базовые модули Apache (проверяем, не загружены ли уже) +# Загрузка необходимых модулей LoadModule rewrite_module modules/mod_rewrite.so @@ -691,59 +693,23 @@ proceed_with_installation() { # Обработка PHP файлов через PHP-FPM - SetHandler "proxy:unix:SOCKET_PATH_PLACEHOLDER|fcgi://localhost" + SetHandler "proxy:unix:$SOCKET_PATH|fcgi://localhost" -# Настройки директивы для улучшения производительности +# Настройки производительности ProxyTimeout 300 -ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:SOCKET_PATH_PLACEHOLDER|fcgi://localhost/var/www/html/ +ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:$SOCKET_PATH|fcgi://localhost/var/www/html/ EOF +} - # Заменяем плейсхолдер на реальный путь к сокету - sed -i "s|SOCKET_PATH_PLACEHOLDER|$SOCKET_PATH|g" "/etc/httpd/conf.d/php-fpm.conf" - - log_info "Настройка PHP-FPM..." - - # Создаем резервную копию конфигурации - cp "$PHP_FPM_CONF" "${PHP_FPM_CONF}.backup.$(date +%Y%m%d_%H%M%S)" - - # Настраиваем PHP-FPM pool - sed -i 's/;*listen = .*/listen = '"${SOCKET_PATH//\//\\/}"'/' "$PHP_FPM_CONF" - sed -i 's/;*listen.owner = .*/listen.owner = apache/' "$PHP_FPM_CONF" - sed -i 's/;*listen.group = .*/listen.group = apache/' "$PHP_FPM_CONF" - sed -i 's/;*listen.mode = .*/listen.mode = 0660/' "$PHP_FPM_CONF" - sed -i 's/;*user = .*/user = apache/' "$PHP_FPM_CONF" - sed -i 's/;*group = .*/group = apache/' "$PHP_FPM_CONF" - - # Настраиваем производительность PHP-FPM - sed -i 's/;*pm = .*/pm = dynamic/' "$PHP_FPM_CONF" - sed -i 's/;*pm.max_children = .*/pm.max_children = 50/' "$PHP_FPM_CONF" - sed -i 's/;*pm.start_servers = .*/pm.start_servers = 5/' "$PHP_FPM_CONF" - sed -i 's/;*pm.min_spare_servers = .*/pm.min_spare_servers = 5/' "$PHP_FPM_CONF" - sed -i 's/;*pm.max_spare_servers = .*/pm.max_spare_servers = 35/' "$PHP_FPM_CONF" - - # Создаем директорию для socket - SOCKET_DIR=$(dirname "$SOCKET_PATH") - mkdir -p "$SOCKET_DIR" - chown apache:apache "$SOCKET_DIR" - - # Запускаем и включаем PHP-FPM - systemctl start $PHP_FPM_SERVICE >/dev/null 2>&1 - systemctl enable $PHP_FPM_SERVICE >/dev/null 2>&1 - - if ! systemctl is-active --quiet $PHP_FPM_SERVICE; then - log_error "PHP-FPM не удалось запустить" - systemctl status $PHP_FPM_SERVICE --no-pager -l - exit 1 - fi - - log_success "PHP-FPM настроен и запущен" - fi +# Создание основной конфигурации Altcor +create_altcor_config() { + log_info "Создание конфигурации Altcor..." cat > "/etc/httpd/conf.d/altcor.conf" << 'EOF' # Altcor main configuration -# Отключаем информацию о сервере для безопасности +# Безопасность сервера ServerTokens Prod ServerSignature Off @@ -753,40 +719,32 @@ ServerSignature Off AllowOverride All Require all granted - # Настройки сжатия + # Сжатие контента SetOutputFilter DEFLATE - # Исключаем уже сжатые файлы SetEnvIfNoCase Request_URI \ \.(?:gif|jpe?g|png|ico|exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary - # Исключаем старые браузеры SetEnvIfNoCase User-Agent "^Mozilla/4\.0[678]" no-gzip - SetEnvIfNoCase User-Agent "^Mozilla/4\.[0678]" no-gzip SetEnvIfNoCase User-Agent "MSIE [1-6]\." no-gzip # Кэширование статических ресурсов ExpiresActive On - # Изображения ExpiresByType image/jpg "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" ExpiresByType image/webp "access plus 1 month" - ExpiresByType image/ico "access plus 1 month" ExpiresByType image/x-icon "access plus 1 month" - # CSS и JS ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" - # Шрифты ExpiresByType font/woff "access plus 1 month" ExpiresByType font/woff2 "access plus 1 month" ExpiresByType font/ttf "access plus 1 month" ExpiresByType font/otf "access plus 1 month" - # HTML и PHP - без кэширования ExpiresByType text/html "access plus 0 seconds" ExpiresByType application/x-httpd-php "access plus 0 seconds" @@ -797,7 +755,6 @@ ServerSignature Off Header always set X-Frame-Options SAMEORIGIN Header always set X-XSS-Protection "1; mode=block" Header always set Referrer-Policy "strict-origin-when-cross-origin" - # Добавляем заголовки кэширования для статических файлов Header set Cache-Control "public, max-age=2592000" @@ -805,7 +762,7 @@ ServerSignature Off # Запрет доступа к служебным файлам - + Require all denied @@ -813,54 +770,61 @@ ServerSignature Off Require all denied - - Require all denied - - - - Require all denied - - -# Запрет доступа к директориям .git и подобным Require all denied -# Дополнительная защита от выполнения скриптов в uploads +# Защита директории uploads - - Require all denied - - - Require all denied - - - Require all denied - - - Require all denied - - - Require all denied - - - Require all denied - - + Require all denied EOF +} + +# Настройка PHP.ini +configure_php_ini() { + log_info "Настройка PHP.ini..." + + if [ ! -f "$PHP_INI_PATH" ]; then + log_warning "Файл PHP.ini не найден по пути: $PHP_INI_PATH" + return fi - log_success "Модули Apache настроены" + # Создание резервной копии + cp "$PHP_INI_PATH" "${PHP_INI_PATH}.backup.$(date +%Y%m%d_%H%M%S)" + + # Основные настройки + sed -i 's/;*upload_max_filesize = .*/upload_max_filesize = 64M/' "$PHP_INI_PATH" + sed -i 's/;*post_max_size = .*/post_max_size = 64M/' "$PHP_INI_PATH" + sed -i 's/;*max_execution_time = .*/max_execution_time = 300/' "$PHP_INI_PATH" + sed -i 's/;*memory_limit = .*/memory_limit = 256M/' "$PHP_INI_PATH" + sed -i 's/;*max_input_vars = .*/max_input_vars = 3000/' "$PHP_INI_PATH" + + # Настройки OPcache + sed -i 's/;*opcache.enable=.*/opcache.enable=1/' "$PHP_INI_PATH" + sed -i 's/;*opcache.enable_cli=.*/opcache.enable_cli=1/' "$PHP_INI_PATH" + sed -i 's/;*opcache.memory_consumption=.*/opcache.memory_consumption=128/' "$PHP_INI_PATH" + sed -i 's/;*opcache.revalidate_freq=.*/opcache.revalidate_freq=2/' "$PHP_INI_PATH" + sed -i 's/;*opcache.max_accelerated_files=.*/opcache.max_accelerated_files=4000/' "$PHP_INI_PATH" + + # Настройки безопасности + sed -i 's/;*expose_php = .*/expose_php = Off/' "$PHP_INI_PATH" + sed -i 's/;*display_errors = .*/display_errors = Off/' "$PHP_INI_PATH" + sed -i 's/;*log_errors = .*/log_errors = On/' "$PHP_INI_PATH" + + log_success "PHP.ini настроен" +} - log_step "Создание конфигурации виртуального хоста..." +# Создание виртуального хоста +create_virtual_host() { + log_info "Создание конфигурации виртуального хоста..." + mkdir -p "$WEBROOT" - - # Для Debian/Ubuntu создаем стандартный VirtualHost + if [ "$DISTRO_FAMILY" = "debian" ]; then - cat > "$APACHE_CONF" < "$APACHE_CONF" << EOF DocumentRoot $WEBROOT ServerName localhost @@ -884,11 +848,7 @@ EOF SetHandler application/x-httpd-php - - Require all denied - - - + Require all denied @@ -898,10 +858,8 @@ EOF ExpiresByType image/jpeg "access plus 1 month" ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" - ExpiresByType image/svg+xml "access plus 1 month" ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" - ExpiresByType text/javascript "access plus 1 month" ErrorLog \${APACHE_LOG_DIR}/error.log @@ -909,208 +867,366 @@ EOF EOF fi +} - log_success "Конфигурация виртуального хоста создана" - - log_step "Настройка PHP.ini..." +# Проверка конфигурации Apache +verify_apache_config() { + log_info "Проверка конфигурации Apache..." + if [ "$DISTRO_FAMILY" = "debian" ]; then - PHP_INI_PATH="/etc/php/8.3/apache2/php.ini" - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - if [ "$DISTRO" = "fedora" ]; then - PHP_INI_PATH="/etc/php.ini" - else - PHP_INI_PATH="/etc/opt/remi/php83/php.ini" - [ ! -f "$PHP_INI_PATH" ] && PHP_INI_PATH="/etc/php.ini" + if ! apache2ctl configtest >/dev/null 2>&1; then + log_error "Конфигурация Apache содержит ошибки:" + apache2ctl configtest 2>&1 | tee -a "$LOG_FILE" + exit 1 + fi + else + if ! httpd -t >/dev/null 2>&1; then + log_error "Конфигурация Apache (httpd) содержит ошибки:" + httpd -t 2>&1 | tee -a "$LOG_FILE" + + # Попытка исправления + if ! httpd -M 2>/dev/null | grep -q "rewrite_module"; then + echo "LoadModule rewrite_module modules/mod_rewrite.so" >> /etc/httpd/conf.d/altcor.conf + fi + + if ! httpd -t >/dev/null 2>&1; then + log_error "Не удалось исправить конфигурацию Apache" + exit 1 + fi fi fi + + log_success "Конфигурация Apache проверена" +} - if [ -f "$PHP_INI_PATH" ]; then - cp "$PHP_INI_PATH" "${PHP_INI_PATH}.backup.$(date +%Y%m%d_%H%M%S)" - - sed -i 's/;*upload_max_filesize = .*/upload_max_filesize = 64M/' "$PHP_INI_PATH" - sed -i 's/;*post_max_size = .*/post_max_size = 64M/' "$PHP_INI_PATH" - sed -i 's/;*max_execution_time = .*/max_execution_time = 300/' "$PHP_INI_PATH" - sed -i 's/;*memory_limit = .*/memory_limit = 256M/' "$PHP_INI_PATH" - sed -i 's/;*max_input_vars = .*/max_input_vars = 3000/' "$PHP_INI_PATH" - - sed -i 's/;*opcache.enable=.*/opcache.enable=1/' "$PHP_INI_PATH" - sed -i 's/;*opcache.enable_cli=.*/opcache.enable_cli=1/' "$PHP_INI_PATH" - sed -i 's/;*opcache.memory_consumption=.*/opcache.memory_consumption=128/' "$PHP_INI_PATH" - sed -i 's/;*opcache.revalidate_freq=.*/opcache.revalidate_freq=2/' "$PHP_INI_PATH" - sed -i 's/;*opcache.max_accelerated_files=.*/opcache.max_accelerated_files=4000/' "$PHP_INI_PATH" - - sed -i 's/;*expose_php = .*/expose_php = Off/' "$PHP_INI_PATH" - sed -i 's/;*display_errors = .*/display_errors = Off/' "$PHP_INI_PATH" - sed -i 's/;*log_errors = .*/log_errors = On/' "$PHP_INI_PATH" - - log_success "PHP.ini настроен" - else - log_warning "Файл PHP.ini не найден по пути: $PHP_INI_PATH" +# Настройка базы данных +configure_database() { + log_step "Настройка базы данных MariaDB..." + + local db_password=$(generate_password) + + if ! systemctl is-active --quiet mariadb; then + log_error "MariaDB не запущен" + exit 1 fi + + # Выполнение настройки безопасности MariaDB + setup_mariadb_security "$db_password" + + # Создание конфигурационного файла БД + create_db_config "$db_password" + + # Сохранение учетных данных + save_db_credentials "$db_password" + + echo "$db_password" # Возвращаем пароль для использования в main +} - log_step "Создание конфигурации базы данных..." - if [ "$DISTRO_FAMILY" = "debian" ]; then - DB_SOCKET="/var/run/mysqld/mysqld.sock" +# Настройка безопасности MariaDB +setup_mariadb_security() { + local db_password="$1" + + log_info "Выполнение базовой настройки безопасности MariaDB..." + + if mysql -u root -e "SELECT 1;" >/dev/null 2>&1; then + log_info "Первичная настройка MariaDB..." + setup_fresh_mariadb "$db_password" + elif mysql -u root -p"$db_password" -e "SELECT 1;" >/dev/null 2>&1; then + log_info "MariaDB уже настроен, обновляем базу данных..." + update_existing_mariadb "$db_password" else - DB_SOCKET="/var/lib/mysql/mysql.sock" + log_warning "Требуется сброс пароля root в MariaDB..." + reset_mariadb_password "$db_password" fi +} +# Первичная настройка MariaDB +setup_fresh_mariadb() { + local db_password="$1" + local script_file="/tmp/mysql_secure_$(date +%s).sql" + + cat > "$script_file" << MYSQL_SCRIPT +ALTER USER 'root'@'localhost' IDENTIFIED BY '$db_password'; +DELETE FROM mysql.user WHERE User=''; +DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); +DROP DATABASE IF EXISTS test; +DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; +CREATE DATABASE IF NOT EXISTS ALTCor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +GRANT ALL PRIVILEGES ON ALTCor.* TO 'root'@'localhost'; +FLUSH PRIVILEGES; +MYSQL_SCRIPT + + if mysql -u root < "$script_file" >/dev/null 2>&1; then + log_success "Первичная настройка MariaDB выполнена" + else + log_error "Ошибка при настройке MariaDB" + rm -f "$script_file" + exit 1 + fi + rm -f "$script_file" +} + +# Обновление существующей MariaDB +update_existing_mariadb() { + local db_password="$1" + local script_file="/tmp/mysql_update_$(date +%s).sql" + + cat > "$script_file" << MYSQL_SCRIPT +CREATE DATABASE IF NOT EXISTS ALTCor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; +GRANT ALL PRIVILEGES ON ALTCor.* TO 'root'@'localhost'; +FLUSH PRIVILEGES; +MYSQL_SCRIPT + + if mysql -u root -p"$db_password" < "$script_file" >/dev/null 2>&1; then + log_success "База данных ALTCor обновлена" + else + log_error "Ошибка при обновлении базы данных" + rm -f "$script_file" + exit 1 + fi + rm -f "$script_file" +} + +# Сброс пароля MariaDB +reset_mariadb_password() { + local db_password="$1" + + log_info "Сброс пароля root в MariaDB..." + + systemctl stop mariadb + mysqld_safe --skip-grant-tables --skip-networking & + local mysqld_pid=$! + sleep 5 + + local reset_script="/tmp/mysql_reset_$(date +%s).sql" + cat > "$reset_script" << MYSQL_SCRIPT +USE mysql; +UPDATE user SET password=PASSWORD('$db_password') WHERE User='root'; +UPDATE user SET plugin='mysql_native_password' WHERE User='root'; +FLUSH PRIVILEGES; +MYSQL_SCRIPT + + if mysql -u root < "$reset_script" >/dev/null 2>&1; then + kill $mysqld_pid 2>/dev/null || true + sleep 3 + killall mysqld_safe mysqld 2>/dev/null || true + sleep 3 + + systemctl start mariadb + sleep 3 + + if systemctl is-active --quiet mariadb && mysql -u root -p"$db_password" -e "SELECT 1;" >/dev/null 2>&1; then + update_existing_mariadb "$db_password" + log_success "Пароль MariaDB сброшен и база данных настроена" + else + log_error "MariaDB не запустился после сброса пароля" + exit 1 + fi + else + log_error "Не удалось сбросить пароль root в MariaDB" + kill $mysqld_pid 2>/dev/null || true + exit 1 + fi + rm -f "$reset_script" +} + +# Создание конфигурационного файла БД +create_db_config() { + local db_password="$1" + + log_info "Создание конфигурации базы данных..." + cat > "$WEBROOT/db_config.php" << EOF EOF - - log_success "Конфигурация БД создана" - - chown $WEBSERVER_USER:$WEBSERVER_USER "$WEBROOT/db_config.php" - chmod 644 "$WEBROOT/db_config.php" - - if sudo -u $WEBSERVER_USER test -r "$WEBROOT/db_config.php"; then - log_success "Веб-сервер может читать db_config.php" - else - log_error "Веб-сервер НЕ МОЖЕТ читать db_config.php" - fi - - if [ ! -f "$WEBROOT/db_config.php" ]; then - log_error "Не удалось создать файл db_config.php" + + # Установка правильных прав доступа + chown "$WEBSERVER_USER:$WEBSERVER_USER" "$WEBROOT/db_config.php" + chmod 600 "$WEBROOT/db_config.php" + + # Проверка доступности файла + if ! sudo -u "$WEBSERVER_USER" test -r "$WEBROOT/db_config.php"; then + log_error "Веб-сервер не может читать db_config.php" exit 1 fi + + log_success "Конфигурация БД создана" +} - if ! sudo -u $WEBSERVER_USER test -r "$WEBROOT/db_config.php"; then - log_warning "Веб-сервер не может прочитать db_config.php, исправляем права..." - chown $WEBSERVER_USER:$WEBSERVER_USER "$WEBROOT/db_config.php" - chmod 644 "$WEBROOT/db_config.php" +# Сохранение учетных данных +save_db_credentials() { + local db_password="$1" + local credentials_file="/root/.db_password" + + cat > "$credentials_file" << EOF +# Altcor Database Credentials +DB_HOST=localhost +DB_USER=root +DB_PASSWORD=$db_password +DB_NAME=ALTCor +DB_SOCKET=$DB_SOCKET +CREATED=$(date) +EOF + + chmod 600 "$credentials_file" + log_info "Учетные данные сохранены в $credentials_file" +} + +# Установка веб-приложения +setup_web_application() { + log_step "Настройка веб-приложения..." + + # Очистка старых файлов (кроме db_config.php) + find "$WEBROOT" -type f ! -name "db_config.php" -delete 2>/dev/null || true + + # Загрузка файлов приложения + download_application_files + + # Создание .htaccess + create_htaccess_file + + # Настройка прав доступа + setup_file_permissions +} + +# Загрузка файлов приложения +download_application_files() { + local download_url="https://cloud.altcor.ru/setup/download.php" + + log_info "Загрузка файлов приложения..." + + if curl -f -L --max-time 30 -o "$WEBROOT/index.php" "$download_url" 2>/dev/null; then + if head -n 1 "$WEBROOT/index.php" | grep -q "/dev/null; then + log_success "Файлы приложения загружены" + return + fi fi + + # Если загрузка не удалась, создаем резервную страницу + log_warning "Не удалось загрузить файлы с $download_url, создаем резервную страницу" + create_fallback_index +} - DOWNLOAD_URL="https://cloud.altcor.ru/setup/download.php" - TEMP_DOWNLOAD="/tmp/web_files_$(date +%s)" - - create_fallback_index() { - cat > "$WEBROOT/index.php" << 'EOF' +# Создание резервной индексной страницы +create_fallback_index() { + cat > "$WEBROOT/index.php" << 'EOF' "; -echo ""; -echo ""; -echo ""; -echo ""; -echo "Сервер готов к работе"; -echo ""; -echo ""; -echo ""; -echo "
"; -echo "

Сервер готов к работе

"; -echo "
"; -echo "PHP " . phpversion() . " работает
"; -echo "Время сервера: " . date('Y-m-d H:i:s T') . "
"; -echo "Document Root: " . $_SERVER['DOCUMENT_ROOT']; -echo "
"; - -// Диагностика конфигурации БД -echo "
"; -echo "Диагностика конфигурации БД:
"; - -if (file_exists(__DIR__ . '/db_config.php')) { - echo "✓ Файл db_config.php существует
"; - echo "✓ Размер файла: " . filesize(__DIR__ . '/db_config.php') . " байт
"; - echo "✓ Права доступа: " . substr(sprintf('%o', fileperms(__DIR__ . '/db_config.php')), -4) . "
"; - - if (is_readable(__DIR__ . '/db_config.php')) { - echo "✓ Файл читаемый
"; - - try { - require_once __DIR__ . '/db_config.php'; - echo "✓ Файл успешно подключен
"; - echo "✓ DB_HOST: " . (defined('DB_HOST') ? DB_HOST : 'НЕ ОПРЕДЕЛЕН') . "
"; - echo "✓ DB_USER: " . (defined('DB_USER') ? DB_USER : 'НЕ ОПРЕДЕЛЕН') . "
"; - echo "✓ DB_NAME: " . (defined('DB_NAME') ? DB_NAME : 'НЕ ОПРЕДЕЛЕН') . "
"; - } catch (Exception $e) { - echo "✗ Ошибка подключения файла: " . htmlspecialchars($e->getMessage()) . "
"; +?> + + + + + + Altcor - Сервер готов + + + +
+

🚀 Altcor - Сервер готов к работе

+ +
+ ✅ Система успешно установлена
+ PHP работает корректно
+ Время сервера: +
+ +
+
+

🔧 Системная информация

+

Document Root:

+

Server Software:

+

PHP Version:

+
+ +
+

💾 База данных

+ ✅ Подключение успешно

"; + echo "

База: " . DB_NAME . "

"; + echo "

Хост: " . DB_HOST . "

"; + } catch (PDOException $e) { + echo "

❌ Ошибка подключения

"; + echo "

" . htmlspecialchars($e->getMessage()) . "

"; + } + ?> +
+
+ +
+ 🎉 Установка завершена!
+ Система готова для развертывания вашего приложения Altcor. +
+
+ + EOF - } - - log_step "Загрузка файлов приложения..." - find "$WEBROOT" -type f ! -name "db_config.php" -delete 2>/dev/null || true - - if curl -f -L --max-time 30 -o "$WEBROOT/index.php" "$DOWNLOAD_URL" 2>/dev/null; then - if ! head -n 1 "$WEBROOT/index.php" | grep -q "/dev/null; then - create_fallback_index - log_warning "Скачанный файл не является PHP-скриптом, создана резервная страница" - else - log_success "Файлы приложения загружены" - fi - else - create_fallback_index - log_warning "Не удалось загрузить файл с $DOWNLOAD_URL, создана резервная страница" - fi - - log_step "Настройка прав доступа к файлам..." - chown $WEBSERVER_USER:$WEBSERVER_USER "$WEBROOT/index.php" - chmod 644 "$WEBROOT/db_config.php" - chown $WEBSERVER_USER:$WEBSERVER_USER "$WEBROOT/db_config.php" +} +# Создание .htaccess файла +create_htaccess_file() { + log_info "Создание .htaccess файла..." + cat > "$WEBROOT/.htaccess" << 'EOF' +# Altcor .htaccess Configuration - +# Безопасность + Require all denied - + Require all denied +# Сжатие AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json application/xml +# Кэширование ExpiresActive On ExpiresByType image/jpg "access plus 1 month" @@ -1118,342 +1234,323 @@ EOF ExpiresByType image/gif "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" + ExpiresByType image/webp "access plus 1 month" ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" ExpiresByType text/javascript "access plus 1 month" + ExpiresByType font/woff "access plus 1 month" + ExpiresByType font/woff2 "access plus 1 month" +# Заголовки безопасности Header always set X-Content-Type-Options nosniff - Header always set X-Frame-Options DENY + Header always set X-Frame-Options SAMEORIGIN Header always set X-XSS-Protection "1; mode=block" + Header always set Referrer-Policy "strict-origin-when-cross-origin" +# URL Rewriting RewriteEngine On # RewriteCond %{REQUEST_FILENAME} !-f # RewriteCond %{REQUEST_FILENAME} !-d # RewriteRule ^(.*)$ index.php [QSA,L] EOF +} - chown -R $WEBSERVER_USER:$WEBSERVER_USER "$WEBROOT" - chmod -R 755 "$WEBROOT" - chmod 644 "$WEBROOT/.htaccess" 2>/dev/null || true - chmod 600 "$WEBROOT/db_config.php" - log_success "Права доступа настроены" - - log_step "Настройка базы данных MariaDB..." - - if ! systemctl is-active --quiet mariadb; then - log_error "MariaDB не запущен. Попытка запуска..." - systemctl start mariadb - sleep 3 - - if ! systemctl is-active --quiet mariadb; then - log_error "Не удалось запустить MariaDB" - exit 1 - fi - fi - - log_info "Выполнение базовой настройки безопасности MariaDB..." - - if mysql -u root -e "SELECT 1;" >/dev/null 2>&1; then - log_info "Первичная настройка MariaDB (подключение без пароля доступно)..." - - MYSQL_SECURE_SCRIPT="/tmp/mysql_secure_$(date +%s).sql" - cat > "$MYSQL_SECURE_SCRIPT" << MYSQL_SCRIPT --- Устанавливаем пароль для root -ALTER USER 'root'@'localhost' IDENTIFIED BY '$DB_PASSWORD'; - --- Удаляем анонимных пользователей -DELETE FROM mysql.user WHERE User=''; - --- Удаляем root-доступ с удаленных хостов -DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); - --- Удаляем тестовую базу данных -DROP DATABASE IF EXISTS test; -DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; - --- Создаем нашу базу данных -CREATE DATABASE IF NOT EXISTS ALTCor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - --- Даем права на новую базу данных -GRANT ALL PRIVILEGES ON ALTCor.* TO 'root'@'localhost'; - --- Применяем изменения -FLUSH PRIVILEGES; -MYSQL_SCRIPT - - if mysql -u root < "$MYSQL_SECURE_SCRIPT" >/dev/null 2>&1; then - log_success "Первичная настройка MariaDB выполнена успешно" - else - log_error "Не удалось выполнить первичную настройку MariaDB" - rm -f "$MYSQL_SECURE_SCRIPT" - exit 1 - fi - rm -f "$MYSQL_SECURE_SCRIPT" - - elif mysql -u root -p"$DB_PASSWORD" -e "SELECT 1;" >/dev/null 2>&1; then - log_info "MariaDB уже настроен с текущим паролем..." - - MYSQL_UPDATE_SCRIPT="/tmp/mysql_update_$(date +%s).sql" - cat > "$MYSQL_UPDATE_SCRIPT" << MYSQL_SCRIPT -CREATE DATABASE IF NOT EXISTS ALTCor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -GRANT ALL PRIVILEGES ON ALTCor.* TO 'root'@'localhost'; -FLUSH PRIVILEGES; -MYSQL_SCRIPT - - if mysql -u root -p"$DB_PASSWORD" < "$MYSQL_UPDATE_SCRIPT" >/dev/null 2>&1; then - log_success "База данных ALTCor создана/обновлена" - else - log_error "Не удалось обновить базу данных" - rm -f "$MYSQL_UPDATE_SCRIPT" - exit 1 - fi - rm -f "$MYSQL_UPDATE_SCRIPT" - - else - log_error "Не удалось подключиться к MariaDB ни с пустым паролем, ни с текущим паролем" - log_info "Попытка сброса пароля root в MariaDB..." - - systemctl stop mariadb - - mysqld_safe --skip-grant-tables --skip-networking & - MYSQLD_SAFE_PID=$! - - sleep 5 - - MYSQL_RESET_SCRIPT="/tmp/mysql_reset_$(date +%s).sql" - cat > "$MYSQL_RESET_SCRIPT" << MYSQL_SCRIPT -USE mysql; -UPDATE user SET password=PASSWORD('$DB_PASSWORD') WHERE User='root'; -UPDATE user SET plugin='mysql_native_password' WHERE User='root'; -FLUSH PRIVILEGES; -MYSQL_SCRIPT - - if mysql -u root < "$MYSQL_RESET_SCRIPT" >/dev/null 2>&1; then - log_info "Пароль root сброшен" - - kill $MYSQLD_SAFE_PID 2>/dev/null || true - sleep 2 - killall mysqld_safe 2>/dev/null || true - killall mysqld 2>/dev/null || true - sleep 3 - - systemctl start mariadb - sleep 3 - - if systemctl is-active --quiet mariadb && mysql -u root -p"$DB_PASSWORD" -e "SELECT 1;" >/dev/null 2>&1; then - MYSQL_FINAL_SCRIPT="/tmp/mysql_final_$(date +%s).sql" - cat > "$MYSQL_FINAL_SCRIPT" << MYSQL_SCRIPT -CREATE DATABASE IF NOT EXISTS ALTCor CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -GRANT ALL PRIVILEGES ON ALTCor.* TO 'root'@'localhost'; -FLUSH PRIVILEGES; -MYSQL_SCRIPT - - if mysql -u root -p"$DB_PASSWORD" < "$MYSQL_FINAL_SCRIPT" >/dev/null 2>&1; then - log_success "MariaDB настроен после сброса пароля" - else - log_error "Не удалось создать базу данных после сброса пароля" - exit 1 - fi - rm -f "$MYSQL_FINAL_SCRIPT" - else - log_error "MariaDB не запустился после сброса пароля" - exit 1 - fi - else - log_error "Не удалось сбросить пароль root в MariaDB" - kill $MYSQLD_SAFE_PID 2>/dev/null || true - exit 1 - fi - rm -f "$MYSQL_RESET_SCRIPT" - fi - - log_success "База данных настроена" - - log_step "Проверка конфигурации Apache..." - if [ "$DISTRO_FAMILY" = "debian" ]; then - if ! apache2ctl configtest >/dev/null 2>&1; then - log_error "Конфигурация Apache содержит ошибки." - apache2ctl configtest # Показываем ошибки для диагностики - exit 1 - fi - - WEBSERVER_SERVICE="apache2" +# Настройка прав доступа к файлам +setup_file_permissions() { + log_info "Настройка прав доступа к файлам..." - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - # Для Rocky Linux/RHEL сначала проверим синтаксис конфигурации - if ! httpd -t >/dev/null 2>&1; then - log_error "Конфигурация Apache (httpd) содержит ошибки:" - echo "" - httpd -t # Показываем детали ошибок - echo "" - log_info "Попытка исправления..." - - # Проверяем наличие основных модулей - if ! httpd -M 2>/dev/null | grep -q "rewrite_module"; then - echo "LoadModule rewrite_module modules/mod_rewrite.so" >> /etc/httpd/conf.d/altcor.conf - fi - - # Повторная проверка - if ! httpd -t >/dev/null 2>&1; then - log_error "Не удалось исправить конфигурацию Apache:" - httpd -t - exit 1 - else - log_success "Конфигурация исправлена" - fi - fi - - WEBSERVER_SERVICE="httpd" - fi - log_success "Конфигурация Apache проверена" + # Установка владельца и группы + chown -R "$WEBSERVER_USER:$WEBSERVER_USER" "$WEBROOT" + + # Установка прав доступа + find "$WEBROOT" -type d -exec chmod 755 {} \; + find "$WEBROOT" -type f -exec chmod 644 {} \; + + # Специальные права для конфигурации БД + chmod 600 "$WEBROOT/db_config.php" + + log_success "Права доступа настроены" +} +# Запуск и включение сервисов +start_services() { log_step "Запуск и включение сервисов..." + + local services_to_restart="" + local services_to_enable="" + + # Определяем сервисы для перезапуска if [ "$DISTRO_FAMILY" = "debian" ]; then - systemctl restart apache2 >/dev/null 2>&1 - systemctl enable apache2 >/dev/null 2>&1 - elif [ "$DISTRO_FAMILY" = "rhel" ]; then - # Сначала запускаем PHP-FPM, потом Apache - if [ -n "$PHP_FPM_SERVICE" ]; then - systemctl restart $PHP_FPM_SERVICE >/dev/null 2>&1 - systemctl enable $PHP_FPM_SERVICE >/dev/null 2>&1 - fi - systemctl restart httpd >/dev/null 2>&1 - systemctl enable httpd >/dev/null 2>&1 + services_to_restart="apache2 mariadb" + services_to_enable="apache2 mariadb" + else + services_to_restart="$PHP_FPM_SERVICE httpd mariadb" + services_to_enable="$PHP_FPM_SERVICE httpd mariadb" fi + + # Добавляем Redis + if systemctl list-unit-files | grep -q "redis-server.service"; then + services_to_restart="$services_to_restart redis-server" + services_to_enable="$services_to_enable redis-server" + elif systemctl list-unit-files | grep -q "redis.service"; then + services_to_restart="$services_to_restart redis" + services_to_enable="$services_to_enable redis" + fi + + # Перезапуск сервисов + for service in $services_to_restart; do + if safe_execute "Перезапуск $service" systemctl restart "$service"; then + log_success "$service перезапущен" + else + log_error "Не удалось перезапустить $service" + fi + done + + # Включение в автозагрузку + for service in $services_to_enable; do + safe_execute "Включение $service в автозагрузку" systemctl enable "$service" || true + done + + log_success "Все сервисы настроены" +} - systemctl restart mariadb >/dev/null 2>&1 - systemctl restart redis-server >/dev/null 2>&1 || systemctl restart redis >/dev/null 2>&1 || true - - systemctl enable mariadb >/dev/null 2>&1 - systemctl enable redis-server >/dev/null 2>&1 || systemctl enable redis >/dev/null 2>&1 || true - - log_success "Все сервисы запущены и добавлены в автозагрузку" - - # В секции финальной проверки добавьте проверку PHP-FPM: +# Финальная проверка работоспособности +final_verification() { log_step "Финальная проверка работоспособности..." - if ! systemctl is-active --quiet $WEBSERVER_SERVICE; then - log_error "Веб-сервер не запущен" - exit 1 + + local errors=0 + + # Проверка веб-сервера + if ! systemctl is-active --quiet "$WEBSERVER_SERVICE"; then + log_error "Веб-сервер ($WEBSERVER_SERVICE) не запущен" + ((errors++)) + else + log_success "Веб-сервер работает" fi - + + # Проверка PHP-FPM (для RHEL семейства) if [ "$DISTRO_FAMILY" = "rhel" ] && [ -n "$PHP_FPM_SERVICE" ]; then - if ! systemctl is-active --quiet $PHP_FPM_SERVICE; then - log_error "PHP-FPM не запущен" - exit 1 + if ! systemctl is-active --quiet "$PHP_FPM_SERVICE"; then + log_error "PHP-FPM ($PHP_FPM_SERVICE) не запущен" + ((errors++)) + else + log_success "PHP-FPM работает" fi fi - + + # Проверка MariaDB if ! systemctl is-active --quiet mariadb; then log_error "MariaDB не запущен" - exit 1 - fi - - if ! php -r "echo phpversion();" >/dev/null 2>&1; then - log_error "PHP не работает корректно" - exit 1 - fi - - if ! mysql -u root -p"$DB_PASSWORD" -e "USE ALTCor; SELECT 1;" >/dev/null 2>&1; then - log_error "Не удается подключиться к базе данных ALTCor" - exit 1 - fi - - log_success "Все компоненты работают корректно" - - log_step "Сохранение учетных данных..." - DB_CREDENTIALS_FILE="/root/.db_password" - cat > "$DB_CREDENTIALS_FILE" << EOF - -DB_HOST=localhost -DB_USER=root -DB_PASSWORD=$DB_PASSWORD -DB_NAME=ALTCor -EOF - - chmod 600 "$DB_CREDENTIALS_FILE" - log_info "Учетные данные сохранены в $DB_CREDENTIALS_FILE" - - IP_ADDR=$(hostname -I | awk '{print $1}') - - echo "" - if [ "$REINSTALL" = true ]; then - log_success "Переустановка Altcor успешно завершена." + ((errors++)) else - log_success "Установка Altcor успешно завершена." + log_success "MariaDB работает" fi + + # Проверка PHP + if ! php -r "echo 'PHP OK';" >/dev/null 2>&1; then + log_error "PHP не работает корректно" + ((errors++)) + else + log_success "PHP работает корректно" + fi + + # Проверка подключения к базе данных + if [ -f "$WEBROOT/db_config.php" ]; then + if php -r " + require '$WEBROOT/db_config.php'; + try { + \$pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=' . DB_CHARSET, DB_USER, DB_PASS); + echo 'DB OK'; + } catch (Exception \$e) { + exit(1); + } + " >/dev/null 2>&1; then + log_success "Подключение к базе данных работает" + else + log_error "Не удается подключиться к базе данных" + ((errors++)) + fi + else + log_error "Файл конфигурации БД не найден" + ((errors++)) + fi + + if [ $errors -eq 0 ]; then + log_success "Все компоненты работают корректно" + return 0 + else + log_error "Обнаружено $errors ошибок в работе системы" + return 1 + fi +} + +# Отображение итоговой информации +show_final_info() { + local db_password="$1" + local ip_addr=$(hostname -I | awk '{print $1}' 2>/dev/null || echo "N/A") + echo "" - echo " Доступ к сайту:" + echo "==============================================================" + if [ "$REINSTALL" = true ]; then + log_success "Переустановка Altcor успешно завершена!" + else + log_success "Установка Altcor успешно завершена!" + fi + echo "==============================================================" + echo "" + echo -e "${CYAN}🌐 Доступ к сайту:${NC}" echo " • http://localhost/" - echo " • http://$IP_ADDR/" + echo " • http://$ip_addr/" echo "" - echo " Доступ к БД:" + echo -e "${CYAN}💾 Доступ к БД:${NC}" echo " • Хост: localhost" echo " • Логин: root" - echo " • Пароль: $DB_PASSWORD" + echo " • Пароль: $db_password" echo " • База данных: ALTCor" echo "" - echo " Расположение файлов:" + echo -e "${CYAN}📁 Расположение файлов:${NC}" echo " • Веб-корень: $WEBROOT" echo " • Конфигурация БД: $WEBROOT/db_config.php" echo " • Логи Apache: /var/log/apache2/ или /var/log/httpd/" + echo " • Лог установки: $LOG_FILE" echo "" - echo " Дополнительная информация:" - echo " • Учетные данные БД: $DB_CREDENTIALS_FILE" - echo " • Для удаления: ./install.sh -u" - echo " • Для переустановки: ./install.sh -r" + echo -e "${CYAN}ℹ️ Дополнительная информация:${NC}" + echo " • Учетные данные БД: /root/.db_password" + echo " • Для удаления: $0 -u" + echo " • Для переустановки: $0 -r" + echo "" + echo -e "${GREEN}Система готова к работе!${NC}" + echo "==============================================================" echo "" } -if [[ $EUID -ne 0 ]]; then - log_error "Запустите этот скрипт вместе с sudo." - exit 1 -fi - -if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO="$ID" - FAMILY="$ID_LIKE" -else - log_error "Не удалось определить дистрибутив." - exit 1 -fi - -if echo "$DISTRO $FAMILY" | grep -qi "debian\|ubuntu"; then - PKG_MANAGER="apt" - DISTRO_FAMILY="debian" -elif echo "$DISTRO $FAMILY" | grep -qi "rhel\|centos\|fedora"; then - PKG_MANAGER="dnf" - DISTRO_FAMILY="rhel" - if ! command -v dnf >/dev/null 2>&1; then - PKG_MANAGER="yum" +# Основная функция установки +proceed_with_installation() { + echo "" + echo "🚀 Начинаем установку Altcor..." + echo "" + + # Обновление системы и установка базовых пакетов + update_system + + # Настройка репозиториев PHP 8.3 + setup_php_repositories + + # Установка основных компонентов + install_components + + # Настройка Apache и PHP + configure_apache_php + + # Настройка базы данных + local db_password + db_password=$(configure_database) + + # Настройка веб-приложения + setup_web_application + + # Запуск сервисов + start_services + + # Финальная проверка + if final_verification; then + show_final_info "$db_password" + else + log_error "Установка завершена с ошибками. Проверьте лог: $LOG_FILE" + exit 1 fi -else - log_error "Ваш дистрибутив '$DISTRO' не поддерживается. Поддерживаются: Debian/Ubuntu, CentOS/RHEL/Fedora." - exit 1 -fi +} -if [ "$UNINSTALL" = true ]; then - full_uninstall -elif [ "$REINSTALL" = true ]; then - echo "" - log_step "Начинаем переустановку Altcor..." - echo "" +# Интерактивный выбор действий при обнаружении существующей установки +handle_existing_installation() { + local need_reinstall=$1 - full_uninstall - - proceed_with_installation -else - check_result=0 - check_existing_installation || check_result=$? - - if [ $check_result -eq 1 ]; then + if [ $need_reinstall -eq 0 ]; then if [ "$REINSTALL" = true ]; then - full_uninstall + log_warning "Обнаружена существующая установка. Начинаем переустановку..." + return 1 # Требуется переустановка + else + log_success "Все компоненты уже установлены и работают корректно" + echo "" + echo -e "${YELLOW}Altcor уже полностью установлен и функционирует.${NC}" + echo "" + read -p "Хотите переустановить систему? [y/n]: " -n 1 -r + echo "" + if [[ $REPLY =~ ^[Yy]$ ]]; then + log_info "Начинаем переустановку по запросу пользователя..." + REINSTALL=true + return 1 # Требуется переустановка + else + echo "" + log_info "Переустановка отменена. Система остается без изменений." + echo "" + echo "Для принудительной переустановки используйте: $0 -r" + echo "" + exit 0 + fi fi + else + log_warning "Обнаружены проблемы с установленными компонентами." + echo "" + read -p "Хотите переустановить всю систему? [y/n]: " -n 1 -r + echo "" + if [[ $REPLY =~ ^[Yy]$ ]]; then + log_info "Начинаем полную переустановку..." + REINSTALL=true + return 1 # Требуется переустановка + else + log_info "Продолжаем обычную установку/обновление компонентов..." + return 0 # Продолжить обычную установку + fi + fi +} + +# Главная функция +main() { + # Инициализация + log_to_file "=== Начало установки Altcor $(date) ===" + + # Проверка прав администратора + check_root + + # Определение дистрибутива + detect_distro + + # Обработка различных режимов работы + if [ "$UNINSTALL" = true ]; then + full_uninstall + elif [ "$REINSTALL" = true ]; then + echo "" + log_step "Начинаем переустановку Altcor..." + echo "" + full_uninstall proceed_with_installation - elif [ $check_result -eq 0 ]; then - proceed_with_installation -fi \ No newline at end of file + else + # Проверка существующей установки + local check_result=0 + check_existing_installation || check_result=$? + + local action_result=0 + handle_existing_installation $check_result || action_result=$? + + if [ $action_result -eq 1 ]; then + if [ "$REINSTALL" = true ]; then + full_uninstall + fi + proceed_with_installation + elif [ $action_result -eq 0 ]; then + proceed_with_installation + fi + fi + + log_to_file "=== Завершение установки Altcor $(date) ===" +} + +# Обработка сигналов для корректного завершения +trap 'log_error "Установка прервана пользователем"; exit 130' INT TERM + +# Запуск основной функции +main "$@" \ No newline at end of file