#!/usr/bin/env bash # ============================================================================= # preflight.sh — BEDS environment preflight checklist # # Checks that all required services and tools are present and reachable. # Installs anything missing (Debian/Ubuntu only). # Idempotent — safe to run multiple times. # # Usage: # ./scripts/preflight.sh # check + install missing # ./scripts/preflight.sh --check # check only, no installs # # Requirements: bash 5+, sudo access (for installs) # Supported: Debian 11+ / Ubuntu 22.04+ # ============================================================================= set -euo pipefail # --- config ------------------------------------------------------------------ RABBITMQ_HOST="${RABBITMQ_HOST:-localhost}" RABBITMQ_PORT="${RABBITMQ_PORT:-5672}" MONGO_HOST="${MONGO_HOST:-localhost}" MONGO_PORT="${MONGO_PORT:-27017}" MARIADB_HOST="${MARIADB_HOST:-localhost}" MARIADB_PORT="${MARIADB_PORT:-3306}" CHECK_ONLY=false if [[ "${1:-}" == "--check" ]]; then CHECK_ONLY=true fi # --- output helpers ---------------------------------------------------------- RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' BOLD='\033[1m' RESET='\033[0m' PASS=0 FAIL=0 WARN=0 pass() { echo -e " ${GREEN}[PASS]${RESET} $1"; PASS=$(( PASS + 1 )); } fail() { echo -e " ${RED}[FAIL]${RESET} $1"; FAIL=$(( FAIL + 1 )); } warn() { echo -e " ${YELLOW}[WARN]${RESET} $1"; WARN=$(( WARN + 1 )); } info() { echo -e " ${CYAN} ${RESET} $1"; } section() { echo; echo -e "${BOLD}$1${RESET}"; echo "$(printf '%.0s-' {1..60})"; } # --- distro check ------------------------------------------------------------ detect_distro() { if [[ -f /etc/os-release ]]; then source /etc/os-release DISTRO_ID="${ID:-unknown}" DISTRO_LIKE="${ID_LIKE:-}" else DISTRO_ID="unknown" DISTRO_LIKE="" fi } is_debian_family() { [[ "$DISTRO_ID" == "debian" || "$DISTRO_ID" == "ubuntu" || "$DISTRO_LIKE" == *"debian"* ]] } apt_install() { if $CHECK_ONLY; then fail "$1 — not installed (run without --check to install)" return fi info "Installing $*..." sudo apt-get install -y "$@" 2>&1 | tail -3 } # Check via systemd (more reliable than searching sbin paths) svc_installed() { systemctl cat "$1" &>/dev/null } svc_active() { systemctl is-active --quiet "$1" 2>/dev/null } # Check via dpkg (fast, no PATH issues) pkg_installed() { dpkg -s "$1" &>/dev/null && dpkg -s "$1" | grep -q 'Status: install ok installed' } # --- tcp reachability -------------------------------------------------------- tcp_check() { local host="$1" port="$2" timeout 2 bash -c ">/dev/tcp/${host}/${port}" 2>/dev/null } # ============================================================================= section "BEDS Preflight Checklist" echo " Mode: $( $CHECK_ONLY && echo 'check only' || echo 'check + install')" detect_distro echo " Distro: ${DISTRO_ID:-unknown} ${VERSION_ID:-}" echo # ============================================================================= section "1. Build Toolchain" if command -v rustc &>/dev/null; then RUST_VER=$(rustc --version) pass "Rust — $RUST_VER" else fail "Rust — not found" info "Install: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh" info "(rustup is not managed by apt — install manually)" fi if command -v cargo &>/dev/null; then CARGO_VER=$(cargo --version) pass "Cargo — $CARGO_VER" else fail "Cargo — not found (install Rust via rustup)" fi # ============================================================================= section "2. RabbitMQ" if pkg_installed rabbitmq-server; then pass "RabbitMQ — installed" else if $CHECK_ONLY; then fail "RabbitMQ — not installed" else if is_debian_family; then info "Adding RabbitMQ apt repository..." curl -fsSL https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/rabbitmq-archive-keyring.gpg 2>/dev/null echo "deb [signed-by=/usr/share/keyrings/rabbitmq-archive-keyring.gpg] https://packagecloud.io/rabbitmq/rabbitmq-server/debian/ $(source /etc/os-release && echo $VERSION_CODENAME) main" \ | sudo tee /etc/apt/sources.list.d/rabbitmq.list > /dev/null sudo apt-get update -qq apt_install rabbitmq-server else fail "RabbitMQ — not installed; automatic install only supported on Debian/Ubuntu" info "See: https://www.rabbitmq.com/docs/install-debian" fi fi fi if tcp_check "$RABBITMQ_HOST" "$RABBITMQ_PORT"; then pass "RabbitMQ reachable at ${RABBITMQ_HOST}:${RABBITMQ_PORT}" else fail "RabbitMQ not reachable at ${RABBITMQ_HOST}:${RABBITMQ_PORT}" info "Start: sudo systemctl start rabbitmq-server" fi if svc_active rabbitmq-server; then # Check management plugin via the HTTP API (no sudo needed) if tcp_check localhost 15672; then pass "RabbitMQ management plugin enabled (port 15672 open)" else warn "RabbitMQ management plugin not enabled" info "Enable: sudo rabbitmq-plugins enable rabbitmq_management" info " (provides the admin UI at http://localhost:15672)" fi fi # ============================================================================= section "3. MongoDB" if svc_installed mongod; then MONGO_VER=$(mongod --version 2>/dev/null | head -1 || echo 'installed') pass "MongoDB — $MONGO_VER" else if $CHECK_ONLY; then fail "MongoDB — not installed" else if is_debian_family; then info "Adding MongoDB apt repository..." curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | sudo gpg --dearmor -o /usr/share/keyrings/mongodb-server-8.0.gpg 2>/dev/null echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg] https://repo.mongodb.org/apt/debian bookworm/mongodb-org/8.0 main" \ | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list > /dev/null sudo apt-get update -qq apt_install mongodb-org else fail "MongoDB — not installed; automatic install only supported on Debian/Ubuntu" info "See: https://www.mongodb.org/docs/manual/installation/" fi fi fi if tcp_check "$MONGO_HOST" "$MONGO_PORT"; then pass "MongoDB reachable at ${MONGO_HOST}:${MONGO_PORT}" else fail "MongoDB not reachable at ${MONGO_HOST}:${MONGO_PORT}" info "Start: sudo systemctl start mongod" fi # ============================================================================= section "4. MariaDB" if svc_installed mariadb; then pass "MariaDB — installed" else if $CHECK_ONLY; then fail "MariaDB — not installed" else if is_debian_family; then apt_install mariadb-server else fail "MariaDB — not installed; automatic install only supported on Debian/Ubuntu" info "See: https://mariadb.org/download/" fi fi fi if tcp_check "$MARIADB_HOST" "$MARIADB_PORT"; then pass "MariaDB reachable at ${MARIADB_HOST}:${MARIADB_PORT}" else fail "MariaDB not reachable at ${MARIADB_HOST}:${MARIADB_PORT}" info "Start: sudo systemctl start mariadb" fi # ============================================================================= section "5. Apache + PHP (Observer Tool)" if svc_installed apache2; then APACHE_VER=$(apache2 -v 2>/dev/null | head -1 | awk '{print $3}' || echo 'installed') pass "Apache — $APACHE_VER" else if $CHECK_ONLY; then fail "Apache — not installed" else if is_debian_family; then apt_install apache2 else fail "Apache — not installed; automatic install only supported on Debian/Ubuntu" fi fi fi if tcp_check localhost 80; then pass "Apache reachable at localhost:80" else fail "Apache not reachable at localhost:80" info "Start: sudo systemctl start apache2" fi if pkg_installed php; then PHP_VER=$(php --version 2>/dev/null | head -1 || echo 'installed') pass "PHP — $PHP_VER" else if $CHECK_ONLY; then fail "PHP — not installed" else if is_debian_family; then apt_install php libapache2-mod-php php-mongodb php-cli sudo systemctl restart apache2 else fail "PHP — not installed; automatic install only supported on Debian/Ubuntu" fi fi fi # Check php-mongodb extension specifically if pkg_installed php-mongodb; then pass "PHP mongodb extension — installed" else warn "PHP mongodb extension — not installed" info "Install: sudo apt install php-mongodb && sudo systemctl restart apache2" fi # ============================================================================= section "Summary" TOTAL=$(( PASS + FAIL + WARN )) echo echo -e " Checked : $TOTAL" echo -e " ${GREEN}Passed : $PASS${RESET}" if [[ $WARN -gt 0 ]]; then echo -e " ${YELLOW}Warnings: $WARN${RESET}" fi if [[ $FAIL -gt 0 ]]; then echo -e " ${RED}Failed : $FAIL${RESET}" echo if $CHECK_ONLY; then echo -e " Run ${BOLD}./scripts/preflight.sh${RESET} (without --check) to install missing dependencies." else echo -e " Some checks failed. Review output above and resolve before running BEDS." fi exit 1 else echo echo -e " ${GREEN}${BOLD}All checks passed. Environment is ready.${RESET}" if ! $CHECK_ONLY; then echo echo -e " Next steps:" echo -e " 1. Copy config template: cp config/beds.toml.example config/beds.toml" echo -e " 2. Edit credentials: \$EDITOR config/env_dev.toml" echo -e " 3. Build and run: cargo run" fi fi