Files
altcorAutoinstall/install.sh

1372 lines
48 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 ;;
\?)
echo -e "${RED}[Ошибка]${NC} Неизвестный параметр: -$OPTARG" >&2
echo "Использование: $0 [-u] [-r]"
echo " -u Полное удаление"
echo " -r Переустановка (удаление + установка)"
exit 1
;;
esac
done
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() {
if command -v openssl >/dev/null 2>&1; then
openssl rand -base64 32 | tr -d "=+/" | cut -c1-16
else
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16
fi
}
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
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 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
else
return 1
fi
else
return 0
fi
else
return 2
fi
}
check_existing_installation() {
log_step "Проверка существующей установки..."
local apache_status php_status mariadb_status redis_status
local need_reinstall=false
log_info "Проверка Apache..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
check_component_status "Apache" "apache2" "apache2"
apache_status=$?
else
check_component_status "Apache" "httpd" "httpd"
apache_status=$?
fi
log_info "Проверка PHP..."
check_component_status "PHP" "php" ""
php_status=$?
log_info "Проверка MariaDB..."
check_component_status "MariaDB" "mysql" "mariadb"
mariadb_status=$?
log_info "Проверка Redis..."
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
if [ -f "/var/www/html/db_config.php" ]; then
echo -e "Конфигурация БД: ${GREEN}Найдена${NC}"
else
echo -e "Конфигурация БД: ${RED}Не найдена${NC}"
need_reinstall=true
fi
echo ""
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
}
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 "Остановка сервисов..."
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
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
safe_execute "Удаление пакетов (Debian/Ubuntu)" \
apt purge -y nginx* apache2* php* mariadb* mysql* redis*
safe_execute "Очистка неиспользуемых пакетов" apt autoremove -y
else
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 /etc/opt/remi/php83 /opt/remi/php83 2>/dev/null || true
log_success "Полное удаление завершено."
if [ "$REINSTALL" = false ]; then
exit 0
else
log_info "Переустановка: удаление завершено, продолжаем установку..."
echo ""
fi
}
update_system() {
log_step "Обновление системы и установка базовых пакетов..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
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
}
setup_php_repositories() {
log_step "Настройка репозиториев для PHP 8.3..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
if ! apt-cache show php8.3 &>/dev/null; then
log_info "Добавление репозитория Sury для PHP 8.3..."
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
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
safe_execute "Обновление списка пакетов после добавления репозитория PHP" apt update -y
if ! apt-cache show php8.3 &>/dev/null; then
log_error "PHP 8.3 недоступен после добавления репозиториев"
exit 1
fi
fi
log_success "Репозиторий PHP 8.3 настроен"
else
log_info "Настройка репозиториев Remi для RHEL-семейства..."
local version_id=$(echo "$VERSION_ID" | cut -d'.' -f1)
if [ "$DISTRO" = "fedora" ]; then
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
safe_execute "Установка Remi репозитория для RHEL/CentOS" \
$PKG_MANAGER install -y "https://rpms.remirepo.net/enterprise/remi-release-${version_id}.rpm"
fi
if command -v dnf >/dev/null 2>&1; then
safe_execute "Сброс модуля PHP" dnf module reset php -y || true
safe_execute "Включение модуля PHP 8.3" dnf module enable php:remi-8.3 -y || true
fi
log_success "Репозиторий Remi настроен"
fi
}
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
if [ "$DISTRO_FAMILY" = "debian" ]; then
safe_execute "Установка Apache" apt install -y apache2
else
safe_execute "Установка Apache (httpd)" $PKG_MANAGER install -y httpd
fi
install_mariadb
install_php83
install_additional_components
}
remove_old_packages() {
log_info "Удаление старых версий пакетов..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
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
rm -rf /var/lib/mysql* /etc/mysql* /var/log/mysql* /etc/my.cnf* 2>/dev/null || true
}
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
safe_execute "Установка MariaDB" apt install -y mariadb-server
else
safe_execute "Установка MariaDB" $PKG_MANAGER install -y mariadb-server
fi
safe_execute "Запуск MariaDB" systemctl start mariadb
safe_execute "Включение MariaDB в автозагрузку" systemctl enable mariadb
log_info "Ожидание полного запуска MariaDB..."
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 не удалось запустить"
exit 1
fi
}
install_php83() {
log_info "Установка PHP 8.3 и расширений..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
export DEBIAN_FRONTEND=noninteractive
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
if $PKG_MANAGER list available | grep -q "php83-php\b"; then
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
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
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
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
verify_php_installation
}
verify_php_installation() {
log_info "Проверка установки PHP..."
if ! command -v php >/dev/null 2>&1; then
log_error "PHP не найден после установки"
exit 1
fi
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" ] && [ -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
if [[ "$php_version" == "8.3" ]]; then
log_success "PHP 8.3 успешно установлен"
else
log_error "Не удалось установить PHP 8.3 (текущая версия: $php_version)"
exit 1
fi
verify_php_extensions
}
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_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
}
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
}
configure_apache_php() {
log_step "Настройка Apache и PHP..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
configure_apache_debian
else
configure_apache_rhel
fi
configure_php_ini
create_virtual_host
verify_apache_config
}
configure_apache_debian() {
log_info "Настройка Apache для Debian/Ubuntu..."
a2enmod php8.3 rewrite ssl headers expires deflate 2>/dev/null || true
for php_ver in 7.4 8.0 8.1 8.2; do
a2dismod "php$php_ver" 2>/dev/null || true
done
}
configure_apache_rhel() {
log_info "Настройка Apache для RHEL семейства..."
rm -f /etc/httpd/conf.d/php.conf /etc/httpd/conf.modules.d/*php*.conf 2>/dev/null || true
configure_php_fpm
create_php_fpm_config
create_altcor_config
}
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)"
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"
local socket_dir=$(dirname "$SOCKET_PATH")
mkdir -p "$socket_dir"
chown apache:apache "$socket_dir"
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
}
create_php_fpm_config() {
log_info "Создание конфигурации PHP-FPM для Apache..."
cat > "/etc/httpd/conf.d/php-fpm.conf" << EOF
# PHP-FPM configuration for Apache
# Использование только PHP-FPM, без mod_php
# Загрузка необходимых модулей
<IfModule !mod_rewrite.c>
LoadModule rewrite_module modules/mod_rewrite.so
</IfModule>
<IfModule !mod_headers.c>
LoadModule headers_module modules/mod_headers.so
</IfModule>
<IfModule !mod_expires.c>
LoadModule expires_module modules/mod_expires.so
</IfModule>
<IfModule !mod_deflate.c>
LoadModule deflate_module modules/mod_deflate.so
</IfModule>
<IfModule !mod_proxy.c>
LoadModule proxy_module modules/mod_proxy.so
</IfModule>
<IfModule !mod_proxy_fcgi.c>
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
</IfModule>
# Обработка PHP файлов через PHP-FPM
<FilesMatch \.php$>
SetHandler "proxy:unix:$SOCKET_PATH|fcgi://localhost"
</FilesMatch>
# Настройки производительности
ProxyTimeout 300
ProxyPassMatch ^/(.*\.php(/.*)?)$ unix:$SOCKET_PATH|fcgi://localhost/var/www/html/
EOF
}
create_altcor_config() {
log_info "Создание конфигурации Altcor..."
cat > "/etc/httpd/conf.d/altcor.conf" << 'EOF'
# Altcor main configuration
# Безопасность сервера
ServerTokens Prod
ServerSignature Off
# Основные настройки директории
<Directory "/var/www/html">
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
# Сжатие контента
<IfModule mod_deflate.c>
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 "MSIE [1-6]\." no-gzip
</IfModule>
# Кэширование статических ресурсов
<IfModule mod_expires.c>
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/x-icon "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"
ExpiresByType font/ttf "access plus 1 month"
ExpiresByType font/otf "access plus 1 month"
ExpiresByType text/html "access plus 0 seconds"
ExpiresByType application/x-httpd-php "access plus 0 seconds"
</IfModule>
# Заголовки безопасности
<IfModule mod_headers.c>
Header always set X-Content-Type-Options nosniff
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"
<FilesMatch "\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|otf)$">
Header set Cache-Control "public, max-age=2592000"
</FilesMatch>
</IfModule>
</Directory>
# Запрет доступа к служебным файлам
<Files ~ "\.(conf|env|log|bak|backup)$">
Require all denied
</Files>
<Files ".htaccess">
Require all denied
</Files>
<DirectoryMatch "^\.|\/\.">
Require all denied
</DirectoryMatch>
# Защита директории uploads
<Directory "/var/www/html/uploads">
<Files ~ "\.(php|phtml|pl|py|jsp|asp|sh|cgi)$">
Require all denied
</Files>
</Directory>
EOF
}
configure_php_ini() {
log_info "Настройка PHP.ini..."
if [ ! -f "$PHP_INI_PATH" ]; then
log_warning "Файл PHP.ini не найден по пути: $PHP_INI_PATH"
return
fi
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 настроен"
}
create_virtual_host() {
log_info "Создание конфигурации виртуального хоста..."
mkdir -p "$WEBROOT"
if [ "$DISTRO_FAMILY" = "debian" ]; then
cat > "$APACHE_CONF" << EOF
<VirtualHost *:80>
DocumentRoot $WEBROOT
ServerName localhost
ServerAlias www.localhost
<Directory $WEBROOT>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \
\.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
</IfModule>
</Directory>
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
<Files ~ "\.(conf|env|log)$">
Require all denied
</Files>
<IfModule mod_expires.c>
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 text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
ErrorLog \${APACHE_LOG_DIR}/error.log
CustomLog \${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
EOF
fi
}
verify_apache_config() {
log_info "Проверка конфигурации Apache..."
if [ "$DISTRO_FAMILY" = "debian" ]; then
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 проверена"
}
configure_database() {
log_step "Настройка базы данных MariaDB..."
local db_password=$(generate_password)
if ! systemctl is-active --quiet mariadb; then
log_error "MariaDB не запущен"
exit 1
fi
setup_mariadb_security "$db_password"
create_db_config "$db_password"
save_db_credentials "$db_password"
echo "$db_password"
}
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
log_warning "Требуется сброс пароля root в MariaDB..."
reset_mariadb_password "$db_password"
fi
}
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"
}
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"
}
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
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '$db_password');
define('DB_NAME', 'ALTCor');
define('DB_SOCKET', '$DB_SOCKET');
define('DB_CHARSET', 'utf8mb4');
define('OFFICE', '/usr/bin/libreoffice');
?>
EOF
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 "Конфигурация БД создана"
}
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 "Настройка веб-приложения..."
find "$WEBROOT" -type f ! -name "db_config.php" -delete 2>/dev/null || true
download_application_files
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 "<?php" || grep -q "<?php" "$WEBROOT/index.php" 2>/dev/null; then
log_success "Файлы приложения загружены"
return
fi
fi
log_warning "Не удалось загрузить файлы с $download_url, создаем резервную страницу"
create_fallback_index
}
create_fallback_index() {
cat > "$WEBROOT/index.php" << 'EOF'
<?php require_once __DIR__ . '/db_config.php'; ?>
<!DOCTYPE html>
<html lang='ru'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<title>Altcor - Сервер готов</title>
<style>
body { font-family: -apple-system, sans-serif; margin: 40px; background: linear-gradient(135deg, #667eea, #764ba2); min-height: 90vh; }
.container { max-width: 600px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }
h1 { color: #2c5282; text-align: center; margin-top: 0; }
.status { padding: 15px; margin: 15px 0; border-radius: 5px; }
.success { background: #c6f6d5; color: #22543d; border-left: 4px solid #38a169; }
.info { background: #bee3f8; color: #2a4365; border-left: 4px solid #3182ce; }
</style>
</head>
<body>
<div class='container'>
<h1>Altcor - Система готова</h1>
<div class='status success'>
<strong>PHP <?= phpversion() ?> работает</strong><br>
Время: <?= date('Y-m-d H:i:s') ?>
</div>
<div class='status <?=
try {
new PDO("mysql:host=" . DB_HOST . ";dbname=" . DB_NAME, DB_USER, DB_PASS);
echo "success'>✅ База данных подключена";
} catch (PDOException $e) {
echo "info'>⚠️ БД: " . htmlspecialchars($e->getMessage());
}
?>
</div>
<div class='status info'>
<strong>Установка завершена!</strong><br>
Система готова для развертывания Altcor.
</div>
</div>
</body>
</html>
EOF
}
create_htaccess_file() {
log_info "Создание .htaccess файла..."
cat > "$WEBROOT/.htaccess" << 'EOF'
# Altcor .htaccess Configuration
# Безопасность
<Files ~ "\.(conf|env|log|bak|backup|sql)$">
Require all denied
</Files>
<Files ".htaccess">
Require all denied
</Files>
# Сжатие
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json application/xml
</IfModule>
# Кэширование
<IfModule mod_expires.c>
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 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"
</IfModule>
# Заголовки безопасности
<IfModule mod_headers.c>
Header always set X-Content-Type-Options nosniff
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"
</IfModule>
# URL Rewriting
RewriteEngine On
# RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
# RewriteRule ^(.*)$ index.php [QSA,L]
EOF
}
setup_file_permissions() {
log_info "Настройка прав доступа к файлам..."
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
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
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 "Все сервисы настроены"
}
final_verification() {
log_step "Финальная проверка работоспособности..."
local errors=0
if ! systemctl is-active --quiet "$WEBSERVER_SERVICE"; then
log_error "Веб-сервер ($WEBSERVER_SERVICE) не запущен"
((errors++))
else
log_success "Веб-сервер работает"
fi
if [ "$DISTRO_FAMILY" = "rhel" ] && [ -n "$PHP_FPM_SERVICE" ]; then
if ! systemctl is-active --quiet "$PHP_FPM_SERVICE"; then
log_error "PHP-FPM ($PHP_FPM_SERVICE) не запущен"
((errors++))
else
log_success "PHP-FPM работает"
fi
fi
if ! systemctl is-active --quiet mariadb; then
log_error "MariaDB не запущен"
((errors++))
else
log_success "MariaDB работает"
fi
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 ""
if [ "$REINSTALL" = true ]; then
log_success "Переустановка Altcor успешно завершена"
else
log_success "Установка Altcor успешно завершена"
fi
echo ""
echo -e "${CYAN}Доступ к сайту:${NC}"
echo " • http://localhost/"
echo " • http://$ip_addr/"
echo ""
echo -e "${CYAN}Доступ к БД:${NC}"
echo " • Хост: localhost"
echo " • Логин: root"
echo " • Пароль: $db_password"
echo " • База данных: ALTCor"
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 -e "${CYAN}Дополнительная информация:${NC}"
echo " • Учетные данные БД: /root/.db_password"
echo " • Для удаления: $0 -u"
echo " • Для переустановки: $0 -r"
echo ""
echo -e "${GREEN}Система готова к работе!${NC}"
echo "=============================================================="
echo ""
}
proceed_with_installation() {
echo ""
echo "Начинаем установку Altcor..."
echo ""
update_system
setup_php_repositories
install_components
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
}
handle_existing_installation() {
local need_reinstall=$1
if [ $need_reinstall -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
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
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 "$@"