Files
docker-podman-installation-…/README.md
duffyduckandClaude Opus 5 1693330162 Terminal-Browser, konfigurierbarer Admin-Port und Einstellungsmenue
Der NGINX Proxy Manager laesst sich jetzt auch dann einrichten, wenn
seine Oberflaeche auf Port 81 aus dem Netz nicht erreichbar ist.

browser
  Terminal-Browser in einem eigenen Container, gestartet mit
  "run --rm -it --network host" - damit erreicht er 127.0.0.1 genau wie
  der Proxy Manager selbst. Engines: browsh und carbonyl (rendern einen
  echten Browser und koennen JavaScript, das die Adminoberflaeche
  benoetigt) sowie links2/w3m/lynx und eine Shell mit curl/jq/openssl
  fuer Diagnose. Werkzeug-Image unter containers/browser/.
  Bewusst kein Compose-Dienst: ein Browser ist interaktiv, und
  podman-compose behandelt Profile unzuverlaessig.

npm-port
  Port der Adminoberflaeche frei waehlbar. Das Image bindet fest auf 81
  ("listen 81 default;"), eine Umgebungsvariable dafuer gibt es in 2.15.1
  noch nicht. Ein abweichender Port wird deshalb ueber den nginx-
  Erweiterungspunkt /data/nginx/custom/http.conf bereitgestellt. Nur der
  markierte Block wird verwaltet, eigene Eintraege bleiben erhalten.
  Port 81 lauscht weiterhin lokal und ist per Firewall zu sperren.

config
  Alle Werte der .env sind menuegefuehrt bzw. ueber config get/set
  aenderbar - der Editor bleibt als Menuepunkt erhalten. Geprueft wird
  beim Setzen: Portbereich und Kollisionen, Site-Namen, vollqualifizierte
  Image-Namen, installierte Runtime, Zahlen- und URL-Felder.

Fehlerbehebungen
  - ui_*-Funktionen initialisieren sich selbst; eine von aussen gesetzte
    UI_BIN fuehrte unter "set -u" zum Abbruch.
  - Eine nicht installierte CMK_RUNTIME machte das gesamte Werkzeug
    unbenutzbar, auch den Aufruf zum Korrigieren. Jetzt wird gewarnt und
    selbst gesucht.
  - env_set setzt Werte mit Leerzeichen in Anfuehrungszeichen und laesst
    optional leere Werte zu.

README auf 22 Kapitel erweitert: Kapitel 11 (Terminal-Browser inkl.
NPM-API als Fallback fuer den Zertifikats-Upload), Kapitel 12 (Admin-Port)
und Abschnitt 14.3 (Einstellungsmenue).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 10:48:42 +02:00

56 KiB
Raw Permalink Blame History

Checkmk im Container Docker (Debian) & Podman (RHEL) mit NGINX Proxy Manager

