Files
worst-scan-web/install.sh
T
Renato 18cee972f5 feat: install.sh auto-installs Docker when missing
- OS detection (ubuntu/debian, arch, fedora, centos/rhel)
- Docker Engine: official repo (apt), pacman, or dnf
- Compose plugin: docker-compose-v2, docker-compose-plugin, or CLI plugin fallback
- Docker daemon auto-start via systemd/service/dockerd
- User added to docker group + sg fallback for current shell
- DOCKER_CMD variable handles sudo vs non-sudo transparently
- Wider summary box (60 chars) for full path display
2026-07-27 23:30:01 +02:00

242 lines
9.6 KiB
Bash
Executable File

#!/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)
ARCH=$(uname -m)
# ── 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)
sudo apt update -qq
sudo apt install -y -qq ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/"$OS"/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$ARCH signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$OS $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update -qq
sudo apt install -y -qq docker-ce docker-ce-cli containerd.io
;;
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
if $NEED_COMPOSE && ! command -v docker &>/dev/null; then
# fresh install — compose plugin is already included in docker-ce package
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="sg docker -c 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_CMD 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"