#!/usr/bin/env bash homelab_preflight() { local phase="${1:-full}" local failures=0 require_debian_server "preflight" if truthy "${LAB_SKIP_PREFLIGHT:-false}"; then echo "Skipping homelab preflight because LAB_SKIP_PREFLIGHT=${LAB_SKIP_PREFLIGHT}." return 0 fi case "${phase}" in early | full) ;; *) echo "Unsupported preflight phase '${phase}'." >&2 exit 1 ;; esac echo "Running ${phase} homelab preflight checks from ${HOMELAB_INVENTORY_FILE:-${REPO_ROOT}/homelab.yml}..." preflight_check "Debian Docker root is ${LAB_DEBIAN_DOCKER_ROOT:-/var/lib/docker}" check_debian_docker_root || failures=$((failures + 1)) preflight_check "Debian Tailscale IP ${LAB_DEBIAN_TAILSCALE_IP:-unset}" check_debian_tailscale_ip || failures=$((failures + 1)) preflight_check "RPi SSH ${LAB_RPI_USER:-${LAB_RASPBERRY_USER:-jv}}@${LAB_RPI_HOST:-${LAB_RASPBERRY_HOST:-192.168.100.89}}" check_rpi_ssh || failures=$((failures + 1)) if [[ "${phase}" == "full" ]]; then preflight_check "Gitea reachable at ${LAB_GITEA_LOCAL_URL:-http://${LAB_GITEA_HOST:-192.168.100.73}:${LAB_GITEA_HTTP_PORT:-3000}/}" check_gitea_reachable || failures=$((failures + 1)) preflight_check "RPi Docker root is NVMe or fallback" check_rpi_docker_root_state || failures=$((failures + 1)) fi preflight_warn "RPi Tailscale IP ${LAB_RPI_TAILSCALE_IP:-unset}" check_rpi_tailscale_ip preflight_check "Pimox storage ${LAB_PIMOX_WORKER_STORAGE:-${TF_VAR_pimox_worker_storage:-opi5_ssd}} is active" check_pimox_storage || failures=$((failures + 1)) preflight_check "OCI edge SSH ${LAB_EDGE_USER:-ubuntu}@${LAB_EDGE_HOST:?LAB_EDGE_HOST is required from homelab.yml}" check_edge_ssh || failures=$((failures + 1)) if ((failures > 0)); then echo "Preflight failed with ${failures} blocking check(s). Fix the inventory or host state before continuing." >&2 exit 1 fi echo "${phase^} preflight checks passed." } doctor_preapply() { local failures=0 require_debian_server "doctor-preapply" echo "Running pre-apply readiness checks..." preflight_check "Debian / has at least ${LAB_PREFLIGHT_ROOT_MIN_FREE_GIB:-10} GiB free" check_local_disk_free_gib / "${LAB_PREFLIGHT_ROOT_MIN_FREE_GIB:-10}" || failures=$((failures + 1)) preflight_check "Debian /data has at least ${LAB_PREFLIGHT_DATA_MIN_FREE_GIB:-20} GiB free" check_local_disk_free_gib /data "${LAB_PREFLIGHT_DATA_MIN_FREE_GIB:-20}" || failures=$((failures + 1)) preflight_check "Docker is active" check_systemd_active docker || failures=$((failures + 1)) preflight_check "containerd is active" check_systemd_active containerd || failures=$((failures + 1)) preflight_check "RPi Docker root is writable" check_rpi_docker_writable || failures=$((failures + 1)) preflight_check "Pimox storage ${LAB_PIMOX_WORKER_STORAGE:-${TF_VAR_pimox_worker_storage:-opi5_ssd}} is active" check_pimox_storage || failures=$((failures + 1)) preflight_check "OCI edge / has at least ${LAB_PREFLIGHT_EDGE_MIN_FREE_GIB:-2} GiB free" check_edge_disk_free || failures=$((failures + 1)) preflight_check "Pi-hole DNS query resolves" check_pihole_dns_query || failures=$((failures + 1)) if ((failures > 0)); then echo "Pre-apply doctor failed with ${failures} blocking check(s)." >&2 exit 1 fi echo "Pre-apply doctor checks passed." } inventory_check() { "${REPO_ROOT}/scripts/validate-homelab-inventory" "${HOMELAB_INVENTORY_FILE:-${REPO_ROOT}/homelab.yml}" }