Configure web panel auth from Linux install user
Этот коммит содержится в:
@@ -2,7 +2,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Virtuality Web Panel Installer
|
# Virtuality Web Panel Installer
|
||||||
# Clean step-by-step installer with readable statuses and log file.
|
# Clean step-by-step installer with readable statuses, Linux-user auth and log file.
|
||||||
|
|
||||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
WEB_DIR="${REPO_DIR}/web"
|
WEB_DIR="${REPO_DIR}/web"
|
||||||
@@ -10,9 +10,10 @@ APP_DIR="/opt/virtuality/web"
|
|||||||
VENV_DIR="/opt/virtuality/venv"
|
VENV_DIR="/opt/virtuality/venv"
|
||||||
SERVICE_FILE="/etc/systemd/system/virtuality-web.service"
|
SERVICE_FILE="/etc/systemd/system/virtuality-web.service"
|
||||||
PORT="${VIRTUALITY_WEB_PORT:-8088}"
|
PORT="${VIRTUALITY_WEB_PORT:-8088}"
|
||||||
|
AUTH_USER="${VIRTUALITY_AUTH_USER:-${SUDO_USER:-viktor}}"
|
||||||
LOG_DIR="/var/log/virtuality"
|
LOG_DIR="/var/log/virtuality"
|
||||||
LOG_FILE="${LOG_DIR}/install_web_panel_$(date +%Y%m%d_%H%M%S).log"
|
LOG_FILE="${LOG_DIR}/install_web_panel_$(date +%Y%m%d_%H%M%S).log"
|
||||||
TOTAL_STEPS=10
|
TOTAL_STEPS=11
|
||||||
CURRENT_STEP=0
|
CURRENT_STEP=0
|
||||||
|
|
||||||
ESC="\033"
|
ESC="\033"
|
||||||
@@ -30,10 +31,7 @@ mkdir -p "$LOG_DIR"
|
|||||||
|
|
||||||
timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
|
timestamp() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||||
line() { printf '%*s\n' 72 '' | tr ' ' '─'; }
|
line() { printf '%*s\n' 72 '' | tr ' ' '─'; }
|
||||||
|
log() { echo "[$(timestamp)] $*" >> "$LOG_FILE"; }
|
||||||
log() {
|
|
||||||
echo "[$(timestamp)] $*" >> "$LOG_FILE"
|
|
||||||
}
|
|
||||||
|
|
||||||
print_header() {
|
print_header() {
|
||||||
clear 2>/dev/null || true
|
clear 2>/dev/null || true
|
||||||
@@ -44,6 +42,7 @@ print_header() {
|
|||||||
echo
|
echo
|
||||||
echo -e "${GRAY}Лог установки:${RESET} ${LOG_FILE}"
|
echo -e "${GRAY}Лог установки:${RESET} ${LOG_FILE}"
|
||||||
echo -e "${GRAY}Порт панели:${RESET} ${PORT}"
|
echo -e "${GRAY}Порт панели:${RESET} ${PORT}"
|
||||||
|
echo -e "${GRAY}Linux auth user:${RESET} ${AUTH_USER}"
|
||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,23 +53,9 @@ step() {
|
|||||||
log "STEP ${CURRENT_STEP}/${TOTAL_STEPS}: $*"
|
log "STEP ${CURRENT_STEP}/${TOTAL_STEPS}: $*"
|
||||||
}
|
}
|
||||||
|
|
||||||
ok() {
|
ok() { echo -e " ${GREEN}✓${RESET} $*"; log "OK: $*"; }
|
||||||
echo -e " ${GREEN}✓${RESET} $*"
|
warn() { echo -e " ${YELLOW}!${RESET} $*"; log "WARN: $*"; }
|
||||||
log "OK: $*"
|
fail() { echo -e " ${RED}✗${RESET} $*"; log "ERROR: $*"; echo; echo -e "${RED}${BOLD}Установка остановлена.${RESET} Подробности в логе: ${LOG_FILE}"; exit 1; }
|
||||||
}
|
|
||||||
|
|
||||||
warn() {
|
|
||||||
echo -e " ${YELLOW}!${RESET} $*"
|
|
||||||
log "WARN: $*"
|
|
||||||
}
|
|
||||||
|
|
||||||
fail() {
|
|
||||||
echo -e " ${RED}✗${RESET} $*"
|
|
||||||
log "ERROR: $*"
|
|
||||||
echo
|
|
||||||
echo -e "${RED}${BOLD}Установка остановлена.${RESET} Подробности в логе: ${LOG_FILE}"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
run_logged() {
|
run_logged() {
|
||||||
local description="$1"
|
local description="$1"
|
||||||
@@ -83,39 +68,35 @@ run_logged() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
service_state() {
|
service_state() { systemctl is-active "$1" 2>/dev/null || echo "inactive"; }
|
||||||
systemctl is-active "$1" 2>/dev/null || echo "inactive"
|
require_root() { [[ "$EUID" -eq 0 ]] || fail "Запусти через sudo: sudo bash scripts/install_web_panel.sh"; }
|
||||||
}
|
|
||||||
|
|
||||||
require_root() {
|
|
||||||
if [[ "$EUID" -ne 0 ]]; then
|
|
||||||
fail "Запусти через sudo: sudo bash scripts/install_web_panel.sh"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_header
|
print_header
|
||||||
|
|
||||||
step "Проверяем права и структуру проекта"
|
step "Проверяем права и структуру проекта"
|
||||||
require_root
|
require_root
|
||||||
ok "Права root подтверждены"
|
ok "Права root подтверждены"
|
||||||
if [[ -d "$WEB_DIR" ]]; then
|
[[ -d "$WEB_DIR" ]] || fail "Не найдена директория web: $WEB_DIR"
|
||||||
ok "Исходники web найдены: $WEB_DIR"
|
ok "Исходники web найдены: $WEB_DIR"
|
||||||
else
|
[[ -f "$WEB_DIR/app.py" ]] || fail "Не найден web/app.py"
|
||||||
fail "Не найдена директория web: $WEB_DIR"
|
|
||||||
fi
|
|
||||||
if [[ -f "$WEB_DIR/app.py" ]]; then
|
|
||||||
ok "FastAPI entrypoint найден: web/app.py"
|
ok "FastAPI entrypoint найден: web/app.py"
|
||||||
else
|
[[ -f "$WEB_DIR/requirements.txt" ]] || fail "Не найден web/requirements.txt"
|
||||||
fail "Не найден web/app.py"
|
|
||||||
fi
|
|
||||||
if [[ -f "$WEB_DIR/requirements.txt" ]]; then
|
|
||||||
ok "requirements.txt найден"
|
ok "requirements.txt найден"
|
||||||
|
|
||||||
|
step "Проверяем Linux-пользователя для входа"
|
||||||
|
if id "$AUTH_USER" >/dev/null 2>&1; then
|
||||||
|
ok "Пользователь найден: $AUTH_USER"
|
||||||
else
|
else
|
||||||
fail "Не найден web/requirements.txt"
|
fail "Пользователь $AUTH_USER не найден. Создай его или передай VIRTUALITY_AUTH_USER=username"
|
||||||
|
fi
|
||||||
|
if getent shadow "$AUTH_USER" | cut -d: -f2 | grep -Eq '^(!|\*|!!)?$'; then
|
||||||
|
warn "У пользователя $AUTH_USER может быть заблокирован пароль. Установи пароль: sudo passwd $AUTH_USER"
|
||||||
|
else
|
||||||
|
ok "У пользователя $AUTH_USER есть пароль для Linux-auth"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
step "Проверяем базовые команды"
|
step "Проверяем базовые команды"
|
||||||
for cmd in apt systemctl rsync python3 hostname; do
|
for cmd in apt systemctl rsync python3 hostname openssl; do
|
||||||
if command -v "$cmd" >/dev/null 2>&1; then
|
if command -v "$cmd" >/dev/null 2>&1; then
|
||||||
ok "$cmd найден: $(command -v "$cmd")"
|
ok "$cmd найден: $(command -v "$cmd")"
|
||||||
else
|
else
|
||||||
@@ -127,12 +108,22 @@ step "Обновляем apt cache"
|
|||||||
run_logged "apt update выполнен" apt update
|
run_logged "apt update выполнен" apt update
|
||||||
|
|
||||||
step "Устанавливаем системные зависимости"
|
step "Устанавливаем системные зависимости"
|
||||||
run_logged "Пакеты Python/venv/pip/rsync установлены" apt install -y python3 python3-venv python3-pip rsync
|
run_logged "Пакеты Python/venv/pip/rsync установлены" apt install -y python3 python3-venv python3-pip rsync openssl
|
||||||
|
|
||||||
step "Копируем web-панель в /opt/virtuality"
|
step "Копируем web-панель в /opt/virtuality"
|
||||||
run_logged "Создана директория /opt/virtuality" mkdir -p /opt/virtuality
|
run_logged "Создана директория /opt/virtuality" mkdir -p /opt/virtuality
|
||||||
run_logged "Файлы панели синхронизированы в $APP_DIR" rsync -a --delete "$WEB_DIR/" "$APP_DIR/"
|
run_logged "Файлы панели синхронизированы в $APP_DIR" rsync -a --delete "$WEB_DIR/" "$APP_DIR/"
|
||||||
|
|
||||||
|
step "Создаём конфиг авторизации"
|
||||||
|
SESSION_SECRET="$(openssl rand -hex 32)"
|
||||||
|
cat > "${APP_DIR}/.env" <<EOF
|
||||||
|
VIRTUALITY_AUTH_USER=${AUTH_USER}
|
||||||
|
VIRTUALITY_SESSION_SECRET=${SESSION_SECRET}
|
||||||
|
EOF
|
||||||
|
chmod 600 "${APP_DIR}/.env"
|
||||||
|
ok "Создан ${APP_DIR}/.env"
|
||||||
|
ok "Вход будет по Linux-пользователю: ${AUTH_USER}"
|
||||||
|
|
||||||
step "Создаём Python virtualenv"
|
step "Создаём Python virtualenv"
|
||||||
if [[ -d "$VENV_DIR" ]]; then
|
if [[ -d "$VENV_DIR" ]]; then
|
||||||
warn "Virtualenv уже существует, будет переиспользован: $VENV_DIR"
|
warn "Virtualenv уже существует, будет переиспользован: $VENV_DIR"
|
||||||
@@ -160,6 +151,7 @@ RestartSec=3
|
|||||||
User=root
|
User=root
|
||||||
Group=root
|
Group=root
|
||||||
Environment=PYTHONUNBUFFERED=1
|
Environment=PYTHONUNBUFFERED=1
|
||||||
|
Environment=VIRTUALITY_AUTH_USER=${AUTH_USER}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
@@ -199,11 +191,12 @@ echo -e "${GREEN}${BOLD}│${RESET} ${BOLD}Установка Virtuality Web Pan
|
|||||||
echo -e "${GREEN}${BOLD}╰────────────────────────────────────────────────────────────╯${RESET}"
|
echo -e "${GREEN}${BOLD}╰────────────────────────────────────────────────────────────╯${RESET}"
|
||||||
echo
|
echo
|
||||||
echo -e "${BOLD}URL:${RESET} http://${SERVER_IP}:${PORT}"
|
echo -e "${BOLD}URL:${RESET} http://${SERVER_IP}:${PORT}"
|
||||||
|
echo -e "${BOLD}Login:${RESET} ${AUTH_USER} / пароль Linux-пользователя"
|
||||||
echo -e "${BOLD}Service:${RESET} virtuality-web.service"
|
echo -e "${BOLD}Service:${RESET} virtuality-web.service"
|
||||||
echo -e "${BOLD}Status:${RESET} systemctl status virtuality-web --no-pager"
|
echo -e "${BOLD}Status:${RESET} systemctl status virtuality-web --no-pager"
|
||||||
echo -e "${BOLD}Logs:${RESET} journalctl -u virtuality-web -f"
|
echo -e "${BOLD}Logs:${RESET} journalctl -u virtuality-web -f"
|
||||||
echo -e "${BOLD}Install log:${RESET} ${LOG_FILE}"
|
echo -e "${BOLD}Install log:${RESET} ${LOG_FILE}"
|
||||||
echo
|
echo
|
||||||
line
|
line
|
||||||
echo -e "${DIM}Следующий шаг: добавить авторизацию и страницу создания VM.${RESET}"
|
echo -e "${DIM}Следующий шаг: страница создания VM из интерфейса.${RESET}"
|
||||||
line
|
line
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user