#!/usr/bin/env bash # ===================================================================== # install.sh - Installation des Checkmk-/NGINX-Proxy-Manager-Stacks # # Debian/Ubuntu : Docker CE + Compose-Plugin # RHEL/Rocky/Alma/CentOS/Fedora : Podman + podman-compose # # Zusaetzlich: dialog (ncurses-Oberflaeche), openssl, tar, curl # ===================================================================== set -euo pipefail PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" . "$PROJECT_DIR/scripts/lib/common.sh" WITH_SYSTEMD="" WITH_QUADLET="" SKIP_RUNTIME="" ROOTLESS="" usage() { cat <<'EOF' install.sh - Installation des Checkmk-Container-Stacks OPTIONEN --with-systemd systemd-Unit einrichten, damit der Stack nach einem Neustart des Hosts automatisch wieder startet (Vorgabe bei Podman) --quadlet statt der Compose-Unit Podman-Quadlet-Dateien (/etc/containers/systemd/) einrichten --rootless Podman rootless vorbereiten (linger + Ports ab 80) --skip-runtime Docker/Podman nicht installieren (nur Projekt einrichten) -h, --help Hilfe EOF } while [ $# -gt 0 ]; do case "$1" in --with-systemd) WITH_SYSTEMD=1; shift ;; --quadlet) WITH_QUADLET=1; WITH_SYSTEMD=1; shift ;; --rootless) ROOTLESS=1; shift ;; --skip-runtime) SKIP_RUNTIME=1; shift ;; -h|--help) usage; exit 0 ;; *) die "Unbekannte Option: $1" ;; esac done [ "$(id -u)" -eq 0 ] || die "Bitte als root ausfuehren: sudo ./install.sh" # --------------------------------------------------------------------- # Distribution erkennen # --------------------------------------------------------------------- [ -r /etc/os-release ] || die "/etc/os-release nicht lesbar - Distribution unbekannt." # shellcheck disable=SC1091 . /etc/os-release OS_ID="${ID:-unknown}" OS_LIKE="${ID_LIKE:-}" OS_NAME="${PRETTY_NAME:-$OS_ID}" FAMILY="" case "$OS_ID" in debian|ubuntu|linuxmint|raspbian|pop) FAMILY=debian ;; rhel|centos|rocky|almalinux|fedora|ol|oracle|scientific) FAMILY=rhel ;; *) case " $OS_LIKE " in *debian*) FAMILY=debian ;; *rhel*|*fedora*|*centos*) FAMILY=rhel ;; esac ;; esac [ -n "$FAMILY" ] || die "Nicht unterstuetzte Distribution: $OS_NAME" printf '\n%s=== Checkmk Container-Stack - Installation ===%s\n\n' "$C_BLD" "$C_RST" log "System : $OS_NAME" log "Familie : $FAMILY" log "Projektpfad : $PROJECT_DIR" # --------------------------------------------------------------------- # Runtime installieren # --------------------------------------------------------------------- install_debian() { log "Installiere Docker CE aus dem offiziellen Docker-Repository ..." export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y ca-certificates curl gnupg tar dialog openssl if [ "$OS_ID" = debian ] || [ "$OS_ID" = ubuntu ]; then install -m 0755 -d /etc/apt/keyrings if [ ! -f /etc/apt/keyrings/docker.asc ]; then curl -fsSL "https://download.docker.com/linux/$OS_ID/gpg" -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc fi local codename="${VERSION_CODENAME:-}" [ -n "$codename" ] || codename="$(. /etc/os-release && echo "${UBUNTU_CODENAME:-stable}")" echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/$OS_ID $codename stable" \ >/etc/apt/sources.list.d/docker.list apt-get update -qq apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin else warn "Abgeleitete Distribution ($OS_NAME) - verwende die Distributionspakete." apt-get install -y docker.io docker-compose fi systemctl enable --now docker ok "Docker installiert: $(docker --version)" } install_rhel() { log "Installiere Podman ..." local PM=dnf command -v dnf >/dev/null 2>&1 || PM=yum $PM install -y podman tar dialog openssl || die "Podman-Installation fehlgeschlagen." # podman-compose besorgen (Reihenfolge: Distro-Repo -> EPEL -> pip) if ! command -v podman-compose >/dev/null 2>&1; then log "Suche podman-compose ..." if ! $PM install -y podman-compose 2>/dev/null; then if [ "$OS_ID" != fedora ]; then local rel; rel="${VERSION_ID%%.*}" log "Aktiviere EPEL ${rel} ..." $PM install -y "https://dl.fedoraproject.org/pub/epel/epel-release-latest-${rel}.noarch.rpm" 2>/dev/null || true $PM install -y podman-compose 2>/dev/null || true fi fi fi if ! command -v podman-compose >/dev/null 2>&1; then log "Versuche podman-compose per pip ..." $PM install -y python3-pip 2>/dev/null || true pip3 install --quiet podman-compose 2>/dev/null || true fi if command -v podman-compose >/dev/null 2>&1; then ok "podman-compose vorhanden: $(podman-compose --version 2>&1 | head -n1)" else warn "podman-compose konnte nicht installiert werden. Alternative: Installation ueber Quadlet ( ./install.sh --quadlet ), dafuer wird kein Compose benoetigt." fi ok "Podman installiert: $(podman --version)" # SELinux: Bind-Mounts brauchen den passenden Kontext (:Z ist im Compose gesetzt) if command -v getenforce >/dev/null 2>&1 && [ "$(getenforce)" = "Enforcing" ]; then log "SELinux ist aktiv - die Bind-Mounts sind im Compose mit ':Z' versehen." fi } if [ -z "$SKIP_RUNTIME" ]; then case "$FAMILY" in debian) install_debian ;; rhel) install_rhel ;; esac else log "Runtime-Installation uebersprungen (--skip-runtime)." fi # --------------------------------------------------------------------- # Projekt vorbereiten # --------------------------------------------------------------------- log "Bereite Projektverzeichnis vor ..." mkdir -p "$PROJECT_DIR/data/checkmk/sites" \ "$PROJECT_DIR/data/npm/data" \ "$PROJECT_DIR/data/npm/letsencrypt" \ "$PROJECT_DIR/data/npm/custom-certs" \ "$PROJECT_DIR/backups" chmod +x "$PROJECT_DIR"/scripts/*.sh "$PROJECT_DIR/install.sh" 2>/dev/null || true if [ ! -f "$PROJECT_DIR/.env" ]; then cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env" chmod 600 "$PROJECT_DIR/.env" ok ".env aus .env.example erzeugt - bitte Passwort und Site-Namen anpassen!" else log ".env ist bereits vorhanden - bleibt unveraendert." fi load_env "$PROJECT_DIR/.env" detect_runtime ok "Verwendete Runtime: $RUNTIME" # Podman: Autostart nach Reboot ohne systemd-Unit funktioniert nicht -> # Unit standardmaessig einrichten. if [ "$RUNTIME" = podman ] && [ -z "$WITH_SYSTEMD" ]; then warn "Podman hat keinen Daemon: ohne systemd-Unit starten die Container nach einem Reboot NICHT automatisch. Die Unit wird jetzt eingerichtet." WITH_SYSTEMD=1 fi # --------------------------------------------------------------------- # Rootless-Vorbereitung (optional) # --------------------------------------------------------------------- if [ -n "$ROOTLESS" ]; then log "Bereite rootless-Betrieb vor ..." echo 'net.ipv4.ip_unprivileged_port_start=80' >/etc/sysctl.d/99-checkmk-rootless.conf sysctl -q --system || true ok "Unprivilegierte Ports ab 80 erlaubt." warn "Zusaetzlich noetig: loginctl enable-linger und die Unit als '--user'-Unit einrichten (siehe README)." fi # --------------------------------------------------------------------- # systemd # --------------------------------------------------------------------- install_compose_unit() { local compose_bin detect_compose compose_bin="${COMPOSE_CMD[*]}" log "Richte systemd-Unit 'checkmk-stack.service' ein ..." cat >/etc/systemd/system/checkmk-stack.service <"/etc/containers/systemd/$(basename "$f")" done systemctl daemon-reload ok "Quadlet-Units geschrieben. Start: systemctl start checkmk nginx-proxy-manager" log "Die Units starten durch 'WantedBy=multi-user.target' automatisch nach einem Reboot." } if [ -n "$WITH_SYSTEMD" ]; then if [ -n "$WITH_QUADLET" ]; then [ "$RUNTIME" = podman ] || die "--quadlet ist nur mit Podman moeglich." install_quadlet_units else install_compose_unit fi fi # --------------------------------------------------------------------- # Firewall-Hinweise # --------------------------------------------------------------------- print_firewall_hint() { if command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then cat <<'EOF' Firewall (firewalld) - empfohlene Regeln: firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --permanent --add-port=8000/tcp # Agent-Receiver # Admin-Oberflaeche des Proxy Managers nur aus dem Admin-Netz: firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.0/24 port port=81 protocol=tcp accept' # Checkmk-Port 5000 NICHT nach aussen oeffnen (nur ueber den Proxy) firewall-cmd --reload EOF elif command -v ufw >/dev/null 2>&1; then cat <<'EOF' Firewall (ufw) - empfohlene Regeln: ufw allow 80/tcp ufw allow 443/tcp ufw allow 8000/tcp # Agent-Receiver ufw allow from 10.0.0.0/24 to any port 81 proto tcp # Proxy-Manager-Admin # Port 5000 (Checkmk direkt) bleibt zu - Zugriff nur ueber den Proxy EOF fi } print_firewall_hint cat <