diff --git a/.env.example b/.env.example index e41f863..403ddae 100644 --- a/.env.example +++ b/.env.example @@ -18,8 +18,11 @@ CADDY_AUTH_API_TOKEN= # Опционально: Subscription Page (например https://sub.example.com) REMNAWAVE_SUBSCRIPTION_URL= -# PostgreSQL (docker-compose подставляет URL к сервису db) -DATABASE_URL=postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable +# PostgreSQL (должен совпадать с POSTGRES_* ниже; install.sh сгенерирует автоматически) +POSTGRES_USER=tgvpn +POSTGRES_PASSWORD=change_me_strong_password +POSTGRES_DB=tgvpn +DATABASE_URL=postgres://tgvpn:change_me_strong_password@db:5432/tgvpn?sslmode=disable # Создание пользователей по умолчанию DEFAULT_USER_DAYS=30 diff --git a/CHANGELOG.md b/CHANGELOG.md index 77f96ab..72fb2a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Добавлено +- `install.sh` — интерактивный установщик на Linux-сервер (опрос параметров, `.env`, Docker) - PostgreSQL 16 в Docker Compose (`DATABASE_URL`) - Создание пользователей Remnawave: `/admin user`, `/admin user <логин> [дней]` - Назначение сквадов: external + internal (`/admin assign <логин>`, мастер с кнопками) diff --git a/README.md b/README.md index c53f094..656bf32 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Telegram-бот на Go для управления VPN через панель ## Содержание - [Требования](#требования) +- [Установщик (рекомендуется)](#установщик-на-сервере) - [Быстрый старт](#быстрый-старт-docker-compose) - [PostgreSQL](#postgresql) - [Развёртывание на VPS](#развёртывание-на-vps-linux) @@ -29,6 +30,63 @@ Telegram-бот на Go для управления VPN через панель --- +## Установщик на сервере + +Интерактивный скрипт запросит все параметры, создаст `.env` и запустит Docker. + +### Требования на сервере + +- Linux (Ubuntu 22.04/24.04, Debian 12) +- `curl`, `git` (для клонирования) +- Права `sudo` (для установки Docker при необходимости) + +### Установка одной командой + +Если репозиторий уже на сервере: + +```bash +cd tgvpn +chmod +x install.sh +./install.sh +``` + +Или скачайте скрипт и укажите каталог `/opt/tgvpn`: + +```bash +sudo mkdir -p /opt/tgvpn +cd /opt/tgvpn +git clone . +chmod +x install.sh +./install.sh +``` + +### Что спрашивает установщик + +| Блок | Параметры | +|------|-----------| +| Telegram | `BOT_TOKEN`, `TELEGRAM_ADMIN_ID`, `BOT_DEBUG` | +| Remnawave | URL панели, API token, Caddy token, subscription URL | +| PostgreSQL | пользователь, база, пароль (можно сгенерировать случайный) | +| VPN | срок по умолчанию, UUID сквадов (опционально) | +| Система | каталог установки, URL git (если не из текущей папки) | + +После завершения: `docker compose up -d --build`, проверка `docker compose ps`. + +### Переменные окружения для PostgreSQL в compose + +В `.env` должны совпадать `POSTGRES_PASSWORD` и пароль в `DATABASE_URL`: + +```env +POSTGRES_USER=tgvpn +POSTGRES_PASSWORD=ваш_сильный_пароль +POSTGRES_DB=tgvpn +DATABASE_URL=postgres://tgvpn:ваш_сильный_пароль@db:5432/tgvpn?sslmode=disable +``` + +Установщик заполняет это автоматически. + +--- + ## Быстрый старт (Docker Compose) ### 1. Клонирование @@ -645,6 +703,7 @@ tgvpn/ │ │ └── migrations/ # SQL-миграции (001_init.sql) │ └── remnawave/ # API панели (users, squads) ├── Dockerfile # multi-stage сборка +├── install.sh # интерактивный установщик на сервер ├── docker-compose.yml # bot + PostgreSQL (volume pgdata) ├── .env.example # шаблон переменных ├── .dockerignore diff --git a/docker-compose.yml b/docker-compose.yml index 6770186..24cf6cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,11 @@ services: container_name: tgvpn-db restart: unless-stopped environment: - POSTGRES_USER: tgvpn - POSTGRES_PASSWORD: tgvpn - POSTGRES_DB: tgvpn + POSTGRES_USER: ${POSTGRES_USER:-tgvpn} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-tgvpn} + POSTGRES_DB: ${POSTGRES_DB:-tgvpn} + env_file: + - .env volumes: - pgdata:/var/lib/postgresql/data healthcheck: @@ -29,7 +31,7 @@ services: - .env environment: BOT_DEBUG: ${BOT_DEBUG:-false} - DATABASE_URL: postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable + DATABASE_URL: ${DATABASE_URL:-postgres://tgvpn:tgvpn@db:5432/tgvpn?sslmode=disable} volumes: pgdata: diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..4d343cb --- /dev/null +++ b/install.sh @@ -0,0 +1,281 @@ +#!/usr/bin/env bash +# Интерактивная установка tgvpn на Linux-сервер (Docker + PostgreSQL) +set -euo pipefail + +INSTALL_DIR="${INSTALL_DIR:-/opt/tgvpn}" +REPO_URL="" +USE_CURRENT_DIR=false +SKIP_DOCKER_INSTALL=false + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' + +info() { echo -e "${CYAN}[*]${NC} $*"; } +ok() { echo -e "${GREEN}[✓]${NC} $*"; } +warn() { echo -e "${YELLOW}[!]${NC} $*"; } +fail() { echo -e "${RED}[✗]${NC} $*" >&2; exit 1; } + +prompt() { + local label="$1" + local default="${2:-}" + local val + if [[ -n "$default" ]]; then + read -r -p "$label [$default]: " val + echo "${val:-$default}" + else + read -r -p "$label: " val + echo "$val" + fi +} + +prompt_required() { + local label="$1" + local val="" + while [[ -z "$val" ]]; do + read -r -p "$label: " val + [[ -z "$val" ]] && warn "Поле обязательно." + done + echo "$val" +} + +prompt_secret() { + local label="$1" + local val="" + while [[ -z "$val" ]]; do + read -r -s -p "$label: " val + echo "" + [[ -z "$val" ]] && warn "Поле обязательно." + done + echo "$val" +} + +prompt_yn() { + local label="$1" + local default="${2:-y}" + local hint="Y/n" + [[ "$default" == "n" ]] && hint="y/N" + local ans + read -r -p "$label [$hint]: " ans + ans="${ans:-$default}" + [[ "$ans" =~ ^[Yy] ]] +} + +need_cmd() { + command -v "$1" >/dev/null 2>&1 +} + +check_docker() { + need_cmd docker && docker compose version >/dev/null 2>&1 +} + +install_docker() { + info "Установка Docker (официальный репозиторий)..." + if need_cmd apt-get; then + sudo apt-get update -qq + sudo apt-get install -y ca-certificates curl + sudo install -m 0755 -d /etc/apt/keyrings + if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then + 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}") stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + fi + sudo apt-get update -qq + sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin + sudo usermod -aG docker "$USER" 2>/dev/null || true + ok "Docker установлен. Если команда docker требует sudo — перелогиньтесь или выполните: newgrp docker" + else + fail "Автоустановка Docker поддерживается только для Debian/Ubuntu (apt). Установите Docker вручную: https://docs.docker.com/engine/install/" + fi +} + +write_env() { + local env_file="$1" + cat > "$env_file" </dev/null || true + warn "Старая копия: .env.bak.*" + fi + + write_env ".env" + ok "Создан .env" + + echo "" + info "=== Запуск контейнеров ===" + DC="docker compose" + if ! docker compose version >/dev/null 2>&1; then + DC="sudo docker compose" + fi + + $DC pull db 2>/dev/null || true + $DC up -d --build + + echo "" + sleep 3 + $DC ps + + echo "" + ok "Установка завершена!" + echo "" + echo " Каталог: $INSTALL_DIR" + echo " Логи бота: $DC logs -f bot" + echo " Логи БД: $DC logs -f db" + echo " Перезапуск: $DC up -d --build" + echo "" + echo " В Telegram (аккаунт админа $TELEGRAM_ADMIN_ID):" + echo " /start" + echo " /admin check" + echo " /admin squads" + echo " /admin user" + echo "" +} + +main "$@"