From 0029cf302bd07d42b8b15a73c84ec1b554d128f0 Mon Sep 17 00:00:00 2001 From: Ezra Date: Sun, 5 Apr 2026 12:16:16 +0000 Subject: [PATCH] Add host readiness checker for Matrix/Conduit deployment (#166) Pre-flight validation script that tests Docker, ports, DNS, disk, and memory before running deploy-matrix.sh. --- infra/matrix/host-readiness-check.sh | 124 +++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 infra/matrix/host-readiness-check.sh diff --git a/infra/matrix/host-readiness-check.sh b/infra/matrix/host-readiness-check.sh new file mode 100644 index 00000000..dc92dfa0 --- /dev/null +++ b/infra/matrix/host-readiness-check.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +# host-readiness-check.sh — Validate target host before Matrix/Conduit deployment +# Usage: ./host-readiness-check.sh [DOMAIN] +# Issue: #166 / #183 + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DOMAIN="${1:-${MATRIX_DOMAIN:-}}" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +PASS=0 +FAIL=0 +WARN=0 + +pass() { echo -e "${GREEN}[PASS]${NC} $*"; ((PASS++)); } +fail() { echo -e "${RED}[FAIL]${NC} $*"; ((FAIL++)); } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; ((WARN++)); } + +log() { echo -e "\n==> $*"; } + +log "Matrix/Conduit Host Readiness Check" +log "====================================" + +# === Domain check === +if [[ -z "$DOMAIN" ]]; then + fail "DOMAIN not specified. Usage: ./host-readiness-check.sh matrix.timmytime.net" + exit 1 +else + pass "Domain specified: $DOMAIN" +fi + +# === Docker === +log "Checking Docker..." +if command -v docker &>/dev/null; then + DOCKER_VER=$(docker --version) + pass "Docker installed: $DOCKER_VER" +else + fail "Docker not installed" +fi + +if docker compose version &>/dev/null || docker-compose --version &>/dev/null; then + pass "Docker Compose available" +else + fail "Docker Compose not available" +fi + +if docker info &>/dev/null; then + pass "Docker daemon is running" +else + fail "Docker daemon is not running or user lacks permissions" +fi + +# === Ports === +log "Checking ports..." +for port in 80 443 8448; do + if ss -tln | grep -q ":$port "; then + warn "Port $port is already in use (may conflict)" + else + pass "Port $port is available" + fi +done + +# === DNS Resolution === +log "Checking DNS..." +RESOLVED_IP=$(dig +short "$DOMAIN" || true) +if [[ -n "$RESOLVED_IP" ]]; then + HOST_IP=$(curl -s ifconfig.me || true) + if [[ "$RESOLVED_IP" == "$HOST_IP" ]]; then + pass "DNS A record resolves to this host ($HOST_IP)" + else + warn "DNS A record resolves to $RESOLVED_IP (this host is $HOST_IP)" + fi +else + fail "DNS A record for $DOMAIN not found" +fi + +# === Disk Space === +log "Checking disk space..." +AVAILABLE_GB=$(df -BG "$SCRIPT_DIR" | awk 'NR==2 {gsub(/G/,""); print $4}') +if [[ "$AVAILABLE_GB" -ge 20 ]]; then + pass "Disk space: ${AVAILABLE_GB}GB available" +else + warn "Disk space: ${AVAILABLE_GB}GB available (recommended: 20GB+)" +fi + +# === Memory === +log "Checking memory..." +MEM_GB=$(free -g | awk '/^Mem:/ {print $2}') +if [[ "$MEM_GB" -ge 2 ]]; then + pass "Memory: ${MEM_GB}GB" +else + warn "Memory: ${MEM_GB}GB (recommended: 2GB+)" +fi + +# === Reverse proxy detection === +log "Checking reverse proxy..." +if command -v caddy &>/dev/null; then + pass "Caddy installed" +elif command -v nginx &>/dev/null; then + pass "Nginx installed" +elif ss -tln | grep -q ":80 " || ss -tln | grep -q ":443 "; then + warn "No Caddy/Nginx found, but something is bound to 80/443" +else + warn "No reverse proxy detected (Caddy or Nginx recommended)" +fi + +# === Summary === +log "====================================" +echo -e "Results: ${GREEN}$PASS passed${NC}, ${YELLOW}$WARN warnings${NC}, ${RED}$FAIL failures${NC}" + +if [[ $FAIL -gt 0 ]]; then + echo "" + echo "Host is NOT ready for deployment. Fix failures above, then re-run." + exit 1 +else + echo "" + echo "Host looks ready. Next step: ./deploy-matrix.sh $DOMAIN" + exit 0 +fi