Vollständige, produktionstaugliche Container-Installation von Checkmk mit NGINX Proxy Manager als HTTPS-Terminierung (Let's Encrypt oder selbstsigniert), inklusive Werkzeugen für Backup, Restore und die Migration bestehender Sites von einer Direktinstallation ohne dass die Agents neu eingerichtet werden müssen.


Inhaltsverzeichnis

  1. Überblick & Architektur
  2. Verzeichnisstruktur
  3. Voraussetzungen & Ports
  4. Installation auf Debian/Ubuntu (Docker)
  5. Installation auf RHEL/Rocky/Alma/Fedora (Podman)
  6. Autostart nach einem Neustart des Hosts (Podman)
  7. Konfiguration (.env)
  8. Checkmk-Image beschaffen (Raw, Enterprise & Co.)
  9. Erststart
  10. HTTPS einrichten Let's Encrypt oder selbstsigniert
  11. Proxy Manager lokal einrichten (Terminal-Browser)
  12. Adminoberfläche auf einen anderen Port legen
  13. Firewall
  14. Verwaltung: cmk-manage.sh (CLI und ncurses-Oberfläche)
  15. Backup
  16. Restore
  17. Migration einer Direktinstallation (migrate_creator.sh)
  18. Mehrere Sites in einem Container
  19. Checkmk aktualisieren
  20. Fehlersuche
  21. Sicherheitshinweise
  22. Deinstallation

1. Überblick & Architektur

                    Internet / LAN
                          |
                     :80  :443  :81
                          |
        +-----------------------------------+
        |  NGINX Proxy Manager (Container)  |   network_mode: host
        |  - Let's Encrypt ODER self-signed |
        |  - Weboberfläche auf Port 81      |
        +-----------------------------------+
                          |  http://127.0.0.1:5000
                          v
        +-----------------------------------+
        |  Checkmk / OMD (Container)        |   network_mode: host
        |  :5000  Web-GUI (Apache)          |
        |  :8000  Agent-Receiver            |   <-- Agents (cmk-agent-ctl)
        |  :6557  Livestatus (optional)     |
        +-----------------------------------+
                          |
             Bind-Mount: ./data/checkmk/sites  ->  /omd/sites

Bewusste Entwurfsentscheidungen

Punkt Umsetzung Grund
Checkmk im Host-Netzwerk network_mode: host, keine ports:-Angaben Agents, SNMP-Traps, ICMP und der Agent-Receiver arbeiten ohne NAT; die Quell-IP der überwachten Hosts bleibt erhalten
NGINX Proxy Manager ebenfalls im Host-Netzwerk network_mode: host erreicht das Checkmk-Backend direkt über 127.0.0.1:5000; kein Bridge-Netz, keine host-gateway-Tricks nötig funktioniert unter Docker und Podman identisch
Keine Named Volumes ausschließlich Bind-Mounts nach ./data/ alle Daten liegen sichtbar im Projektverzeichnis, einfach zu sichern, zu kopieren und zu prüfen
Eine Compose-Datei für beides docker compose und podman-compose identische Bedienung auf Debian und RHEL
:Z an den Bind-Mounts SELinux-Relabeling nötig unter RHEL; unter Debian/Docker wirkungslos (kein Fehler)

2. Verzeichnisstruktur

.
├── README.md
├── docker-compose.yml               # für Docker UND Podman
├── .env.example                     # Vorlage -> .env
├── install.sh                       # Installation Docker (Debian) / Podman (RHEL)
│
├── scripts/
│   ├── cmk-manage.sh                # Stack, Backup, Restore, Import + ncurses-GUI
│   ├── migrate_creator.sh           # -> auf den QUELLSERVER kopieren
│   └── lib/
│       └── common.sh                # gemeinsame Funktionen + TUI-Helfer
│
├── containers/
│   └── browser/
│       └── Containerfile        # Werkzeug-Image: Textbrowser, curl, jq, openssl
│
├── systemd/
│   ├── checkmk-stack.service.example # Compose-basierte Unit (Autostart)
│   └── quadlet/
│       ├── checkmk.container         # Podman-Quadlet (Alternative)
│       └── nginx-proxy-manager.container
│
├── data/                            # ALLE Nutzdaten (Bind-Mounts)
│   ├── checkmk/sites/               # -> /omd/sites   (komplette OMD-Sites)
│   └── npm/
│       ├── data/                    # -> /data            (NPM-Konfiguration/DB)
│       ├── letsencrypt/             # -> /etc/letsencrypt (Zertifikate)
│       └── custom-certs/            # selbstsignierte Zertifikate zum Hochladen
│
├── backups/                         # Backups und Migrations-Bundles (*.tar.gz)
└── images/                          # heruntergeladene Checkmk-Image-Tarballs

3. Voraussetzungen & Ports

  • 64-Bit-Linux, mind. 2 CPU-Kerne, 4 GB RAM (Empfehlung: 4 Kerne, 8 GB)
  • Plattenplatz: Faustregel 1 GB je 100 überwachte Hosts und Jahr, plus Backups
  • root-Rechte
  • Ausgehender Internetzugang für den Image-Download

Belegte Ports (Host-Netzwerk!)

Port Dienst Erreichbar von
80/tcp NGINX Proxy Manager HTTP, Let's-Encrypt-Challenge Internet/LAN
443/tcp NGINX Proxy Manager HTTPS Internet/LAN
81/tcp NGINX Proxy Manager Adminoberfläche (Vorgabe; per npm-port änderbar) nur Admin-Netz!
5000/tcp Checkmk Apache (Backend) nur localhost nicht freigeben
8000/tcp Checkmk Agent-Receiver (TLS-registrierte Agents) überwachte Hosts
6557/tcp Livestatus (nur bei CMK_LIVESTATUS_TCP=on) verteilte Sites

Wichtig: Da beide Container im Host-Netzwerk laufen, dürfen die Ports 80, 443 und 81 auf dem Host nicht bereits belegt sein (z. B. durch einen installierten Apache/NGINX). Prüfen mit ss -tlnp | grep -E ':(80|81|443|5000)\b'.


4. Installation auf Debian/Ubuntu (Docker)

# Projekt an den gewünschten Ort legen
sudo mkdir -p /opt/checkmk-stack
sudo cp -r ./* ./.env.example /opt/checkmk-stack/
cd /opt/checkmk-stack

# Docker CE + Compose-Plugin installieren, Projekt vorbereiten
sudo ./install.sh --with-systemd

install.sh erledigt dabei:

  1. Docker-Repository von download.docker.com einbinden (GPG-Key + Sources-Liste)
  2. docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin, docker-compose-plugin installieren
  3. dialog, openssl, tar, curl installieren (für die ncurses-Oberfläche)
  4. systemctl enable --now docker
  5. Verzeichnisse unter data/ und backups/ anlegen, .env aus .env.example erzeugen
  6. optional die systemd-Unit checkmk-stack.service einrichten

Anschließend:

sudo $EDITOR /opt/checkmk-stack/.env     # mindestens CMK_PASSWORD und CMK_SITE_ID

# Image festlegen (Raw geht ohne Anmeldung, Enterprise siehe Kapitel 8)
sudo ./scripts/cmk-manage.sh image pull --edition raw --version 2.3.0-latest

sudo ./scripts/cmk-manage.sh up
sudo ./scripts/cmk-manage.sh status

Unter Docker sorgt bereits restart: unless-stopped dafür, dass die Container nach einem Reboot wieder starten (der Docker-Daemon startet sie). Die systemd-Unit ist trotzdem sinnvoll, weil sie zusätzlich alle Sites startet (siehe Kapitel 18).


5. Installation auf RHEL/Rocky/Alma/Fedora (Podman)

Auf Red-Hat-Systemen steht Docker nicht zur Verfügung hier wird Podman verwendet. Die Compose-Datei ist dieselbe.

sudo mkdir -p /opt/checkmk-stack
sudo cp -r ./* ./.env.example /opt/checkmk-stack/
cd /opt/checkmk-stack

sudo ./install.sh --with-systemd

install.sh installiert dabei:

  1. podman, tar, dialog, openssl
  2. podman-compose in dieser Reihenfolge versucht: Distributions-Repository → EPEL → pip3 install podman-compose
  3. richtet die systemd-Unit ein (bei Podman immer, siehe nächstes Kapitel)

Manuell entspricht das:

sudo dnf install -y podman podman-compose tar dialog openssl
# Falls podman-compose nicht im Repo ist:
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install -y podman-compose

Starten:

sudo $EDITOR /opt/checkmk-stack/.env

# Image beschaffen - bei Enterprise mit Zugangsdaten, siehe Kapitel 8
sudo ./scripts/cmk-manage.sh image pull --edition enterprise --version 2.3.0p23 \
     --user <benutzer> --password <kennwort>

sudo ./scripts/cmk-manage.sh up          # nutzt automatisch podman-compose
sudo ./scripts/cmk-manage.sh status

Auf RHEL unbedingt Kapitel 8.2 lesen: kurze Image-Namen und podman import statt podman load sind die beiden Ursachen fuer „Image unbekannt“.

SELinux

Die Bind-Mounts sind in docker-compose.yml mit :Z versehen, Podman setzt dadurch automatisch den Kontext container_file_t. Falls Zugriffe dennoch scheitern:

sudo semanage fcontext -a -t container_file_t "/opt/checkmk-stack/data(/.*)?"
sudo restorecon -Rv /opt/checkmk-stack/data
sudo ausearch -m avc -ts recent          # AVC-Meldungen prüfen

6. Autostart nach einem Neustart des Hosts (Podman)

Das ist bei Podman der wichtigste Unterschied zu Docker: Podman hat keinen Daemon. Die Angabe restart: unless-stopped in der Compose-Datei wirkt deshalb nicht über einen Reboot hinweg. Der Autostart muss über systemd erfolgen. Es gibt zwei erprobte Wege.

Variante A Compose-basierte systemd-Unit (empfohlen, identisch zu Docker)

Wird von ./install.sh --with-systemd automatisch erzeugt und aktiviert. Manuell:

sudo tee /etc/systemd/system/checkmk-stack.service >/dev/null <<'EOF'
[Unit]
Description=Checkmk + NGINX Proxy Manager (Container-Stack)
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/checkmk-stack
EnvironmentFile=/opt/checkmk-stack/.env
TimeoutStartSec=0
ExecStart=/bin/sh -c '/usr/bin/podman-compose up -d'
ExecStartPost=/opt/checkmk-stack/scripts/cmk-manage.sh start-all-sites
ExecStop=/bin/sh -c '/usr/bin/podman-compose down'

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now checkmk-stack.service
sudo systemctl status checkmk-stack.service

Prüfen, dass es einen Reboot übersteht:

sudo systemctl is-enabled checkmk-stack     # -> enabled
sudo reboot
# nach dem Neustart:
sudo podman ps
sudo /opt/checkmk-stack/scripts/cmk-manage.sh status

ExecStartPost ruft start-all-sites auf. Das ist nötig, weil der Checkmk-Entrypoint nur die in CMK_SITE_ID eingetragene Site startet bei mehreren Sites blieben die übrigen sonst gestoppt.

Variante B Podman-Quadlet (ab Podman 4.4, ohne Compose)

Quadlet erzeugt aus einfachen Beschreibungsdateien echte systemd-Units. Vorteil: kein podman-compose nötig, saubere Abhängigkeiten, natives Podman.

sudo ./install.sh --quadlet

Das schreibt (mit den Werten aus der .env) nach /etc/containers/systemd/:

  • checkmk.container
  • nginx-proxy-manager.container

Danach:

sudo systemctl daemon-reload
sudo systemctl start checkmk nginx-proxy-manager
sudo systemctl status checkmk

Die Units werden durch WantedBy=multi-user.target default.target beim Systemstart automatisch aktiviert ein separates systemctl enable ist bei Quadlet nicht nötig (und auch nicht möglich, da die Units generiert werden).

Vorlagen liegen unter systemd/quadlet/.

Variante C rootless Podman (optional, erhöhter Aufwand)

sudo ./install.sh --rootless
sudo loginctl enable-linger checkmk           # Dienstbenutzer
# Unit als Benutzer-Unit:
mkdir -p ~/.config/systemd/user
cp systemd/checkmk-stack.service.example ~/.config/systemd/user/checkmk-stack.service
systemctl --user daemon-reload
systemctl --user enable --now checkmk-stack

--rootless setzt net.ipv4.ip_unprivileged_port_start=80, damit die Ports 80/443 ohne root gebunden werden dürfen. loginctl enable-linger sorgt dafür, dass die Benutzer-Units auch ohne Anmeldung nach einem Reboot starten.

Hinweis: Im rootless-Betrieb werden die UIDs der Site-Benutzer über User-Namespaces abgebildet. Die Dateien unter data/checkmk/sites gehören dann Subordinate-UIDs (z. B. 165536). Das ist normal, erschwert aber die Arbeit mit den Dateien vom Host aus. Für Migrationen wird der rootful Betrieb empfohlen.


7. Konfiguration (.env)

cp .env.example .env
chmod 600 .env
$EDITOR .env

Die wichtigsten Schalter:

Variable Bedeutung
CMK_RUNTIME leer = automatische Erkennung, sonst docker oder podman
CMK_IMAGE das tatsaechlich verwendete Image, immer vollqualifiziert siehe Kapitel 8
CMK_EDITION, CMK_VERSION nur Vorgaben fuer den Image-Downloader
CMK_REGISTRY_USER/-PASSWORD Anmeldung an registry.checkmk.com (Enterprise)
CMK_DOWNLOAD_USER/-PASSWORD Anmeldung am Checkmk-Downloadportal
CMK_SITE_ID Site, die der Container anlegt bzw. beim Start hochfährt
CMK_PASSWORD Startpasswort für den Benutzer cmkadmin (nur bei Neuanlage)
CMK_LIVESTATUS_TCP on öffnet Port 6557 für verteilte Überwachung
MAIL_RELAY_HOST SMTP-Relay für Benachrichtigungen
TZ Zeitzone, z. B. Europe/Berlin
NPM_ADMIN_PORT Port der Proxy-Manager-Oberfläche (Vorgabe 81) nur über npm-port bzw. das Menü ändern
NPM_ADMIN_URL Startseite des Terminal-Browsers; leer = automatisch aus NPM_ADMIN_PORT
BACKUP_DIR Ablage für Backups/Bundles (Vorgabe ./backups)
CERT_DOMAIN, CERT_DAYS Vorgaben für selbstsignierte Zertifikate

7.1 Wer liest die .env und warum gibt es sie zusätzlich zum Skript?

Die .env ist die einzige Konfigurationsdatei. Es gibt bewusst keine zweite Konfiguration im Verwaltungsskript:

                    .env  (einzige Quelle der Wahrheit)
                      |
      +---------------+----------------+------------------+
      |               |                |                  |
docker-compose    systemd-Unit    cmk-manage.sh      migrate_creator.sh
(Variablen-       (EnvironmentFile)  (source)         (unabhaengig, laeuft
 ersetzung)                                            auf dem Quellserver)
  • Gelesen wird sie von compose, von der systemd-Unit und vom Skript.
  • Geschrieben wird sie durch das Skript entweder gezielt (image … setzt CMK_IMAGE, import --set-default-site setzt CMK_SITE_ID, npm-port setzt NPM_ADMIN_PORT) oder über das Einstellungsmenü bzw. config set (siehe Kapitel 14). Ein Editor ist damit nicht mehr nötig, bleibt aber als Menüpunkt erhalten.
  • Das Skript selbst haelt nur Rueckfallwerte fuer den Fall, dass ein Schluessel in der .env fehlt (in scripts/lib/common.sh, Funktion load_env). Es ueberschreibt niemals einen gesetzten Wert.

Kurz: die .env sagt was laeuft, das Skript macht etwas damit. Doppelt gepflegt werden muss nichts.


8. Checkmk-Image beschaffen (Raw, Enterprise & Co.)

8.1 Welche Edition liegt wo?

Das ist die haeufigste Stolperfalle: die Enterprise-Edition liegt nicht auf Docker Hub. Im Namensraum checkmk auf Docker Hub gibt es ausschliesslich:

Edition (CMK_EDITION) Bezugsquelle Anmeldung
raw (bis 2.4) docker.io/checkmk/check-mk-raw nein
community (ab 2.5, Nachfolger von raw) docker.io/checkmk/check-mk-community nein
cloud docker.io/checkmk/check-mk-cloud nein
managed (bis 2.4) docker.io/checkmk/check-mk-managed nein
pro (ab 2.5, Nachfolger von enterprise) docker.io/checkmk/check-mk-pro nein
ultimate, ultimatemt (ab 2.5) docker.io/checkmk/check-mk-ultimate[mt] nein
enterprise (2.0 2.4) registry.checkmk.com/enterprise/check-mk-enterprise oder Image-Tarball aus dem Kundenportal ja
free (historisch, bis 2.1) docker.io/checkmk/check-mk-free nein

Ab Checkmk 2.5 wurden die Editionen umbenannt (Raw → Community, Enterprise → Pro, Managed → Ultimate MT); diese Images liegen wieder offen auf Docker Hub. Wer also eine 2.5 oder neuer einsetzt, nimmt einfach pro. Fuer 2.2/2.3/2.4-Enterprise fuehrt nur der Weg ueber registry.checkmk.com oder den Tarball.

Frei herunterladbar heisst nicht lizenzfrei der Lizenzschluessel wird anschliessend in Checkmk selbst hinterlegt.

8.2 Zwei Podman-Fallstricke (genau die aus der Praxis)

1. Kurze Image-Namen. Podman kennt keine Vorgabe-Registry. Kurze Namen wie checkmk/check-mk-enterprise:2.3.0p23 werden ueber unqualified-search-registries aus /etc/containers/registries.conf aufgeloest auf RHEL steht dort registry.access.redhat.com an erster Stelle. Podman sucht das Image also bei Red Hat, findet es nicht und meldet image not known bzw. fragt interaktiv nach. Deshalb steht in .env und docker-compose.yml konsequent der vollqualifizierte Name:

CMK_IMAGE=registry.checkmk.com/enterprise/check-mk-enterprise:2.3.0p23

Aktuelle Auflösungsreihenfolge ansehen:

grep -A3 unqualified-search-registries /etc/containers/registries.conf

2. import statt load. Ein heruntergeladener Image-Tarball wird mit load eingespielt:

Kommando Erwartet Ergebnis
podman import datei.tar.gz ein Dateisystem-Archiv (rootfs) Image ohne Entrypoint, ohne Umgebung, ohne Tag → unbrauchbar, „Image unbekannt“
podman load -i datei.tar.gz ein Image-Archiv (docker save/OCI) vollstaendiges Image inkl. Metadaten und Tag ✔

Ein mit import erzeugtes Fehl-Image wieder loswerden:

podman images | grep '<none>'
podman rmi <image-id>

cmk-manage.sh image load prueft das Archiv vorher auf manifest.json bzw. oci-layout und weist ein falsches Archiv mit genau diesem Hinweis ab.

8.3 Zugangsdaten in der .env hinterlegen

CMK_EDITION=enterprise
CMK_VERSION=2.3.0p23

# Bezugsweg 1 - private Registry
CMK_REGISTRY=registry.checkmk.com
CMK_REGISTRY_USER=<benutzer-aus-dem-kundenportal>
CMK_REGISTRY_PASSWORD=<kennwort>

# Bezugsweg 2 - Tarball vom Downloadportal
CMK_DOWNLOAD_BASEURL=https://download.checkmk.com/checkmk
CMK_DOWNLOAD_USER=<benutzer>
CMK_DOWNLOAD_PASSWORD=<kennwort>

Die Zugangsdaten stammen aus dem Checkmk-Kundenportal (portal.checkmk.com). Die .env sollte deshalb chmod 600 haben install.sh setzt das.

8.4 Image holen drei Wege

a) Aus einer Registry (empfohlen)

# frei verfuegbar, ohne Anmeldung
sudo ./scripts/cmk-manage.sh image pull --edition raw --version 2.3.0-latest

# Enterprise mit Anmeldung an registry.checkmk.com
sudo ./scripts/cmk-manage.sh image pull --edition enterprise --version 2.3.0p23 \
     --user <benutzer> --password <kennwort>

b) Image-Tarball vom Downloadportal (mit Zugangsdaten)

sudo ./scripts/cmk-manage.sh image download --edition enterprise --version 2.3.0p23 \
     --user <benutzer> --password <kennwort>

Der Downloader probiert die ueblichen Dateinamen unter <CMK_DOWNLOAD_BASEURL>/<version>/ durch (check-mk-enterprise-<version>.docker.tar.gz und check-mk-enterprise-docker-<version>.tar.gz). Falls Checkmk das Schema geaendert hat, laesst sich die vollstaendige URL direkt vorgeben:

sudo ./scripts/cmk-manage.sh image download \
     --url 'https://download.checkmk.com/checkmk/2.3.0p23/check-mk-enterprise-2.3.0p23.docker.tar.gz' \
     --user <benutzer> --password <kennwort>

Die Zugangsdaten werden per temporaerer .netrc-Datei an curl uebergeben und tauchen damit nicht in der Prozessliste auf.

c) Bereits heruntergeladene Datei einspielen

Wer die Datei im Browser aus dem Kundenportal geladen hat:

sudo ./scripts/cmk-manage.sh image load --file /root/check-mk-enterprise-2.3.0p23.docker.tar.gz

In allen drei Faellen ermittelt das Skript den tatsaechlichen Image-Namen (bei load z. B. localhost/checkmk/check-mk-enterprise:2.3.0p23) und traegt ihn als CMK_IMAGE in die .env ein. Danach:

sudo ./scripts/cmk-manage.sh up

8.5 Nachsehen, was gilt

./scripts/cmk-manage.sh image status     # konfiguriertes + lokale Images
./scripts/cmk-manage.sh image list       # nur lokale Checkmk-Images
./scripts/cmk-manage.sh image use localhost/checkmk/check-mk-enterprise:2.3.0p23

image status warnt ausdruecklich, wenn CMK_IMAGE ein kurzer Name ohne Registry ist.

In der ncurses-Oberflaeche liegt derselbe Ablauf unter dem Menuepunkt „Checkmk-Image beschaffen/auswaehlen“ (Edition auswaehlen → Version → Zugangsdaten → holen).


9. Erststart

sudo ./scripts/cmk-manage.sh up
sudo ./scripts/cmk-manage.sh status

Ausgabe (Beispiel):

Container
  checkmk                  läuft
  nginx-proxy-manager      läuft

Sites im Container
  SITE                 VERSION            STATUS
  cmk                  2.3.0p23.cre       läuft

Zugang
  Checkmk (direkt)        : http://10.0.0.5:5000/cmk/
  Checkmk (über Proxy)    : https://<FQDN>/cmk/
  Agent-Receiver          : 10.0.0.5:8000
  NGINX Proxy Manager     : http://10.0.0.5:81/  (Erstlogin: admin@example.com / changeme)

Der Port der Adminoberfläche folgt NPM_ADMIN_PORT aus der .env; die Ausgabe zeigt immer den tatsächlich eingestellten Wert.

Anmeldung an Checkmk: Benutzer cmkadmin, Passwort aus CMK_PASSWORD.


10. HTTPS einrichten Let's Encrypt oder selbstsigniert

9.1 NGINX Proxy Manager vorbereiten

  1. http://<server>:81 aufrufen bzw. den in NPM_ADMIN_PORT gesetzten Port (siehe Kapitel 12); ist der Port im Netz gesperrt, hilft der Terminal-Browser aus Kapitel 11
  2. Erstanmeldung: admin@example.com / changeme
  3. Sofort E-Mail-Adresse und Passwort ändern (wird beim ersten Login erzwungen)

9.2 Proxy-Host für Checkmk anlegen

Hosts → Proxy Hosts → Add Proxy Host

Feld Wert
Domain Names checkmk.example.com (bzw. der interne Name)
Scheme http
Forward Hostname / IP 127.0.0.1
Forward Port 5000
Block Common Exploits ein
Websockets Support ein (für die Livedaten der Oberfläche)

Reiter Advanced (empfohlen, damit Checkmk die echte Client-IP sieht und große Agent-Uploads funktionieren):

client_max_body_size 0;
proxy_read_timeout 300s;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

9.3 Variante A Let's Encrypt (öffentlich erreichbarer Server)

Voraussetzungen: der DNS-Name zeigt öffentlich auf diesen Server und Port 80 ist aus dem Internet erreichbar (HTTP-01-Challenge).

Im Proxy-Host, Reiter SSL:

  • SSL Certificate → Request a new SSL Certificate
  • Force SSL ein
  • HTTP/2 Support ein
  • HSTS Enabled nach Bedarf
  • E-Mail-Adresse angeben, Nutzungsbedingungen bestätigen → Save

Die Erneuerung übernimmt der Proxy Manager automatisch; die Zertifikate liegen im Bind-Mount data/npm/letsencrypt/ und sind damit im Projektverzeichnis gesichert.

Bei interner DNS-Zone ohne öffentlichen Zugang: DNS-Challenge verwenden (SSL → Use a DNS Challenge → Provider auswählen, API-Token hinterlegen).

9.4 Variante B Selbstsigniertes Zertifikat (interne Umgebung)

Erzeugen:

sudo ./scripts/cmk-manage.sh cert \
     --domain checkmk.intern.example \
     --alt 10.0.0.5 --alt checkmk \
     --days 3650

Ergebnis in data/npm/custom-certs/checkmk.intern.example/:

  • privkey.pem privater Schlüssel
  • fullchain.pem Zertifikat (mit SAN für alle angegebenen Namen/IPs)

Einbinden:

  1. SSL Certificates → Add SSL Certificate → Custom
  2. Name vergeben, privkey.pem als Certificate Key, fullchain.pem als Certificate hochladen
  3. Im Proxy-Host unter SSL dieses Zertifikat auswählen, Force SSL und HTTP/2 aktivieren

Damit die Checkmk-Agents und Browser dem Zertifikat vertrauen, muss fullchain.pem auf den Clients als vertrauenswürdiges Zertifikat installiert werden (Windows: Computerzertifikate → Vertrauenswürdige Stammzertifizierungsstellen; Linux: /usr/local/share/ca-certificates/ + update-ca-certificates). Für die reine Agent-Kommunikation über Port 8000 ist das nicht nötig dort verwendet Checkmk eine eigene, site-interne CA.

Die ncurses-Oberfläche bietet denselben Ablauf unter „Selbstsigniertes Zertifikat erzeugen“.


11. Proxy Manager lokal einrichten (Terminal-Browser)

Wenn Port 81 aus dem Netz nicht erreichbar ist, muss die Adminoberfläche des NGINX Proxy Managers auf der Maschine selbst bedient werden. Dafür startet cmk-manage.sh browser einen weiteren Container im Host-Netzwerk der erreicht 127.0.0.1:81 genauso wie der Proxy Manager selbst.

sudo ./scripts/cmk-manage.sh browser

Das ist bewusst kein Dienst in der docker-compose.yml: ein Browser ist ein interaktives Programm mit Terminal, kein Hintergrunddienst. Er wird mit run --rm -it gestartet und verschwindet beim Beenden wieder rückstandslos.

11.1 Warum kein lynx

Die Adminoberfläche des Proxy Managers ist eine JavaScript-Anwendung. Klassische Textbrowser können sie nicht darstellen man sieht eine leere Seite. Es gibt deshalb zwei Engines, die einen vollwertigen Browser im Terminal rendern:

Engine Basis JavaScript Proxy Manager bedienbar
browsh Firefox ja ja Vorgabe, gepflegt
carbonyl Chromium ja ja schönere Darstellung, Stand 2023
links (links2) Textbrowser nein nein
w3m Textbrowser nein nein
lynx Textbrowser nein nein
shell Bash + curl/jq/openssl für Diagnose und die API

Die Textbrowser sind trotzdem eingebaut, weil sie für schnelle Prüfungen praktisch sind. Wählt man sie, warnt das Skript ausdrücklich.

11.2 Bedienung

# Vorgabe: browsh auf http://127.0.0.1:81
sudo ./scripts/cmk-manage.sh browser

# andere Engine oder andere Seite
sudo ./scripts/cmk-manage.sh browser --engine carbonyl
sudo ./scripts/cmk-manage.sh browser --engine links --url http://127.0.0.1:5000/cmk/

# Shell mit Netzwerkwerkzeugen im Host-Netzwerk
sudo ./scripts/cmk-manage.sh browser --engine shell

Tastenbelegung in browsh:

Taste Wirkung
Strg+L Adresszeile
Strg+T neuer Tab
Strg+W Tab schließen
Strg+Q beenden

Beim ersten Aufruf einer Textbrowser- oder shell-Engine baut das Skript ein kleines Werkzeug-Image (Debian slim mit links2, w3m, lynx, curl, jq, openssl, rund 170 MB). Vorab bauen auch ohne Terminal, etwa im Installationsskript:

sudo ./scripts/cmk-manage.sh browser --build-only

browsh und carbonyl werden dagegen als fertige Images geladen; die Namen stehen in der .env (BROWSH_IMAGE, CARBONYL_IMAGE) und sind vollqualifiziert, damit Podman sie nicht bei registry.access.redhat.com sucht.

In der ncurses-Oberfläche liegt alles unter „Terminal-Browser (Proxy Manager lokal bedienen)".

11.3 Grenze: Datei-Upload

Ein Terminal-Browser kann keinen Dateiauswahl-Dialog des Betriebssystems öffnen. Für Let's Encrypt ist das egal (dort werden nur Formularfelder ausgefüllt), aber das Hochladen eines selbstsignierten Zertifikats (SSL Certificates → Custom) funktioniert so nicht zuverlässig.

Für genau diesen Fall führt der Weg über die REST-Schnittstelle des Proxy Managers. Zertifikat wie in Kapitel 10.4 erzeugen, dann:

NPM=http://127.0.0.1:81
CERTDIR=./data/npm/custom-certs/checkmk.intern.example

# 1) Anmelden und Token holen
TOKEN=$(curl -s -X POST "$NPM/api/tokens" \
  -H 'Content-Type: application/json' \
  -d '{"identity":"admin@example.com","secret":"<kennwort>"}' | jq -r .token)

# 2) Zertifikatseintrag anlegen (provider "other" = eigenes Zertifikat)
CERT_ID=$(curl -s -X POST "$NPM/api/nginx/certificates" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"provider":"other","nice_name":"checkmk-selfsigned","domain_names":["checkmk.intern.example"]}' \
  | jq -r .id)

# 3) Schlüssel und Zertifikat hochladen
curl -s -X POST "$NPM/api/nginx/certificates/$CERT_ID/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -F "certificate=@$CERTDIR/fullchain.pem" \
  -F "certificate_key=@$CERTDIR/privkey.pem"

# 4) Proxy-Host für Checkmk anlegen
curl -s -X POST "$NPM/api/nginx/proxy-hosts" \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d "{\"domain_names\":[\"checkmk.intern.example\"],
       \"forward_scheme\":\"http\",
       \"forward_host\":\"127.0.0.1\",
       \"forward_port\":5000,
       \"certificate_id\":$CERT_ID,
       \"ssl_forced\":true,
       \"http2_support\":true,
       \"block_exploits\":true,
       \"allow_websocket_upgrade\":true,
       \"advanced_config\":\"client_max_body_size 0;\",
       \"enabled\":true,
       \"meta\":{}}"

curl und jq sind im Werkzeug-Image enthalten, falls der Host sie nicht hat:

sudo ./scripts/cmk-manage.sh browser --engine shell

Beim allerersten Login erzwingt der Proxy Manager das Ändern von E-Mail-Adresse und Kennwort. Das geht am einfachsten im Browser (cmk-manage.sh browser); danach funktioniert die API mit den neuen Daten.

11.4 Alternative: SSH-Tunnel

Falls SSH auf die Maschine möglich ist, ist der Tunnel der bequemste Weg dann bedient man die Oberfläche im gewohnten Browser:

ssh -N -L 8081:127.0.0.1:81 benutzer@checkmk-server
# danach lokal:  http://127.0.0.1:8081

Das ändert nichts an der Firewall: Port 81 bleibt von außen dicht, der Zugriff läuft durch die bestehende SSH-Verbindung.


12. Adminoberfläche auf einen anderen Port legen

Die Weboberfläche des NGINX Proxy Managers hört im Image fest auf Port 81 (listen 81 default; in /etc/nginx/conf.d/production.conf). Eine Umgebungsvariable dafür gibt es in den veröffentlichten 2.x-Versionen noch nicht im Entwicklungszweig ist NPM_ADMIN_PORT bereits vorbereitet, in Version 2.15.1 aber noch nicht enthalten. Und weil beide Container im Host-Netzwerk laufen, lässt sich der Port auch nicht per Port-Mapping verschieben.

Ist Port 81 im Netz gesperrt, hilft deshalb:

sudo ./scripts/cmk-manage.sh npm-port 10443

12.1 Was dabei passiert

nginx bindet innerhalb seines http{}-Blocks einen offiziellen Erweiterungspunkt ein:

include /data/nginx/custom/http.conf;

/data ist unser Bind-Mount ./data/npm/data. Dort legt das Kommando einen zusätzlichen Server an, der auf dem gewünschten Port lauscht und an die Oberfläche auf 127.0.0.1:81 weiterreicht:

./data/npm/data/nginx/custom/http.conf

# >>> cmk-manage.sh: Admin-Port - nicht von Hand aendern >>>
server {
    listen 10443;
    listen [::]:10443;
    server_name _;
    client_max_body_size 0;
    location / {
        proxy_pass http://127.0.0.1:81;
        ...
    }
}
# <<< cmk-manage.sh: Admin-Port <<<

Nur der Bereich zwischen den beiden Markierungen wird verwaltet eigene Ergänzungen in derselben Datei bleiben unangetastet. Anschließend startet das Skript den Proxy-Manager-Container neu, damit nginx die Datei liest, und trägt NPM_ADMIN_PORT sowie NPM_ADMIN_URL in die .env ein. Der Terminal-Browser aus Kapitel 11 startet dann automatisch auf dem neuen Port.

12.2 Wichtig: Port 81 bleibt lokal bestehen

Der eingebaute Server auf Port 81 lässt sich so nicht abschalten er lauscht weiter auf allen Adressen. Das ist unkritisch, solange die Firewall ihn sperrt, und genau so ist die Empfehlung:

# firewalld
sudo firewall-cmd --permanent --add-port=10443/tcp
sudo firewall-cmd --permanent --remove-port=81/tcp 2>/dev/null
sudo firewall-cmd --reload

# ufw
sudo ufw allow 10443/tcp
sudo ufw delete allow 81/tcp 2>/dev/null

12.3 Stand ansehen und zurücksetzen

./scripts/cmk-manage.sh npm-port          # aktuellen Stand anzeigen
sudo ./scripts/cmk-manage.sh npm-port 81  # zurück auf die Vorgabe

Bei 81 wird der verwaltete Block wieder entfernt; ist die Datei danach leer, verschwindet sie ganz. Es gilt dann wieder ausschließlich die Konfiguration aus dem Image.

Das Kommando lehnt Ports ab, die im Stack schon vergeben sind (80, 443, 5000, 8000, 6557), prüft den Zahlenbereich und warnt, wenn auf dem Wunschport bereits ein anderer Dienst lauscht.

Sobald eine NPM-Version mit NPM_ADMIN_PORT erscheint, wird dieser Umweg überflüssig dann genügt die Umgebungsvariable. Bis dahin ist der Erweiterungspunkt der Weg, der ohne Änderung am Image auskommt.


13. Firewall

firewalld (RHEL/Rocky/Alma):

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --add-port=8000/tcp          # Agent-Receiver
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.0/24 port port=81 protocol=tcp accept'
sudo firewall-cmd --reload

# Bei abweichendem Admin-Port (z.B. 10443) stattdessen dessen Nummer freigeben -
# das passende Kommando gibt "cmk-manage.sh npm-port <port>" direkt aus.

ufw (Debian/Ubuntu):

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 8000/tcp
sudo ufw allow from 10.0.0.0/24 to any port 81 proto tcp
sudo ufw enable

Port 5000 bleibt geschlossen der Zugriff erfolgt ausschließlich über den Proxy. Port 81 nur aus dem Administrationsnetz freigeben.


14. Verwaltung: cmk-manage.sh

Das Skript ist gleichzeitig Kommandozeilenwerkzeug und ncurses-Oberfläche.

11.1 ncurses-Oberfläche (wie im Midnight Commander)

sudo ./scripts/cmk-manage.sh gui
 ┌──────────────── Checkmk Stack Manager ─────────────────┐
 │ Projekt : /opt/checkmk-stack                           │
 │ Runtime : podman     Standard-Site: cmk                │
 │ Backups : /opt/checkmk-stack/backups                   │
 │                                                        │
 │   status    Status von Containern und Sites            │
 │   stack     Stack steuern (Start/Stop/Logs/Update)     │
 │   backup    Backup erstellen                           │
 │   restore   Backup wiederherstellen                    │
 │   import    Site von Direktinstallation importieren    │
 │   manage    Backups verwalten (Liste/Details/Löschen)  │
 │   sites     Sites im Container verwalten               │
 │   image     Checkmk-Image beschaffen/auswählen         │
 │   browser   Terminal-Browser (Proxy Manager lokal)      │
 │   cert      Selbstsigniertes Zertifikat erzeugen       │
 │   config    Einstellungen (.env) - menügeführt         │
 │   shell     Root-Shell im Checkmk-Container            │
 │   quit      Beenden                                    │
 │                  <  OK  >   <Cancel>                   │
 └────────────────────────────────────────────────────────┘

Bedienung: Pfeiltasten, Leertaste markiert in Auswahllisten (z. B. mehrere Sites für ein Backup), Enter bestätigt, ESC/Cancel geht zurück. Es wird dialog bevorzugt; ist nur whiptail vorhanden, wird dieses genutzt. Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut.

11.2 Kommandozeile

./scripts/cmk-manage.sh --help
Kommando Wirkung
up / down / restart / pull Stack steuern
status Container, Sites, Zugangsadressen
logs [-f] Container-Logs
sites Sites im Container auflisten
site-start SITE / site-stop SITE einzelne Site steuern
start-all-sites alle Sites starten (wird von systemd aufgerufen)
backup … Backup als .tar.gz-Bundle
list / verify / prune --keep N Backups verwalten
restore … Backup zurückspielen
import … Migrations-Bundle einspielen
image status|list|pull|download|load|use Checkmk-Image beschaffen und auswaehlen
browser [--engine …] Terminal-Browser im Container Proxy Manager lokal bedienen
config list|get|set|edit Einstellungen der .env anzeigen und ändern
npm-port [PORT] Port der Proxy-Manager-Oberfläche setzen/anzeigen
cert … selbstsigniertes Zertifikat erzeugen
shell Root-Shell im Checkmk-Container
omd … beliebiges omd-Kommando im Container

Globale Optionen: --env-file DATEI, -y/--yes (keine Rückfragen, z. B. für Cronjobs), -v/--verbose.

14.3 Einstellungen ändern ohne Editor

Sämtliche Werte der .env lassen sich über das Menü pflegen. In der Oberfläche: Einstellungen (.env) menügeführt. Die Werte sind nach Bereichen gruppiert:

 ┌──────────────────── Einstellungen ─────────────────────┐
 │ Alle Werte der Datei .env - direkt hier änderbar.      │
 │ Datei: /opt/checkmk-stack/.env                         │
 │                                                        │
 │   runtime   Runtime und Zeitzone                       │
 │   image     Checkmk-Image und Zugangsdaten             │
 │   checkmk   Checkmk-Site und Container                 │
 │   npm       NGINX Proxy Manager                        │
 │   browser   Terminal-Browser                           │
 │   paths     Verzeichnisse                              │
 │   cert      Selbstsignierte Zertifikate                │
 │   show      Alle Werte auflisten                       │
 │   editor    Datei .env im Editor öffnen                │
 │   back      zurück                                     │
 └────────────────────────────────────────────────────────┘

Jeder Eintrag zeigt seinen aktuellen Wert und öffnet beim Bestätigen die passende Eingabe: Freitext, Zahl, Auswahlliste oder Kennwortfeld (Kennwörter erscheinen in der Übersicht als ******** und bleiben unverändert, wenn man das Feld leer lässt). Der Editor bleibt als Menüpunkt erhalten.

Dieselben Werte über die Kommandozeile:

./scripts/cmk-manage.sh config list                  # alles mit aktuellen Werten
./scripts/cmk-manage.sh config list --category npm   # nur ein Bereich
./scripts/cmk-manage.sh config get CMK_SITE_ID
./scripts/cmk-manage.sh config set CMK_SITE_ID prod
./scripts/cmk-manage.sh config set NPM_ADMIN_PORT 10443

Geprüft wird beim Setzen, nicht erst beim nächsten Start:

Schlüssel Prüfung
NPM_ADMIN_PORT Zahl 165535, nicht 80/443/5000/8000/6557, Warnung wenn belegt
CMK_SITE_ID nur Buchstaben, Ziffern, _; höchstens 16 Zeichen
CMK_IMAGE, NPM_IMAGE, … muss vollqualifiziert sein (Podman-Fallstrick)
CMK_RUNTIME muss auf diesem System installiert sein
CERT_DAYS u. a. Zahlenfelder
URL-Felder müssen mit http:// oder https:// beginnen

Werte mit Leerzeichen werden automatisch in Anführungszeichen gesetzt, damit die .env weiterhin von compose, systemd und der Shell gelesen werden kann. Ändert man NPM_ADMIN_PORT, zieht das Skript die nginx-Zusatzdatei automatisch mit (siehe Kapitel 12). Bei Werten, die erst nach dem Neuerstellen der Container greifen, weist das Menü ausdrücklich darauf hin.


15. Backup

Backups werden mit omd backup erstellt und als Bundle verpackt:

cmkbackup_<site>_<version>_<zeitstempel>.tar.gz
└── cmkbundle/
    ├── MANIFEST              Site, Version, Quelle, Prüfsumme …
    ├── INFO.txt              lesbare Zusammenfassung
    ├── site.tar.gz           das eigentliche omd-Backup
    └── site.tar.gz.sha256

Dadurch weiß das Restore-/Import-Werkzeug immer, welche Site und welche Checkmk-Version im Archiv steckt, und kann die Integrität prüfen.

# eine Site
sudo ./scripts/cmk-manage.sh backup --site cmk

# alle Sites, ohne Logdateien, mit Kennzeichnung
sudo ./scripts/cmk-manage.sh backup --all --no-logs --label vor-update

# konsistentestes Backup: Site wird kurz gestoppt
sudo ./scripts/cmk-manage.sh backup --site cmk --stop

# ohne Performance-Daten (deutlich kleiner)
sudo ./scripts/cmk-manage.sh backup --site cmk --no-rrds --dir /mnt/nas/checkmk

Auflisten und prüfen:

./scripts/cmk-manage.sh list
./scripts/cmk-manage.sh verify --file backups/cmkbackup_cmk_2.3.0p23.cre_20260820-030000.tar.gz
./scripts/cmk-manage.sh prune --keep 7

Nächtliches Backup per Cron

sudo crontab -e
15 2 * * * /opt/checkmk-stack/scripts/cmk-manage.sh -y backup --all --no-logs >>/var/log/cmk-backup.log 2>&1
30 3 * * 0 /opt/checkmk-stack/scripts/cmk-manage.sh -y prune --keep 14   >>/var/log/cmk-backup.log 2>&1

16. Restore

# Einfachster Fall: Site existiert nicht mehr
sudo ./scripts/cmk-manage.sh restore --file backups/cmkbackup_cmk_2.3.0p23.cre_20260820-030000.tar.gz

# Vorhandene Site überschreiben (laufende Prozesse beenden)
sudo ./scripts/cmk-manage.sh restore --file backups/… --reuse --kill

# Unter anderem Namen zurückspielen (z. B. für einen Test)
sudo ./scripts/cmk-manage.sh restore --file backups/… --as-site test

Ablauf des Skripts:

  1. Archivstruktur und SHA256-Prüfsumme kontrollieren
  2. prüfen, ob die Checkmk-Version des Backups im Container vorhanden ist
  3. bei vorhandener Site Rückfrage/--reuse, Site stoppen
  4. Archiv in den Container kopieren und omd restore ausführen
  5. TMPFS der Site abschalten (im Container nicht nutzbar)
  6. Site starten und Hinweise ausgeben

--as-site ändert den Site-Namen registrierte Agents zeigen dann ins Leere und müssten neu registriert werden. Für eine Migration also nicht verwenden.

Ein rohes omd backup-Archiv (ohne Bundle-Hülle) wird ebenfalls akzeptiert; der Site-Name wird dann aus dem Archiv gelesen.


17. Migration einer Direktinstallation (migrate_creator.sh)

Ziel: eine bestehende Checkmk-Installation auf Blech/VM in den Container übernehmen ohne die Agents anzufassen.

14.1 Warum die Agents weiterlaufen

Ein omd backup enthält die komplette Site inklusive etc/ssl (site-eigene CA und Zertifikate der registrierten Agents), etc/check_mk (Regeln, Hosts, Passwörter) und der Monitoring-Historie. Wird die Site unter demselben Namen wiederhergestellt und ist der Server unter derselben IP-Adresse erreichbar, dann

  • finden Push-/Pull-Agents (cmk-agent-ctl) ihre Registrierung wieder,
  • bleibt die TLS-Verbindung zum Agent-Receiver auf Port 8000 gültig,
  • stimmen alle URLs (https://<ip>/<site>/check_mk/…) weiterhin,
  • bleiben Performance-Daten und Historie erhalten.

Voraussetzung ist deshalb, dass das Zielsystem die IP des Quellservers übernimmt (bzw. der DNS-Name darauf umgestellt wird) das ist im geplanten Vorgehen ohnehin so.

14.2 Schritt 1 Skript auf den Quellserver kopieren

scp scripts/migrate_creator.sh root@alt-server:/root/
ssh root@alt-server 'chmod +x /root/migrate_creator.sh'

Das Skript ist eigenständig es braucht auf dem Quellserver nur bash, tar und omd (für die Oberfläche zusätzlich dialog oder whiptail).

14.3 Schritt 2 Bundle auf dem Quellserver erzeugen

Vorhandene Sites anzeigen:

sudo ./migrate_creator.sh --list
SITE                 VERSION            STATUS       GROESSE
prod                 2.3.0p23.cre       laeuft       4.7 GiB
test                 2.3.0p23.cre       gestoppt     318.2 MiB

Mit Oberfläche (Sites per Leertaste auswählen):

sudo ./migrate_creator.sh --gui

Der Dialog fragt nacheinander ab: Sites → Optionen (Site stoppen, RRDs/Logs auslassen) → Zielverzeichnis → Kennzeichnung → optionale Übertragung per scp.

Mit Parametern:

# eine Site, Site während des Backups stoppen (konsistenteste Variante)
sudo ./migrate_creator.sh --site prod --stop --out /var/tmp

# alle Sites, ohne Logs, direkt auf das Zielsystem übertragen
sudo ./migrate_creator.sh --all --no-logs \
     --scp root@10.0.0.5:/opt/checkmk-stack/backups/

Ergebnis:

/var/tmp/cmkmigrate_prod_2.3.0p23.cre_20260820-101500.tar.gz

Das Bundle enthält zusätzlich zum omd-Backup ein MANIFEST mit Site-Name, Checkmk-Version, Quell-Hostname, Quell-IP-Adressen, Quell-Betriebssystem und SHA256-Prüfsumme sowie ein Verzeichnis siteinfo/ mit omd config show, omd status und der IP-Konfiguration des Altsystems zur späteren Kontrolle.

14.4 Schritt 3 Zielsystem auf die richtige Version bringen

omd restore kann eine Site nur wiederherstellen, wenn genau deren Checkmk-Version im Zielsystem installiert ist. Im Container kommt die Version aus dem Image also muss der Image-Tag passen:

tar -xzOf backups/cmkmigrate_prod_*.tar.gz cmkbundle/MANIFEST | grep CMK_VERSION
# CMK_VERSION=2.3.0p23.cre   ->  Version 2.3.0p23, Endung .cre = Raw Edition

# passendes Image holen und als CMK_IMAGE eintragen lassen
sudo ./scripts/cmk-manage.sh image pull --edition raw --version 2.3.0p23
sudo ./scripts/cmk-manage.sh up

Bei einer Enterprise-Quelle (.cee) entsprechend:

sudo ./scripts/cmk-manage.sh image pull --edition enterprise --version 2.3.0p23 \
     --user <benutzer> --password <kennwort>
# oder, wenn die Registry nicht erreichbar ist:
sudo ./scripts/cmk-manage.sh image download --edition enterprise --version 2.3.0p23 \
     --user <benutzer> --password <kennwort>

Das Import-Skript prüft das selbst und bricht mit einer entsprechenden Meldung ab, wenn die Version fehlt.

Edition beachten: die Endung der Version verrät sie .cre = Raw, .cee = Enterprise, .cce = Cloud, .cme = Managed. Das Import-Skript liest sie aus dem Manifest und nennt im Fehlerfall direkt das passende image pull-Kommando. Enterprise-Images gibt es nicht auf Docker Hub siehe Kapitel 8.

14.5 Schritt 4 Bundle importieren

Mit Oberfläche:

sudo ./scripts/cmk-manage.sh gui      # -> "import"

Mit Parametern:

sudo ./scripts/cmk-manage.sh import \
     --file backups/cmkmigrate_prod_2.3.0p23.cre_20260820-101500.tar.gz \
     --set-default-site

Das Skript

  1. erkennt das Migrations-Bundle und zeigt Quell-Host und Quell-IP an,
  2. warnt, wenn die IP dieses Hosts von der Quell-IP abweicht (dann müssten die Agents nachgeführt werden),
  3. prüft Prüfsumme, Version und Edition,
  4. fragt bei bereits vorhandener Site nach (--reuse überschreibt),
  5. führt omd restore unter dem unveränderten Site-Namen aus,
  6. setzt auf Wunsch CMK_SITE_ID in der .env (--set-default-site), damit der Container die Site auch nach einem Reboot automatisch startet,
  7. startet die Site und gibt die nächsten Schritte aus.

14.6 Schritt 5 Umschalten und kontrollieren

# 1) Alten Server abschalten bzw. dessen Site stoppen (kein Doppel-Monitoring!)
ssh root@alt-server 'omd stop prod'

# 2) Zielsystem auf die IP/den DNS-Namen des Altsystems umstellen
#    (statische IP übernehmen oder DNS-Eintrag umbiegen)

# 3) Container neu erstellen, falls CMK_SITE_ID geändert wurde
sudo ./scripts/cmk-manage.sh up
sudo ./scripts/cmk-manage.sh status

# 4) Kontrolle in Checkmk
sudo ./scripts/cmk-manage.sh omd su prod
   OMD[prod]:~$ cmk -O                # Konfiguration aktivieren
   OMD[prod]:~$ omd status
   OMD[prod]:~$ exit

Danach in der Oberfläche prüfen:

  • Monitor → All hosts melden sich die Agents wieder?
  • Bei TLS-Agents: der Service „Check_MK Agent“ darf keine Registrierungsfehler melden.
  • Ein Agent lässt sich vom überwachten Host aus testen mit cmk-agent-ctl status dort muss die Site prod mit dem Zielserver und „Connection: TLS“ erscheinen.

14.7 Checkliste Migration

  • migrate_creator.sh auf den Quellserver kopiert
  • Bundle erzeugt (möglichst mit --stop)
  • Bundle auf das Zielsystem kopiert (backups/)
  • passendes Image geholt (image pull/image download), CMK_IMAGE gesetzt, Stack neu erstellt
  • import --set-default-site ausgeführt, Site läuft
  • Alte Site gestoppt / alter Server abgeschaltet
  • IP bzw. DNS auf das Zielsystem umgestellt
  • Ports 80/443/8000 in der Firewall offen
  • Proxy-Host im NGINX Proxy Manager mit Zertifikat eingerichtet
  • Agents melden sich, cmk -O ausgeführt
  • Backup des neuen Systems eingerichtet (Cron)

18. Mehrere Sites in einem Container

Der Checkmk-Entrypoint legt beim Start nur die Site aus CMK_SITE_ID an und startet auch nur diese. Weitere Sites (z. B. mehrere importierte) existieren im Bind-Mount, werden aber nach einem Neustart nicht automatisch hochgefahren.

Deshalb:

sudo ./scripts/cmk-manage.sh start-all-sites

Dieses Kommando wird von der systemd-Unit (ExecStartPost) bzw. der Quadlet-Unit automatisch nach dem Containerstart ausgeführt und startet alle vorhandenen Sites.

Empfehlung: Für sauber getrennte Umgebungen lieber je Site ein eigenes Projektverzeichnis mit eigener .env betreiben. Da beide Container im Host-Netzwerk laufen, kann pro Host allerdings nur ein Checkmk-Container die Ports 5000/8000 belegen für echte Mehrfachinstanzen dann getrennte Hosts oder eine Bridge-Netzwerk-Variante verwenden.


19. Checkmk aktualisieren

Da /omd/sites ein Bind-Mount ist, überleben die Daten den Austausch des Images. Die Checkmk-Software selbst steckt im Image unter /omd/versions.

# 1) IMMER zuerst sichern
sudo ./scripts/cmk-manage.sh backup --all --label vor-update

# 2) neues Image holen (traegt CMK_IMAGE automatisch in die .env ein)
sudo ./scripts/cmk-manage.sh image pull --edition raw --version 2.3.0p28

# 3) Container neu erstellen
sudo ./scripts/cmk-manage.sh up

# 4) Site aktualisieren (interaktiv, Konflikte bestätigen)
sudo ./scripts/cmk-manage.sh omd stop cmk
sudo ./scripts/cmk-manage.sh omd update cmk
sudo ./scripts/cmk-manage.sh omd start cmk

Bei einem Versionssprung (z. B. 2.2 → 2.3) unbedingt vorher die Checkmk-Werksnotizen (Werks/Release Notes) lesen.


20. Fehlersuche

Symptom Ursache / Lösung
Port 80/443 already in use Auf dem Host läuft bereits ein Webserver: ss -tlnp | grep ':80'systemctl disable --now apache2 nginx httpd
Nach Reboot laufen die Container nicht (Podman) systemd-Unit fehlt: ./install.sh --with-systemd bzw. --quadlet, danach systemctl is-enabled checkmk-stack
omd restore: version is not installed passendes Image holen: cmk-manage.sh image pull --edition <ed> --version <v>, dann up
Import bricht mit Editions-Warnung ab Enterprise-Backup benötigt ein Enterprise-Image, siehe Kapitel 8
image not known / Podman sucht bei registry.access.redhat.com kurzer Image-Name. CMK_IMAGE vollqualifiziert setzen: cmk-manage.sh image use docker.io/… bzw. registry.checkmk.com/enterprise/…
checkmk/check-mk-enterprise nicht auf Docker Hub gefunden richtig so Enterprise liegt nur auf registry.checkmk.com oder als Tarball vor; ab 2.5 heißt die Edition pro und liegt frei auf Docker Hub
Tarball mit podman import eingespielt, Image „unbekannt“ import erzeugt ein Image ohne Metadaten. Fehl-Image mit podman rmi <id> entfernen und cmk-manage.sh image load --file … verwenden (nutzt load)
Download des Image-Tarballs schlägt fehl (401/404) Zugangsdaten des Kundenportals prüfen, exakte Version angeben (kein -latest), notfalls image download --url '<vollständige URL>'
Proxy zeigt 502 Bad Gateway Checkmk-Container läuft nicht oder Weiterleitung nicht auf 127.0.0.1:5000 gesetzt: ./scripts/cmk-manage.sh status, curl -I http://127.0.0.1:5000/
Let's Encrypt schlägt fehl Port 80 aus dem Internet nicht erreichbar oder DNS falsch; Alternative: DNS-Challenge oder selbstsigniertes Zertifikat
Agents melden sich nach der Migration nicht Site-Name geändert (--as-site), IP nicht übernommen oder Port 8000 blockiert; auf dem Agent prüfen: cmk-agent-ctl status
Permission denied auf data/ unter RHEL SELinux: restorecon -Rv /opt/checkmk-stack/data, :Z an den Mounts prüfen
podman-compose nicht gefunden EPEL aktivieren oder auf Quadlet umstellen (./install.sh --quadlet)
Adminoberfläche aus dem LAN nicht erreichbar Port 81 gesperrt. Auf einen freien Port legen: cmk-manage.sh npm-port 10443 und in der Firewall freigeben
Nach npm-port antwortet der neue Port nicht Proxy Manager wurde nicht neu gestartet: cmk-manage.sh restart; Datei prüfen: data/npm/data/nginx/custom/http.conf
cmk-manage.sh bricht mit „CMK_RUNTIME … ist nicht installiert" ab wird nur noch gewarnt und selbst gesucht; sauber setzen mit config set CMK_RUNTIME auto
Proxy-Manager-Oberfläche im Browser leer / nur Textfragmente Textbrowser ohne JavaScript verwendet. cmk-manage.sh browser --engine browsh (bzw. carbonyl) nehmen
Selbstsigniertes Zertifikat lässt sich im Terminal-Browser nicht hochladen Datei-Dialoge gibt es dort nicht Upload über die API, siehe Kapitel 11.3
browser meldet „braucht ein echtes Terminal" Aufruf aus Pipe/Skript. Direkt auf der Konsole oder per SSH aufrufen; nur der Bau geht headless mit --build-only
TUI startet nicht dialog installieren: apt-get install -y dialog bzw. dnf install -y dialog
Site startet nicht, tmp-Fehler ./scripts/cmk-manage.sh omd config <site> set TMPFS off, danach Site starten

Nützliche Kommandos:

./scripts/cmk-manage.sh logs -f                  # Container-Logs
./scripts/cmk-manage.sh omd status cmk           # Dienste der Site
./scripts/cmk-manage.sh shell                    # Root-Shell im Container
docker exec -it checkmk omd su cmk               # bzw. podman exec …

21. Sicherheitshinweise

  • CMK_PASSWORD sofort nach der Installation in der Oberfläche ändern und aus der .env entfernen (wird nur bei der Neuanlage ausgewertet); chmod 600 .env ist gesetzt.
  • Standardzugang des Proxy Managers (admin@example.com / changeme) beim ersten Login zwingend ändern.
  • Port 81 (Adminoberfläche) nur aus dem Administrationsnetz erreichbar machen, Port 5000 gar nicht nach außen öffnen.
  • Backups enthalten alle Passwörter und Zertifikate der Site verschlüsselt ablegen bzw. Zugriffsrechte eng fassen (chmod 700 backups).
  • Regelmäßig ./scripts/cmk-manage.sh pull + up für Sicherheitsupdates der Images einplanen.
  • Host-Netzwerk bedeutet: der Container teilt sich den Netzwerk-Stack des Hosts. Es gibt keine zusätzliche Netzwerkisolierung die Absicherung erfolgt über die Firewall des Hosts.

22. Deinstallation

sudo ./scripts/cmk-manage.sh down

# systemd
sudo systemctl disable --now checkmk-stack.service
sudo rm -f /etc/systemd/system/checkmk-stack.service
# bzw. Quadlet
sudo rm -f /etc/containers/systemd/checkmk.container \
           /etc/containers/systemd/nginx-proxy-manager.container
sudo systemctl daemon-reload

# Images entfernen (Namen aus "cmk-manage.sh image list")
docker image rm docker.io/checkmk/check-mk-raw:2.3.0-latest docker.io/jc21/nginx-proxy-manager:2
# podman image rm …

# ggf. gespeicherte Registry-Anmeldung entfernen
podman logout registry.checkmk.com   # bzw. docker logout

# Daten (ACHTUNG: löscht die komplette Überwachung!)
sudo rm -rf /opt/checkmk-stack/data

Lizenz / Hinweise

Dieses Projekt enthält lediglich Konfiguration und Hilfsskripte. Checkmk (Raw Edition, GPLv2) und NGINX Proxy Manager (MIT) unterliegen den Lizenzbedingungen der jeweiligen Hersteller.