Bitrix native VPS infra: nginx+php-fpm+MySQL socket+memcached x2+fail2ban+crowdsec, domain-agnostic

This commit is contained in:
infra-bot
2026-08-27 16:13:28 +03:00
commit e14bfc676f
3 changed files with 321 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
#!/usr/bin/env bash
# ============================================================
# Bitrix native VPS provisioning (Ubuntu 24.04, no Docker)
# nginx + php-fpm + Percona MySQL (socket) + memcached x2
# + fail2ban + CrowdSec + ufw + swap + logrotate + cron
#
# Usage: sudo ./install.sh (edit vars below first!)
# Idempotent-ish: re-running is safe but configs get overwritten.
# ============================================================
set -euo pipefail
# ------------------- EDIT BEFORE RUN -------------------
DOMAIN="" # primary site domain, no www, REQUIRED
SITE_DIR="/home/bitrix/www" # webroot (match old server layout)
DB_NAME="sitemanager"
DB_USER="bitrix"
DB_PASS="" # empty = auto-generate, printed at end
FPM_MAX_CHILDREN=30 # ~150MB/worker; budget: RAM - mysql(5G) - memcached(1.2G)
TZ_REGION="Asia/Yekaterinburg"
MEMCACHED_CACHE_MB=1024 # bitrix managed cache
MEMCACHED_SESSIONS_MB=128 # php sessions via .settings.php
CROWDSEC_ENROLL_KEY="" # optional: console.enroll key from app.crowdsec.net
BACKUP_DIR="/var/backups/bitrix"
MYSQL_ROOT_PASSWORD="" # empty = socket-auth only (recommended)
# -------------------------------------------------------
REPO_ROOT="$(cd "$(dirname "$0")" && pwd)" # install.sh sits at repo root
CREDS_FILE="/root/bitrix-install-creds.txt"
step() { printf '\n==> %s\n' "$*"; }
die() { echo "ERROR: $*" >&2; exit 1; }
[[ $EUID -eq 0 ]] || die "run as root"
[[ -n "$DOMAIN" ]] || die "edit install.sh: fill DOMAIN= at the top first"
export DEBIAN_FRONTEND=noninteractive
step "Base packages"
apt-get update -y
apt-get install -y curl ca-certificates gnupg lsb-release unzip git jq \
logrotate unattended-upgrades software-properties-common util-linux
step "Timezone -> $TZ_REGION"
timedatectl set-timezone "$TZ_REGION" || true
step "System user 'bitrix'"
id -u bitrix >/dev/null 2>&1 || useradd --create-home --shell /bin/bash bitrix
mkdir -p "$SITE_DIR" "$BACKUP_DIR" /tmp/php_sessions/www /tmp/php/upload /var/log/php
chown bitrix:bitrix /tmp/php_sessions/www /tmp/php/upload
chmod 700 /tmp/php_sessions/www
chown www-data:www-data /var/log/php
step "Swap 4G + vm.swappiness=10"
if [[ ! -f /swapfile ]]; then
fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
grep -q '^/swapfile' /etc/fstab || echo '/swapfile none swap sw 0 0' >> /etc/fstab
fi
cat > /etc/sysctl.d/99-bitrix.conf <<EOF
vm.swappiness = 10
EOF
sysctl --system > /dev/null
step "PHP 8.4 via ondrej PPA (fpm + cli)"
add-apt-repository -y ppa:ondrej/php
apt-get update -y
apt-get install -y \
php8.4-fpm php8.4-cli php8.4-common php8.4-mysql php8.4-curl php8.4-gd \
php8.4-intl php8.4-mbstring php8.4-xml php8.4-zip php8.4-bz2 php8.4-bcmath \
php8.4-opcache php8.4-readline php8.4-igbinary php8.4-msgpack \
php8.4-memcached php8.4-redis php8.4-apcu
step "nginx"
apt-get install -y nginx
step "Percona MySQL 8.0 LTS"
curl -sL https://www.percona.com/downloads/percona-release/percona-release_latest.generic_all.deb -o /tmp/percona-release.deb
dpkg -i /tmp/percona-release.deb || apt-get -f install -y
apt-get update -y
apt-get install -y percona-server-server || apt-get install -y mysql-server
[[ -n "$DB_PASS" ]] || DB_PASS="$(openssl rand -hex 16)"
step "memcached (dual instances)"
apt-get install -y memcached
systemctl disable --now memcached.service 2>/dev/null || true # distro single instance off
step "fail2ban"
apt-get install -y fail2ban
step "CrowdSec + firewall bouncer"
curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | bash
apt-get update -y
apt-get install -y crowdsec crowdsec-firewall-bouncer \
|| echo "WARN: firewall-bouncer install failed; run manually later"
step "Deploy nginx configs"
cp "$REPO_ROOT/config/nginx/nginx.conf" /etc/nginx/nginx.conf
mkdir -p /etc/nginx/snippets
cp "$REPO_ROOT/config/nginx/snippets/fastcgi-bitrix.conf" /etc/nginx/snippets/
cp "$REPO_ROOT/config/nginx/conf.d/maps.conf" /etc/nginx/conf.d/maps.conf
cp "$REPO_ROOT/config/nginx/sites-available/bitrix.conf" /etc/nginx/sites-available/bitrix.conf
rm -f /etc/nginx/sites-enabled/default
ln -sf ../sites-available/bitrix.conf /etc/nginx/sites-enabled/bitrix.conf
sed -i "s/__DOMAIN__/$DOMAIN/g" /etc/nginx/sites-available/bitrix.conf
step "Deploy php-fpm pool + ini overrides"
cp "$REPO_ROOT/config/php/fpm-pool-bitrix.conf" /etc/php/8.4/fpm/pool.d/bitrix.conf
rm -f /etc/php/8.4/fpm/pool.d/www.conf
cp "$REPO_ROOT/config/php/95-bitrix.ini" /etc/php/8.4/fpm/conf.d/95-bitrix.ini
cp "$REPO_ROOT/config/php/95-bitrix.ini" /etc/php/8.4/cli/conf.d/95-bitrix.ini
sed -i "s/__MAX_CHILDREN__/$FPM_MAX_CHILDREN/g" /etc/php/8.4/fpm/pool.d/bitrix.conf
step "MySQL tuning config (socket-only binds)"
mkdir -p /etc/mysql/conf.d
cp "$REPO_ROOT/config/mysql/99-bitrix.cnf" /etc/mysql/conf.d/99-bitrix.cnf
step "memcached dual systemd units"
cp "$REPO_ROOT/config/memcached/memcached-cache.service" /etc/systemd/system/
cp "$REPO_ROOT/config/memcached/memcached-sessions.service" /etc/systemd/system/
sed -i "s/__CACHE_MB__/$MEMCACHED_CACHE_MB/g" /etc/systemd/system/memcached-cache.service
sed -i "s/__SESSIONS_MB__/$MEMCACHED_SESSIONS_MB/g" /etc/systemd/system/memcached-sessions.service
systemctl daemon-reload
step "fail2ban jail.local"
cp "$REPO_ROOT/config/fail2ban/jail.local" /etc/fail2ban/jail.local
step "CrowdSec acquis.yaml"
mkdir -p /etc/crowdsec/acquis.d
cp "$REPO_ROOT/config/crowdsec/acquis.yaml" /etc/crowdsec/acquis.yaml
if [[ -n "$CROWDSEC_ENROLL_KEY" ]]; then
cscli console enroll --name "${DOMAIN}-vps" "$CROWDSEC_ENROLL_KEY" || true
fi
step "cron + logrotate"
cp "$REPO_ROOT/config/cron/bitrix" /etc/cron.d/bitrix
chmod 644 /etc/cron.d/bitrix
sed -i "s|__SITE__|$SITE_DIR|g; s|__BACKUP_SCRIPT__|$REPO_ROOT/scripts/backup.sh|g" /etc/cron.d/bitrix
cp "$REPO_ROOT/config/logrotate/bitrix" /etc/logrotate.d/bitrix
step "Database: create db + user"
mysql <<SQL
CREATE DATABASE IF NOT EXISTS \`$DB_NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';
ALTER USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';
GRANT ALL PRIVILEGES ON \`$DB_NAME\`.* TO '$DB_USER'@'localhost';
FLUSH PRIVILEGES;
SQL
step "UFW firewall (ssh/80/443)"
apt-get install -y ufw
ufw allow OpenSSH > /dev/null 2>&1 || true
ufw allow 80/tcp > /dev/null 2>&1 || true
ufw allow 443/tcp > /dev/null 2>&1 || true
yes | ufw enable > /dev/null 2>&1 || true
step "Restart everything"
phpenmod apcu igbinary 2>/dev/null || true
systemctl daemon-reload
systemctl restart mysql 2>/dev/null || systemctl restart mysqld 2>/dev/null || systemctl restart mariadb 2>/dev/null || true
systemctl enable --now memcached-cache memcached-sessions
systemctl restart php8.4-fpm
systemctl restart fail2ban
systemctl restart crowdsec
systemctl restart crowdsec-firewall-bouncer 2>/dev/null || true
nginx -t || die "nginx config test failed"
systemctl restart nginx
step "Save credentials"
cat > "$CREDS_FILE" <<EOF
# generated $(date -u +%FT%TZ)
DOMAIN=$DOMAIN
SITE_DIR=$SITE_DIR
DB_NAME=$DB_NAME
DB_USER=$DB_USER
DB_PASS=$DB_PASS
PHP_FPM_SOCK=/run/php/bitrix-fpm.sock
CACHE_MEMCACHED=127.0.0.1:11211
SESSIONS_MEMCACHED=127.0.0.1:11212
BACKUP_DIR=$BACKUP_DIR
EOF
chmod 600 "$CREDS_FILE"
echo
echo "========================================================"
echo " Provisioning done."
echo " Creds: $CREDS_FILE"
echo " Next: put site into $SITE_DIR (see README 'Migrate')"
echo " apply bitrix-app/*.php.example changes"
echo " certbot --nginx -d $DOMAIN -d www.$DOMAIN"
echo " README: $REPO_ROOT/README.md"
echo "========================================================"