From 4debee966a2b21094cf28ecf7e491732719b3cb4 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:24:55 +0200 Subject: [PATCH] feat(installer): add prerequisite checks and auto-detection --- installer/install.sh | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/installer/install.sh b/installer/install.sh index 9a10a11..6089102 100644 --- a/installer/install.sh +++ b/installer/install.sh @@ -287,3 +287,91 @@ load_env_overrides() { [ -z "$DOCKER_SOCKET" ] && DOCKER_SOCKET="$_ENV_DOCKER_SOCKET" [ -z "$NODE_TLS_REJECT" ] && NODE_TLS_REJECT="$_ENV_NODE_TLS_REJECT" } + +# --- Prerequisites --- + +check_prerequisites() { + log_info "Checking prerequisites..." + local errors=0 + + if ! command -v docker >/dev/null 2>&1; then + log_error "Docker is not installed." + echo " Install Docker Engine: https://docs.docker.com/engine/install/" + errors=$((errors + 1)) + else + local docker_version + docker_version=$(docker version --format '{{.Server.Version}}' 2>/dev/null || echo "unknown") + log_info "Docker version: $docker_version" + fi + + if ! docker compose version >/dev/null 2>&1; then + log_error "Docker Compose v2 is not available." + echo " 'docker compose' subcommand required (not standalone docker-compose)." + errors=$((errors + 1)) + else + local compose_version + compose_version=$(docker compose version --short 2>/dev/null || echo "unknown") + log_info "Docker Compose version: $compose_version" + fi + + if ! command -v openssl >/dev/null 2>&1; then + log_error "OpenSSL is not installed (needed for password generation)." + errors=$((errors + 1)) + fi + + local socket="${DOCKER_SOCKET:-$DEFAULT_DOCKER_SOCKET}" + if [ ! -S "$socket" ]; then + log_warn "Docker socket not found at $socket" + fi + + check_port_available "${HTTP_PORT:-$DEFAULT_HTTP_PORT}" "HTTP" + check_port_available "${HTTPS_PORT:-$DEFAULT_HTTPS_PORT}" "HTTPS" + check_port_available "${LOGTO_CONSOLE_PORT:-$DEFAULT_LOGTO_CONSOLE_PORT}" "Logto Console" + + if [ $errors -gt 0 ]; then + log_error "$errors prerequisite(s) not met. Please install missing dependencies and retry." + exit 1 + fi + log_success "All prerequisites met." +} + +check_port_available() { + local port="$1" name="$2" + if command -v ss >/dev/null 2>&1; then + if ss -tlnp 2>/dev/null | grep -q ":${port} "; then + log_warn "Port $port ($name) is already in use." + fi + elif command -v netstat >/dev/null 2>&1; then + if netstat -tlnp 2>/dev/null | grep -q ":${port} "; then + log_warn "Port $port ($name) is already in use." + fi + fi +} + +# --- Auto-detection --- + +auto_detect() { + if [ -z "$PUBLIC_HOST" ]; then + PUBLIC_HOST=$(hostname -f 2>/dev/null || hostname 2>/dev/null || echo "localhost") + local primary_ip + primary_ip=$(ip route get 1.1.1.1 2>/dev/null | awk '{print $7; exit}' || true) + if [ -n "$primary_ip" ]; then + local rdns + rdns=$(dig +short -x "$primary_ip" 2>/dev/null | sed 's/\.$//' || true) + [ -n "$rdns" ] && PUBLIC_HOST="$rdns" + fi + fi + + if [ -z "$DOCKER_SOCKET" ]; then + DOCKER_SOCKET="$DEFAULT_DOCKER_SOCKET" + fi +} + +detect_existing_install() { + local dir="${INSTALL_DIR:-$DEFAULT_INSTALL_DIR}" + if [ -f "$dir/cameleer.conf" ]; then + IS_RERUN=true + INSTALL_DIR="$dir" + load_config_file "$dir/cameleer.conf" + fi +}