feat: self-contained Docker installer with web setup wizard
- settings.ts: persistent settings.json in data volume (survives restarts) - /api/setup: POST to save API_BASE_URL, API_KEY, WEB_PASSWORD, WEBHOOK_SECRET - /setup: web-based setup wizard for first-time configuration - /api/health: JSON health check endpoint for Docker healthcheck - api.ts: dynamic API_BASE_URL/API_KEY resolution from settings - login route: fallback WEB_PASSWORD from settings.json - middleware: /setup and /api/setup are public paths - Dockerfile: HEALTHCHECK instruction - docker-compose.yml: healthcheck + optional .env file - .env.example: full documentation of all env vars - install.sh: single-command VPS installer (clone, build, run)
This commit is contained in:
Executable
+129
@@ -0,0 +1,129 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# worst-scan-web — Docker auto-installer
|
||||
# Usage: bash <(curl -fsSL https://gitea.cbcren.online/renato97/worst-scan-web/raw/branch/main/install.sh)
|
||||
# Or: curl -fsSL https://gitea.cbcren.online/renato97/worst-scan-web/raw/branch/main/install.sh -o install.sh && bash install.sh
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
REPO_URL="https://gitea.cbcren.online/renato97/worst-scan-web.git"
|
||||
INSTALL_DIR="${HOME}/worst-scan-web"
|
||||
BRANCH="main"
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
NC='\033[0m'
|
||||
|
||||
log() { printf "${GREEN}✓${NC} %s\n" "$1"; }
|
||||
warn() { printf "${YELLOW}⚠${NC} %s\n" "$1"; }
|
||||
err() { printf "${RED}✗${NC} %s\n" "$1"; }
|
||||
info() { printf "${CYAN}→${NC} %s\n" "$1"; }
|
||||
|
||||
# ── Prerequisites ────────────────────────────────
|
||||
prereqs=("git" "docker")
|
||||
missing=()
|
||||
for cmd in "${prereqs[@]}"; do
|
||||
if ! command -v "$cmd" &>/dev/null; then
|
||||
missing+=("$cmd")
|
||||
fi
|
||||
done
|
||||
|
||||
if ! docker compose version &>/dev/null && ! docker-compose --version &>/dev/null; then
|
||||
missing+=("docker compose plugin")
|
||||
fi
|
||||
|
||||
if [ ${#missing[@]} -gt 0 ]; then
|
||||
err "Missing prerequisites: ${missing[*]}"
|
||||
info "Install them and re-run:"
|
||||
info " Ubuntu/Debian: sudo apt update && sudo apt install -y git docker.io docker-compose-v2"
|
||||
info " Arch: sudo pacman -S git docker docker-compose"
|
||||
info " Fedora: sudo dnf install -y git docker docker-compose"
|
||||
exit 1
|
||||
fi
|
||||
log "Prerequisites satisfied"
|
||||
|
||||
# Check docker is running
|
||||
if ! docker info &>/dev/null; then
|
||||
err "Docker daemon is not running. Start it with: sudo systemctl start docker"
|
||||
exit 1
|
||||
fi
|
||||
log "Docker daemon is running"
|
||||
|
||||
# ── Clone / Pull ─────────────────────────────────
|
||||
if [ -d "$INSTALL_DIR" ]; then
|
||||
info "Directory $INSTALL_DIR already exists — pulling latest"
|
||||
cd "$INSTALL_DIR"
|
||||
git fetch origin "$BRANCH"
|
||||
git reset --hard "origin/$BRANCH"
|
||||
log "Updated to latest commit"
|
||||
else
|
||||
info "Cloning repository..."
|
||||
git clone --depth=1 -b "$BRANCH" "$REPO_URL" "$INSTALL_DIR"
|
||||
cd "$INSTALL_DIR"
|
||||
log "Repository cloned"
|
||||
fi
|
||||
|
||||
INSTALL_DIR="$(cd "$INSTALL_DIR" && pwd)"
|
||||
|
||||
# ── .env ─────────────────────────────────────────
|
||||
if [ -f "$INSTALL_DIR/.env" ]; then
|
||||
warn ".env already exists — not overwriting"
|
||||
info "Edit $INSTALL_DIR/.env if you need to change settings"
|
||||
else
|
||||
cp "$INSTALL_DIR/.env.example" "$INSTALL_DIR/.env"
|
||||
log "Created .env from .env.example"
|
||||
info "Open $INSTALL_DIR/.env and set up your API_BASE_URL, API_KEY, WEB_PASSWORD"
|
||||
info "Then run the web setup wizard at http://YOUR_IP:3000/setup after starting"
|
||||
fi
|
||||
|
||||
# ── Data directory ────────────────────────────────
|
||||
mkdir -p "$INSTALL_DIR/data"
|
||||
log "Data directory ready"
|
||||
|
||||
# ── Build & Start ────────────────────────────────
|
||||
info "Building Docker image (this may take a few minutes)..."
|
||||
docker compose build web
|
||||
log "Build complete"
|
||||
|
||||
info "Starting containers..."
|
||||
docker compose up -d
|
||||
log "Containers are running"
|
||||
|
||||
# ── Wait for health ──────────────────────────────
|
||||
info "Waiting for web service to be healthy..."
|
||||
for i in $(seq 1 30); do
|
||||
if docker compose exec -T web wget --no-verbose --tries=1 --spider http://127.0.0.1:3000/api/health &>/dev/null; then
|
||||
log "Web service is healthy"
|
||||
break
|
||||
fi
|
||||
if [ "$i" -eq 30 ]; then
|
||||
warn "Timed out waiting for health check — check logs with: docker compose logs web"
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# ── Get IP ──────────────────────────────────────
|
||||
IP=$(curl -fsSL http://checkip.amazonaws.com 2>/dev/null || curl -fsSL https://api.ipify.org 2>/dev/null || echo "localhost")
|
||||
|
||||
# ── Summary ──────────────────────────────────────
|
||||
printf "\n"
|
||||
printf "╔══════════════════════════════════════════════╗\n"
|
||||
printf "║ ${GREEN}worst-scan-web installed!${NC} ║\n"
|
||||
printf "╠══════════════════════════════════════════════╣\n"
|
||||
printf "║ Web: http://%s:3000 ║\n" "$IP"
|
||||
printf "║ Config: %s/.env ║\n" "$INSTALL_DIR"
|
||||
printf "║ Logs: docker compose logs -f ║\n"
|
||||
printf "║ Restart: docker compose restart ║\n"
|
||||
printf "║ Stop: docker compose down ║\n"
|
||||
printf "║ Update: bash %s/install.sh ║\n" "$INSTALL_DIR"
|
||||
printf "╚══════════════════════════════════════════════╝\n"
|
||||
printf "\n"
|
||||
info "Next steps:"
|
||||
printf " 1. Open http://%s:3000/setup in your browser\n" "$IP"
|
||||
printf " 2. Complete the web setup wizard\n"
|
||||
printf " 3. Log in and start using worst-scan-web\n"
|
||||
printf "\n"
|
||||
Reference in New Issue
Block a user