#!/usr/bin/env bash # Интерактивный установщик: Ubuntu + Docker + PostgreSQL 17 (docker compose). # Запуск: chmod +x install.sh && ./install.sh set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' ask_yes_no() { local prompt="$1" local default="${2:-n}" local hint="[y/N]" [[ "$default" == "y" ]] && hint="[Y/n]" while true; do read -r -p "$prompt $hint: " ans ans="${ans:-$default}" case "$ans" in [Yy]|[Yy][Ee][Ss]) return 0 ;; [Nn]|[Nn][Oo]) return 1 ;; *) echo "Введите y или n." ;; esac done } info() { echo -e "${GREEN}[*]${NC} $*"; } warn() { echo -e "${YELLOW}[!]${NC} $*"; } err() { echo -e "${RED}[x]${NC} $*" >&2; } step_header() { echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo " $1" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" } require_cmd() { command -v "$1" >/dev/null 2>&1 } read_env_val() { local key="$1" grep -m1 "^${key}=" "$ENV_FILE" | sed "s/^${key}=//" } # --- Шаг 0: приветствие --- step_header "Шаг 0 — Обзор" echo "Проект: Lineage 2 Essence, клиент protocol 520, PostgreSQL 17." echo "БД: login + game (минимум для входа). Login/Game JAR — профиль l2 (server/login, server/game)." if ! ask_yes_no "Продолжить?" "y"; then info "Выход." exit 0 fi # --- Шаг 1: проверка Ubuntu (мягко) --- step_header "Шаг 1 — Система" if [[ -f /etc/os-release ]]; then # shellcheck source=/dev/null source /etc/os-release if [[ "${ID:-}" != "ubuntu" ]]; then warn "Обнаружено не Ubuntu (${PRETTY_NAME:-unknown}). Скрипт рассчитан на Ubuntu; продолжайте на свой риск." ask_yes_no "Всё равно продолжить?" "n" || exit 1 else info "ОС: ${PRETTY_NAME:-Ubuntu}" fi else warn "Не удалось прочитать /etc/os-release." fi # --- Шаг 2: Docker --- step_header "Шаг 2 — Docker Engine и Compose" if require_cmd docker && docker compose version >/dev/null 2>&1; then info "Docker и 'docker compose' уже доступны." else if ask_yes_no "Установить Docker из официального репозитория Docker (apt)?" "y"; then if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then warn "Для установки пакетов нужны права sudo." SUDO="sudo" else SUDO="" fi $SUDO apt-get update -y $SUDO apt-get install -y ca-certificates curl $SUDO install -m 0755 -d /etc/apt/keyrings $SUDO curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc $SUDO chmod a+r /etc/apt/keyrings/docker.asc echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "${VERSION_CODENAME:-jammy}") stable" | $SUDO tee /etc/apt/sources.list.d/docker.list >/dev/null $SUDO apt-get update -y $SUDO apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin info "Docker установлен." if [[ "${EUID:-$(id -u)}" -ne 0 ]] && ask_yes_no "Добавить текущего пользователя $(whoami) в группу docker?" "y"; then $SUDO usermod -aG docker "$(whoami)" warn "Выйдите из сессии и войдите снова (или newgrp docker), чтобы использовать docker без sudo." fi else err "Без Docker дальнейшие шаги невозможны." exit 1 fi fi # Проверка доступа к docker if ! docker info >/dev/null 2>&1; then err "Docker недоступен (возможно нужен sudo или перелогин после добавления в группу docker)." exit 1 fi # --- Шаг 3: .env --- step_header "Шаг 3 — Файл .env (PostgreSQL 17)" ENV_FILE="$SCRIPT_DIR/.env" EXAMPLE="$SCRIPT_DIR/.env.example" if [[ ! -f "$EXAMPLE" ]]; then err "Нет файла .env.example" exit 1 fi if [[ -f "$ENV_FILE" ]]; then if ! ask_yes_no ".env уже есть. Перезаписать значениями из мастера?" "n"; then info "Оставляем существующий .env" else rm -f "$ENV_FILE" fi fi if [[ ! -f "$ENV_FILE" ]]; then info "Создаём .env. Введите параметры БД (Enter — значение по умолчанию в скобках)." read -r -p "POSTGRES_USER [l2user]: " u u="${u:-l2user}" while true; do read -r -s -p "POSTGRES_PASSWORD (обязательно): " p echo "" [[ -n "$p" ]] && break err "Пароль не может быть пустым." done read -r -p "POSTGRES_DB [l2essence]: " d d="${d:-l2essence}" read -r -p "POSTGRES_PORT [5432]: " port port="${port:-5432}" if [[ "$p" == "change_me_strong_password" ]]; then err "Смените пароль по умолчанию." exit 1 fi { printf '%s\n' "POSTGRES_USER=$u" "POSTGRES_PASSWORD=$p" "POSTGRES_DB=$d" "POSTGRES_PORT=$port" echo '# L2_SERVER_IMAGE=your-registry/l2-essence-542:latest' } >"$ENV_FILE" fi # --- Шаг 4: pull --- step_header "Шаг 4 — Загрузка образов" if ask_yes_no "Выполнить docker compose pull?" "y"; then docker compose pull fi # --- Шаг 5: запуск Postgres --- step_header "Шаг 5 — Запуск PostgreSQL 17" if ask_yes_no "Поднять только PostgreSQL (рекомендуется)?" "y"; then chmod +x "$SCRIPT_DIR"/docker/initdb/*.sh 2>/dev/null || true chmod +x "$SCRIPT_DIR"/scripts/*.sh 2>/dev/null || true docker compose up -d postgres info "Ожидание готовности PostgreSQL (pg_isready)..." EV_USER="$(read_env_val POSTGRES_USER)" EV_DB="$(read_env_val POSTGRES_DB)" for _ in $(seq 1 60); do if docker compose exec -T postgres pg_isready -U "$EV_USER" -d "$EV_DB" >/dev/null 2>&1; then break fi sleep 1 done docker compose ps fi # --- Шаг 6: конфиг и Login/Game --- step_header "Шаг 6 — Конфиг Essence 520" if [[ -f "$SCRIPT_DIR/scripts/sync-config-password.sh" ]]; then if ask_yes_no "Подставить пароль БД из .env в config/login и config/game?" "y"; then bash "$SCRIPT_DIR/scripts/sync-config-password.sh" fi fi step_header "Шаг 7 — Login / Game (Docker profile l2)" warn "Положите LoginServer.jar и GameServer.jar в server/login и server/game." if ask_yes_no "Запустить контейнеры login + game (profile l2)?" "n"; then docker compose --profile l2 up -d login game docker compose ps fi # --- Готово --- step_header "Готово" EV_USER="$(read_env_val POSTGRES_USER)" EV_DB="$(read_env_val POSTGRES_DB)" EV_PORT="$(read_env_val POSTGRES_PORT)" info "Строка подключения с хоста Ubuntu: postgresql://${EV_USER}:***@127.0.0.1:${EV_PORT}/${EV_DB}" info "Из контейнеров в этой compose-сети: хост postgres, порт 5432." info "Тест-аккаунты: admin/admin и test/test." info "Классы: ref_classes / class_list (создание: 0,10,18,25,31,38,44,49,53,123,124,182,183)." info "Клиент: protocol 520, логин 127.0.0.1:2106, мир 127.0.0.1:7777." echo "" info "Полезные команды:" echo " docker compose logs -f postgres" echo " docker compose --profile l2 up -d login game" echo " ./scripts/apply-essence-schema.sh # если БД уже была без новых таблиц" echo " docker compose down"