#!/usr/bin/env bash # # Установка портала администрирования на чистую ВМ (Ubuntu 22.04/24.04 или Debian 12). # Запускать от root: sudo bash scripts/install.sh # # Скрипт идемпотентен настолько, насколько это возможно для apt/systemd, # но НЕ подставляет секреты за вас — .env нужно подготовить заранее # (см. README.md, шаг 5) и положить путь к нему в переменную ENV_FILE ниже # либо передать первым аргументом. set -euo pipefail APP_USER="adminportal" APP_DIR="/opt/admin-portal" ENV_DIR="/etc/admin-portal" ENV_FILE="${1:-$(pwd)/.env}" REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" if [[ $EUID -ne 0 ]]; then echo "Запускать от root: sudo bash scripts/install.sh [путь_к_.env]" >&2 exit 1 fi if [[ ! -f "$ENV_FILE" ]]; then echo "Не найден .env файл: $ENV_FILE" >&2 echo "Скопируйте .env.example -> .env, заполните значения и повторите запуск." >&2 exit 1 fi echo "== 1/9: системные пакеты ==" apt-get update DEBIAN_FRONTEND=noninteractive apt-get install -y \ haproxy nginx postgresql redis-server \ python3 python3-venv python3-dev \ libldap2-dev libsasl2-dev libssl-dev build-essential \ rsync ufw echo "== 2/9: системный пользователь приложения ==" if ! id -u "$APP_USER" >/dev/null 2>&1; then useradd --system --home "$APP_DIR" --shell /usr/sbin/nologin "$APP_USER" fi echo "== 3/9: код приложения ==" mkdir -p "$APP_DIR" rsync -a --delete "$REPO_ROOT/django_app/" "$APP_DIR/django_app/" chown -R "$APP_USER:$APP_USER" "$APP_DIR" echo "== 4/9: виртуальное окружение Python ==" if [[ ! -d "$APP_DIR/venv" ]]; then python3 -m venv "$APP_DIR/venv" fi "$APP_DIR/venv/bin/pip" install --upgrade pip "$APP_DIR/venv/bin/pip" install -r "$APP_DIR/django_app/requirements.txt" chown -R "$APP_USER:$APP_USER" "$APP_DIR/venv" echo "== 5/9: конфигурация окружения ==" mkdir -p "$ENV_DIR" install -o root -g "$APP_USER" -m 640 "$ENV_FILE" "$ENV_DIR/admin-portal.env" echo "== 6/9: PostgreSQL — база и пользователь ==" # Значения читаем из .env, чтобы не дублировать вручную set -a; source "$ENV_DIR/admin-portal.env"; set +a sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='${POSTGRES_USER}'" | grep -q 1 || \ sudo -u postgres psql -c "CREATE ROLE ${POSTGRES_USER} LOGIN PASSWORD '${POSTGRES_PASSWORD}';" sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='${POSTGRES_DB}'" | grep -q 1 || \ sudo -u postgres psql -c "CREATE DATABASE ${POSTGRES_DB} OWNER ${POSTGRES_USER};" systemctl enable --now postgresql redis-server echo "== 7/9: миграции и статика Django ==" sudo -u "$APP_USER" bash -c "set -a; source $ENV_DIR/admin-portal.env; set +a; \ $APP_DIR/venv/bin/python $APP_DIR/django_app/manage.py migrate --noinput && \ $APP_DIR/venv/bin/python $APP_DIR/django_app/manage.py collectstatic --noinput" echo "== 8/9: systemd-юнит приложения ==" install -m 644 "$REPO_ROOT/systemd/admin-portal.service" /etc/systemd/system/admin-portal.service systemctl daemon-reload systemctl enable --now admin-portal echo "== 9/9: HAProxy, Nginx (демо-бэкенды), фаервол ==" install -m 644 "$REPO_ROOT/haproxy/haproxy.cfg" /etc/haproxy/haproxy.cfg install -m 644 "$REPO_ROOT/haproxy/group_map.cfg" /etc/haproxy/group_map.cfg mkdir -p /etc/haproxy/certs chmod 700 /etc/haproxy/certs for res in resource1 resource2; do mkdir -p "/var/www/admin-demo-${res}" cp "$REPO_ROOT/backend_demo/${res}/index.html" "/var/www/admin-demo-${res}/index.html" install -m 644 "$REPO_ROOT/backend_demo/${res}/nginx.conf" "/etc/nginx/sites-available/admin-demo-${res}" ln -sf "/etc/nginx/sites-available/admin-demo-${res}" "/etc/nginx/sites-enabled/admin-demo-${res}" done rm -f /etc/nginx/sites-enabled/default nginx -t && systemctl enable --now nginx && systemctl reload nginx ufw allow 80/tcp || true ufw allow 443/tcp || true echo echo "Готово. Дальше:" echo " 1) положите TLS-сертификат в /etc/haproxy/certs/fqdn.pem" echo " 2) haproxy -c -f /etc/haproxy/haproxy.cfg && systemctl reload haproxy" echo " 3) создайте суперпользователя:" echo " sudo -u ${APP_USER} bash -c 'set -a; source ${ENV_DIR}/admin-portal.env; set +a; ${APP_DIR}/venv/bin/python ${APP_DIR}/django_app/manage.py createsuperuser'" echo " 4) наполните каталог ресурсов через /django-admin/ или sync_resources (см. README.md)"