mirror of
https://github.com/andrey271192/kaskad_web_vpn.git
synced 2026-09-20 11:55:35 +00:00
Flask + Docker, header support links, install/uninstall curl scripts, password file or ADMIN_PASSWORD. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
3.1 KiB
Bash
Executable File
97 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Однострочная установка (пример в README): клон/скачивание с GitHub, сборка образа, запуск контейнера.
|
||
set -euo pipefail
|
||
|
||
REPO="${KASKAD_REPO:-andrey271192/kaskad_web_vpn}"
|
||
REF="${KASKAD_REF:-main}"
|
||
IMAGE="${KASKAD_IMAGE:-kaskad-web-vpn:latest}"
|
||
CONTAINER="${KASKAD_CONTAINER:-kaskad-web-vpn}"
|
||
INSTALL_ROOT="${KASKAD_INSTALL_ROOT:-/opt}"
|
||
HOST_PORT="${HOST_PORT:-8088}"
|
||
BASIC_AUTH_USER="${BASIC_AUTH_USER:-user1}"
|
||
BASIC_AUTH_REALM="${BASIC_AUTH_REALM:-kaskad}"
|
||
PASSWORD_FILE="${PASSWORD_FILE:-/root/kaskad_web.initial-password}"
|
||
PANEL_URL="${PANEL_URL:-}"
|
||
|
||
need_cmd() {
|
||
command -v "$1" >/dev/null 2>&1 || {
|
||
echo "Нужна команда: $1" >&2
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
need_cmd docker
|
||
|
||
if ! docker info >/dev/null 2>&1; then
|
||
echo "Docker недоступен (запустите сервис или добавьте пользователя в группу docker)." >&2
|
||
exit 1
|
||
fi
|
||
|
||
SRC="${INSTALL_ROOT}/kaskad_web_vpn_src"
|
||
mkdir -p "$(dirname "$SRC")"
|
||
|
||
TMP="$(mktemp -d)"
|
||
trap 'rm -rf "$TMP"' EXIT
|
||
|
||
ARCHIVE_URL="https://github.com/${REPO}/archive/refs/heads/${REF}.tar.gz"
|
||
echo "Скачивание ${ARCHIVE_URL} …"
|
||
curl -fsSL "$ARCHIVE_URL" -o "${TMP}/src.tar.gz"
|
||
tar -xzf "${TMP}/src.tar.gz" -C "$TMP"
|
||
EXTRACTED="$(find "$TMP" -maxdepth 1 -type d -name "*-${REF}" | head -n1)"
|
||
if [[ -z "$EXTRACTED" ]]; then
|
||
EXTRACTED="$(find "$TMP" -maxdepth 1 -type d ! -path "$TMP" | head -n1)"
|
||
fi
|
||
rm -rf "$SRC"
|
||
mkdir -p "$SRC"
|
||
shopt -s dotglob
|
||
mv "$EXTRACTED"/* "$SRC"/
|
||
|
||
echo "Сборка образа ${IMAGE} …"
|
||
docker build -t "$IMAGE" "$SRC"
|
||
|
||
if docker ps -a --format '{{.Names}}' | grep -qx "$CONTAINER"; then
|
||
echo "Удаление старого контейнера ${CONTAINER} …"
|
||
docker rm -f "$CONTAINER" >/dev/null
|
||
fi
|
||
|
||
if [[ -n "${ADMIN_PASSWORD:-}" ]]; then
|
||
BASIC_AUTH_PASSWORD="$ADMIN_PASSWORD"
|
||
elif [[ -f "$PASSWORD_FILE" ]] && grep -qs . "$PASSWORD_FILE"; then
|
||
BASIC_AUTH_PASSWORD="$(tr -d '\r\n' <"$PASSWORD_FILE")"
|
||
else
|
||
if command -v openssl >/dev/null 2>&1; then
|
||
BASIC_AUTH_PASSWORD="$(openssl rand -hex 16)"
|
||
else
|
||
BASIC_AUTH_PASSWORD="$(head -c 32 /dev/urandom | base64 | tr -dc 'A-Za-z0-9' | head -c 24)"
|
||
fi
|
||
umask 077
|
||
printf '%s\n' "$BASIC_AUTH_PASSWORD" >"$PASSWORD_FILE"
|
||
echo "Сгенерирован пароль Basic Auth, сохранён в ${PASSWORD_FILE}"
|
||
fi
|
||
|
||
if [[ -z "$BASIC_AUTH_PASSWORD" ]]; then
|
||
echo "BASIC_AUTH_PASSWORD пуст — задайте ADMIN_PASSWORD или файл ${PASSWORD_FILE}" >&2
|
||
exit 1
|
||
fi
|
||
|
||
RUN_ARGS=(
|
||
-d
|
||
--name "$CONTAINER"
|
||
--restart unless-stopped
|
||
-p "${HOST_PORT}:8088"
|
||
-e "BASIC_AUTH_USER=${BASIC_AUTH_USER}"
|
||
-e "BASIC_AUTH_PASSWORD=${BASIC_AUTH_PASSWORD}"
|
||
-e "BASIC_AUTH_REALM=${BASIC_AUTH_REALM}"
|
||
)
|
||
|
||
if [[ -n "$PANEL_URL" ]]; then
|
||
RUN_ARGS+=(-e "PANEL_URL=${PANEL_URL}")
|
||
fi
|
||
|
||
docker run "${RUN_ARGS[@]}" "$IMAGE"
|
||
|
||
echo "Готово."
|
||
echo " URL: http://$(hostname -f 2>/dev/null || hostname):${HOST_PORT}/"
|
||
echo " Логин: ${BASIC_AUTH_USER}"
|
||
echo " Пароль: см. ${PASSWORD_FILE} (или переменная ADMIN_PASSWORD при установке)"
|