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:
Renato
2026-07-27 23:30:01 +02:00
parent 0fc421f234
commit 18cee972f5
+143 -31
View File
@@ -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"