Bisher liess sich eine zweite Site nur importieren, nicht anlegen - der
Entrypoint des Abbilds macht ausschliesslich die Site aus CMK_SITE_ID.
Absicht war das nicht, es fehlte schlicht.
site-create NAME [--password PW] [--expose] [--no-start]
site-delete NAME [--force]
Im Container laeuft "omd create --no-tmpfs"; ohne --no-tmpfs scheitert
es, weil sich dort kein tmpfs einhaengen laesst. Laeuft der Container
nicht im Host-Netz, wird der Apache der Site zusaetzlich auf 0.0.0.0
gebunden - im Host-Netz genuegt 127.0.0.1, und der Proxy kommt trotzdem
hin. Das wird am Container nachgesehen, nicht geraten.
Der eigentliche Punkt sind die Ports. omd vergibt sie selbst weiter, am
laufenden Container nachgemessen:
erste zweite dritte
Oberflaeche 5000 5001 5002
Agent-Receiver 8000 8001 8002
Livestatus 6557 6558 6559
Die Agents einer zweiten Site sprechen also 8001 an, nicht 8000 - das
faellt sonst erst auf, wenn niemand Daten liefert. "site-create" gibt
deshalb beides fertig aus: den Proxy-Pfad mit der richtigen Portnummer
und den Firewall-Eintrag fuer den Receiver, dazu den Hinweis auf den
Standard-Server, falls er eingerichtet ist.
Beim Loeschen war "omd rm" zuerst wirkungslos: es fragt selbst nach, die
Site blieb stehen, waehrend hier Erfolg gemeldet wurde. Jetzt mit dem
globalen -f, und danach wird nachgesehen, ob sie wirklich weg ist. Die
Standard-Site ist geschuetzt - der Entrypoint legt sie ohnehin wieder
an.
In der Oberflaeche unter "Sites im Container verwalten": anlegen mit
Namens- und Kennwortabfrage, entfernen mit Rueckfrage.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3263 lines
132 KiB
Markdown
3263 lines
132 KiB
Markdown
# Checkmk im Container – Docker (Debian) & Podman (RHEL) mit NGINX Proxy Manager
|
||
|
||
*[English version: README_en.md](README_en.md)*
|
||
|
||
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](#1-überblick--architektur)
|
||
2. [Verzeichnisstruktur](#2-verzeichnisstruktur)
|
||
3. [Voraussetzungen & Ports](#3-voraussetzungen--ports)
|
||
4. [Installation auf Debian/Ubuntu (Docker)](#4-installation-auf-debianubuntu-docker)
|
||
5. [Installation auf RHEL/Rocky/Alma/Fedora (Podman)](#5-installation-auf-rhelrockyalmafedora-podman)
|
||
* [5.1 Unregistriertes RHEL: woher die Pakete kommen](#51-unregistriertes-rhel-woher-die-pakete-kommen)
|
||
6. [Autostart nach einem Neustart des Hosts (Podman)](#6-autostart-nach-einem-neustart-des-hosts-podman)
|
||
7. [Konfiguration (`.env`)](#7-konfiguration-env)
|
||
8. [Checkmk-Image beschaffen (Raw, Enterprise & Co.)](#8-checkmk-image-beschaffen-raw-enterprise--co)
|
||
9. [Erststart](#9-erststart)
|
||
10. [HTTPS einrichten – Let's Encrypt oder selbstsigniert](#10-https-einrichten--lets-encrypt-oder-selbstsigniert)
|
||
11. [Proxy Manager lokal einrichten (Terminal-Browser)](#11-proxy-manager-lokal-einrichten-terminal-browser)
|
||
12. [Adminoberfläche auf einen anderen Port legen](#12-adminoberfläche-auf-einen-anderen-port-legen)
|
||
13. [Firewall](#13-firewall)
|
||
14. [Verwaltung: `cmk-manage.sh` (CLI und ncurses-Oberfläche)](#14-verwaltung-cmk-managesh)
|
||
15. [Backup](#15-backup)
|
||
16. [Restore](#16-restore)
|
||
17. [Migration einer Direktinstallation (`migrate_creator.sh`)](#17-migration-einer-direktinstallation-migrate_creatorsh)
|
||
18. [Mehrere Sites in einem Container](#18-mehrere-sites-in-einem-container)
|
||
19. [Checkmk aktualisieren](#19-checkmk-aktualisieren)
|
||
20. [Fehlersuche](#20-fehlersuche)
|
||
21. [Sicherheitshinweise](#21-sicherheitshinweise)
|
||
22. [Deinstallation](#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 # deutsche Dokumentation
|
||
├── README_en.md # englische Fassung
|
||
├── 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`](#12-adminoberfläche-auf-einen-anderen-port-legen) änderbar) | nur Admin-Netz! |
|
||
| 5000/tcp | Checkmk Apache (Backend) | **nur localhost** – nicht freigeben. Ausnahme: bei abgeschaltetem Proxy Manager ([12.4](#124-proxy-manager-ganz-abschalten-externer-nginx)) nur für die IP des externen Proxys |
|
||
| 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)
|
||
|
||
```bash
|
||
# 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:
|
||
|
||
```bash
|
||
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](#18-mehrere-sites-in-einem-container)).
|
||
|
||
---
|
||
|
||
## 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.
|
||
|
||
> ### Schritt 0 bei RHEL: Subskription prüfen
|
||
>
|
||
> **Ein nicht registriertes RHEL installiert überhaupt keine Pakete** – weder
|
||
> `podman` noch `git`, `dialog` oder `tar`. `dnf` meldet dann nur
|
||
> *„This system is not registered with an entitlement server"*. Das ist der
|
||
> häufigste Grund, warum `install.sh` auf einem frischen RHEL nicht durchläuft.
|
||
>
|
||
> ```bash
|
||
> # Ist das System registriert?
|
||
> sudo subscription-manager status # -> "Overall Status: Current" = in Ordnung
|
||
> sudo dnf repolist # -> darf nicht leer sein
|
||
>
|
||
> # Falls nicht: kostenloses Konto auf https://developers.redhat.com anlegen
|
||
> # (Developer Subscription for Individuals, bis zu 16 Systeme) und dann:
|
||
> sudo subscription-manager register --username <benutzer>
|
||
> ```
|
||
>
|
||
> RHEL 9 nutzt *Simple Content Access*, ein `subscription-manager attach` ist
|
||
> **nicht** mehr nötig. Ohne Konto geht es auch per Installations-DVD oder durch
|
||
> den Wechsel auf Rocky/Alma – alle drei Wege stehen ausführlich in
|
||
> [Abschnitt 5.1](#51-unregistriertes-rhel-woher-die-pakete-kommen).
|
||
>
|
||
> **Rocky Linux, AlmaLinux, CentOS Stream und Fedora** brauchen nichts davon –
|
||
> dort einfach weiterlesen.
|
||
|
||
```bash
|
||
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. prüft zuerst, ob überhaupt ein nutzbares Repository vorhanden ist, und
|
||
nennt andernfalls die drei Wege aus [Abschnitt 5.1](#51-unregistriertes-rhel-woher-die-pakete-kommen)
|
||
2. `podman`, `tar`, `openssl`
|
||
3. `dialog` für die ncurses-Oberfläche – schlägt das fehl, wird `newt`
|
||
(`whiptail`) genommen; beides unterstützen die Skripte
|
||
4. `podman-compose` – in dieser Reihenfolge versucht:
|
||
Distributions-Repository → EPEL → `pip3 install podman-compose`
|
||
5. richtet die systemd-Unit ein (bei Podman **immer**, siehe nächstes Kapitel)
|
||
|
||
Manuell entspricht das:
|
||
|
||
```bash
|
||
sudo dnf install -y podman podman-compose tar openssl
|
||
sudo dnf install -y dialog || sudo dnf install -y newt # dialog: AppStream, newt: BaseOS
|
||
|
||
# Falls podman-compose nicht im Repo ist - EPEL nachrüsten:
|
||
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
|
||
sudo dnf install -y podman-compose
|
||
```
|
||
|
||
> **EPEL setzt eine funktionierende Subskription voraus.** Das Paket
|
||
> `epel-release` konfiguriert nur die EPEL-Quelle; seine Abhängigkeiten und
|
||
> alles, was danach daraus installiert wird, kommen weiterhin aus Red Hats
|
||
> BaseOS/AppStream. Auf einem nicht registrierten System scheitert deshalb
|
||
> schon der Befehl oben – EPEL ist **kein** Ersatz für die Registrierung.
|
||
>
|
||
> Bleibt `podman-compose` deswegen unerreichbar, ist das kein Hindernis:
|
||
> mit **Quadlet** ([Kapitel 6, Variante B](#variante-b--podman-quadlet-ab-podman-44-ohne-compose))
|
||
> läuft der Stack ganz ohne Compose, direkt über systemd.
|
||
|
||
Starten:
|
||
|
||
```bash
|
||
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](#82-zwei-podman-fallstricke-genau-die-aus-der-praxis)
|
||
> lesen: kurze Image-Namen und `podman import` statt `podman load` sind die
|
||
> beiden Ursachen fuer „Image unbekannt“.
|
||
|
||
### 5.1 Unregistriertes RHEL: woher die Pakete kommen
|
||
|
||
Ein frisch installiertes Red Hat Enterprise Linux ohne Subskription liefert
|
||
gar nichts aus:
|
||
|
||
```
|
||
$ sudo dnf install -y podman
|
||
This system is not registered with an entitlement server.
|
||
You can use "rhc" or "subscription-manager" to register.
|
||
Error: There are no enabled repositories in "/etc/yum.repos.d".
|
||
```
|
||
|
||
Das betrifft **alle** Pakete – `podman`, `git`, `dialog`, `tar`. Es gibt drei
|
||
Wege, und `install.sh` erkennt die Lage inzwischen selbst und nennt sie.
|
||
|
||
> Nur RHEL selbst ist betroffen. **Rocky Linux, AlmaLinux, CentOS Stream und
|
||
> Fedora** brauchen keine Registrierung – dort funktioniert `dnf` sofort.
|
||
|
||
#### Weg 1 – kostenlose Developer-Subskription (empfohlen)
|
||
|
||
Red Hat vergibt die *Developer Subscription for Individuals* kostenlos. Sie
|
||
gilt für **bis zu 16 Systeme**, physisch oder virtuell, und deckt neben
|
||
Entwicklung und Test ausdrücklich auch **kleine Produktivnutzung** ab. Sie wird
|
||
an die Person vergeben, nicht an die Firma.
|
||
|
||
1. Kostenloses Konto auf <https://developers.redhat.com> anlegen
|
||
2. Auf dem Server registrieren:
|
||
|
||
```bash
|
||
sudo subscription-manager register --username <benutzer>
|
||
# Kennwort wird abgefragt; alternativ --password <kennwort>
|
||
```
|
||
|
||
RHEL 9 nutzt *Simple Content Access* – die Repositories sind damit sofort
|
||
freigeschaltet, ein `subscription-manager attach` ist **nicht** mehr nötig.
|
||
|
||
3. Kontrolle:
|
||
|
||
```bash
|
||
sudo subscription-manager status # -> Overall Status: Current
|
||
sudo dnf repolist # -> rhel-9-for-x86_64-baseos-rpms u.a.
|
||
sudo dnf install -y git podman
|
||
```
|
||
|
||
Fehlen einzelne Repositories:
|
||
|
||
```bash
|
||
sudo subscription-manager repos --list-enabled
|
||
sudo subscription-manager repos --enable=rhel-9-for-x86_64-appstream-rpms
|
||
```
|
||
|
||
Bei einem Firmenkonto mit Aktivierungsschlüssel stattdessen:
|
||
|
||
```bash
|
||
sudo subscription-manager register --org <org-id> --activationkey <schluessel>
|
||
```
|
||
|
||
#### Weg 2 – Installations-DVD als lokales Repository (ohne Konto, offline)
|
||
|
||
Funktioniert ohne jede Registrierung und ohne Internet. Voraussetzung ist die
|
||
**DVD-ISO** (`rhel-9.x-x86_64-dvd.iso`, mehrere GB) – die kleine `boot.iso`
|
||
enthält keine Pakete.
|
||
|
||
```bash
|
||
# ISO dauerhaft einhängen
|
||
sudo mkdir -p /mnt/rhel
|
||
sudo mount -o loop,ro /pfad/rhel-9.8-x86_64-dvd.iso /mnt/rhel
|
||
|
||
# beim Booten automatisch einhängen
|
||
echo '/pfad/rhel-9.8-x86_64-dvd.iso /mnt/rhel iso9660 loop,ro,nofail 0 0' \
|
||
| sudo tee -a /etc/fstab
|
||
|
||
# Repository-Datei anlegen
|
||
sudo tee /etc/yum.repos.d/rhel-local.repo >/dev/null <<'REPO'
|
||
[rhel-local-baseos]
|
||
name=RHEL local - BaseOS
|
||
baseurl=file:///mnt/rhel/BaseOS
|
||
enabled=1
|
||
gpgcheck=1
|
||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
|
||
|
||
[rhel-local-appstream]
|
||
name=RHEL local - AppStream
|
||
baseurl=file:///mnt/rhel/AppStream
|
||
enabled=1
|
||
gpgcheck=1
|
||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
|
||
REPO
|
||
|
||
sudo dnf clean all
|
||
sudo dnf repolist
|
||
sudo dnf install -y podman tar openssl dialog git
|
||
```
|
||
|
||
> **Grenze:** Das lokale Repository enthält exakt den Stand der ISO – es gibt
|
||
> **keine Sicherheitsupdates**. Für einen dauerhaft betriebenen
|
||
> Monitoring-Server ist das kein Zustand; als Überbrückung, bis die
|
||
> Registrierung steht, ist es in Ordnung.
|
||
|
||
#### Weg 3 – auf Rocky Linux oder AlmaLinux wechseln
|
||
|
||
Beide sind binärkompatible Nachbauten von RHEL, dauerhaft kostenfrei und ohne
|
||
Registrierung. Dieses Projekt läuft dort unverändert – `install.sh` erkennt sie
|
||
als RHEL-Familie.
|
||
|
||
```bash
|
||
# Rocky Linux
|
||
sudo dnf install -y git
|
||
sudo git clone https://github.com/rocky-linux/rocky-tools.git
|
||
sudo bash rocky-tools/migrate2rocky/migrate2rocky.sh -r
|
||
|
||
# AlmaLinux
|
||
curl -O https://raw.githubusercontent.com/AlmaLinux/almalinux-deploy/master/almalinux-deploy.sh
|
||
sudo bash almalinux-deploy.sh
|
||
```
|
||
|
||
> Vorher ein Backup bzw. einen Snapshot anlegen. Die Umstellung tauscht die
|
||
> Basispakete im laufenden System aus.
|
||
|
||
#### Was dieses Projekt tatsächlich braucht
|
||
|
||
| Paket | Wofür | Repository |
|
||
|---|---|---|
|
||
| `podman` | Container-Runtime | AppStream |
|
||
| `tar` | Backups und Migrations-Bundles | BaseOS |
|
||
| `openssl` | selbstsignierte Zertifikate | BaseOS |
|
||
| `dialog` | ncurses-Oberfläche | AppStream |
|
||
| `newt` (`whiptail`) | Ersatz, falls `dialog` fehlt | BaseOS |
|
||
| `curl` | Image-Download | BaseOS |
|
||
| `podman-compose` | Compose-Unterstützung | EPEL oder `pip3` |
|
||
| `git` | nur zum Klonen dieses Projekts | AppStream |
|
||
|
||
`dialog` ist **optional**: fehlt es, nutzen die Skripte automatisch `whiptail`
|
||
aus dem Paket `newt`, das in BaseOS liegt. `install.sh` versucht genau diese
|
||
Reihenfolge und bricht deswegen nicht mehr ab.
|
||
|
||
`git` wird nicht zwingend gebraucht – das Projekt lässt sich genauso als ZIP
|
||
oder per `scp` auf den Server bringen.
|
||
|
||
> **EPEL hilft hier nicht:** Das EPEL-Repository setzt die Basis-Repositories
|
||
> von Red Hat voraus. Ohne Subskription oder lokales Repository lässt sich auch
|
||
> `epel-release` nicht installieren – und damit kein `podman-compose`. In dem
|
||
> Fall ist der Quadlet-Weg aus [Kapitel 6](#6-autostart-nach-einem-neustart-des-hosts-podman)
|
||
> die Lösung: er kommt ganz ohne Compose aus.
|
||
|
||
### 5.2 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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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.
|
||
|
||
```bash
|
||
sudo ./install.sh --quadlet
|
||
```
|
||
|
||
Das schreibt (mit den Werten aus der `.env`) nach `/etc/containers/systemd/`:
|
||
|
||
* `checkmk.container`
|
||
* `nginx-proxy-manager.container`
|
||
|
||
Danach:
|
||
|
||
```bash
|
||
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/](systemd/quadlet/).
|
||
|
||
### Variante C – rootless Podman (optional, erhöhter Aufwand)
|
||
|
||
```bash
|
||
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`)
|
||
|
||
```bash
|
||
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](#8-checkmk-image-beschaffen-raw-enterprise--co) |
|
||
| `CMK_EDITION`, `CMK_VERSION` | nur Vorgaben fuer den Image-Downloader |
|
||
| `CMK_IMAGE_SOURCE` | `auto`/`registry`/`download` – woher das Image geholt wird |
|
||
| `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_ENABLED` | `on`/`off` – soll der Proxy-Manager-Container überhaupt laufen? Siehe [12.4](#124-proxy-manager-ganz-abschalten-externer-nginx) |
|
||
| `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 **manuelle** Backups (Vorgabe `./backups`); geplante Jobs haben eigene Pfade |
|
||
| `BACKUP_AUTO` | `on`/`off` – sollen die Backup-Jobs per cron laufen? |
|
||
| `CERT_DOMAIN`, `CERT_DAYS` | Vorgaben für selbstsignierte Zertifikate |
|
||
| `CERT_EXTERNAL_DIR`, `CERT_EXTERNAL_FULLCHAIN`, `CERT_EXTERNAL_KEY` | Verzeichnis und Dateinamen eines von außen gelieferten Zertifikats |
|
||
| `CERT_EXTERNAL_WATCH` | täglich prüfen, ob es ausgetauscht wurde |
|
||
| `FW_ROLE` | `single`/`central`/`remote` – Rolle im verteilten Monitoring, steuert die Firewall-Prüfung |
|
||
| `FW_EC_SYSLOG`, `FW_EC_SNMPTRAP`, `FW_EC_TCP` | Event Console: Syslog (514), SNMP-Traps (162/udp), Status über TCP (6558) |
|
||
| `FW_AGENT` | läuft auf diesem Host ein Checkmk-Agent im Pull-Betrieb? (6556) |
|
||
| `FW_EXTRA_PORTS` | weitere Ports für die Prüfung, z. B. `3000/tcp=Grafana` |
|
||
|
||
### 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](#14-verwaltung-cmk-managesh)).
|
||
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; 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.
|
||
|
||
#### Vorsicht bei den Namen
|
||
|
||
Die Umbenennung ist die zweite grosse Stolperfalle. **checkmk.com zeigt nur
|
||
noch die neuen Namen, die Dateien und Repositories tragen bis 2.4 aber die
|
||
alten.** Konkret für 2.3.0p9 – geprüft am Versionsarchiv:
|
||
|
||
| Auswahl auf checkmk.com | `--edition` hier | tatsächlicher Dateiname |
|
||
|---|---|---|
|
||
| Community | `raw` | `check-mk-raw-docker-2.3.0p9.tar.gz` |
|
||
| **Pro** | **`enterprise`** | **`check-mk-enterprise-docker-2.3.0p9.tar.gz`** |
|
||
| Ultimate | `cloud` | `check-mk-cloud-docker-2.3.0p9.tar.gz` |
|
||
| Ultimate MT | `managed` | `check-mk-managed-docker-2.3.0p9.tar.gz` |
|
||
|
||
Wer auf der Website „Pro" wählt und daraus `check-mk-pro-docker-2.3.0p9.tar.gz`
|
||
ableitet, bekommt ein **HTTP 404** – diese Datei gibt es für 2.3 nicht.
|
||
|
||
Das Skript nimmt einem das ab: es liest den echten Dateinamen aus dem
|
||
Versionsarchiv und probiert zusätzlich beide Namensvarianten durch. In der
|
||
Oberfläche steht in der Editionsauswahl jeweils beides.
|
||
|
||
> 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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
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 Zugangsdaten vorab prüfen
|
||
|
||
Bevor ein mehrere Gigabyte grosser Download an einer falschen Anmeldung
|
||
scheitert, lässt sich beides in Sekunden testen:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image test --edition enterprise --version 2.3.0p23
|
||
```
|
||
|
||
Geprüft wird ohne jeden Download und ohne dass eine Anmeldung gespeichert wird:
|
||
|
||
| Prüfung | Was sie beantwortet |
|
||
|---|---|
|
||
| Registry erreichbar | Netzwerk, Proxy, DNS |
|
||
| Anmeldung akzeptiert | stimmen Benutzer und Kennwort? |
|
||
| Zugriff auf das Repository | hat das Konto die nötige Berechtigung (Subskription)? |
|
||
| Downloadportal | liegt der Image-Tarball dort und wird die Anmeldung akzeptiert? |
|
||
|
||
Beispiel mit korrekten Zugangsdaten aus der `.env`:
|
||
|
||
```
|
||
Registry registry.checkmk.com
|
||
[ OK ] erreichbar (HTTP 401)
|
||
[ OK ] Anmeldung akzeptiert
|
||
[ OK ] Zugriff auf 'enterprise/check-mk-enterprise' vorhanden
|
||
|
||
Downloadportal download.checkmk.com
|
||
[ OK ] Datei erreichbar (HTTP 200)
|
||
https://download.checkmk.com/checkmk/2.3.0p23/check-mk-enterprise-2.3.0p23.docker.tar.gz
|
||
|
||
[ OK ] Zugangsweg nutzbar.
|
||
```
|
||
|
||
Bei falschem Kennwort:
|
||
|
||
```
|
||
Registry registry.checkmk.com
|
||
[ OK ] erreichbar (HTTP 401)
|
||
[FEHLER] Anmeldung abgelehnt (HTTP 401)
|
||
Benutzername/Kennwort des Checkmk-Kundenportals pruefen
|
||
```
|
||
|
||
Nützliche Unterscheidungen, die der Test trifft:
|
||
|
||
* **Anmeldung akzeptiert, aber kein Zugriff auf das Repository** – die
|
||
Zugangsdaten stimmen, der Subskription fehlt aber die Berechtigung für diese
|
||
Edition.
|
||
* **Anmeldung akzeptiert, aber HTTP 404 im Downloadportal** – Benutzer und
|
||
Kennwort sind richtig, nur Version oder Dateiname passen nicht. Dann die
|
||
exakte Version angeben (kein `-latest`) oder `CMK_DOWNLOAD_URL` setzen.
|
||
* Bei den frei verfügbaren Editionen (`raw`, `pro`, `cloud` …) meldet der Test
|
||
„öffentliches Repository – keine Anmeldung nötig" und prüft trotzdem, ob das
|
||
Repository wirklich abrufbar ist.
|
||
|
||
Optionen:
|
||
|
||
```bash
|
||
# Zugangsdaten einmalig angeben, ohne sie in die .env zu schreiben
|
||
./scripts/cmk-manage.sh image test --edition enterprise --version 2.3.0p23 \
|
||
--user <benutzer> --password <kennwort>
|
||
|
||
# nur einen Bezugsweg prüfen
|
||
./scripts/cmk-manage.sh image test --only registry
|
||
./scripts/cmk-manage.sh image test --only download
|
||
```
|
||
|
||
Die Zugangsdaten werden über `curl --config -` von der Standardeingabe
|
||
übergeben und erscheinen daher **nicht** in der Prozessliste.
|
||
|
||
> **Kennwörter mit Sonderzeichen:** Bis dahin lief das über eine temporäre
|
||
> `.netrc`-Datei. Deren Format trennt die Felder durch Leerzeichen – ein
|
||
> Kennwort mit Leerzeichen, `#` oder Anführungszeichen kam dadurch still
|
||
> verstümmelt an, und die Anmeldung schlug scheinbar grundlos fehl.
|
||
> Gegen einen Testserver nachgemessen: bei einem Kennwort mit Leerzeichen,
|
||
> `#`, `"` und `$` liefert der neue Weg HTTP 200, der alte HTTP 401. Fehlt `curl`, weicht der Test
|
||
für die Registry auf `podman login` bzw. `docker login` aus – auch dann in eine
|
||
Wegwerfdatei, die gespeicherte Anmeldung des Systems bleibt unberührt.
|
||
|
||
In der ncurses-Oberfläche ist der Test an zwei Stellen erreichbar:
|
||
|
||
* **Hauptmenü → image → „Zugangsdaten prüfen"**
|
||
* **Einstellungen → „Checkmk-Image und Zugangsdaten" →
|
||
„>> Zugangsdaten jetzt prüfen"** – also direkt dort, wo Benutzer und
|
||
Kennwort eingetragen werden
|
||
|
||
Nach dem Ändern eines Zugangsdaten-Feldes fragt das Menü ausserdem von sich
|
||
aus, ob gleich geprüft werden soll.
|
||
|
||
### 8.5 Verfügbare Versionen auflisten
|
||
|
||
Statt Versionsnummern zu raten:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image versions --edition enterprise --filter 2.3.0p
|
||
```
|
||
|
||
Abgefragt werden bis zu drei Quellen:
|
||
|
||
| Quelle | `--source` | Zugangsdaten |
|
||
|---|---|---|
|
||
| Versionsarchiv von checkmk.com | `web` | **nein** |
|
||
| Registry (Docker Hub bzw. registry.checkmk.com) | `registry` | nur für Enterprise |
|
||
| Downloadportal (Verzeichnis-Listing) | `download` | ja |
|
||
|
||
> **Registry und Downloadportal führen nicht dasselbe.** Die Registry hält in
|
||
> der Regel nur die **jüngsten** Patchstände vor – bei `2.4.0` etwa `p31`
|
||
> aufwärts, dazu `2.4.0-latest` und die täglichen Bauten. Ältere Stände sind
|
||
> dort herausgerollt. Das Downloadportal ist dagegen ein **Archiv** und hat sie
|
||
> weiterhin.
|
||
>
|
||
> Das ist genau dann entscheidend, wenn eine **bestimmte** Version gebraucht
|
||
> wird – bei einer Migration nämlich, weil `omd restore` exakt die Version der
|
||
> Quell-Site verlangt ([Kapitel 17.4](#174-schritt-3--zielsystem-auf-die-richtige-version-bringen)).
|
||
> Für solche Fälle ist der Tarball der richtige Weg, nicht die Registry.
|
||
> `image why` weist von sich aus darauf hin, wenn ein Tag in der Registry
|
||
> fehlt, die Version im Archiv aber vorhanden ist.
|
||
|
||
Ohne `--source` werden alle drei versucht – so kommt auch ohne hinterlegte
|
||
Zugangsdaten eine brauchbare Liste zustande:
|
||
|
||
```
|
||
Versionsarchiv https://checkmk.com/download/archive
|
||
(oeffentlich, keine Zugangsdaten noetig)
|
||
2.3.0p50
|
||
2.3.0p49
|
||
2.3.0p48
|
||
...
|
||
|
||
Uebernehmen
|
||
aus der Registry : ./scripts/cmk-manage.sh image pull --edition enterprise --version <version>
|
||
als Tarball : ./scripts/cmk-manage.sh image download --edition enterprise --version <version>
|
||
nur eintragen : ./scripts/cmk-manage.sh config set CMK_VERSION <version>
|
||
```
|
||
|
||
Weitere Optionen: `--limit N` (Vorgabe 25), `--all`, `--filter TEXT` und
|
||
`--bare` für die nackte Liste ohne Rahmen – praktisch zum Weiterverarbeiten:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image versions --source web --filter 2.3.0p --bare | head -1
|
||
```
|
||
|
||
In der Oberfläche gibt es den Punkt **image → „Verfügbare Versionen
|
||
auflisten"**; beim Holen eines Images muss die Version ohnehin nicht mehr
|
||
abgetippt werden – dort erscheint eine Auswahlliste.
|
||
|
||
### 8.6 Image holen – ein Kommando, drei Wege
|
||
|
||
Stehen Edition und Version fest, genügt:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh image get
|
||
```
|
||
|
||
Woher geholt wird, steuert **`CMK_IMAGE_SOURCE`**:
|
||
|
||
| Wert | Wirkung |
|
||
|---|---|
|
||
| `auto` (Vorgabe) | erst die Registry, dann das Downloadportal |
|
||
| `registry` | nur aus der Registry |
|
||
| `download` | nur als Tarball vom Downloadportal |
|
||
|
||
Einmalig abweichen: `image get --source download`.
|
||
|
||
`auto` ist die sinnvolle Vorgabe, weil Registries nur die jüngsten Patchstände
|
||
vorhalten – eine ältere, für eine Migration nötige Version liegt dann nur noch
|
||
im Downloadportal. Der Wechsel geschieht automatisch, ohne Rückfrage.
|
||
|
||
**Beim `up` wird automatisch geholt.** Fehlt das Image lokal und sind Edition
|
||
und Version gesetzt, beschafft `up` es zuerst über diesen Weg – sonst versucht
|
||
compose einen nackten Pull, der bei einer nur im Archiv vorhandenen Version
|
||
scheitern muss:
|
||
|
||
```
|
||
[ INFO ] Das Image ist lokal nicht vorhanden - hole es (auto) ...
|
||
[ INFO ] Bezugsweg 'auto': zuerst die Registry ...
|
||
[ WARN ] Aus der Registry nicht zu bekommen - versuche das Downloadportal.
|
||
```
|
||
|
||
Mit `up --no-fetch` bleibt das aus.
|
||
|
||
In der Oberfläche liegt das unter **image → „Image holen"**. Dort wird nur noch
|
||
der Bezugsweg abgefragt – der eingestellte ist gekennzeichnet. Wer Edition oder
|
||
Version ändern will, wählt dort **„Etwas anderes waehlen"** oder gleich den
|
||
Assistenten.
|
||
|
||
#### Die Einzelschritte
|
||
|
||
> **In der Oberfläche geht das als Assistent:** **image → „Image beschaffen"**
|
||
> führt in einem Durchgang durch Edition, Version und Bezugsweg, setzt danach
|
||
> `CMK_EDITION`, `CMK_VERSION` **und** `CMK_IMAGE` und fragt **nicht** erneut
|
||
> nach Zugangsdaten, die schon in der `.env` stehen. Nur wenn sie für den
|
||
> gewählten Weg fehlen, werden sie erfragt – auf Wunsch gleich gespeichert.
|
||
> Derselbe Assistent liegt auch unter **Einstellungen → Checkmk-Image und
|
||
> Zugangsdaten → „>> Image beschaffen"**.
|
||
|
||
Auf der Kommandozeile bleiben die Einzelschritte:
|
||
|
||
**a) Aus einer Registry (empfohlen)**
|
||
|
||
Für die Enterprise-Edition entspricht das genau diesen beiden Schritten – das
|
||
Skript erledigt sie in einem Aufruf und trägt das Ergebnis in die `.env` ein:
|
||
|
||
```bash
|
||
podman login registry.checkmk.com # bzw. docker login
|
||
podman pull registry.checkmk.com/enterprise/check-mk-enterprise:2.3.0p9
|
||
```
|
||
|
||
|
||
```bash
|
||
# 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)**
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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 über `curl --config -` übergeben und erscheinen
|
||
daher nicht in der Prozessliste.
|
||
|
||
**c) Bereits heruntergeladene Datei einspielen**
|
||
|
||
Wer die Datei im Browser aus dem Kundenportal geladen hat:
|
||
|
||
```bash
|
||
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. `docker.io/checkmk/check-mk-enterprise:2.4.0p9`) und traegt
|
||
ihn als `CMK_IMAGE` in die `.env` ein. Danach:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh up
|
||
```
|
||
|
||
### 8.7 `CMK_IMAGE` gegenüber `CMK_EDITION`/`CMK_VERSION`
|
||
|
||
Diese drei Werte haben unterschiedliche Aufgaben, und das ist eine häufige
|
||
Verwechslung:
|
||
|
||
| Wert | Wer liest ihn | Wozu |
|
||
|---|---|---|
|
||
| **`CMK_IMAGE`** | **compose und die systemd-Units** | das Image, das tatsächlich gestartet wird |
|
||
| `CMK_EDITION` | nur `cmk-manage.sh image …` | Vorgabe für den Downloader |
|
||
| `CMK_VERSION` | nur `cmk-manage.sh image …` | Vorgabe für den Downloader |
|
||
|
||
`CMK_IMAGE` lässt sich **nicht** aus Edition und Version ableiten – je nach
|
||
Bezugsweg sieht dieselbe Version völlig anders aus:
|
||
|
||
```
|
||
docker.io/checkmk/check-mk-raw:2.3.0-latest (Docker Hub)
|
||
registry.checkmk.com/enterprise/check-mk-enterprise:2.3.0p9 (Registry)
|
||
docker.io/checkmk/check-mk-enterprise:2.4.0p9 (aus Tarball geladen)
|
||
```
|
||
|
||
> **Der Name nach `image download` überrascht.** Der Tarball trägt intern den
|
||
> unqualifizierten Namen `checkmk/check-mk-enterprise:<version>`, und Podman
|
||
> ergänzt daraus beim Einspielen `docker.io/` – obwohl es das Image dort gar
|
||
> nicht gibt. Das ist richtig und stört nicht: das Image liegt lokal, `up`
|
||
> verwendet es. Nur **pullen** ließe es sich unter diesem Namen nicht. Fehlt es
|
||
> später einmal, holt `image get` es wieder über das Downloadportal – nicht
|
||
> über `podman pull`.
|
||
|
||
Deshalb hält `CMK_IMAGE` fest, was **wirklich gilt**. Gesetzt wird der Wert von
|
||
`image pull`, `image download`, `image load` und `image use` – von Hand muss man
|
||
dort nichts eintragen. In der Oberfläche sind die drei Werte deshalb nicht
|
||
einzeln editierbar: der Assistent setzt sie gemeinsam. Auf der Kommandozeile
|
||
bleiben sie einzeln setzbar (`config set …`).
|
||
|
||
**Nur eintragen, ohne etwas herunterzuladen.** Aus Edition und Version lässt
|
||
sich die Referenz bilden – ein Download ist dafür nicht nötig:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image use --edition enterprise --version 2.4.0p9
|
||
# -> CMK_IMAGE=registry.checkmk.com/enterprise/check-mk-enterprise:2.4.0p9
|
||
# CMK_EDITION=enterprise
|
||
# CMK_VERSION=2.4.0p9
|
||
```
|
||
|
||
Das Image selbst holt die Runtime beim nächsten `up`. Im Assistenten heißt
|
||
dieser Weg **„Nur eintragen – geholt wird beim nächsten Start"**. Braucht die
|
||
Registry eine Anmeldung (Enterprise), muss die einmal erfolgt sein – entweder
|
||
über den Weg „Registry holen" oder mit
|
||
`podman login registry.checkmk.com`.
|
||
|
||
> **Alle vier Wege des Assistenten setzen `CMK_IMAGE`** – sie unterscheiden
|
||
> sich nur darin, ob dabei schon etwas geholt wird. Deshalb bleiben die drei
|
||
> Werte von selbst stimmig, und die Abweichungswarnung tritt im normalen
|
||
> Betrieb gar nicht mehr auf.
|
||
|
||
Auf der Kommandozeile übernehmen `image pull` und `image download` mit
|
||
`--remember` die Edition und Version gleich mit in die `.env`:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image pull --edition enterprise --version 2.3.0p9 --remember
|
||
```
|
||
|
||
> **Daraus folgt:** Edition oder Version zu ändern, startet **keine** andere
|
||
> Ausgabe. Erst `image pull` (bzw. `download`/`load`) schreibt das Ergebnis
|
||
> nach `CMK_IMAGE`, und erst `up` erstellt den Container neu.
|
||
|
||
Damit das nicht unbemerkt auseinanderläuft, prüft das Skript die drei Werte
|
||
gegeneinander – in `image status`, in `status` und im Einstellungsmenü direkt
|
||
nach dem Ändern von Edition oder Version:
|
||
|
||
```
|
||
[ WARN ] CMK_IMAGE passt nicht zu den eingestellten Vorgaben.
|
||
|
||
verwendet wird : docker.io/checkmk/check-mk-raw:2.3.0-latest
|
||
Edition : eingestellt "enterprise", im Image steckt "raw"
|
||
|
||
Compose und die systemd-Units verwenden ausschliesslich CMK_IMAGE.
|
||
...
|
||
./scripts/cmk-manage.sh image pull --edition enterprise --version 2.3.0-latest
|
||
./scripts/cmk-manage.sh up
|
||
```
|
||
|
||
Aus einem Tarball geladene Images (`localhost/…`) gelten dabei als stimmig,
|
||
solange Name und Tag passen.
|
||
|
||
**Wenn das Holen fehlschlägt**, bleibt `CMK_IMAGE` unverändert – das ist
|
||
Absicht, denn das alte Image läuft ja weiter. Der Assistent sagt das dann auch
|
||
ausdrücklich („Image wurde NICHT geholt") statt nur auf die Abweichung
|
||
hinzuweisen. Es bleibt trotzdem ein Zustand, in dem Edition und Version etwas
|
||
anderes behaupten als das benutzte Image. Dafür gibt es zwei Auswege – beide
|
||
im Menü unter den drei Werten:
|
||
|
||
| Weg | Richtung | Wirkung |
|
||
|---|---|---|
|
||
| **Assistent starten** | – | führt durch Edition, Version und Bezugsweg |
|
||
| **Image aus den Vorgaben setzen** | Edition/Version → Image | bildet die Referenz und trägt sie ein, **ohne etwas zu laden**; der Menüeintrag zeigt gleich, was dabei herauskommt |
|
||
| **Vorgaben aus dem Image ableiten** | Image → Edition/Version | schreibt Edition und Version aus `CMK_IMAGE` zurück; am Betrieb ändert sich nichts |
|
||
|
||
Auf der Kommandozeile ist das zweite:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image use "$CMK_IMAGE" --remember
|
||
```
|
||
|
||
### 8.8 Registry-Pfad herausfinden
|
||
|
||
„Login Succeeded" heisst noch nicht, dass der Pfad stimmt. Meldet der Pull
|
||
`unable to copy from source docker://…`, existiert das Repository unter diesem
|
||
Namen nicht oder die Subskription deckt es nicht ab:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image repos --edition enterprise
|
||
```
|
||
|
||
Das fragt zuerst den Katalog (`/v2/_catalog`) ab – den sperren allerdings viele
|
||
Registries – und probiert danach die üblichen Pfade durch:
|
||
|
||
```
|
||
Uebliche Pfade fuer "raw" durchprobiert
|
||
STATUS TAGS PFAD
|
||
200 = nutzbar, 404 = gibt es nicht, 401/403 = kein Zugriff
|
||
401 - raw/check-mk-raw (kein Zugriff - oder gibt es nicht)
|
||
200 2394 checkmk/check-mk-raw
|
||
...
|
||
[ OK ] Nutzbar: docker.io/checkmk/check-mk-raw
|
||
```
|
||
|
||
Scheitert ein `image pull` gegen eine private Registry, läuft diese Prüfung
|
||
automatisch an und zeigt gleich, was dort wirklich liegt.
|
||
|
||
> **401 heisst nicht zwingend „vorhanden".** Viele Registries – Docker Hub
|
||
> zum Beispiel – antworten auch auf nicht existierende Repositories mit 401,
|
||
> um deren Existenz nicht zu verraten. Verlässlich ist nur **200 = nutzbar**
|
||
> und **404 = gibt es nicht**.
|
||
|
||
Führt kein Pfad zum Ziel, bleibt der Tarball-Weg. Er ist für Enterprise
|
||
ohnehin der dokumentierte und funktioniert unabhängig von der Registry:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh image download --edition enterprise --version 2.4.0p9
|
||
```
|
||
|
||
### 8.9 Nachsehen, was gilt
|
||
|
||
```bash
|
||
./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
|
||
|
||
```bash
|
||
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/
|
||
```
|
||
|
||
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
|
||
|
||
### 10.1 Das Administratorkonto
|
||
|
||
> **Die früher üblichen Standardzugangsdaten `admin@example.com` / `changeme`
|
||
> gibt es seit Version 2.15 nicht mehr.** Der Container legt das erste Konto
|
||
> nur noch an, wenn beim **ersten** Start `INITIAL_ADMIN_EMAIL` und
|
||
> `INITIAL_ADMIN_PASSWORD` gesetzt sind – sonst erscheint im Browser ein
|
||
> Einrichtungsassistent. Nachgelesen in `backend/setup.js` von v2.15.1 und am
|
||
> laufenden Container überprüft.
|
||
|
||
Deshalb stehen die Werte in der `.env` und werden von `docker-compose.yml`
|
||
durchgereicht:
|
||
|
||
```bash
|
||
NPM_ADMIN_EMAIL=admin@example.com
|
||
NPM_ADMIN_PASSWORD=ein-ordentliches-kennwort
|
||
```
|
||
|
||
Beides **vor dem ersten Start** setzen. Dann ist das Konto sofort da – und
|
||
damit auch die REST-Schnittstelle nutzbar, über die
|
||
[Kapitel 10.2](#102-proxy-host-anlegen--ohne-browser) den Proxy-Host anlegt.
|
||
|
||
Ist der Stack schon gelaufen und das Konto von Hand über den Assistenten
|
||
angelegt worden, wirken die Variablen nicht mehr (die Datenbank ist nicht mehr
|
||
leer). Dann einfach die selbst vergebenen Zugangsdaten eintragen – das Skript
|
||
meldet sich damit an.
|
||
|
||
#### Wenn die Anmeldung fehlt
|
||
|
||
Fehlen die Zugangsdaten, sagt das Skript je nach Lage, was zu tun ist – es
|
||
sieht dafür nach, ob `data/npm/data/database.sqlite` schon existiert:
|
||
|
||
| Lage | Weg |
|
||
|---|---|
|
||
| **noch keine Datenbank** | `config set NPM_ADMIN_EMAIL …` und `…_PASSWORD …`, dann `up` – der Container legt das Konto selbst an |
|
||
| **Datenbank vorhanden** | Konto im Browser anlegen (`cmk-manage.sh browser`), dieselben Daten anschließend mit `config set` eintragen |
|
||
|
||
Wer lieber sauber neu beginnt – in der Oberfläche unter **Einstellungen →
|
||
NGINX Proxy Manager → „>> Datenbank zurücksetzen"** oder auch im
|
||
**Proxy-Hosts**-Menü, auf der Kommandozeile:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh npm-reset
|
||
```
|
||
|
||
Das legt die Datenbank beiseite (umbenannt, nicht gelöscht), sodass der
|
||
Container beim nächsten `up` das Konto aus `NPM_ADMIN_EMAIL`/`NPM_ADMIN_PASSWORD`
|
||
neu anlegt. **Proxy-Hosts, Weiterleitungen und Zugriffslisten sind damit weg**
|
||
– die Zertifikate bleiben. Das Kommando zeigt vorher genau das an und fragt
|
||
nach. Die Proxy-Hosts lassen sich mit `proxy add` in einem Aufruf neu anlegen.
|
||
|
||
### 10.2 Proxy-Host anlegen – ohne Browser
|
||
|
||
Die Weboberfläche lässt sich im Terminal-Browser nur mühsam bedienen; Formulare
|
||
mit Datei-Upload funktionieren dort gar nicht. Da der Proxy Manager ohnehin
|
||
lokal läuft, ist die Schnittstelle der verlässlichere Weg:
|
||
|
||
```bash
|
||
# Checkmk unter checkmk.example.com veröffentlichen, mit selbstsigniertem Zertifikat
|
||
sudo ./scripts/cmk-manage.sh proxy add --domain checkmk.example.com --cert self
|
||
|
||
# oder mit Let's Encrypt (Port 80 muss aus dem Internet erreichbar sein)
|
||
sudo ./scripts/cmk-manage.sh proxy add --domain checkmk.example.com --cert letsencrypt
|
||
|
||
# auf einen anderen Zielport statt 5000
|
||
sudo ./scripts/cmk-manage.sh proxy add --domain checkmk.example.com --forward-port 8080
|
||
```
|
||
|
||
Das Kommando erledigt in einem Zug: Zertifikat erzeugen (bzw. bei Let's
|
||
Encrypt anfordern), in den Proxy Manager hochladen, Proxy-Host anlegen, HTTPS
|
||
erzwingen, HTTP/2 und Websockets einschalten und den empfohlenen
|
||
`advanced_config`-Abschnitt setzen.
|
||
|
||
| Kommando | Wirkung |
|
||
|---|---|
|
||
| `proxy status` | Anmeldung prüfen, Anzahl Hosts und Zertifikate |
|
||
| `proxy list` | vorhandene Proxy-Hosts |
|
||
| `proxy certs` | vorhandene Zertifikate mit Ablaufdatum |
|
||
| `proxy add …` | Proxy-Host anlegen (`--update` ersetzt einen vorhandenen) |
|
||
| `proxy show --domain X` | Einzelheiten samt zusätzlicher Pfade |
|
||
| `proxy del --id N` | Proxy-Host löschen |
|
||
| `proxy edit --id N …` | vorhandenen Proxy-Host ändern – nur die angegebenen Felder |
|
||
| `proxy default --domain X` | HTTPS über die blanke IP ermöglichen (spiegelt X in einen Standard-Server) |
|
||
| `proxy default --off` | diese Spiegelung wieder entfernen |
|
||
| `proxy admin --domain X` / `--root` | Adminoberfläche erreichbar machen – per Name oder über die Wurzel |
|
||
| `proxy check` | antwortet hinter jedem Pfad etwas? (aus dem Proxy-Container geprüft) |
|
||
| `proxy reload` | nginx die Konfiguration neu einlesen lassen – ohne Unterbrechung |
|
||
| `proxy restart` | den Proxy-Manager-Container neu starten |
|
||
|
||
Optionen von `proxy add`:
|
||
|
||
| Option | Vorgabe | Bedeutung |
|
||
|---|---|---|
|
||
| `--domain FQDN` | `PROXY_DOMAIN` | öffentlicher Name |
|
||
| `--forward-host H` | `127.0.0.1` | Weiterleitungsziel |
|
||
| `--forward-port P` | `5000` | Zielport – **frei wählbar**, nicht auf Checkmk festgelegt |
|
||
| `--scheme http\|https` | `http` | Schema zum Ziel |
|
||
| `--cert self\|letsencrypt\|none` | `self` | Zertifikat |
|
||
| `--update` | – | vorhandenen Eintrag ersetzen |
|
||
| `--advanced TEXT` | siehe unten | eigener nginx-Abschnitt |
|
||
| `--location /P=HOST:PORT` | – | weiterer Dienst unter einem Pfad, mehrfach angebbar – siehe [10.3](#103-mehrere-dienste-hinter-einem-port-pfade-statt-namen) |
|
||
| `--no-force-ssl`, `--no-http2`, `--no-websockets`, `--no-block-exploits` | – | Abschalter |
|
||
|
||
#### Der `advanced_config`-Abschnitt
|
||
|
||
Ohne `--advanced` setzt `proxy add` diesen Block – dieselben vier Zeilen, die
|
||
man sonst im Reiter **Advanced** von Hand einträgt:
|
||
|
||
```nginx
|
||
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;
|
||
```
|
||
|
||
Wozu die vier:
|
||
|
||
| Zeile | Grund |
|
||
|---|---|
|
||
| `client_max_body_size 0` | hebt die Größenbegrenzung auf – sonst scheitern große Agent-Uploads und Bakery-Pakete |
|
||
| `proxy_read_timeout 300s` | lange laufende Checkmk-Ansichten laufen sonst in eine Zeitüberschreitung |
|
||
| `X-Forwarded-Proto` | Checkmk erzeugt sonst `http://`-Verweise hinter dem HTTPS-Proxy |
|
||
| `X-Forwarded-For` | im Checkmk-Zugriffsprotokoll steht sonst nur die Proxy-Adresse statt der echten Client-IP |
|
||
|
||
Ersetzen (nicht ergänzen) lässt sich der Block mit `--advanced`:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh proxy add --domain checkmk.example.com \
|
||
--advanced 'client_max_body_size 0;
|
||
proxy_read_timeout 600s;'
|
||
```
|
||
|
||
Mit `--advanced ''` bleibt das Feld leer. Der Assistent in der Oberfläche
|
||
verwendet immer die Vorgabe oben; wer etwas anderes braucht, nimmt die
|
||
Kommandozeile oder passt den Eintrag anschließend im Proxy Manager an.
|
||
|
||
In der Oberfläche liegt derselbe Ablauf unter **proxy → „Proxy-Host anlegen"**
|
||
(Name → Zielport → Zertifikat) sowie unter **Einstellungen → NGINX Proxy
|
||
Manager → „>> Proxy-Hosts anlegen/verwalten"**.
|
||
|
||
> Ein selbstsigniertes Zertifikat wird bei wiederholtem Aufruf
|
||
> **wiederverwendet** statt jedes Mal neu angelegt – sonst sammeln sich im
|
||
> Proxy Manager Dutzende Einträge gleichen Namens an.
|
||
|
||
### 10.3 Mehrere Dienste hinter einem Port (Pfade statt Namen)
|
||
|
||
Der typische Fall: von außen ist **nur ein Port** erreichbar, auf dem Server
|
||
laufen aber mehrere Oberflächen – Checkmk, Grafana, vielleicht noch etwas. Statt
|
||
für jeden Dienst einen eigenen Namen zu brauchen, lassen sie sich über den
|
||
**Pfad** unterscheiden:
|
||
|
||
```
|
||
https://10.0.0.5/cmk/ -> Checkmk (127.0.0.1:5000)
|
||
https://10.0.0.5/grafana -> Grafana (127.0.0.1:3000)
|
||
https://10.0.0.5/sonstwas -> ein weiterer Dienst
|
||
```
|
||
|
||
Genau dafür ist der Proxy Manager da. In einem Aufruf:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh proxy add \
|
||
--domain 10.0.0.5 \
|
||
--forward-port 5000 \
|
||
--cert self \
|
||
--location /grafana=127.0.0.1:3000 \
|
||
--location /sonstwas=127.0.0.1:8080
|
||
```
|
||
|
||
* `--domain` darf eine **IP-Adresse** sein – ein DNS-Name ist nicht nötig.
|
||
(Die Schnittstelle akzeptiert alles außer einer Handvoll Sonderzeichen.)
|
||
* `--forward-port` ist das Ziel für alles, was **nicht** von einem Pfad
|
||
abgedeckt ist – hier Checkmk.
|
||
* `--location` ist beliebig oft angebbar. Schreibweise
|
||
`/pfad=host:port`, wahlweise mit Schema (`https://host:port`) und mit einem
|
||
Pfad, der beim Ziel vorangestellt wird (`/alt=host:3000/basis`).
|
||
|
||
Anzeigen lässt sich das Ergebnis mit:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy show --domain 10.0.0.5
|
||
```
|
||
|
||
In der Oberfläche fragt der Assistent nach dem Zertifikat, ob weitere Dienste
|
||
unter demselben Namen liegen sollen, und nimmt dann Pfad und Ziel im Wechsel
|
||
auf, bis man ein Feld leer lässt.
|
||
|
||
> **Die Pfadliste ist vollständig zu verstehen.** `proxy add --update`
|
||
> ersetzt den Eintrag mitsamt allen Pfaden. Wer später einen Pfad ergänzt, gibt
|
||
> die bereits vorhandenen also wieder mit an – `proxy show` zeigt, welche das
|
||
> sind.
|
||
|
||
#### Was die Dienste selbst wissen müssen
|
||
|
||
Ein Dienst hinter einem Unterpfad erzeugt sonst Verweise auf `/`, die ins Leere
|
||
gehen. **Checkmk** ist davon nicht betroffen – es liegt ohnehin unter
|
||
`/<site>/`. Andere brauchen eine Einstellung:
|
||
|
||
**Grafana** (`/etc/grafana/grafana.ini` bzw. `GF_*`-Umgebungsvariablen):
|
||
|
||
```ini
|
||
[server]
|
||
domain = 10.0.0.5
|
||
root_url = %(protocol)s://%(domain)s/grafana/
|
||
serve_from_sub_path = true
|
||
```
|
||
|
||
Als Container:
|
||
|
||
```yaml
|
||
environment:
|
||
GF_SERVER_ROOT_URL: https://10.0.0.5/grafana/
|
||
GF_SERVER_SERVE_FROM_SUB_PATH: "true"
|
||
```
|
||
|
||
Bleibt das aus, lädt Grafana zwar, sucht sein JavaScript aber unter
|
||
`https://10.0.0.5/public/...` statt `/grafana/public/...` – die Seite bleibt
|
||
weiß. Dasselbe gilt sinngemäß für jeden anderen Dienst: er muss seinen
|
||
Basispfad kennen.
|
||
|
||
#### Warum überhaupt der Proxy Manager
|
||
|
||
Alle Container laufen im Host-Netzwerk, die Dienste hören also direkt auf ihren
|
||
Ports (Checkmk 5000, Grafana 3000, …). Nach außen geben Sie davon **keinen**
|
||
frei – nur 443. Der Proxy Manager verteilt dahinter nach Pfad und erledigt
|
||
zugleich die HTTPS-Terminierung mit einem Zertifikat für alle Dienste.
|
||
|
||
```
|
||
Internet / LAN
|
||
|
|
||
:443 (einziger offener Port)
|
||
|
|
||
NGINX Proxy Manager
|
||
| | |
|
||
/cmk/ /grafana /sonstwas
|
||
| | |
|
||
:5000 :3000 :8080 (nur auf localhost)
|
||
```
|
||
|
||
### 10.4 Wenn doch die Weboberfläche
|
||
|
||
1. `http://<server>:81` aufrufen – bzw. den in `NPM_ADMIN_PORT` gesetzten Port
|
||
(siehe [Kapitel 12](#12-adminoberfläche-auf-einen-anderen-port-legen));
|
||
ist der Port im Netz gesperrt, hilft der Terminal-Browser aus
|
||
[Kapitel 11](#11-proxy-manager-lokal-einrichten-terminal-browser)
|
||
2. Anmelden mit `NPM_ADMIN_EMAIL` / `NPM_ADMIN_PASSWORD`
|
||
|
||
### 10.5 Proxy-Host im Browser 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):
|
||
|
||
```nginx
|
||
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;
|
||
```
|
||
|
||
### 10.6 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).
|
||
|
||
### 10.7 Variante B – Selbstsigniertes Zertifikat (interne Umgebung)
|
||
|
||
Erzeugen:
|
||
|
||
```bash
|
||
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“*.
|
||
|
||
### 10.8 HTTPS über die blanke IP
|
||
|
||
Ruft man den Server als `https://172.0.250.82/cmk/` auf, endet das im Browser
|
||
mit **`ERR_SSL_UNRECOGNIZED_NAME_ALERT`** – über `http://` funktioniert
|
||
dieselbe Adresse. Das liegt nicht am Zertifikat.
|
||
|
||
Der Grund steckt in TLS: Der Browser teilt dem Server beim Verbindungsaufbau
|
||
mit, welchen Namen er sprechen will (*SNI*). Laut RFC 6066 dürfen dort **keine
|
||
IP-Adressen** stehen, also sendet der Browser bei einer IP gar nichts. nginx
|
||
kann den passenden Server-Block dann nicht über den Namen auswählen und fällt
|
||
auf seinen Standard-Server zurück. Bei NPM ist das dieser Block aus
|
||
`/etc/nginx/conf.d/default.conf`:
|
||
|
||
```nginx
|
||
server {
|
||
listen 443 ssl;
|
||
server_name localhost;
|
||
ssl_reject_handshake on; # <- genau das meldet der Browser
|
||
return 444;
|
||
}
|
||
```
|
||
|
||
Über HTTP fällt es nicht auf, weil nginx den Server-Block dort am `Host`-Kopf
|
||
erkennt – und der trägt die IP.
|
||
|
||
Abhilfe ist ein eigener Standard-Server, der diese namenlosen Aufrufe annimmt:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh proxy default --domain checkmk.example.local --restart
|
||
```
|
||
|
||
Der Befehl liest den genannten Proxy-Host über die API aus und spiegelt ihn –
|
||
Ziel, Zertifikat und **alle zusätzlichen Pfade** – in einen Block mit
|
||
`default_server`, der in die Zusatzkonfiguration geschrieben wird. Aufrufe mit
|
||
Namen bleiben unberührt: nginx wählt weiterhin zuerst nach SNI aus, der
|
||
Standard-Server greift nur, wenn kein Name passt. Keiner der von NPM erzeugten
|
||
Blöcke setzt `default_server` selbst, deshalb gibt es darum keinen Streit.
|
||
|
||
| Befehl | Wirkung |
|
||
|---|---|
|
||
| `proxy default` | zeigt, ob eingerichtet, und welchen Proxy-Host es spiegelt |
|
||
| `proxy default --domain X` | Proxy-Host `X` spiegeln |
|
||
| `proxy default --off` | Spiegelung entfernen |
|
||
| `--restart` | den Proxy Manager gleich neu starten |
|
||
|
||
In der Oberfläche liegt das unter **Proxy-Hosts → HTTPS über die blanke IP
|
||
(ohne Namen) ermöglichen**.
|
||
|
||
Zwei Dinge sind zu beachten:
|
||
|
||
- Das **Zertifikat muss die IP als Alternativnamen führen**, sonst meldet der
|
||
Browser einen Namensfehler (anklickbar, aber unschön). `cmk-manage.sh cert`
|
||
und `proxy add --cert self` tragen die IP des Hosts von sich aus ein; bei
|
||
einem Let's-Encrypt-Zertifikat geht das prinzipbedingt nicht – dafür gibt es
|
||
keine Zertifikate auf IP-Adressen. Der Befehl prüft das und sagt es.
|
||
- Die Zusatzkonfiguration liegt im Datenverzeichnis des Proxy Managers, und das
|
||
gehört dem Container. Deshalb **mit `sudo`** aufrufen.
|
||
|
||
Die saubere Alternative bleibt ein Name: ein DNS-Eintrag oder eine Zeile in der
|
||
`hosts`-Datei der Clients genügt, damit der Browser SNI sendet und der
|
||
Proxy-Host ganz normal greift.
|
||
|
||
### 10.9 Einen Proxy-Host ändern
|
||
|
||
`proxy add --update` schreibt den Eintrag **vollständig** neu – wer damit nur
|
||
den Port ändern will, verliert unbeabsichtigt die Pfade und die erweiterte
|
||
Konfiguration. Dafür gibt es `proxy edit`: angegeben wird nur, was sich ändern
|
||
soll, alles Übrige bleibt unangetastet.
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy edit --id 3 --forward-port 5001
|
||
./scripts/cmk-manage.sh proxy edit --domain checkmk.example.local --cert self
|
||
./scripts/cmk-manage.sh proxy edit --id 3 --location /grafana=127.0.0.1:3000
|
||
./scripts/cmk-manage.sh proxy edit --id 3 --del-location /grafana
|
||
./scripts/cmk-manage.sh proxy edit --id 3 # nur ansehen
|
||
```
|
||
|
||
Der Eintrag wird über `--id` oder `--domain` gewählt.
|
||
|
||
| Option | Ändert |
|
||
|---|---|
|
||
| `--rename NAME` | den Domainnamen |
|
||
| `--forward-host HOST`, `--forward-port PORT` | das Weiterleitungsziel |
|
||
| `--scheme http\|https` | wie der Proxy das Ziel anspricht |
|
||
| `--cert self\|letsencrypt\|none\|ID` | das Zertifikat |
|
||
| `--advanced 'TEXT'` | die erweiterte nginx-Konfiguration (`\n` trennt Zeilen) |
|
||
| `--force-ssl`, `--http2`, `--websockets`, `--block-exploits` | jeweils `on`/`off` |
|
||
| `--enable`, `--disable` | den Eintrag ein- oder ausschalten |
|
||
| `--location /pfad=host:port` | einen Pfad hinzufügen oder ersetzen |
|
||
| `--del-location /pfad` | einen Pfad entfernen |
|
||
|
||
Zwei Dinge sind dabei zu wissen:
|
||
|
||
- **Pfade** kennt die Schnittstelle nur als Ganzes. `--location` und
|
||
`--del-location` lesen deshalb den Bestand, ändern den einen Eintrag und
|
||
schreiben die Liste zurück. Hatte ein ersetzter Pfad eine eigene erweiterte
|
||
Konfiguration, wird das vorher gesagt.
|
||
- Der Proxy Manager **biegt manches still zurecht**: ohne Zertifikat schaltet
|
||
er `http2_support` und `ssl_forced` von sich aus ab. `proxy edit` vergleicht
|
||
danach, was gespeichert wurde, und meldet eine Abweichung – sonst sucht man
|
||
den Fehler später an der falschen Stelle.
|
||
|
||
In der Oberfläche liegt dasselbe unter **Proxy-Hosts → Proxy-Host bearbeiten**;
|
||
dort sind die Felder mit den aktuellen Werten vorbelegt, und die Schalter
|
||
stehen als Auswahlliste bereit.
|
||
|
||
> Wurde der Standard-Server für den IP-Zugang eingerichtet
|
||
> ([Kapitel 10.8](#108-https-über-die-blanke-ip)), spiegelt er einen Stand von
|
||
> vorher. Nach inhaltlichen Änderungen neu schreiben – `proxy edit` erinnert
|
||
> daran.
|
||
|
||
### 10.10 Änderungen wirksam machen
|
||
|
||
Was über die API läuft – Proxy-Hosts anlegen, ändern, löschen –, schreibt der
|
||
Proxy Manager selbst und lädt nginx dabei neu. Die **Zusatzkonfiguration**
|
||
dagegen (der Standard-Server aus [Kapitel 10.8](#108-https-über-die-blanke-ip),
|
||
der Adminport aus [Kapitel 12](#12-adminoberfläche-auf-einen-anderen-port-legen))
|
||
liegt als Datei im Datenverzeichnis und wird erst beim nächsten Einlesen
|
||
beachtet:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy reload # nginx neu einlesen, ohne Unterbrechung
|
||
./scripts/cmk-manage.sh proxy restart # Container neu starten
|
||
```
|
||
|
||
`reload` prüft die Konfiguration **vorher** mit `nginx -t` und lädt nur dann
|
||
neu. Ist etwas kaputt, steht die Ursache samt Zeilennummer da, und es passiert
|
||
nichts:
|
||
|
||
```
|
||
[FEHLER] Die nginx-Konfiguration ist fehlerhaft - es wird nichts neu geladen.
|
||
nginx: [emerg] invalid parameter "kaputt" in /data/nginx/custom/http.conf:1
|
||
```
|
||
|
||
`restart` ist nur nötig, wenn sich Umgebungsvariablen geändert haben oder nginx
|
||
gar nicht mehr antwortet. Er wartet danach, bis nginx wieder läuft **und** die
|
||
Adminoberfläche antwortet – nginx ist nach einer Sekunde zurück, der Dienst
|
||
dahinter braucht länger, und ein „fertig" wäre sonst gelogen.
|
||
|
||
In der Oberfläche liegt beides unter **Proxy-Hosts → Proxy Manager neu starten
|
||
/ nginx neu laden**.
|
||
|
||
### 10.11 Die Adminoberfläche des Proxy Managers erreichbar machen
|
||
|
||
Sie ist eine Single-Page-Anwendung und lädt ihre Dateien über **absolute**
|
||
Pfade:
|
||
|
||
```html
|
||
<link rel="preload" href="/images/logo-no-text.svg" ...>
|
||
```
|
||
|
||
Unter einem Unterpfad wie `/npm` kommt deshalb nur die Startseite an, alles
|
||
Weitere landet bei dem, was auf der Wurzel liegt – im Browser eine **weiße
|
||
Seite**. Gemessen an einem laufenden Proxy Manager:
|
||
|
||
| Zugriff | `/` | `/images/…` | Anmeldung (`POST /api/tokens`) |
|
||
|---|---|---|---|
|
||
| Unterpfad `/npm` | 200 | **502** | – |
|
||
| eigener Name | 200 | 200 | 200 |
|
||
| Wurzel | 200 | 200 | 200 |
|
||
|
||
Checkmk funktioniert unter `/cmk/` nur deshalb, weil es für einen URL-Präfix
|
||
gebaut ist und ihn in jede erzeugte Adresse einsetzt. Der Proxy Manager kann
|
||
das nicht. Es bleiben zwei Wege – **beide kommen mit dem einen freien Port
|
||
aus**:
|
||
|
||
**Variante A – eigener Name** (wenn es Namensauflösung gibt):
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy admin --domain npm.example.local
|
||
./scripts/cmk-manage.sh proxy reload
|
||
```
|
||
|
||
Legt einen Proxy-Host an, der auf `127.0.0.1:81` zeigt – die Oberfläche liegt
|
||
dort auf `/`, alles funktioniert. Checkmk bleibt unter seinem eigenen Namen
|
||
oder unter der IP erreichbar; welcher Server-Block greift, entscheidet der
|
||
Name (SNI), nicht der Port. Ohne DNS genügt eine Zeile in der `hosts`-Datei
|
||
der Arbeitsplätze.
|
||
|
||
**Variante B – Wurzel** (wenn es *keine* Namensauflösung gibt):
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy admin --root
|
||
./scripts/cmk-manage.sh proxy default --domain <name> --restart # falls eingerichtet
|
||
```
|
||
|
||
Die Wurzel des vorhandenen Proxy-Hosts zeigt danach auf die Adminoberfläche,
|
||
das bisherige Ziel wandert auf `/cmk` (bzw. `CMK_SITE_ID`):
|
||
|
||
```
|
||
https://172.0.250.82/ Adminoberfläche des Proxy Managers
|
||
https://172.0.250.82/cmk/ Checkmk
|
||
```
|
||
|
||
Das geht, weil Checkmk nur seinen Site-Pfad belegt – der Rest der Wurzel ist
|
||
frei. Zurück:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy admin --root --off
|
||
```
|
||
|
||
> Bei Variante B liegt die **Anmeldemaske offen im Netz**. Für die Dauer einer
|
||
> Einrichtung ist das vertretbar; danach entweder zurücknehmen oder den Zugang
|
||
> per Firewall auf das Adminnetz begrenzen.
|
||
|
||
Weitere Angaben: `--id N` bzw. `--host NAME`, wenn es mehrere Proxy-Hosts gibt,
|
||
`--path /pfad` für einen abweichenden Site-Pfad, `--cert self|letsencrypt|none`
|
||
bei Variante A. Ohne Angabe zeigt `proxy admin` den Stand.
|
||
|
||
In der Oberfläche liegt beides unter **Proxy-Hosts → Adminoberfläche erreichbar
|
||
machen**.
|
||
|
||
### 10.12 Weitere Dienste dazunehmen – Beispiel Grafana
|
||
|
||
Mit einem einzigen freien Port lassen sich mehrere Dienste über Pfade
|
||
auseinanderhalten:
|
||
|
||
```
|
||
https://172.0.250.82/ Adminoberfläche des Proxy Managers
|
||
https://172.0.250.82/cmk/ Checkmk
|
||
https://172.0.250.82/grafana/ Grafana
|
||
```
|
||
|
||
Ob ein Dienst das mitmacht, hängt an ihm selbst – nicht am Proxy. Er muss
|
||
wissen, dass er unter einem Präfix liegt, und ihn in jede Adresse einsetzen,
|
||
die er erzeugt. Checkmk kann das von Haus aus (der Site-Pfad *ist* der
|
||
Präfix), die Oberfläche des Proxy Managers kann es gar nicht
|
||
([Kapitel 10.11](#1011-die-adminoberfläche-des-proxy-managers-erreichbar-machen)),
|
||
**Grafana kann es, wenn man es ihm sagt**:
|
||
|
||
```yaml
|
||
# docker-compose.yml, Dienst grafana
|
||
environment:
|
||
GF_SERVER_ROOT_URL: "https://172.0.250.82/grafana/"
|
||
GF_SERVER_SERVE_FROM_SUB_PATH: "true"
|
||
```
|
||
|
||
Gleichwertig in der `grafana.ini`:
|
||
|
||
```ini
|
||
[server]
|
||
root_url = https://172.0.250.82/grafana/
|
||
serve_from_sub_path = true
|
||
```
|
||
|
||
Damit setzt Grafana ein `<base href="/grafana/" />` in seine Seiten, und alle
|
||
Dateien werden relativ dazu geladen. Ohne die beiden Zeilen leitet es auf
|
||
`/login` um – also auf die Wurzel, wo etwas ganz anderes liegt. Gemessen:
|
||
|
||
| Grafana-Einstellung | `/grafana/login` | Dateien der Seite |
|
||
|---|---|---|
|
||
| ohne `serve_from_sub_path` | 302 auf `/login` | gehen an die Wurzel |
|
||
| mit `root_url` + `serve_from_sub_path` | 200 | `/grafana/public/…` → 200 |
|
||
|
||
Auf der Proxy-Seite ist es dann ein Pfad mehr:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy edit --id 1 --location /grafana=127.0.0.1:3000
|
||
./scripts/cmk-manage.sh proxy default --domain <name> --restart # falls eingerichtet
|
||
./scripts/cmk-manage.sh proxy check
|
||
```
|
||
|
||
`proxy check` fragt jedes Ziel **aus dem Proxy-Container heraus** ab – von dort
|
||
baut nginx die Verbindung auf, nicht von deinem Arbeitsplatz:
|
||
|
||
```
|
||
Proxy-Host 1 stack.local
|
||
PFAD ZIEL ANTWORT
|
||
/ http://127.0.0.1:81 HTTP 200
|
||
/grafana http://127.0.0.1:3000 HTTP 302
|
||
/cmk http://127.0.0.1:9999 nicht erreichbar
|
||
```
|
||
|
||
Genau so findet man einen Tippfehler in der Zieladresse, bevor der Browser
|
||
`502 Bad Gateway` zeigt. In der Oberfläche liegt das unter **Proxy-Hosts →
|
||
Ziele prüfen**.
|
||
|
||
> Port **3000 bleibt in der Firewall zu**. Grafana wird ausschließlich über den
|
||
> Proxy erreicht, genau wie Checkmk auf 5000. `firewall close` bietet einen
|
||
> versehentlich geöffneten Port wieder an.
|
||
|
||
### 10.13 Ein von außen geliefertes Zertifikat verwenden
|
||
|
||
Wenn eine fremde Stelle das Zertifikat in ein Verzeichnis legt und es beim
|
||
Erneuern dort **ersetzt** – gleicher Dateiname, neuer Inhalt –, passt der
|
||
übliche Weg nicht: Der Proxy Manager kopiert hochgeladene Zertifikate nach
|
||
`/data/custom_ssl/npm-<id>/` und bekommt von einer ersetzten Datei nichts mit.
|
||
|
||
Deshalb wird das Verzeichnis **schreibgeschützt als `/certs` in den Container
|
||
gehängt**, und die beiden Dateien unter `custom_ssl` werden durch Verweise
|
||
darauf ersetzt:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh config set CERT_EXTERNAL_DIR /etc/ssl/kunde
|
||
./scripts/cmk-manage.sh up # Container neu erstellen, damit er /certs sieht
|
||
./scripts/cmk-manage.sh cert external --domain kunde.example.com
|
||
```
|
||
|
||
| Einstellung | Bedeutung |
|
||
|---|---|
|
||
| `CERT_EXTERNAL_DIR` | Verzeichnis auf dem Host (Vorgabe `./data/npm/external-certs`) |
|
||
| `CERT_EXTERNAL_FULLCHAIN` | Dateiname der Zertifikatskette (Vorgabe `fullchain.pem`) |
|
||
| `CERT_EXTERNAL_KEY` | Dateiname des privaten Schlüssels (Vorgabe `privkey.pem`) |
|
||
| `CERT_EXTERNAL_WATCH` | täglich auf Austausch prüfen (`on`/`off`) |
|
||
|
||
Vor dem Umstellen wird geprüft, ob beide Dateien lesbar sind, **ob Zertifikat
|
||
und Schlüssel zusammengehören** (Vergleich der öffentlichen Schlüssel) und wie
|
||
lange es noch gilt:
|
||
|
||
```
|
||
[FEHLER] Zertifikat und Schluessel gehoeren nicht zusammen.
|
||
[ WARN ] Das Zertifikat laeuft in weniger als 14 Tagen ab (Sep 25 20:03:58 2026 GMT).
|
||
```
|
||
|
||
**Der Austausch allein genügt nicht.** nginx liest Zertifikatsdateien beim
|
||
Start und beim Neuladen – nachgemessen an einem ausgetauschten Zertifikat:
|
||
|
||
| | ausgeliefert |
|
||
|---|---|
|
||
| Datei ersetzt, kein Neuladen | **altes** Zertifikat |
|
||
| nach `nginx -s reload` | neues Zertifikat |
|
||
|
||
Dafür gibt es zwei Wege:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh cert external --refresh # einmalig, lädt nur bei Änderung neu
|
||
sudo ./scripts/cmk-manage.sh cert external --watch on # täglich per cron
|
||
```
|
||
|
||
`--refresh` vergleicht den SHA256-Fingerabdruck mit dem zuletzt gesehenen
|
||
(`cert-external.state`) und lädt nginx nur dann neu. Der Wächter schreibt dafür
|
||
`/etc/cron.d/checkmk-cert-external`.
|
||
|
||
Zurück auf eine eigene Kopie – danach lebt der Proxy Manager wieder mit seinen
|
||
eigenen Dateien weiter:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh cert external --off --id 3
|
||
```
|
||
|
||
`cert external` ohne Angabe zeigt den Stand: Verzeichnis, Ablaufdatum,
|
||
Aussteller, ob `/certs` im Container ankommt, welche Zertifikate darauf zeigen
|
||
und ob der Wächter eingetragen ist. In der Oberfläche liegt alles unter
|
||
**Selbstsigniertes Zertifikat erzeugen → Extern geliefertes Zertifikat
|
||
verwenden**.
|
||
|
||
> Wird das Zertifikat im Proxy Manager über die **Weboberfläche** neu
|
||
> hochgeladen, ersetzt er die Verweise wieder durch Kopien. Dann einmal
|
||
> `cert external --domain …` nachziehen.
|
||
|
||
---
|
||
|
||
## 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.
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
# 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:
|
||
|
||
```bash
|
||
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 Schwarzes Fenster: die Startseite antwortet nicht
|
||
|
||
Bleibt nach `Starting Browsh …` / `Waiting for Firefox to connect…` alles
|
||
schwarz, liegt es fast immer daran, dass **auf der Startseite nichts
|
||
antwortet** – nicht am Browser. Ein Terminal-Browser zeigt in dem Fall keine
|
||
Fehlerseite, sondern gar nichts. Dass Browsh selbst läuft, merkt man daran,
|
||
dass `Strg+Q` noch ins Menü zurückführt.
|
||
|
||
Das Skript prüft die Startseite deshalb vorher und nennt die Ursache:
|
||
|
||
```
|
||
[ WARN ] Auf http://127.0.0.1:81 antwortet nichts.
|
||
Ein Terminal-Browser zeigt dann nur eine schwarze Seite.
|
||
|
||
Das ist die Oberflaeche des NGINX Proxy Managers.
|
||
Er ist abgeschaltet (NPM_ENABLED=off):
|
||
./scripts/cmk-manage.sh npm-enable on
|
||
|
||
Trotzdem starten? [j/N]
|
||
```
|
||
|
||
Unterschieden werden:
|
||
|
||
| Lage | Meldung |
|
||
|---|---|
|
||
| Proxy Manager abgeschaltet | Hinweis auf `npm-enable on` |
|
||
| Container fehlt oder gestoppt | Hinweis auf `up` |
|
||
| Container läuft, antwortet aber nicht | Hinweis auf `logs` und `npm-port` |
|
||
| Checkmk-Oberfläche (Port 5000) tot | Hinweis auf `up` bzw. `sites` |
|
||
| externe Adresse | Hinweis auf den Netzzugang des Hosts |
|
||
|
||
Mit `--no-check` lässt sich die Prüfung überspringen. In der Oberfläche
|
||
erscheint dieselbe Diagnose als Dialog mit der Wahl, trotzdem zu starten oder
|
||
im Menü eine andere Startseite einzugeben.
|
||
|
||
### 11.4 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.7](#107-variante-b--selbstsigniertes-zertifikat-interne-umgebung)
|
||
erzeugen, dann:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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.5 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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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](#11-proxy-manager-lokal-einrichten-terminal-browser) 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:
|
||
|
||
```bash
|
||
# 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
|
||
|
||
```bash
|
||
./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.
|
||
|
||
### 12.4 Proxy Manager ganz abschalten (externer NGINX)
|
||
|
||
Wer die HTTPS-Terminierung schon anderweitig löst – etwa mit einem NGINX auf
|
||
einem vorgelagerten System – braucht den Container gar nicht. Dafür gibt es
|
||
einen Schalter:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh npm-enable off # abschalten
|
||
sudo ./scripts/cmk-manage.sh npm-enable on # wieder einschalten
|
||
./scripts/cmk-manage.sh npm-enable # Stand anzeigen
|
||
```
|
||
|
||
In der Oberfläche steht er unter **Einstellungen → NGINX Proxy Manager →
|
||
„Proxy Manager betreiben"**, in der `.env` heißt er `NPM_ENABLED`.
|
||
|
||
**Was „aus" bedeutet:** Der Container wird gestoppt und entfernt, und bei
|
||
`up` gar nicht erst angelegt – `compose` bekommt dann nur noch den
|
||
Checkmk-Dienst genannt. Es wird also weder ein Image geladen noch ein
|
||
Container gebaut:
|
||
|
||
```
|
||
NPM_ENABLED=off -> docker compose up -d checkmk
|
||
NPM_ENABLED=on -> docker compose up -d checkmk nginx-proxy-manager
|
||
```
|
||
|
||
**Die Daten bleiben.** Konfiguration, Datenbank und Zertifikate liegen in den
|
||
Bind-Mounts `./data/npm/data` und `./data/npm/letsencrypt`, nicht im Container.
|
||
Vor dem Abschalten zeigt das Kommando beides mit Größe an; beim späteren
|
||
Einschalten wird die vorhandene Konfiguration samt Zertifikaten unverändert
|
||
wieder aufgenommen.
|
||
|
||
**Was danach zu tun ist:** Der externe Proxy leitet auf Port 5000 dieses Hosts
|
||
weiter. Der war bisher nur für localhost gedacht und muss jetzt – möglichst eng
|
||
begrenzt – für den Proxy erreichbar sein:
|
||
|
||
```bash
|
||
# firewalld
|
||
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=<proxy-ip> port port=5000 protocol=tcp accept'
|
||
sudo firewall-cmd --reload
|
||
|
||
# ufw
|
||
sudo ufw allow from <proxy-ip> to any port 5000 proto tcp
|
||
```
|
||
|
||
Im externen NGINX:
|
||
|
||
```nginx
|
||
location / {
|
||
proxy_pass http://<checkmk-host>:5000;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
client_max_body_size 0;
|
||
proxy_read_timeout 300s;
|
||
}
|
||
```
|
||
|
||
Das passende Kommando samt Beispielkonfiguration gibt `npm-enable off` direkt
|
||
mit aus.
|
||
|
||
> **Der Agent-Receiver bleibt davon unberührt.** Die Agents sprechen Port 8000
|
||
> dieses Hosts direkt an, nicht den Proxy – der muss also weiterhin für die
|
||
> überwachten Systeme erreichbar sein.
|
||
|
||
> **Bei Quadlet** ([Kapitel 6, Variante B](#variante-b--podman-quadlet-ab-podman-44-ohne-compose))
|
||
> entfernt `install.sh --quadlet` die Unit `nginx-proxy-manager.container`,
|
||
> solange der Schalter auf `off` steht. Schaltet man ihn später ein, genügt ein
|
||
> erneutes `sudo ./install.sh --quadlet`.
|
||
|
||
---
|
||
|
||
## 13. Firewall
|
||
|
||
RHEL und Rocky bringen firewalld ab Werk mit, und dort ist in der Regel nur
|
||
SSH freigegeben. Ein Stack, der sauber läuft, ist von außen trotzdem nicht
|
||
erreichbar – die Agents kommen nicht durch, und im Browser passiert nichts.
|
||
Deshalb prüft der Manager das auf Wunsch selbst:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh firewall # Prüfbericht
|
||
./scripts/cmk-manage.sh firewall open # Kommandos nur anzeigen
|
||
sudo ./scripts/cmk-manage.sh firewall open --apply
|
||
sudo ./scripts/cmk-manage.sh firewall open --apply --source 10.0.0.0/24
|
||
```
|
||
|
||
Erkannt werden **firewalld**, **ufw**, **nftables** und **iptables** – in dieser
|
||
Reihenfolge, die erste aktive gewinnt. Bei firewalld werden alle *aktiven
|
||
Zonen* ausgewertet, nicht nur die Standardzone: hängen zwei Netzwerkkarten in
|
||
verschiedenen Zonen, zählt ein Port als offen, sobald ihn eine davon freigibt.
|
||
Neben einzelnen Ports werden auch Dienstnamen (`http`, `https`, `ssh`) und
|
||
Rich Rules berücksichtigt.
|
||
|
||
Welche Ports gebraucht werden, hängt an der Konfiguration. Ports werden
|
||
durchweg als `nummer/protokoll` geführt – Syslog und SNMP-Traps laufen über
|
||
UDP, und eine Freigabe für TCP nützt ihnen nichts.
|
||
|
||
**Immer:**
|
||
|
||
| Port | Zweck | Nötig |
|
||
|------|-------|-------|
|
||
| `80/tcp` | HTTP, Prüfung durch Let's Encrypt | nur mit `NPM_ENABLED=on` |
|
||
| `443/tcp` | HTTPS für Checkmk und weitere Dienste | nur mit `NPM_ENABLED=on` |
|
||
| `NPM_ADMIN_PORT/tcp` (81) | Adminoberfläche des Proxy Managers | nur aus dem Adminnetz |
|
||
| `5000/tcp` | Checkmk direkt | **nur** mit `NPM_ENABLED=off`, sonst geschlossen lassen |
|
||
| `8000/tcp` | Agent-Receiver (registrierte Agents) | immer |
|
||
|
||
**Verteiltes Monitoring** – über `FW_ROLE` gesteuert:
|
||
|
||
| Port | Zweck | Nötig |
|
||
|------|-------|-------|
|
||
| `6557/tcp` | Livestatus – die Zentrale fragt diese Site ab | bei `FW_ROLE=remote`, sonst nur mit `CMK_LIVESTATUS_TCP=on` |
|
||
| `443/tcp` | Konfigurationsabgleich und Automations-API der Zentrale | bei `FW_ROLE=remote` |
|
||
|
||
Die **Zentrale** (`FW_ROLE=central`) baut die Verbindungen selbst auf und
|
||
braucht eingehend nichts zusätzlich – dafür muss *ausgehend* 6557/tcp und
|
||
443/tcp zu den Remote-Sites erlaubt sein. Darauf weist der Bericht hin.
|
||
Ebenso auf den häufigsten Stolperstein: `FW_ROLE=remote` bei
|
||
`CMK_LIVESTATUS_TCP=off` – dann ist der Port zwar offen, aber es lauscht
|
||
niemand.
|
||
|
||
**Event Console und Agent** – jeweils eigener Schalter, weil das nicht jeder
|
||
Aufbau braucht:
|
||
|
||
| Port | Zweck | Schalter |
|
||
|------|-------|----------|
|
||
| `514/udp`, `514/tcp` | Syslog-Meldungen annehmen | `FW_EC_SYSLOG=off\|udp\|tcp\|beide` |
|
||
| `162/udp` | SNMP-Traps annehmen | `FW_EC_SNMPTRAP=on` |
|
||
| `6558/tcp` | Status und Ereignisse der Event Console über TCP | `FW_EC_TCP=on` |
|
||
| `6556/tcp` | Checkmk-Agent dieses Hosts (Pull-Betrieb) | `FW_AGENT=on` |
|
||
|
||
Alles Weitere – Grafana, NSCA, was sonst auf dem Rechner liegt – kommt in
|
||
`FW_EXTRA_PORTS`:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh config set FW_EXTRA_PORTS "3000/tcp=Grafana,5667/tcp=NSCA"
|
||
```
|
||
|
||
Der Bericht markiert auch den umgekehrten Fall: Ist 5000 offen, obwohl der
|
||
Proxy Manager läuft, steht dort *„offen – sollte zu sein"*. Ohne Prüfbefund
|
||
endet `firewall` mit Rückgabewert 1, lässt sich also in eigenen Skripten
|
||
auswerten.
|
||
|
||
Portbereiche in bestehenden Regeln werden aufgelöst: Wer `6556-6558/tcp`
|
||
(firewalld, nftables) oder `6556:6558/tcp` (ufw, iptables) freigegeben hat,
|
||
bekommt alle drei Ports als offen gemeldet. Bei ufw zählt eine Regel ohne
|
||
Protokollangabe – `ufw allow 514` – für TCP **und** UDP, so wie ufw sie auch
|
||
anlegt.
|
||
|
||
`--source` begrenzt jede erzeugte Regel auf ein Quellnetz. Für 8000, 6557 und
|
||
514 ist das sinnvoll (nur die überwachten Hosts bzw. die Zentrale), für Port
|
||
80 nicht: Let's Encrypt prüft die Domain von außen, eine Begrenzung lässt die
|
||
Ausstellung scheitern. Darauf weist der Bericht hin.
|
||
|
||
### Wieder zumachen
|
||
|
||
`firewall open` kennt nur eine Richtung. Schaltet man die Event Console wieder
|
||
ab oder streicht einen Eintrag aus `FW_EXTRA_PORTS`, bleibt die Freigabe
|
||
stehen – der Port ist offen, ohne dass noch etwas dahinter lauscht. Dafür gibt
|
||
es die Gegenrichtung:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh firewall close # Kommandos nur anzeigen
|
||
sudo ./scripts/cmk-manage.sh firewall close --apply
|
||
```
|
||
|
||
Angeboten wird nur, was **offen ist, zu diesem Aufbau gehört und gerade nicht
|
||
gebraucht wird**. Dazu zählen die Ports aus der Tabelle oben und alles, was
|
||
`firewall open --apply` selbst geöffnet hat – das merkt sich das Werkzeug in
|
||
`firewall-opened.conf`, damit ein gestrichener `FW_EXTRA_PORTS`-Eintrag nicht
|
||
in Vergessenheit gerät.
|
||
|
||
Drei Sicherungen sind eingebaut:
|
||
|
||
| | |
|
||
|---|---|
|
||
| **SSH bleibt offen** | Port 22, der Port, auf dem `sshd` wirklich lauscht (aus `sshd -T`), und der Port der laufenden Sitzung (`SSH_CONNECTION`) |
|
||
| **Fremde Freigaben bleiben** | Wer 3306 für seine Datenbank offen hat, behält sie – geschlossen wird nur, was dieser Aufbau kennt |
|
||
| **Sammelregeln bleiben** | Eine Regel wie `80,443/tcp` deckt mehrere Ports ab; sie wird nicht angefasst, sondern gemeldet |
|
||
|
||
**Der Adminport des Proxy Managers wird mit angeboten.** Er ist kein
|
||
Pflichtport: die Oberfläche ist auch über `127.0.0.1` erreichbar – per
|
||
Terminal-Browser im Container oder über einen SSH-Tunnel. Offen im Netz hat sie
|
||
nichts verloren, und genau deshalb steht sie hier zur Disposition:
|
||
|
||
```
|
||
PORT GEHOERT ZU ZUSTAND
|
||
10443/tcp Adminoberflaeche des Proxy Managers kann zu - Zugang dann nur lokal
|
||
81/tcp Adminoberflaeche - alter Vorgabeport kann zu
|
||
```
|
||
|
||
Welcher Port das ist, kommt aus `NPM_ADMIN_PORT` – wer ihn auf 10443 verlegt
|
||
hat, bekommt 10443 angeboten. Die Vorgabe **81 steht zusätzlich immer im
|
||
Katalog**: nach einem Portwechsel bliebe sie sonst offen, ohne dass sie noch
|
||
jemand nennt. Soll der Adminzugang aus dem Netz erhalten bleiben:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh firewall close --apply --keep-admin
|
||
```
|
||
|
||
In der Oberfläche wird danach gefragt, sobald ein Adminport betroffen ist.
|
||
|
||
Bei ufw wird dabei bewusst **nicht** nach Regelnummern gelöscht: die
|
||
verschieben sich beim ersten Löschen, der nächste Aufruf träfe die falsche
|
||
Regel. Stattdessen wird über die Regelangabe gelöscht
|
||
(`ufw delete allow 514/udp`), bei nftables über den Handle und bei iptables mit
|
||
derselben Regelangabe, mit der sie eingetragen wurde.
|
||
|
||
In der Oberfläche liegt das unter **Einstellungen → Firewall → Nicht mehr
|
||
benötigte Ports schließen**.
|
||
|
||
> **Docker und ufw:** Veröffentlichte Container-Ports umgehen ufw sonst über die
|
||
> `DOCKER-USER`-Kette. Hier nicht – beide Container laufen im Host-Netz, es
|
||
> gelten die Hostregeln unverändert.
|
||
|
||
In der Oberfläche steckt derselbe Bericht unter **Firewall prüfen**, samt
|
||
Rückfrage, ob die fehlenden Freigaben gleich gesetzt werden sollen. Die
|
||
Schalter liegen unter **Einstellungen → Firewall: was offen sein muss**, und
|
||
dort stehen auch zwei Aktionen:
|
||
|
||
| Menüpunkt | was er tut |
|
||
|---|---|
|
||
| `>> Firewall jetzt prüfen` | derselbe Bericht wie `firewall check` |
|
||
| `>> Firewall-Regeln übernehmen (Ports öffnen)` | fragt erst nach einem Quellnetz, zeigt **danach** die Kommandos, die genau so ausgeführt werden, und setzt sie nach Bestätigung |
|
||
|
||
Die Reihenfolge ist Absicht: das Quellnetz ändert die Kommandos, deshalb wird
|
||
es vor der Anzeige erfragt – was im Fenster steht, wird auch ausgeführt. Ohne
|
||
`root` wird über `sudo` neu aufgerufen. Zum Schluss zeigt die Oberfläche den
|
||
Stand danach, damit man nicht raten muss, ob es gewirkt hat.
|
||
|
||
> Sind die `FW_*`-Schlüssel in einer älteren `.env` noch nicht vorhanden, steht
|
||
> im Menü `<leer>` – es gelten dann die Vorgaben (`single`, alles aus). Sobald
|
||
> ein Wert gesetzt wird, landet der Schlüssel in der `.env`.
|
||
|
||
### Von Hand
|
||
|
||
**firewalld (RHEL/Rocky/Alma):**
|
||
|
||
```bash
|
||
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'
|
||
|
||
# Verteiltes Monitoring: Livestatus nur fuer die Zentrale
|
||
sudo firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.5/32 port port=6557 protocol=tcp accept'
|
||
|
||
# Event Console: Syslog und SNMP-Traps (UDP!)
|
||
sudo firewall-cmd --permanent --add-service=syslog # 514/udp
|
||
sudo firewall-cmd --permanent --add-service=snmptrap # 162/udp
|
||
sudo firewall-cmd --permanent --add-port=6558/tcp # Status ueber TCP
|
||
|
||
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):**
|
||
|
||
```bash
|
||
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 allow from 10.0.0.5 to any port 6557 proto tcp # Livestatus fuer die Zentrale
|
||
sudo ufw allow 514/udp # Event Console: Syslog
|
||
sudo ufw allow 162/udp # Event Console: SNMP-Traps
|
||
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.
|
||
|
||
### 14.1 ncurses-Oberfläche (wie im Midnight Commander)
|
||
|
||
```bash
|
||
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 / planen │
|
||
│ 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 │
|
||
│ proxy Proxy-Hosts anlegen/verwalten (HTTPS) │
|
||
│ browser Terminal-Browser (Proxy Manager lokal) │
|
||
│ cert Selbstsigniertes Zertifikat erzeugen │
|
||
│ firewall Firewall prüfen (benötigte Ports) │
|
||
│ 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.
|
||
Die Fenstergröße richtet sich nach Terminalgröße, Textlänge und Anzahl der
|
||
Einträge – in einem größeren Terminal sind entsprechend mehr Einträge auf
|
||
einmal sichtbar. Das gilt für **alle** Fenster, auch in `migrate_creator.sh`:
|
||
sämtliche Dialoge laufen über drei gemeinsame Stellen in
|
||
[scripts/lib/common.sh](scripts/lib/common.sh), die die Größe selbst berechnen.
|
||
|
||
### 14.4 Rahmen erscheinen als `q`, `x`, `l`, `m` (PuTTY)
|
||
|
||
Sieht die Oberfläche so aus –
|
||
|
||
```
|
||
lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
|
||
x Projekt : /opt/checkmk-stack x
|
||
```
|
||
|
||
– dann fehlt auf dem Server eine **UTF-8-Locale**. Ohne sie zeichnen
|
||
`dialog` und `whiptail` die Rahmen über die alte VT100-Umschaltung `ESC(0`.
|
||
Terminals im UTF-8-Modus – PuTTY in der Vorgabe – ignorieren diese Umschaltung
|
||
und zeigen stattdessen die rohen Buchstaben.
|
||
|
||
Nachgemessen: bei `LC_ALL=C` schickt `whiptail` eine `ESC(0`-Umschaltung und
|
||
**91 rohe `q`**; mit UTF-8-Locale keine einzige.
|
||
|
||
**Das Skript behebt das auf zwei Wegen selbst.**
|
||
|
||
**1. UTF-8-Locale.** Beim Start der Oberfläche setzt es
|
||
`LC_CTYPE` auf die erste verfügbare UTF-8-Locale (`C.UTF-8`, `en_US.UTF-8`, …).
|
||
Nur `LC_CTYPE`, damit Sortierung und Zahlenformat unberührt bleiben. Ist
|
||
`LC_ALL` auf einen Nicht-UTF-8-Wert gesetzt, wird es dabei entfernt – sonst
|
||
würde es `LC_CTYPE` aushebeln. **2. Unicode statt VT100.** Das allein genügt nicht: **ncurses benutzt die
|
||
VT100-Umschaltung auch mit UTF-8-Locale**, solange das terminfo sie anbietet –
|
||
bei `TERM=xterm` der Fall. Deshalb wird zusätzlich `NCURSES_NO_UTF8_ACS=1`
|
||
gesetzt, womit ncurses echte Unicode-Rahmenzeichen zeichnet. Mit `dialog` unter
|
||
`LANG=C.UTF-8` und `TERM=xterm` gemessen:
|
||
|
||
| | `ESC(0` | UTF-8-Rahmenbytes | rohe `q` |
|
||
|---|---|---|---|
|
||
| ohne Schalter | 38 | 0 | **182** |
|
||
| **mit Schalter** | **0** | **220** | **0** |
|
||
|
||
`whiptail` braucht das nicht – es zeichnet bei UTF-8-Locale von sich aus
|
||
Unicode. Wer den umgekehrten Fall hat – ein Terminal, das `ESC(0` beherrscht,
|
||
aber kein UTF-8 – stellt mit `CMK_TUI_ACS=1` das alte Verhalten wieder her.
|
||
|
||
Prüfen lässt sich das mit:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh selftest # Abschnitt "Zeichensatz fuer die Oberflaeche"
|
||
```
|
||
|
||
Meldet die Prüfung, dass **keine** UTF-8-Locale vorhanden ist, fehlt das
|
||
Sprachpaket:
|
||
|
||
```bash
|
||
sudo dnf install -y glibc-langpack-en # RHEL/Rocky/Alma
|
||
sudo apt-get install -y locales # Debian/Ubuntu
|
||
```
|
||
|
||
#### Einstellungen in PuTTY
|
||
|
||
Damit es auch auf der Gegenseite passt:
|
||
|
||
| PuTTY-Bereich | Einstellung |
|
||
|---|---|
|
||
| Window → Translation | **Remote character set: UTF-8** |
|
||
| Window → Translation | Handling of line drawing characters: **Use Unicode line drawing code points** |
|
||
| Connection → Data | Terminal-type string: **`xterm-256color`** (Vorgabe ist nur `xterm`) |
|
||
| Window → Appearance | eine Schrift mit Rahmenzeichen, z. B. *Consolas* oder *DejaVu Sans Mono* |
|
||
|
||
Wer die Sitzung dauerhaft so haben möchte, speichert sie in PuTTY unter
|
||
*Session → Saved Sessions*.
|
||
|
||
#### Wenn es trotzdem nicht passt: nachsehen statt raten
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh tui-check
|
||
```
|
||
|
||
Das gibt zwei Testzeilen aus:
|
||
|
||
* **Zeile A** – echte UTF-8-Rahmenzeichen (`┌──┐`)
|
||
* **Zeile B** – die alte VT100-Umschaltung `ESC(0` mit den Buchstaben `lqk`
|
||
|
||
Daran lässt sich die Ursache ablesen:
|
||
|
||
| Beobachtung | Bedeutung |
|
||
|---|---|
|
||
| A Linien, B Linien | alles in Ordnung |
|
||
| A Linien, **B zeigt `lqqqk`** | das Terminal macht die VT100-Umschaltung nicht mit – **der PuTTY-Fall**, siehe Einstellungen oben |
|
||
| A zeigt Kauderwelsch | das Terminal läuft nicht im UTF-8-Modus |
|
||
| beide zeigen Buchstaben | die Schrift hat keine Rahmenzeichen |
|
||
|
||
Das Kommando nennt zu jeder Beobachtung gleich die passende Abhilfe.
|
||
|
||
> **`dialog` statt `whiptail` installieren** ist auf dieser Seite der wirksamste
|
||
> Griff – es geht mit dem Zeichensatz zuverlässiger um und kann als einziges
|
||
> auch einfache ASCII-Rahmen:
|
||
>
|
||
> ```bash
|
||
> sudo dnf install -y dialog # RHEL/Rocky/Alma
|
||
> sudo apt-get install -y dialog # Debian/Ubuntu
|
||
> ```
|
||
>
|
||
> Das Skript bevorzugt `dialog`, sobald es vorhanden ist. Danach lassen sich
|
||
> notfalls einfache Rahmen erzwingen:
|
||
>
|
||
> ```bash
|
||
> CMK_TUI_ASCII=1 ./scripts/cmk-manage.sh gui
|
||
> ```
|
||
>
|
||
> Ohne `dialog` sagt das Skript das ausdrücklich – `whiptail` kennt keine
|
||
> solche Option.
|
||
|
||
### 14.5 Selbstprüfung
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh selftest
|
||
```
|
||
|
||
Prüft die Skripte auf die Fallstricke, die sich hier als wiederkehrend
|
||
erwiesen haben:
|
||
|
||
| Prüfung | Warum |
|
||
|---|---|
|
||
| Syntax aller vier Skripte | Tippfehler fallen sofort auf |
|
||
| Dialoge gehen über die gemeinsamen Stellen | sonst hätte ein neues Fenster wieder eine feste Größe |
|
||
| keine fest eingetragenen Fenstergrößen | dito |
|
||
| kein `[ … ] && VAR=…` | liefert 1, wenn die Bedingung nicht zutrifft, und beendet unter `set -e` das Skript – dreimal die Ursache eines stillen Abbruchs |
|
||
| Einstellungstabelle vollständig | jeder Schlüssel hat sechs Felder und steht in `.env.example` |
|
||
|
||
Wer eigene Menüpunkte ergänzt, sollte den Aufruf danach einmal machen.
|
||
Es wird `dialog` bevorzugt; ist nur `whiptail` vorhanden, wird dieses genutzt.
|
||
Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut.
|
||
|
||
### 14.2 Kommandozeile
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh --help
|
||
```
|
||
|
||
| Kommando | Wirkung |
|
||
|---|---|
|
||
| `up [--no-fetch]` / `down` / `restart` / `pull` | Stack steuern; `up` holt ein fehlendes Image selbst |
|
||
| `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) |
|
||
| `site-create NAME` | weitere Site im Container anlegen – eigene Ports (5001, 8001, …) |
|
||
| `site-delete NAME` | Site samt Daten entfernen |
|
||
| `backup …` | Backup als `.tar.gz`-Bundle |
|
||
| `list` / `verify` / `prune --keep N` | Backups verwalten |
|
||
| `job list\|add\|set\|del\|run\|auto` | geplante Backups (eigene Zielpfade je Job) |
|
||
| `restore …` | Backup zurückspielen |
|
||
| `import …` | Migrations-Bundle einspielen |
|
||
| `image get` | Image über den eingestellten Bezugsweg holen |
|
||
| `image status\|list\|versions\|repos\|why\|test\|pull\|download\|load\|use` | Checkmk-Image beschaffen, auswählen und Fehler erklären |
|
||
| `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 |
|
||
| `npm-enable [on\|off]` | Proxy Manager ein-/ausschalten (Daten bleiben erhalten) |
|
||
| `npm-reset` | Datenbank beiseitelegen, damit das Konto neu entsteht |
|
||
| `proxy status\|list\|certs\|add\|del` | Proxy-Hosts über die API anlegen und verwalten |
|
||
| `cert …` | selbstsigniertes Zertifikat erzeugen |
|
||
| `cert external …` | von außen geliefertes Zertifikat verwenden (verweisen statt kopieren) |
|
||
| `firewall [check\|open\|close]` | prüfen, öffnen und nicht mehr Benötigtes wieder schließen (firewalld, ufw, nftables, iptables); `close --keep-admin` lässt den Adminport offen |
|
||
| `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:
|
||
|
||
```bash
|
||
./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 1–65535, 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](#12-adminoberfläche-auf-einen-anderen-port-legen)).
|
||
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.
|
||
|
||
```bash
|
||
# 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:
|
||
|
||
```bash
|
||
./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
|
||
```
|
||
|
||
### 15.1 Geplante Backups (Backup-Jobs)
|
||
|
||
Manuelle Backups gehen immer nach `BACKUP_DIR` aus der `.env`. Geplante Jobs
|
||
bringen dagegen **ihr eigenes Zielverzeichnis** mit – so lässt sich täglich auf
|
||
eine NAS-Freigabe und wöchentlich woanders hin sichern.
|
||
|
||
Im Menü: **backup → „Backup erstellen / planen"**
|
||
|
||
```
|
||
┌──────────── Backup erstellen / planen ─────────────────┐
|
||
│ Manuelle Backups gehen immer nach: │
|
||
│ /opt/checkmk-stack/backups (Einstellung BACKUP_DIR)│
|
||
│ │
|
||
│ Geplante Jobs haben ihr eigenes Zielverzeichnis. │
|
||
│ Automatische Ausfuehrung: aus │
|
||
│ │
|
||
│ manuell Backup jetzt erstellen │
|
||
│ jobs Backup-Jobs verwalten │
|
||
│ auto Automatische Ausfuehrung ein/aus │
|
||
│ status Zeitplan und Jobs anzeigen │
|
||
│ jetzt Einen Job sofort ausfuehren │
|
||
│ back zurueck │
|
||
└────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
Dieselben Jobs liegen auch in den **Einstellungen → „Backup-Jobs"**.
|
||
|
||
#### Job anlegen
|
||
|
||
Im Menü führt ein Dialog durch Sites, Zeitplan (täglich / wöchentlich /
|
||
monatlich / freier Cron-Ausdruck), Zielverzeichnis, Aufbewahrung und Optionen.
|
||
Dasselbe per Parameter:
|
||
|
||
```bash
|
||
# täglich 02:15, alle Sites, ohne Logs, 14 Backups aufbewahren
|
||
sudo ./scripts/cmk-manage.sh job add --name nachts \
|
||
--cron "15 2 * * *" --no-logs --keep 14
|
||
|
||
# sonntags 03:30, nur zwei Sites, auf die NAS, ohne RRDs, 8 aufbewahren
|
||
sudo ./scripts/cmk-manage.sh job add --name nas-woche \
|
||
--cron "30 3 * * 0" --sites prod,test \
|
||
--dir /mnt/nas/checkmk --no-rrds --no-logs --keep 8
|
||
```
|
||
|
||
Alle Kommandos:
|
||
|
||
| Kommando | Wirkung |
|
||
|---|---|
|
||
| `job list` | angelegte Jobs anzeigen |
|
||
| `job status` | Zeitplan, Cron-Datei und Schalter |
|
||
| `job add --name N --cron "…"` | Job anlegen |
|
||
| `job set NAME …` | Job ändern (nicht genannte Felder bleiben) |
|
||
| `job del NAME` | Job löschen (die Backups bleiben) |
|
||
| `job enable\|disable NAME` | Job ein-/ausschalten |
|
||
| `job run NAME` | Job sofort ausführen |
|
||
| `job run-all` | alle aktiven Jobs ausführen |
|
||
| `job auto on\|off` | automatische Ausführung ein/aus |
|
||
|
||
Optionen von `job add` / `job set`:
|
||
|
||
| Option | Bedeutung |
|
||
|---|---|
|
||
| `--sites ALL\|a,b` | zu sichernde Sites (Vorgabe `ALL`) |
|
||
| `--cron "15 2 * * *"` | Zeitplan, fünf Cron-Felder |
|
||
| `--dir VERZ` | Zielverzeichnis dieses Jobs (Vorgabe `BACKUP_DIR`) |
|
||
| `--keep N` | wie viele Backups im Ziel bleiben (`0` = alle) |
|
||
| `--no-rrds`, `--no-logs`, `--stop` | wie bei `backup` |
|
||
| `--disabled` | anlegen, aber noch nicht einplanen |
|
||
|
||
#### Automatik ein- und ausschalten
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh job auto on # einplanen
|
||
sudo ./scripts/cmk-manage.sh job auto off # Zeitplan entfernen
|
||
```
|
||
|
||
`on` schreibt aus allen **aktiven** Jobs die Datei `/etc/cron.d/checkmk-backup`
|
||
– je Job eine Zeile mit seinem eigenen Zeitplan:
|
||
|
||
```cron
|
||
15 2 * * * root /opt/checkmk-stack/scripts/cmk-manage.sh -y job run nachts >>/var/log/cmk-backup.log 2>&1
|
||
30 3 * * 0 root /opt/checkmk-stack/scripts/cmk-manage.sh -y job run nas-woche >>/var/log/cmk-backup.log 2>&1
|
||
```
|
||
|
||
Dafür werden root-Rechte gebraucht. Ohne root gibt das Kommando die Zeilen
|
||
aus, damit man sie selbst übernehmen kann. `off` entfernt die Datei wieder; die
|
||
Jobs selbst bleiben erhalten. Der Schalter steht als `BACKUP_AUTO` in der
|
||
`.env`.
|
||
|
||
Nach jedem Lauf räumt der Job sein eigenes Zielverzeichnis auf `--keep` auf –
|
||
ein separater `prune`-Eintrag ist nicht nötig.
|
||
|
||
#### Wo die Jobs liegen
|
||
|
||
In `backup-jobs.conf` im Projektverzeichnis, eine Zeile je Job:
|
||
|
||
```
|
||
name|sites|cron|verzeichnis|optionen|aufbewahren|aktiv
|
||
nachts|ALL|15 2 * * *|/opt/checkmk-stack/backups|--no-logs|14|on
|
||
nas-woche|prod,test|30 3 * * 0|/mnt/nas/checkmk|--no-rrds --no-logs|8|on
|
||
```
|
||
|
||
Die Datei ist bewusst lesbar und versionierbar, gehört aber nicht ins
|
||
Repository (sie steht in `.gitignore`, weil sie systemspezifische Pfade
|
||
enthält).
|
||
|
||
---
|
||
|
||
## 16. Restore
|
||
|
||
```bash
|
||
# 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.
|
||
|
||
### 16.1 Warum ein Restore nach dem Neuerstellen des Containers scheiterte
|
||
|
||
```
|
||
ERROR: apache user www-data must be member of group cmk
|
||
```
|
||
|
||
Beim Anlegen einer Site trägt `omd create` den Apache-Benutzer in die Gruppe
|
||
der Site ein. Diese Zugehörigkeit steht in `/etc/group` – und das liegt **im
|
||
Container**, nicht im Bind-Mount. Wird der Container neu erstellt (jedes `up`
|
||
mit geändertem Image, `podman rm`, ein Update), ist `/etc/group` wieder der
|
||
Stand aus dem Abbild, während die Site im Bind-Mount unverändert weiterlebt.
|
||
|
||
Der offizielle Entrypoint erkennt diesen Fall und legt Gruppe und Benutzer neu
|
||
an – nimmt `www-data` dabei aber **nicht** in die Gruppe auf:
|
||
|
||
```bash
|
||
if ! getent group "$CMK_SITE_ID" >/dev/null; then
|
||
groupadd -g 1000 "$CMK_SITE_ID"
|
||
fi
|
||
if ! getent passwd "$CMK_SITE_ID" >/dev/null; then
|
||
useradd -u 1000 ... -G omd -s /bin/bash "$CMK_SITE_ID"
|
||
fi
|
||
```
|
||
|
||
Im Betrieb fällt das nicht auf: die Site läuft, die Oberfläche antwortet, der
|
||
Agent-Receiver nimmt Daten an. Erst `omd restore --reuse` prüft es
|
||
(`user_verify` in `omdlib/users_and_groups.py`) und bricht ab.
|
||
|
||
Direkt dahinter wartet der zweite Stolperstein:
|
||
|
||
```
|
||
ERROR: fstab entry for /omd/sites/cmk/tmp does not exist
|
||
```
|
||
|
||
`omd` lässt einen fehlenden `/etc/fstab` ausdrücklich durchgehen
|
||
(*„In case there is no fstab (seen in some containers) assume everything is
|
||
OK"*) – im Abbild liegt aber eine Datei mit einer Kommentarzeile. Damit
|
||
existiert `/etc/fstab`, die Ausnahme greift nicht, und der Eintrag wird
|
||
vermisst.
|
||
|
||
Beides ist Zustand des **Containers**, nicht der Daten. `cmk-manage.sh` zieht
|
||
es deshalb vor jedem `restore` und `import` nach – und seit demselben Anlass
|
||
auch nach jedem `up`, damit ein von Hand aufgerufenes `omd` nicht darüber
|
||
stolpert:
|
||
|
||
```
|
||
[ INFO ] Apache-Benutzer www-data -> cmk in die Gruppe aufgenommen
|
||
(nach dem Neuerstellen des Containers verloren gegangen).
|
||
[ INFO ] fstab-Eintrag fuer /omd/sites/cmk/tmp ergaenzt - ohne ihn
|
||
verweigert 'omd restore' den Dienst.
|
||
```
|
||
|
||
Der Apache-Benutzer und das Kommando zum Eintragen werden dabei aus
|
||
`/omd/versions/default/share/omd/distro.info` gelesen – derselben Quelle, aus
|
||
der `omd` sie nimmt. Von Hand wäre es:
|
||
|
||
```bash
|
||
docker exec checkmk gpasswd -a www-data cmk
|
||
docker exec checkmk sh -c 'echo "tmpfs /omd/sites/cmk/tmp tmpfs noauto,user,mode=751,uid=cmk,gid=cmk 0 0" >> /etc/fstab'
|
||
```
|
||
|
||
---
|
||
|
||
## 17. Migration einer Direktinstallation (`migrate_creator.sh`)
|
||
|
||
Ziel: eine bestehende Checkmk-Installation auf Blech/VM in den Container
|
||
übernehmen – **ohne die Agents anzufassen**.
|
||
|
||
### 17.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.
|
||
|
||
### 17.2 Schritt 1 – Skript auf den Quellserver kopieren
|
||
|
||
```bash
|
||
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`).
|
||
|
||
### 17.3 Schritt 2 – Bundle auf dem Quellserver erzeugen
|
||
|
||
Vorhandene Sites anzeigen:
|
||
|
||
```bash
|
||
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):
|
||
|
||
```bash
|
||
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:**
|
||
|
||
```bash
|
||
# 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.
|
||
|
||
### 17.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:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```bash
|
||
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](#8-checkmk-image-beschaffen-raw-enterprise--co).
|
||
|
||
### 17.5 Schritt 4 – Bundle importieren
|
||
|
||
Mit Oberfläche:
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh gui # -> "import"
|
||
```
|
||
|
||
Mit Parametern:
|
||
|
||
```bash
|
||
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.
|
||
|
||
### 17.6 Schritt 5 – Umschalten und kontrollieren
|
||
|
||
```bash
|
||
# 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.
|
||
|
||
### 17.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 Entrypoint des Abbilds legt nur die Site aus `CMK_SITE_ID` an und startet
|
||
auch nur diese. Weitere Sites lassen sich aber anlegen – und mit dem Proxy
|
||
davor liegen sie nebeneinander unter einem einzigen Port:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh site-create zweite
|
||
./scripts/cmk-manage.sh site-create kunde2 --password geheim123
|
||
./scripts/cmk-manage.sh sites
|
||
./scripts/cmk-manage.sh site-delete zweite
|
||
```
|
||
|
||
### 18.1 Eigene Ports je Site
|
||
|
||
`omd` vergibt die Ports selbst weiter – daran hängt alles Weitere:
|
||
|
||
| | erste Site | zweite | dritte |
|
||
|---|---|---|---|
|
||
| Oberfläche (Apache) | 5000 | 5001 | 5002 |
|
||
| **Agent-Receiver** | 8000 | **8001** | **8002** |
|
||
| Livestatus | 6557 | 6558 | 6559 |
|
||
|
||
Zwei Dinge folgen daraus:
|
||
|
||
1. **Im Proxy** bekommt jede Site ihren Pfad:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh proxy edit --domain <name> --location /zweite=127.0.0.1:5001
|
||
./scripts/cmk-manage.sh proxy reload
|
||
```
|
||
|
||
Danach liegt sie neben der ersten: `https://<ip>/cmk/` und
|
||
`https://<ip>/zweite/`. Checkmk kommt mit dem Präfix zurecht, weil der
|
||
Site-Name ohnehin Teil jeder Adresse ist – siehe
|
||
[Kapitel 10.12](#1012-weitere-dienste-dazunehmen--beispiel-grafana).
|
||
|
||
2. **In der Firewall** sprechen die Agents dieser Site einen anderen Port an:
|
||
|
||
```bash
|
||
./scripts/cmk-manage.sh config set FW_EXTRA_PORTS "8001/tcp=Agent-Receiver zweite"
|
||
sudo ./scripts/cmk-manage.sh firewall open --apply
|
||
```
|
||
|
||
`site-create` gibt genau diese beiden Befehle mit den richtigen Portnummern
|
||
aus, dazu die Erinnerung an den Standard-Server für den IP-Zugang, falls er
|
||
eingerichtet ist.
|
||
|
||
### 18.2 Was beim Anlegen passiert
|
||
|
||
Im Container läuft `omd create --no-tmpfs` – ohne `--no-tmpfs` scheitert es,
|
||
weil sich im Container kein tmpfs einhängen lässt. Läuft der Container **nicht**
|
||
im Host-Netz, wird der Apache der Site zusätzlich auf `0.0.0.0` gebunden, sonst
|
||
wäre sie von außen nicht erreichbar; im Host-Netz genügt `127.0.0.1`, und der
|
||
Proxy kommt trotzdem hin. Ohne `--password` erzeugt `omd` eines und zeigt es an.
|
||
|
||
### 18.3 Nach einem Neustart
|
||
|
||
```bash
|
||
sudo ./scripts/cmk-manage.sh start-all-sites
|
||
```
|
||
|
||
Der Entrypoint startet nur die Standard-Site. Dieses Kommando wird von der
|
||
systemd-Unit (`ExecStartPost`) bzw. der Quadlet-Unit automatisch nach dem
|
||
Containerstart ausgeführt und fährt alle vorhandenen Sites hoch.
|
||
|
||
### 18.4 Wann lieber getrennte Projekte?
|
||
|
||
Mehrere Sites in einem Container teilen sich Abbild und Version – ein
|
||
`omd update` betrifft alle. Für sauber getrennte Umgebungen (unterschiedliche
|
||
Checkmk-Versionen, getrennte Wartungsfenster, verschiedene Kunden) ist je Site
|
||
ein eigenes Projektverzeichnis mit eigener `.env` besser. 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.
|
||
|
||
In der Oberfläche liegt alles unter **Sites im Container verwalten**.
|
||
|
||
---
|
||
|
||
## 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`.
|
||
|
||
```bash
|
||
# 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 |
|
||
|---|---|
|
||
| `ERR_SSL_UNRECOGNIZED_NAME_ALERT` beim Aufruf über `https://<IP>/` | Der Browser sendet bei einer IP kein SNI, nginx fällt auf seinen Standard-Server zurück und lehnt ab. `cmk-manage.sh proxy default --domain <name>` – siehe [Kapitel 10.8](#108-https-über-die-blanke-ip) |
|
||
| `omd restore`: *apache user www-data must be member of group `<site>`* | Der Container wurde neu erstellt, die Site liegt im Bind-Mount. `cmk-manage.sh` zieht das beim Restore und beim `up` selbst nach – siehe [Kapitel 16.1](#161-warum-ein-restore-nach-dem-neuerstellen-des-containers-scheiterte) |
|
||
| `omd restore`: *fstab entry for /omd/sites/…/tmp does not exist* | gleiche Ursache, gleiche Behebung |
|
||
| `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](#8-checkmk-image-beschaffen-raw-enterprise--co) |
|
||
| `manifest unknown` beim Pull | Das Repository ist da, **das Tag nicht**. `cmk-manage.sh image why` nennt die vorhandenen Tags des Zweigs |
|
||
| `repository name unknown` / `Login Succeeded`, aber Pull scheitert | Der Repository-Pfad stimmt nicht. `cmk-manage.sh image repos --edition enterprise` zeigt, was die Registry anbietet; sonst über den Tarball gehen |
|
||
| `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`) |
|
||
| `This system is not registered with an entitlement server` | RHEL ohne Subskription – `dnf` liefert dann gar keine Pakete. Registrieren, Installations-DVD als Repository einbinden oder auf Rocky/Alma wechseln: [Abschnitt 5.1](#51-unregistriertes-rhel-woher-die-pakete-kommen) |
|
||
| `epel-release` lässt sich nicht installieren | EPEL setzt Red Hats Basis-Repositories voraus und ersetzt die Registrierung nicht. Ohne Subskription führt der Quadlet-Weg ohne `podman-compose` zum Ziel: [Kapitel 6, Variante B](#variante-b--podman-quadlet-ab-podman-44-ohne-compose) |
|
||
| Proxy-Manager-Container startet nicht mehr mit | Schalter steht auf `off`: `cmk-manage.sh npm-enable on`. Prüfen mit `cmk-manage.sh npm-enable` |
|
||
| 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` |
|
||
| Browser bleibt schwarz, „Waiting for Firefox to connect…" | Die Startseite antwortet nicht – meist läuft der Proxy Manager nicht. Das Skript meldet das jetzt vorab, siehe [Kapitel 11.3](#113-schwarzes-fenster-die-startseite-antwortet-nicht) |
|
||
| 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.4](#114-grenze-datei-upload) |
|
||
| `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` |
|
||
| Menüpunkt bricht mit einer Fehlermeldung in die Shell ab | behoben: fehlende Container, Sites oder Backups werden jetzt als Dialog gemeldet, die Oberfläche bleibt offen |
|
||
| `job auto on` meldet fehlende Rechte | `/etc/cron.d/` braucht root: mit `sudo` aufrufen, oder die ausgegebenen Zeilen selbst übernehmen |
|
||
| Proxy Manager verlangt beim ersten Aufruf ein neues Konto | seit 2.15 normal. `NPM_ADMIN_EMAIL`/`NPM_ADMIN_PASSWORD` **vor** dem ersten Start setzen; ist das Konto schon angelegt, dessen Daten dort eintragen |
|
||
| Im Terminal-Browser erscheint bei Proxy-Hosts ein JSON-Fehler | Die Oberfläche ist dafür zu aufwendig. Proxy-Hosts stattdessen über `cmk-manage.sh proxy add` anlegen ([Kapitel 10.2](#102-proxy-host-anlegen--ohne-browser)) |
|
||
| 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:
|
||
|
||
```bash
|
||
./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.
|
||
* `NPM_ADMIN_PASSWORD` vor dem ersten Start auf ein eigenes Kennwort setzen –
|
||
daraus wird das Administratorkonto des Proxy Managers erzeugt.
|
||
* 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
|
||
|
||
```bash
|
||
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.
|