mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-09-25 01:53:03 +02:00
197 lines
8.1 KiB
Bash
Executable File
197 lines
8.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# Deploy production nginx configuration for XAMXAM
|
|
# Fixes permissions and installs /tmp/xamxam.conf into nginx sites-available.
|
|
#
|
|
# Usage: just deploy-nginx (uploads script + config, then runs this)
|
|
# or: sudo bash /tmp/deploy-server.sh
|
|
|
|
set -e
|
|
|
|
# ── Colors ────────────────────────────────────────────────────────────────────
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
ok() { printf "${GREEN}✓${NC} %s\n" "$*"; }
|
|
err() { printf "${RED}✗${NC} %s\n" "$*" >&2; }
|
|
warn() { printf "${YELLOW}!${NC} %s\n" "$*"; }
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
[ "$EUID" -eq 0 ] || { err "Run as root (sudo)"; exit 1; }
|
|
|
|
printf "🚀 XAMXAM Production Deployment\n"
|
|
printf "================================\n\n"
|
|
|
|
# ── Step 0: System dependencies ───────────────────────────────────────────────
|
|
printf "📋 Step 0: Checking system dependencies...\n"
|
|
echo "--------------------------------------"
|
|
if ! php -m | grep -qi curl; then
|
|
apt-get install -y php-curl
|
|
ok "Installed php-curl"
|
|
else
|
|
ok "php-curl already installed"
|
|
fi
|
|
if ! command -v sqlite3 &>/dev/null; then
|
|
apt-get install -y sqlite3
|
|
ok "Installed sqlite3"
|
|
else
|
|
ok "sqlite3 already installed"
|
|
fi
|
|
|
|
# ── Step 1: Permissions ───────────────────────────────────────────────────────
|
|
printf "📋 Step 1: Fixing file permissions...\n"
|
|
echo "--------------------------------------"
|
|
|
|
chown -R www-data:xamxam /var/www/xamxam/
|
|
ok "Ownership: www-data:xamxam"
|
|
|
|
find /var/www/xamxam -type d -exec chmod 2775 {} \;
|
|
ok "Directories: 2775 (setgid)"
|
|
|
|
find /var/www/xamxam -type f -exec chmod 664 {} \;
|
|
ok "Files: 664"
|
|
|
|
if [ -d "/var/www/xamxam/storage" ]; then
|
|
chmod 2775 /var/www/xamxam/storage
|
|
find /var/www/xamxam/storage -name "*.db" -exec chmod 660 {} \;
|
|
# SQLite WAL sidecar files must also be writable
|
|
find /var/www/xamxam/storage -name "*.db-wal" -exec chmod 660 {} \;
|
|
find /var/www/xamxam/storage -name "*.db-shm" -exec chmod 660 {} \;
|
|
ok "Storage: 2775, databases (+WAL/SHM): 660"
|
|
fi
|
|
|
|
# .env must be 640 (contains secrets)
|
|
if [ -f "/var/www/xamxam/.env" ]; then
|
|
chmod 640 /var/www/xamxam/.env
|
|
ok ".env: 640"
|
|
fi
|
|
|
|
# Migrate posterg.db → xamxam.db if the new name is missing or empty
|
|
if [ -f "/var/www/xamxam/storage/posterg.db" ]; then
|
|
if [ ! -s "/var/www/xamxam/storage/xamxam.db" ]; then
|
|
cp /var/www/xamxam/storage/posterg.db /var/www/xamxam/storage/xamxam.db
|
|
ok "Migrated posterg.db → xamxam.db"
|
|
fi
|
|
rm /var/www/xamxam/storage/posterg.db
|
|
ok "Removed legacy posterg.db"
|
|
fi
|
|
|
|
# Ensure writable cache subdirectories exist for php-fpm (www-data)
|
|
mkdir -p /var/www/xamxam/storage/cache/rate_limit
|
|
chown -R www-data:xamxam /var/www/xamxam/storage/cache
|
|
chmod -R 2775 /var/www/xamxam/storage/cache
|
|
ok "Cache dirs: created and owned by www-data:xamxam"
|
|
|
|
# Ensure PHP upload temp dir exists on storage partition (not /tmp tmpfs)
|
|
mkdir -p /var/www/xamxam/storage/tmp/php-uploads
|
|
chown www-data:xamxam /var/www/xamxam/storage/tmp/php-uploads
|
|
chmod 2775 /var/www/xamxam/storage/tmp/php-uploads
|
|
ok "PHP upload temp dir: /var/www/xamxam/storage/tmp/php-uploads"
|
|
|
|
# Ensure the application log directory exists and is writable by php-fpm.
|
|
# App logs (Monolog) go to /var/log/xamxam/xamxam-{channel}-YYYY-MM-DD.log in
|
|
# production; without this the logger falls back to NullHandler (silent).
|
|
mkdir -p /var/log/xamxam
|
|
chown www-data:xamxam /var/log/xamxam
|
|
chmod 2775 /var/log/xamxam
|
|
ok "Log dir: /var/log/xamxam owned by www-data:xamxam (2775)"
|
|
|
|
# PHP-FPM session GC must not reap active admin sessions early.
|
|
# The app enforces its own server-side idle/absolute timeouts in AdminAuth
|
|
# (30 min idle / 12 h absolute), so session.gc_maxlifetime needs to be at
|
|
# least the absolute timeout, and GC re-enabled to clean up stale files.
|
|
PHP_FPM_INI="/etc/php/8.4/fpm/conf.d/zz-xamxam-session.ini"
|
|
cat > "$PHP_FPM_INI" <<'INI'
|
|
; XAMXAM session tuning.
|
|
; AdminAuth enforces its own idle/absolute timeouts (30 min / 12 h), so
|
|
; gc_maxlifetime must be >= the absolute timeout or PHP would reap active
|
|
; sessions from under the app.
|
|
session.gc_maxlifetime = 43200
|
|
session.gc_probability = 1
|
|
session.gc_divisor = 100
|
|
INI
|
|
ok "PHP-FPM session GC: $PHP_FPM_INI"
|
|
|
|
# Backups dir must be writable by both www-data (cron) and the deploy user
|
|
# (xamxam group) so scripts/migrate.sh can write a pre-deploy snapshot before
|
|
# running migrations.
|
|
mkdir -p /var/backups/xamxam
|
|
chown www-data:xamxam /var/backups/xamxam
|
|
chmod 2775 /var/backups/xamxam
|
|
ok "Backup dir: /var/backups/xamxam owned by www-data:xamxam (2775)"
|
|
|
|
# ── Step 2: Nginx config ──────────────────────────────────────────────────────
|
|
printf "\n📋 Step 2: Deploying nginx configuration...\n"
|
|
echo "--------------------------------------------"
|
|
|
|
if [ ! -f "/tmp/xamxam.conf" ]; then
|
|
err "/tmp/xamxam.conf not found — run: just deploy-nginx"
|
|
exit 1
|
|
fi
|
|
|
|
if [ -f "/etc/nginx/sites-available/xamxam" ]; then
|
|
cp /etc/nginx/sites-available/xamxam \
|
|
"/etc/nginx/sites-available/xamxam.backup.$(date +%Y%m%d_%H%M%S)"
|
|
ok "Backed up existing config"
|
|
fi
|
|
|
|
cp /tmp/xamxam.conf /etc/nginx/sites-available/xamxam
|
|
ok "Installed new nginx config"
|
|
|
|
# Remove legacy posterg symlink if it exists (causes duplicate limit_req_zone)
|
|
if [ -L "/etc/nginx/sites-enabled/posterg" ]; then
|
|
rm /etc/nginx/sites-enabled/posterg
|
|
ok "Removed legacy sites-enabled/posterg symlink"
|
|
fi
|
|
|
|
# Remove legacy posterg config and all its backups from sites-available
|
|
for f in /etc/nginx/sites-available/posterg /etc/nginx/sites-available/posterg.backup.*; do
|
|
[ -f "$f" ] && rm "$f" && ok "Removed legacy $f"
|
|
done
|
|
|
|
# Keep only the 2 most recent xamxam backups, delete older ones
|
|
ls -t /etc/nginx/sites-available/xamxam.backup.* 2>/dev/null | tail -n +3 | xargs -r rm --
|
|
ok "Pruned old xamxam config backups (kept 2 most recent)"
|
|
|
|
if [ ! -L "/etc/nginx/sites-enabled/xamxam" ]; then
|
|
ln -s /etc/nginx/sites-available/xamxam /etc/nginx/sites-enabled/xamxam
|
|
ok "Created sites-enabled symlink"
|
|
fi
|
|
|
|
# ── Step 3: Validate ──────────────────────────────────────────────────────────
|
|
printf "\n📋 Step 3: Testing nginx configuration...\n"
|
|
echo "------------------------------------------"
|
|
|
|
if nginx -t 2>&1; then
|
|
ok "Nginx configuration is valid"
|
|
else
|
|
err "Nginx configuration has errors — restoring backup"
|
|
latest=$(ls -t /etc/nginx/sites-available/xamxam.backup.* 2>/dev/null | head -1)
|
|
[ -n "$latest" ] && cp "$latest" /etc/nginx/sites-available/xamxam
|
|
exit 1
|
|
fi
|
|
|
|
# ── Step 4: Reload nginx ─────────────────────────────────────────────────────
|
|
printf "\n"
|
|
echo "📋 Step 4: Reloading nginx..."
|
|
echo "------------------------------"
|
|
|
|
systemctl reload nginx
|
|
ok "Nginx reloaded"
|
|
|
|
# Reload PHP-FPM so the session GC settings take effect.
|
|
systemctl reload php8.4-fpm 2>/dev/null || systemctl reload php-fpm 2>/dev/null || true
|
|
ok "PHP-FPM reloaded"
|
|
|
|
# ── Done ──────────────────────────────────────────────────────────────────────
|
|
printf "\n"
|
|
ok "Permissions fixed"
|
|
ok "Nginx config installed"
|
|
ok "Configuration validated"
|
|
ok "Nginx reloaded"
|
|
printf "\nVerify:\n"
|
|
printf " https://xamxam.erg.be/\n"
|
|
printf " https://xamxam.erg.be/admin/\n"
|
|
printf " https://xamxam.erg.be/storage/xamxam.db (should 403/404)\n"
|