Files
2026-08-20 10:33:59 +02:00

308 lines
11 KiB
Bash
Executable File

#!/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 <benutzer>
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 <<EOF
[Unit]
Description=Checkmk + NGINX Proxy Manager (Container-Stack)
Documentation=file://$PROJECT_DIR/README.md
Wants=network-online.target
After=network-online.target
$([ "$RUNTIME" = docker ] && echo "Requires=docker.service" || true)
$([ "$RUNTIME" = docker ] && echo "After=docker.service" || true)
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=$PROJECT_DIR
EnvironmentFile=$PROJECT_DIR/.env
TimeoutStartSec=0
ExecStart=/bin/sh -c '$compose_bin up -d'
ExecStartPost=$PROJECT_DIR/scripts/cmk-manage.sh start-all-sites
ExecStop=/bin/sh -c '$compose_bin down'
ExecReload=/bin/sh -c '$compose_bin up -d'
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable checkmk-stack.service
ok "Unit aktiviert. Steuerung: systemctl start|stop|status checkmk-stack"
}
install_quadlet_units() {
log "Richte Podman-Quadlet-Units ein (/etc/containers/systemd/) ..."
[ -d /etc/containers/systemd ] || mkdir -p /etc/containers/systemd
local f
for f in "$PROJECT_DIR"/systemd/quadlet/*.container; do
sed -e "s|__PROJECT_DIR__|$PROJECT_DIR|g" \
-e "s|__CMK_IMAGE__|${CMK_IMAGE_REPO:-checkmk/check-mk-raw}:${CMK_IMAGE_TAG:-2.3.0-latest}|g" \
-e "s|__NPM_IMAGE__|${NPM_IMAGE:-jc21/nginx-proxy-manager:2}|g" \
-e "s|__CMK_SITE_ID__|${CMK_SITE_ID:-cmk}|g" \
-e "s|__CMK_CONTAINER_NAME__|${CMK_CONTAINER_NAME:-checkmk}|g" \
-e "s|__NPM_CONTAINER_NAME__|${NPM_CONTAINER_NAME:-nginx-proxy-manager}|g" \
"$f" >"/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 <<EOF
${C_BLD}Installation abgeschlossen.${C_RST}
Naechste Schritte:
1) Konfiguration anpassen:
\$EDITOR $PROJECT_DIR/.env (CMK_SITE_ID, CMK_PASSWORD, TZ ...)
2) Stack starten:
$PROJECT_DIR/scripts/cmk-manage.sh up
3) NGINX Proxy Manager oeffnen:
http://$(primary_ip):81 Erstlogin: admin@example.com / changeme
4) Verwaltung / Backup / Migration - ncurses-Oberflaeche:
$PROJECT_DIR/scripts/cmk-manage.sh gui
Alles Weitere steht in der README.md.
EOF