#!/bin/bash # ═══════════════════════════════════════════════════════════════ # 00-bootstrap-host.sh # Bootstrap firewalld + Docker pour USINE_APPLICATIONS # # A lancer une fois sur chaque host Fedora avant tout déploiement. # Idempotent. peut être relancé sans risque. # # Usage. sudo ./00-bootstrap-host.sh # ═══════════════════════════════════════════════════════════════ set -euo pipefail # ── Configuration ───────────────────────────────────────────── DNS_PRIMARY="${DNS_PRIMARY:-8.8.8.8}" DNS_SECONDARY="${DNS_SECONDARY:-8.8.4.4}" DOCKER_DAEMON_CONF="/etc/docker/daemon.json" TEST_IMAGE="alpine:latest" LOG_PREFIX="[bootstrap-host]" # ── Helpers ─────────────────────────────────────────────────── log() { echo "${LOG_PREFIX} $*"; } warn() { echo "${LOG_PREFIX} WARN. $*" >&2; } err() { echo "${LOG_PREFIX} ERREUR. $*" >&2; } die() { err "$*"; exit 1; } confirm() { local prompt="${1:-Continuer ?} [o/N] " read -r -p "$prompt" response [[ "$response" =~ ^[oOyY]$ ]] || die "Annulation utilisateur." } # ── Phase 0. Vérifications préalables ───────────────────────── log "Phase 0. vérifications préalables..." [[ $EUID -eq 0 ]] || die "Script à lancer en root (sudo $0)." [[ -f /etc/fedora-release ]] || warn "Système non-Fedora détecté. Le script peut nécessiter des adaptations." command -v docker >/dev/null 2>&1 || die "Docker non installé." command -v firewall-cmd >/dev/null 2>&1 || die "firewalld non installé." systemctl is-active --quiet firewalld || die "firewalld non actif. systemctl start firewalld" systemctl is-active --quiet docker || die "Docker non actif. systemctl start docker" log " Toutes les vérifications passent." # ── Avertissement utilisateur ───────────────────────────────── log "" log "Ce script va." log " 1. Réécrire ${DOCKER_DAEMON_CONF} (backup automatique)" log " 2. Modifier la configuration firewalld (zone trusted + masquerade)" log " 3. Redémarrer le service Docker (tous les containers vont stopper)" log " 4. Exécuter des tests de validation (pull image alpine)" log "" if [[ "${1:-}" != "--force" ]]; then confirm "Confirmer le bootstrap ?" fi # ── Phase 1. Configuration daemon Docker ────────────────────── log "" log "Phase 1. configuration de ${DOCKER_DAEMON_CONF}..." mkdir -p /etc/docker if [[ -f "${DOCKER_DAEMON_CONF}" ]]; then BACKUP="${DOCKER_DAEMON_CONF}.bak.$(date +%Y%m%d-%H%M%S)" cp "${DOCKER_DAEMON_CONF}" "${BACKUP}" log " Backup. ${BACKUP}" fi cat > "${DOCKER_DAEMON_CONF}" </dev/null || true log " docker0 ajouté à la zone trusted." # Bridges Docker custom (br-*) BRIDGES=$(ip -o link show | awk -F: '/br-/{print $2}' | tr -d ' ' | cut -d@ -f1) if [[ -n "${BRIDGES}" ]]; then BRIDGE_COUNT=$(echo "${BRIDGES}" | wc -l) log " ${BRIDGE_COUNT} bridge(s) custom détecté(s)." while IFS= read -r iface; do firewall-cmd --permanent --zone=trusted --add-interface="${iface}" 2>/dev/null || true log " + ${iface}" done <<< "${BRIDGES}" else log " Aucun bridge custom détecté." fi # Masquerade sur la zone par défaut firewall-cmd --permanent --zone="${DEFAULT_ZONE}" --add-masquerade 2>/dev/null || true log " Masquerade activé sur la zone ${DEFAULT_ZONE}." # Reload firewall-cmd --reload log " firewalld rechargé." # ── Phase 3. Redémarrage Docker ─────────────────────────────── log "" log "Phase 3. redémarrage du service Docker..." systemctl restart docker # Attente que Docker soit pleinement opérationnel for i in {1..15}; do if docker info >/dev/null 2>&1; then log " Docker opérationnel après ${i}s." break fi sleep 1 if [[ $i -eq 15 ]]; then die "Docker ne répond pas après 15s." fi done # ── Phase 4. Tests de validation ────────────────────────────── log "" log "Phase 4. tests de validation..." log " Test 1. pull image de test (${TEST_IMAGE})..." docker pull "${TEST_IMAGE}" >/dev/null 2>&1 || die "Pull image échoué. DNS du host probablement HS." log " OK" log " Test 2. résolution DNS depuis un container..." if docker run --rm "${TEST_IMAGE}" nslookup archive.ubuntu.com >/dev/null 2>&1; then log " OK" else err " Échec résolution DNS." err " Lancer manuellement. docker run --rm alpine nslookup archive.ubuntu.com" exit 2 fi log " Test 3. connectivité HTTPS sortante depuis un container..." if docker run --rm "${TEST_IMAGE}" wget -q --spider https://www.cloudflare.com 2>/dev/null; then log " OK" else err " Échec connectivité HTTPS sortante." exit 2 fi # ── Phase 5. Résumé ─────────────────────────────────────────── log "" log "═══════════════════════════════════════════════════════════" log " Bootstrap terminé avec succès." log "═══════════════════════════════════════════════════════════" log " Zone par défaut. ${DEFAULT_ZONE}" log " Masquerade. actif" log " DNS Docker. ${DNS_PRIMARY}, ${DNS_SECONDARY}" log " Daemon config. ${DOCKER_DAEMON_CONF}" log "" log " Interfaces en zone trusted." firewall-cmd --zone=trusted --list-interfaces | tr ' ' '\n' | sed 's/^/ - /' log "" log " USINE_APPLICATIONS prêt pour déploiement." log "═══════════════════════════════════════════════════════════"