#!/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"; } # ── OS detection ────────────────────────────────── detect_os() { if [ -f /etc/os-release ]; then . /etc/os-release echo "$ID" elif command -v lsb_release &>/dev/null; then lsb_release -si | tr '[:upper:]' '[:lower:]' else echo "unknown" fi } OS=$(detect_os) RAW_ARCH=$(uname -m) case "$RAW_ARCH" in x86_64) ARCH="amd64" ;; aarch64) ARCH="arm64" ;; *) ARCH="$RAW_ARCH" ;; esac # ── Git ────────────────────────────────────────── if ! command -v git &>/dev/null; then info "Installing git..." case "$OS" in ubuntu|debian) sudo apt update -qq && sudo apt install -y -qq git ;; arch|endeavouros) sudo pacman -S --noconfirm git ;; fedora|centos|rhel|almalinux|rocky) sudo dnf install -y git ;; *) err "Unsupported OS: $OS. Install git manually." && exit 1 ;; esac log "git installed" fi # ── Docker ─────────────────────────────────────── NEED_DOCKER=false NEED_COMPOSE=false if ! command -v docker &>/dev/null; then NEED_DOCKER=true fi if ! docker compose version &>/dev/null && ! docker-compose --version &>/dev/null; then NEED_COMPOSE=true fi if $NEED_DOCKER; then info "Installing Docker Engine..." case "$OS" in ubuntu|debian) curl -fsSL https://get.docker.com | sh ;; arch|endeavouros) sudo pacman -S --noconfirm docker ;; fedora) sudo dnf install -y dnf-plugins-core sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io ;; centos|rhel|almalinux|rocky) sudo dnf install -y dnf-plugins-core sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install -y docker-ce docker-ce-cli containerd.io ;; *) err "Unsupported OS: $OS. Install Docker manually: https://docs.docker.com/engine/install/" exit 1 ;; esac log "Docker Engine installed" fi # Re-check compose — fresh Docker install may have included it if $NEED_COMPOSE && docker compose version &>/dev/null; then NEED_COMPOSE=false fi if $NEED_COMPOSE; then info "Installing Docker Compose plugin..." case "$OS" in ubuntu|debian) sudo apt install -y -qq docker-compose-v2 2>/dev/null || { sudo apt install -y -qq docker-compose-plugin 2>/dev/null || { warn "Compose plugin not in apt. Installing via CLI plugin..." CLI_PLUGINS="/usr/lib/docker/cli-plugins" sudo mkdir -p "$CLI_PLUGINS" sudo curl -fsSL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o "$CLI_PLUGINS/docker-compose" sudo chmod +x "$CLI_PLUGINS/docker-compose" } } ;; arch|endeavouros) sudo pacman -S --noconfirm docker-compose ;; fedora|centos|rhel|almalinux|rocky) sudo dnf install -y docker-compose-v2 2>/dev/null || { CLI_PLUGINS="/usr/lib/docker/cli-plugins" sudo mkdir -p "$CLI_PLUGINS" sudo curl -fsSL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o "$CLI_PLUGINS/docker-compose" sudo chmod +x "$CLI_PLUGINS/docker-compose" } ;; esac log "Docker Compose plugin installed" fi log "Docker prerequisites satisfied" # ── Start Docker daemon ───────────────────────── if ! docker info &>/dev/null; then info "Starting Docker daemon..." if command -v systemctl &>/dev/null; then sudo systemctl enable --now docker elif command -v service &>/dev/null; then sudo service docker start else sudo dockerd &>/dev/null & sleep 3 fi fi log "Docker daemon is running" # ── Add user to docker group ──────────────────── if ! groups "$USER" | grep -q docker; then info "Adding $USER to the docker group..." sudo usermod -aG docker "$USER" # Spawn subshell with the new group so rest of script can use docker without sudo sg docker -c "true" 2>/dev/null || true warn "You may need to re-login for group changes to take effect in new shells" fi # Use sudo for docker commands if the current shell can't run docker directly if docker info &>/dev/null 2>&1; then docker_cmd() { docker "$@"; } else docker_cmd() { sudo docker "$@"; } fi # ── 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_cmd compose build web log "Build complete" info "Starting containers..." docker_cmd 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_cmd 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 ────────────────────────────────────── BOX_W=60 hr() { printf "║ %-*s ║\n" "$((BOX_W-6))" "$1"; } printf "\n" printf "╔══════════════════════════════════════════════════════════════╗\n" printf "║ ${GREEN}worst-scan-web installed!${NC} ║\n" printf "╠══════════════════════════════════════════════════════════════╣\n" hr "Web: http://$IP:3000" hr "Config: $INSTALL_DIR/.env" hr "Logs: cd $INSTALL_DIR && docker compose logs -f" hr "Restart: cd $INSTALL_DIR && docker compose restart" hr "Stop: cd $INSTALL_DIR && docker compose down" hr "Update: bash install.sh" 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"