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
This commit is contained in:
+143
-31
@@ -23,36 +23,146 @@ 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")
|
||||
# ── 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
|
||||
done
|
||||
}
|
||||
|
||||
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
|
||||
missing+=("docker compose plugin")
|
||||
NEED_COMPOSE=true
|
||||
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"
|
||||
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
|
||||
log "Prerequisites satisfied"
|
||||
|
||||
# Check docker is running
|
||||
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
|
||||
err "Docker daemon is not running. Start it with: sudo systemctl start docker"
|
||||
exit 1
|
||||
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"
|
||||
@@ -86,22 +196,22 @@ log "Data directory ready"
|
||||
|
||||
# ── Build & Start ────────────────────────────────
|
||||
info "Building Docker image (this may take a few minutes)..."
|
||||
docker compose build web
|
||||
$DOCKER_CMD compose build web
|
||||
log "Build complete"
|
||||
|
||||
info "Starting containers..."
|
||||
docker compose up -d
|
||||
$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 compose exec -T web wget --no-verbose --tries=1 --spider http://127.0.0.1:3000/api/health &>/dev/null; then
|
||||
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"
|
||||
warn "Timed out waiting for health check — check logs with: $DOCKER_CMD compose logs web"
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
@@ -110,17 +220,19 @@ done
|
||||
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 "╔══════════════════════════════════════════════════════════════╗\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"
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user