Commit Graph
46 Commits
Author SHA1 Message Date
duffyduckandClaude Opus 5 7d9ed10e09 Weitere Sites anlegen und entfernen
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>
2026-09-20 22:20:21 +02:00
duffyduckandClaude Opus 5 4456f8c3ea Extern geliefertes Zertifikat verwenden, statt es zu kopieren
Liefert eine fremde Stelle das Zertifikat in ein Verzeichnis und
ersetzt es dort beim Erneuern - gleicher Dateiname, neuer Inhalt -,
passt der uebliche Weg nicht: der Proxy Manager kopiert hochgeladene
Zertifikate nach /data/custom_ssl/npm-<id>/ und bekommt von einer
ersetzten Datei nichts mit.

Das Verzeichnis wird deshalb schreibgeschuetzt als /certs in den
Container gehaengt (neuer Mount in der compose-Datei, Vorgabe
./data/npm/external-certs), und "cert external" ersetzt die beiden
Dateien unter custom_ssl durch Verweise darauf. Am Abbild
jc21/nginx-proxy-manager:2 nachgemessen: nginx liefert danach das
externe Zertifikat, und ein Austausch der Datei wirkt - allerdings erst
nach einem Neuladen.

Genau das ist der Haken, und er ist belegt: ohne Neuladen liefert nginx
weiterhin das alte Zertifikat. Dafuer gibt es

  cert external --refresh      vergleicht den SHA256-Fingerabdruck mit
                               dem zuletzt gesehenen und laedt nur bei
                               Aenderung neu
  cert external --watch on     traegt das als taeglichen cron-Eintrag ein

Vor dem Umstellen wird geprueft, ob beide Dateien lesbar sind, ob
Zertifikat und Schluessel zusammengehoeren (Vergleich der oeffentlichen
Schluessel - das faengt auch EC-Schluessel) und wie lange es noch gilt.
Beide Faelle sind durchgespielt: ein fremder Schluessel wird abgelehnt,
ein in fuenf Tagen ablaufendes Zertifikat gemeldet.

"cert external --off --id N" nimmt es zurueck und legt wieder eigene
Kopien an. In der Oberflaeche ist aus dem Menuepunkt "Zertifikat" ein
kleines Menue geworden.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 22:05:20 +02:00
duffyduckandClaude Opus 5 81ff194bd1 Grafana als weiterer Pfad - und "proxy check", damit 502 nicht raten heisst
Ob ein Dienst unter einem Pfad liegen kann, entscheidet der Dienst, nicht
der Proxy: er muss den Praefix kennen und in jede erzeugte Adresse
einsetzen. Checkmk kann das von Haus aus, die Oberflaeche des Proxy
Managers gar nicht - Grafana kann es, wenn man es ihm sagt:

  GF_SERVER_ROOT_URL=https://<ip>/grafana/
  GF_SERVER_SERVE_FROM_SUB_PATH=true

Damit setzt Grafana <base href="/grafana/"> in seine Seiten. An Grafana
13.0.2 hinter dem Proxy Manager gemessen, ueber die IP ohne SNI:
/grafana/ liefert 302 auf /grafana/login, die Anmeldeseite 200, die
Dateien unter /grafana/public/... ebenfalls 200, und POST
/grafana/login meldet 200. Ohne die beiden Zeilen leitet Grafana auf
/login um - also auf die Wurzel, wo etwas anderes liegt.

Neu ist ausserdem "proxy check". Es fragt jedes Ziel eines Proxy-Hosts
AUS DEM PROXY-CONTAINER HERAUS ab, denn von dort baut nginx die
Verbindung auf:

  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

Damit faellt ein Tippfehler in der Zieladresse auf, bevor der Browser
502 zeigt - der Anlass war genau so einer. In der Oberflaeche liegt das
unter Proxy-Hosts > "Ziele pruefen".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 21:57:53 +02:00
duffyduckandClaude Opus 5 f02692e8be Adminoberflaeche erreichbar machen - ueber einen Namen oder ueber die Wurzel
Unter einem Unterpfad wie /npm bleibt die Oberflaeche des Proxy Managers
weiss. Sie ist eine Single-Page-Anwendung und laedt ihre Dateien ueber
absolute Pfade; nur die Startseite kommt an, alles Weitere landet bei
dem, was auf der Wurzel liegt. An einem laufenden Proxy Manager
gemessen: /npm liefert 200, /images/... dagegen 502. Checkmk funktioniert
unter /cmk/ nur deshalb, weil es fuer einen URL-Praefix gebaut ist.

"proxy admin" kann beides, und beides kommt mit dem einen freien Port
aus:

  proxy admin --domain npm.example.local
      Eigener Proxy-Host, Oberflaeche auf "/". Welcher Server-Block
      greift, entscheidet der Name (SNI), nicht der Port. Setzt
      Namensaufloesung voraus - notfalls eine Zeile in der hosts-Datei.

  proxy admin --root
      Ohne Namensaufloesung: die Wurzel zeigt auf die Adminoberflaeche,
      das bisherige Ziel wandert auf /<site>. Checkmk belegt ohnehin nur
      seinen Site-Pfad.

  proxy admin --root --off    nimmt das wieder zurueck
  proxy admin                 zeigt den Stand

Beide Wege sind ueber die IP ohne SNI durchgemessen: Startseite,
/images, /login und die Anmeldung per POST /api/tokens antworten mit
200. In der Oberflaeche liegt das unter Proxy-Hosts >
"Adminoberflaeche erreichbar machen".

Dabei ist ein aelterer Fehler aufgefallen: "die" ruft exit auf, und die
Oberflaeche ruft cmd_* direkt auf - ein Fehlerfall beendete damit die
ganze Oberflaeche, statt ihn anzuzeigen. Betraf auch bestehende
Menuepunkte wie "Einzelheiten eines Proxy-Hosts" (stirbt bei unbekanntem
Namen) und die Jobliste. Alle 24 Aufrufe laufen jetzt in einer Subshell.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 21:48:12 +02:00
duffyduckandClaude Opus 5 9a567c6cca proxy add: nachsehen, ob der Eintrag wirklich steht
Beim Nachstellen eines Problems ist mir aufgefallen, dass "proxy add"
Erfolg meldete - samt vergebener ID -, die Liste der Proxy-Hosts danach
aber leer war und keine nginx-Konfiguration geschrieben wurde. Der
Proxy Manager war noch am Starten: er nimmt den Aufruf an, gibt ein
Objekt mit ID zurueck und verliert es anschliessend wieder.

Nach dem Anlegen wird der Eintrag deshalb einmal abgerufen. Fehlt er,
gibt es einen Fehler statt einer falschen Erfolgsmeldung. Fehlt nur die
erzeugte Datei unter /data/nginx/proxy_host, reicht ein Hinweis auf
"proxy reload".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 21:38:57 +02:00
duffyduckandClaude Opus 5 48228ba910 Proxy Manager neu starten - als Menuepunkt und als Parameter
Die Zusatzkonfiguration - Standard-Server fuer den IP-Zugang, Adminport -
liegt als Datei im Datenverzeichnis und wird erst beim naechsten
Einlesen beachtet. Bisher blieb dafuer nur "restart" fuer den ganzen
Stack.

  proxy reload    nginx neu einlesen, ohne Unterbrechung
  proxy restart   Container neu starten

"reload" prueft vorher mit "nginx -t" und laedt nur bei fehlerfreier
Konfiguration neu; sonst stehen Ursache und Zeilennummer da und es
passiert nichts. In der Oberflaeche liegt beides unter Proxy-Hosts >
"Proxy Manager neu starten / nginx neu laden".

Beim Bauen kamen zwei Dinge heraus:

  - "nginx -t" beantwortet nicht, ob nginx laeuft - es prueft nur die
    Datei und gelingt auch, bevor der Dienst da ist. Als
    Bereitschaftspruefung nach dem Neustart taugt es also nicht; es wird
    jetzt in /proc nach dem Masterprozess gesehen (ohne "ps", das es im
    Container nicht gibt) und anschliessend geprueft, ob die
    Adminoberflaeche wieder antwortet. nginx ist nach einer Sekunde
    zurueck, der Dienst dahinter braucht laenger - ein sofortiges
    "fertig" waere gelogen.
  - ENVFILE_OPT wurde nie an Unterprozesse weitergereicht. Wer die
    Oberflaeche mit --env-file startete, dessen Menuepunkte liefen gegen
    die Standard-.env, also womoeglich gegen den falschen Stack. Alle 43
    Stellen bekommen die Option jetzt mit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 21:24:46 +02:00
duffyduckandClaude Opus 5 08271a04cf firewall close: den Adminport des Proxy Managers mit anbieten
Der Adminport war als "noetig" eingestuft und blieb deshalb offen,
obwohl er gerade der Port ist, der im Netz nichts verloren hat. Die
Oberflaeche ist auch ueber 127.0.0.1 zu erreichen - per Terminal-Browser
im Container oder ueber einen SSH-Tunnel -, der Port ist also kein
Pflichtport. Er wird jetzt zum Schliessen angeboten, mit dem Hinweis,
was das bedeutet; --keep-admin laesst ihn offen, und in der Oberflaeche
wird gefragt, sobald er betroffen ist.

Welcher Port es ist, kommt aus NPM_ADMIN_PORT - wer auf 10443 verlegt
hat, bekommt 10443 angeboten. Die Vorgabe 81 steht zusaetzlich immer im
Katalog: nach einem Portwechsel bliebe sie sonst offen, ohne dass sie
noch jemand nennt. Genau dieser Fall - 81 und 10443 beide offen,
konfiguriert ist 10443 - ist der Testfall.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 21:08:08 +02:00
duffyduckandClaude Opus 5 5861989289 Restore im neu erstellten Container: fehlende Systemteile nachziehen
"omd restore" brach ab mit

  ERROR: apache user www-data must be member of group cmk

Die Ursache liegt nicht im Backup. Beim Anlegen einer Site traegt
"omd create" den Apache-Benutzer in die Gruppe der Site ein - das steht
in /etc/group, und das liegt im Container, nicht im Bind-Mount. Wird der
Container neu erstellt, ist /etc/group wieder der Stand aus dem Abbild,
waehrend die Site unveraendert weiterlebt. Der offizielle Entrypoint
erkennt das und legt Gruppe und Benutzer neu an, nimmt www-data dabei
aber nicht in die Gruppe auf. Im Betrieb faellt es nicht auf: die Site
laeuft, die Oberflaeche antwortet. Erst user_verify beim Restore prueft
es.

Direkt dahinter der zweite Halt:

  ERROR: fstab entry for /omd/sites/cmk/tmp does not exist

omd laesst einen fehlenden /etc/fstab ausdruecklich durchgehen ("seen in
some containers") - das Abbild liefert aber eine Datei mit einer
Kommentarzeile, also greift die Ausnahme nicht.

Beides am Abbild checkmk/check-mk-raw:2.4.0-latest nachgestellt: Site im
Bind-Mount anlegen, Container verwerfen, neuen Container mit demselben
Mount starten - die Gruppenzugehoerigkeit ist weg und der Restore bricht
mit genau dieser Meldung ab. Nach "gpasswd -a www-data cmk" und dem
fstab-Eintrag laeuft er durch.

container_fix_site_system stellt beides her, vor jedem restore und
import (do_restore ist die gemeinsame Stelle) und nach jedem "up", damit
auch ein von Hand aufgerufenes omd nicht darueber stolpert. Der
Apache-Benutzer und das Kommando zum Eintragen kommen aus
share/omd/distro.info - derselben Quelle, aus der omd sie liest, statt
"www-data" fest zu verdrahten. Passt schon alles, bleibt die Funktion
still.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 21:00:59 +02:00
duffyduckandClaude Opus 5 06ae4807ba Firewall: Ports auch wieder zumachen
"firewall open" kannte nur eine Richtung. Wer die Event Console wieder
abschaltet oder einen Eintrag aus FW_EXTRA_PORTS streicht, behielt die
Freigabe - der Port stand offen, ohne dass noch etwas dahinter lauscht.

"firewall close" bietet an, was offen ist, zu diesem Aufbau gehoert und
gerade nicht gebraucht wird. Dazu zaehlen die bekannten Ports des Stacks
und alles, was "firewall open --apply" selbst geoeffnet hat; das merkt
sich firewall-opened.conf, damit ein gestrichener FW_EXTRA_PORTS-Eintrag
nicht in Vergessenheit geraet.

Drei Sicherungen, weil hier das Aussperren droht:

  - SSH wird nie geschlossen: Port 22, der Port aus "sshd -T" und der
    Port der laufenden Sitzung aus SSH_CONNECTION
  - fremde Freigaben bleiben unberuehrt - wer 3306 fuer seine Datenbank
    offen hat, behaelt sie
  - Sammelregeln wie "80,443/tcp" werden gemeldet statt geloescht, sonst
    faellt ein noch gebrauchter Port mit weg

Bei ufw wird bewusst nicht nach Regelnummern geloescht. Die Nummern
verschieben sich beim ersten Loeschen, und da je Port ein eigener
Aufruf erzeugt wird, haette der naechste die falsche Regel getroffen -
im Test waere so eine 443er-Freigabe gefallen. Geloescht wird ueber die
Regelangabe, bei nftables ueber den Handle, bei iptables mit derselben
Angabe, mit der die Regel eingetragen wurde.

Nebenbei: fw_state_del liess die Datei stehen, wenn der letzte Eintrag
entfernt wurde - "grep -v" liefert dann 1. Unter "set -e" brach damit
ausserdem der Ablauf ab, noch vor dem Neuladen der Firewall.

In der Oberflaeche liegt das unter Einstellungen > Firewall als
"Nicht mehr benoetigte Ports schliessen".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 20:40:02 +02:00
duffyduckandClaude Opus 5 59304ae02d Proxy-Host bearbeiten, ohne den Rest zu verlieren
Aendern ging bisher nur ueber "proxy add --update", und das schreibt den
Eintrag vollstaendig neu: wer den Port aendern wollte, verlor still die
zusaetzlichen Pfade und die erweiterte Konfiguration, weil die Nutzlast
aus Vorgaben zusammengesetzt wird.

Die Schnittstelle des Proxy Managers arbeitet als Patch - ein PUT mit
nur einem Feld aendert auch nur dieses; an einem laufenden NPM 2.15.1
nachgemessen. Darauf setzt "proxy edit" auf: angegeben wird, was sich
aendern soll, alles Uebrige bleibt unberuehrt.

  proxy edit --id 3 --forward-port 5001
  proxy edit --domain checkmk.example.local --cert self
  proxy edit --id 3 --location /grafana=127.0.0.1:3000
  proxy edit --id 3 --del-location /grafana

Dazu Ziel, Schema, Name, Zertifikat, erweiterte Konfiguration, die vier
Schalter und ein/aus. Ohne Angabe wird nur der Stand gezeigt. In der
Oberflaeche liegt dasselbe unter "Proxy-Host bearbeiten", mit den
aktuellen Werten vorbelegt.

Pfade kennt die Schnittstelle nur als Ganzes, sie werden deshalb gelesen,
geaendert und zurueckgeschrieben. Das an "}" aufzuteilen geht nicht:
"advanced_config" darf nginx-Bloecke mit geschweiften Klammern und
maskierte Anfuehrungszeichen enthalten. Dafuer gibt es jetzt json_raw
und json_split_array, die die Verschachtelung mitzaehlen und
Zeichenketten erkennen. "proxy show" liest die Pfade ebenfalls darueber.

Zwei Fehler kamen dabei ans Licht:

  - NPM_CODE wurde in npm_api gesetzt, aber npm_api wird fast immer in
    einer Kommandoersetzung aufgerufen - also in einer Subshell. Der
    HTTP-Code kam nie beim Aufrufer an; unter "set -u" brach das Skript
    im Fehlerpfad sogar ab, statt den Fehler zu zeigen. Betraf auch
    "proxy add" und das Anlegen von Zertifikaten. Der Code wird jetzt
    zusaetzlich abgelegt und mit npm_code gelesen.
  - Der Proxy Manager schaltet ohne Zertifikat http2_support und
    ssl_forced von sich aus ab. Das blieb unbemerkt; jetzt wird nach dem
    Schreiben verglichen und eine Abweichung gemeldet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 20:27:55 +02:00
duffyduckandClaude Opus 5 8782c6d5c7 HTTPS ueber die blanke IP: Standard-Server statt abgelehntem Handshake
https://<IP>/cmk/ endete im Browser mit ERR_SSL_UNRECOGNIZED_NAME_ALERT,
waehrend dieselbe Adresse ueber http funktionierte. Die Ursache liegt
nicht beim Zertifikat: RFC 6066 laesst in der SNI-Erweiterung keine
IP-Adressen zu, der Browser schickt bei einer IP also gar keinen Namen.
nginx kann den Server-Block dann nicht ueber den Namen waehlen und
faellt auf den Standard-Server zurueck - bei NPM ist das der Block aus
/etc/nginx/conf.d/default.conf mit "ssl_reject_handshake on". Ueber HTTP
faellt das nicht auf, dort entscheidet der Host-Kopf, und der traegt die
IP.

Nachgeprueft am Image jc21/nginx-proxy-manager:2 (2.15.1): der Block
steht dort in Zeile 36, und nginx.conf liest conf.d/*.conf vor den
Proxy-Hosts ein - damit wird er zum Standard-Server, obwohl keiner der
Bloecke "default_server" gesetzt hat. Mit einem eigenen Block, der das
Kennzeichen ausdruecklich traegt, ist der Fall entschieden; Aufrufe mit
Namen gehen unveraendert an ihren Proxy-Host.

Neu ist "proxy default":

  proxy default                 Stand anzeigen
  proxy default --domain X      Proxy-Host X spiegeln
  proxy default --off           Spiegelung entfernen
  --restart                     Proxy Manager gleich neu starten

Gespiegelt wird ueber die API: Ziel, Zertifikat und die zusaetzlichen
Pfade des Proxy-Hosts landen in einem Standard-Server-Block in der
Zusatzkonfiguration. Fuehrt das Zertifikat die IP nicht als
Alternativnamen, sagt der Befehl das vorher - bei Lets Encrypt geht es
prinzipbedingt nicht.

Dabei aufgefallen: die Zusatzkonfiguration liegt im Datenverzeichnis des
Proxy Managers und gehoert dem Container. Ohne Schreibrecht scheiterte
bisher nur ein nacktes "touch" - jetzt sagt npm_conf_writable, woran es
liegt, und nennt den sudo-Aufruf. Das gilt auch fuer "npm-port".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 20:17:10 +02:00
duffyduckandClaude Opus 5 989256e082 Menuepunkt: Firewall-Regeln uebernehmen
Der Bericht sagte bisher nur, was fehlt - gesetzt wurde es entweder auf
der Kommandozeile mit "firewall open --apply" oder gar nicht. Unter
Einstellungen > Firewall stehen jetzt zwei Aktionen: pruefen und
uebernehmen.

Beim Uebernehmen wird zuerst nach einem Quellnetz gefragt und erst
danach angezeigt, was ausgefuehrt wird. Die Reihenfolge ist Absicht -
das Quellnetz aendert die Kommandos, und was im Fenster steht, soll
auch das sein, was laeuft. Ohne root-Rechte wird ueber sudo neu
aufgerufen; zum Schluss zeigt die Oberflaeche den Stand danach.

Dabei zwei Dinge in Ordnung gebracht:

  - cmd_firewall gab auch nach erfolgreichem Uebernehmen noch 1 zurueck
    (den urspruenglichen Befund). Die Oberflaeche las das als
    "FEHLGESCHLAGEN", obwohl die Regeln gesetzt waren.
  - Die aktiven Zonen werden einmal je Aufruf ermittelt statt erneut
    fuer jede Regelzeile.

Die FW_*-Schluessel fehlen in einer aelteren .env noch; im Menue steht
dann <leer>. Die Beschriftungen nennen deshalb die Vorgabe, die in dem
Fall gilt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 20:01:12 +02:00
duffyduckandClaude Opus 5 b912578f27 Firewall-Pruefung: welche Ports offen sein muessen - und welche nicht
Auf RHEL ist firewalld ab Werk aktiv und gibt in aller Regel nur SSH
frei. Der Stack laeuft dann sauber, ist aber von aussen nicht zu
erreichen: die Agents kommen nicht durch den Receiver auf 8000, und im
Browser passiert nichts. Das war bisher nur eine Handvoll statischer
Beispielzeilen in der README und in install.sh.

Neu ist "cmk-manage.sh firewall". Erkannt werden firewalld, ufw,
nftables und iptables; welche Ports noetig sind, ergibt sich aus der
Konfiguration statt aus einer festen Liste:

  - ohne Proxy Manager wird 5000 zum Pflichtport, mit ihm soll es zu
    bleiben - offenes 5000 wird deshalb ausdruecklich angemerkt
  - der Admin-Port kommt aus NPM_ADMIN_PORT, nicht fest aus 81
  - FW_ROLE unterscheidet single/central/remote: eine Remote-Site
    braucht 6557 eingehend, die Zentrale baut die Verbindungen selbst
    auf und braucht dafuer nichts. Steht FW_ROLE=remote bei
    CMK_LIVESTATUS_TCP=off, ist der Port zwar offen, es lauscht aber
    niemand - auch darauf weist der Bericht hin.
  - Event Console ueber FW_EC_SYSLOG / FW_EC_SNMPTRAP / FW_EC_TCP,
    Agent dieses Hosts ueber FW_AGENT, alles Weitere (Grafana, NSCA)
    ueber FW_EXTRA_PORTS

Syslog und SNMP-Traps laufen ueber UDP, eine TCP-Freigabe nuetzt ihnen
nichts. Ports werden deshalb durchweg als nummer/protokoll gefuehrt -
beim Pruefen wie beim Erzeugen der Regeln. Bestehende Regeln werden
entsprechend gelesen: Portbereiche (6556-6558 bzw. 6556:6558) werden
aufgeloest, firewalld-Dienstnamen und Rich Rules zaehlen mit, bei
firewalld alle aktiven Zonen statt nur der Standardzone, und eine
ufw-Regel ohne Protokoll zaehlt fuer TCP und UDP - so wie ufw sie
anlegt.

"firewall open" zeigt die passenden Kommandos, --apply setzt sie nach
Rueckfrage, --source begrenzt sie auf ein Quellnetz (fuer Port 80 mit
Warnung, weil Lets Encrypt von aussen prueft). Ohne Befund ist der
Rueckgabewert 1, damit sich das auswerten laesst. In der Oberflaeche
steckt derselbe Bericht unter "Firewall pruefen".

Nebenbei: env_set hat Werte mit Leerzeichen samt Anfuehrungszeichen in
die laufende Umgebung exportiert. In der Datei gehoeren sie hin, im
Wert nicht - das fiel erst mit den Beschreibungen in FW_EXTRA_PORTS auf.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:46:33 +02:00
duffyduckandClaude Opus 5 d06ecb2704 Menuepunkt: Datenbank des Proxy Managers zuruecksetzen
Das Kommando gab es schon, den Weg dorthin nicht. Jetzt erreichbar unter
  Einstellungen -> NGINX Proxy Manager -> ">> Datenbank zuruecksetzen"
und zusaetzlich im Proxy-Hosts-Menue.

Der Dialog fuehrt durch die Sache, statt nur auszufuehren:
  * Gibt es noch keine Datenbank, sagt er das und nennt den kuerzeren
    Weg (Zugangsdaten setzen, Stack starten).
  * Fehlen NPM_ADMIN_EMAIL/-PASSWORD, weist er darauf hin, dass sonst
    wieder kein Konto entstuende, und bietet an, sie gleich einzutragen.
  * Vor dem Zuruecksetzen zeigt er Dateigroesse, was verloren geht
    (Konten, Proxy-Hosts, Weiterleitungen, Zugriffslisten) und was
    bleibt (Zertifikate), samt dem Konto, das danach entsteht.
  * Anschliessend bietet er an, den Stack gleich zu starten - ohne das
    entsteht das Konto naemlich noch nicht.

Beide Zweige durchgespielt: ohne Datenbank meldet er "Nichts
zurueckzusetzen", mit Datenbank legt er sie als database.sqlite.alt-<stamp>
beiseite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:22:53 +02:00
duffyduckandClaude Opus 5 ed768f049b Fehlende Proxy-Manager-Anmeldung: nach Lage erklaeren statt nur melden
"Ich dachte, der nginx legt die an" - eine berechtigte Erwartung, die
seit NPM 2.15 nicht mehr stimmt. Die Meldung sagte zwar, WAS fehlt, aber
nicht, was im jeweiligen Zustand zu tun ist.

npm_api_token sieht jetzt nach, ob data/npm/data/database.sqlite schon
existiert, und unterscheidet:

  keine Datenbank   Zugangsdaten setzen und "up" - der Container legt
                    das Konto daraus selbst an
  Datenbank da      Die Variablen wirken nicht mehr. Konto im Browser
                    anlegen und dieselben Daten mit "config set"
                    eintragen.

Dazu "npm-reset" fuer den sauberen Neuanfang: es legt die Datenbank
beiseite (umbenannt, nicht geloescht), sodass der Container das Konto
beim naechsten Start neu erzeugt. Vorher zeigt es an, was dabei verloren
geht - Proxy-Hosts, Weiterleitungen, Zugriffslisten - und was bleibt:
die Zertifikate. Mit Rueckfrage.

Beide Zweige durchgespielt. In beiden Sprachfassungen dokumentiert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:16:18 +02:00
duffyduckandClaude Opus 5 22331ff114 Steuerzeichen in Textanzeigen, veralteter Anmeldehinweis, Image-Name
Drei Dinge aus einem Bildschirmfoto des laufenden Systems:

1. In jeder Textanzeige standen rohe Steuerzeichen (^[[1mImage^[[0m).
   Die Farbvariablen werden beim Laden von common.sh einmal festgelegt -
   das NO_COLOR beim spaeteren Aufruf wirkte deshalb nicht mehr. Statt
   an jeder Aufrufstelle zu flicken, entfernt jetzt _ui_file die
   Sequenzen; das greift fuer ALLE Textanzeigen, auch die von ui_run.

2. Der Status nannte weiterhin "Erstlogin: admin@example.com /
   changeme". Diese Zugangsdaten gibt es seit NPM 2.15 nicht mehr -
   genau das war hier schon Thema. Er zeigt jetzt NPM_ADMIN_EMAIL, und
   weist darauf hin, wenn kein Konto hinterlegt ist.

3. Ein aus dem Tarball geladenes Image heisst nicht
   "localhost/checkmk/..." wie von mir dokumentiert, sondern
   "docker.io/checkmk/check-mk-enterprise:2.4.0p9" - Podman ergaenzt den
   unqualifizierten Namen aus dem Archiv um docker.io, obwohl es das
   Image dort nicht gibt. Beides in beiden Sprachfassungen
   richtiggestellt, mit dem Hinweis, dass das harmlos ist: lokal ist es
   da, "up" nutzt es, nur pullen liesse es sich so nicht - dafuer gibt
   es "image get".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:08:43 +02:00
duffyduckandClaude Opus 5 4d2e234c36 Bezugsweg als Schalter, schlankes "Image holen", up holt selbst
Drei zusammenhaengende Vereinfachungen aus der Bedienung heraus:

1. CMK_IMAGE_SOURCE bestimmt, woher ein fehlendes Image kommt:
     auto      erst Registry, dann Downloadportal (Vorgabe)
     registry  nur Registry
     download  nur Tarball
   "auto" ist die sinnvolle Vorgabe, weil Registries nur die juengsten
   Patchstaende vorhalten - genau die aeltere Version, die eine
   Migration braucht, liegt dann nur noch im Archiv. Der Wechsel
   geschieht ohne Rueckfrage.

2. "image get" holt ueber diesen Weg, ohne dass Edition und Version
   erneut abgefragt werden. Im Menue fragt "Image holen" entsprechend
   nur noch nach dem Bezugsweg; der eingestellte ist gekennzeichnet.
   Der vollstaendige Assistent bleibt als eigener Punkt daneben, fuer
   den Fall, dass Edition oder Version geaendert werden sollen.

3. "up" beschafft ein lokal fehlendes Image selbst, bevor compose
   startet. Vorher lief compose in einen nackten Pull, der bei einer nur
   im Downloadportal vorhandenen Version scheitern musste - genau der
   Fall mit 2.4.0p9. Mit "up --no-fetch" bleibt das aus.

Durchgespielt mit einer absichtlich nicht existierenden Version: up
erkennt das fehlende Image, versucht die Registry, weicht auf das
Downloadportal aus, bricht nach beiden Fehlschlaegen ab - und ruft
compose gar nicht erst auf. Mit --no-fetch geht es direkt zu compose.

Nebenbei: im Auswahlmenue erschien der eingestellte Bezugsweg doppelt
(einmal als "wie eingestellt", einmal unter seinem Namen) - zwei
Eintraege mit derselben Kennung. Jetzt wird der eingestellte nur noch
gekennzeichnet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 19:00:04 +02:00
duffyduckandClaude Opus 5 7a74042394 Fehlendes Tag in der Registry: auf den Tarball verweisen
Die Diagnose auf dem Zielsystem zeigte: enterprise/check-mk-enterprise
fuehrt im Zweig 2.4.0 nur p31 aufwaerts, dazu -latest und die taeglichen
Bauten. 2.4.0p9 ist dort herausgerollt - die Registry haelt nur die
juengsten Patchstaende vor.

Nachgemessen, dass das Downloadportal die Version weiterhin hat:
    .../2.4.0p9/check-mk-enterprise-docker-2.4.0p9.tar.gz   HTTP 401
also vorhanden, nur geschuetzt. Auch das oeffentliche Versionsarchiv
listet sie mit genau diesem Dateinamen.

Das ist kein Randfall, sondern der Normalfall bei einer Migration:
"omd restore" verlangt exakt die Version der Quell-Site, und die ist in
aller Regel aelter als das, was die Registry noch vorhaelt.

image_diagnose_ref sieht deshalb bei einem fehlenden Tag im Archiv nach
und nennt, wenn die Version dort liegt, den Tarball-Weg samt fertigem
Kommando - statt den Benutzer zwischen Registry und Portal suchen zu
lassen. Mit dem Unterschied zwischen beiden Quellen ist das jetzt auch
in beiden Sprachfassungen erklaert.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:49:27 +02:00
duffyduckandClaude Opus 5 43557e9753 Dialog: Image aus den Vorgaben setzen - die fehlende Gegenrichtung
Der Dialog hinter CMK_IMAGE/EDITION/VERSION bot bisher nur eine
Richtung an: Vorgaben aus dem verwendeten Image ableiten. Die
naheliegende Gegenrichtung - aus Edition und Version das Image bilden -
war nur ueber den ganzen Assistenten erreichbar, obwohl beide Werte
schon dastehen.

Neuer Eintrag "Image aus den Vorgaben setzen". Er zeigt gleich in der
Beschriftung, was dabei herauskommt, z.B.

  setzen  Image aus den Vorgaben setzen
          ->  registry.checkmk.com/enterprise/check-mk-enterprise:2.4.0p9

und traegt die Referenz nach Rueckfrage ein, ohne etwas zu laden.
Fehlt Edition oder Version, sagt der Dialog das, statt eine
unbrauchbare Referenz zu bilden.

Die drei Wege stehen jetzt in einer nachvollziehbaren Reihenfolge:
Assistent (alles), setzen (Vorgaben -> Image), angleichen (Image ->
Vorgaben).

Geprueft mit gesetzten Vorgaben: der Eintrag bildet die richtige
Referenz, das Uebernehmen schreibt sie in die .env, und whiptail
rendert den laengeren Eintrag ohne Fehler - die Fensterbreite waechst
mit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:45:50 +02:00
duffyduckandClaude Opus 5 7fb0c6ea9e "manifest unknown" erklaeren - und eine Pipe-Falle beseitigen, die das
Erkennen verhindert hat

Der Pull meldete "manifest unknown". Das heisst, anders als zuvor: der
Repository-Pfad registry.checkmk.com/enterprise/check-mk-enterprise ist
richtig und die Anmeldung auch - nur das Tag 2.4.0p9 gibt es dort nicht.

Neu "image why [REF]" unterscheidet die drei Faelle anhand der Registry
statt anhand der Fehlermeldung:
    401/403  Anmeldung oder Berechtigung
    404      Repository gibt es nicht        -> image repos
    Tag      Repository ja, Tag nein         -> vorhandene Tags des
             Zweigs werden aufgelistet
"up" ruft das von selbst auf, wenn das Starten scheitert und das Image
nicht lokal vorliegt; "image pull" ebenfalls.

Beim Bauen stellte sich heraus, dass die Tag-Pruefung immer "nicht
vorhanden" meldete - auch fuer Tags, die es gibt. Ursache ist eine
Falle, die das ganze Projekt betraf:

    printf ... | grep -q muster

"grep -q" endet beim ersten Treffer. Der Erzeuger bekommt dann SIGPIPE,
und unter "set -o pipefail" gilt die ganze Pipe als fehlgeschlagen -
aber nur, wenn er noch am Schreiben war. Bei drei Zeilen faellt das nie
auf, bei 2393 Tags immer. Nachgestellt:

    set -euo pipefail; seq 1 500000 | grep -qx 3   -> schlaegt fehl

Betroffen waren zwoelf Stellen, darunter zwei, die ernster sind als die
Tag-Liste: bundle_read prueft mit "tar -tzf ... | grep -qx", ob ein
Backup ein Bundle ist. Bei einem grossen Archiv haette ein gueltiges
Bundle als "kein Bundle" gegolten - also ein stiller Fehler bei Restore
und Import genau dann, wenn das Backup gross ist. Alle zwoelf laufen
jetzt in einer Subshell ohne pipefail.

Der Selbsttest hat dafuer eine eigene Pruefung bekommen, damit die
Schreibweise nicht zurueckkehrt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:44:08 +02:00
duffyduckandClaude Opus 5 a8fbc3f557 NCURSES_NO_UTF8_ACS: ncurses zu Unicode-Rahmen zwingen
Die Diagnose auf dem betroffenen Terminal war eindeutig: Zeile A (echte
UTF-8-Rahmenzeichen) zeichnete Linien, Zeile B (VT100-Umschaltung ESC(0)
nicht. Locale war bereits C.UTF-8, dialog war installiert - und die
Oberflaeche sah trotzdem falsch aus.

Grund: ncurses benutzt die VT100-Umschaltung AUCH mit UTF-8-Locale,
solange das terminfo sie anbietet - bei TERM=xterm der Fall. Die
Locale-Korrektur allein reichte deshalb nicht, und der Wechsel von
whiptail zu dialog machte es sogar schlechter, weil whiptail (slang)
bei UTF-8-Locale von sich aus Unicode zeichnet, ncurses aber nicht.

Abhilfe ist NCURSES_NO_UTF8_ACS=1. Mit dialog unter LANG=C.UTF-8 und
TERM=xterm gemessen:
    ohne Schalter :  38 ESC(0,   0 Rahmenbytes, 182 rohe q
    mit  Schalter :   0 ESC(0, 220 Rahmenbytes,   0 rohe q

ui_init setzt den Schalter jetzt, sobald eine UTF-8-Locale gilt.
CMK_TUI_ACS=1 stellt das alte Verhalten wieder her - fuer Terminals, die
ESC(0 beherrschen, aber kein UTF-8.

tui-check zeigt den Stand des Schalters an und erklaert bei "A Linien,
B Buchstaben" jetzt, dass genau dieser Fall abgefangen wird und die
Oberflaeche trotzdem sauber aussehen muss.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:38:54 +02:00
duffyduckandClaude Opus 5 861a9bd71c tui-check: Ursache der Rahmendarstellung am Terminal ablesen
Nach der Locale-Korrektur meldet der Selbsttest UTF-8, die Anzeige blieb
aber unveraendert. Damit liegt es nicht mehr an der Serverseite, und
Weiterraten hat keinen Sinn.

"cmk-manage.sh tui-check" gibt jetzt zwei Testzeilen aus:
  Zeile A  echte UTF-8-Rahmenzeichen (U+2500 ff.)
  Zeile B  die alte VT100-Umschaltung ESC(0 mit den Buchstaben lqk
An deren Aussehen laesst sich die Ursache direkt ablesen - Terminal
ignoriert die Umschaltung (PuTTY-Fall), Terminal nicht im UTF-8-Modus,
oder Schrift ohne Rahmenzeichen. Zu jeder Beobachtung nennt die Ausgabe
die passende Abhilfe samt PuTTY-Einstellungen.

Dazu der ASCII-Schalter, der bisher ins Leere lief: einfache Rahmen kann
nur dialog zeichnen. Ist CMK_TUI_ASCII gesetzt und dialog vorhanden,
wird dialog jetzt dafuer vorgezogen; fehlt es, sagt das Skript das
ausdruecklich statt wirkungslos weiterzumachen.

dialog ist auf dieser Seite ohnehin der wirksamere Griff - es geht mit
dem Zeichensatz zuverlaessiger um als whiptail. Entsprechend in beiden
Sprachfassungen hervorgehoben.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:28:38 +02:00
duffyduckandClaude Opus 5 667c119a6c Rahmen in PuTTY: UTF-8-Locale fuer die Oberflaeche erzwingen
Gemeldet mit Bildschirmfoto: statt Rahmen erscheinen q, x, l und m.
Ursache nachgemessen - ohne UTF-8-Locale zeichnen dialog und whiptail
die Rahmen ueber die alte VT100-Umschaltung ESC(0, die Terminals im
UTF-8-Modus (PuTTY in der Vorgabe) ignorieren:

    LC_ALL=C        ESC(0-Umschaltungen: 1   rohe q: 91
    LC_CTYPE=C.UTF-8  ESC(0-Umschaltungen: 0   rohe q: 0

ui_init setzt jetzt beim Start der Oberflaeche LC_CTYPE auf die erste
verfuegbare UTF-8-Locale. Bewusst nur LC_CTYPE, damit Sortierung und
Zahlenformat unberuehrt bleiben. Dabei war ein zweiter Anlauf noetig:
ein gesetztes LC_ALL sticht jede einzelne Kategorie aus, der erste
Versuch blieb deshalb wirkungslos. Steht LC_ALL auf einem
Nicht-UTF-8-Wert, wird es entfernt.

Gemessen ueber unsere eigene ui_menu unter LC_ALL=C: vorher 91 rohe q,
danach 0.

Gibt es gar keine UTF-8-Locale, faellt die Oberflaeche auf einfache
Rahmen zurueck (dialog --ascii-lines, sofern unterstuetzt); erzwingen
laesst sich das mit CMK_TUI_ASCII=1. Der Selbsttest hat dafuer einen
eigenen Abschnitt, der die Locale vorher und nachher zeigt und im
Zweifel das fehlende Sprachpaket nennt.

Dokumentiert als Abschnitt 14.4 in beiden Sprachfassungen, samt der
vier PuTTY-Einstellungen fuer die Gegenseite.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:20:47 +02:00
duffyduckandClaude Opus 5 9d8a9ecf71 "Nur eintragen" setzt jetzt auch CMK_IMAGE
Berechtigter Einwand: wer Edition und Version waehlt und "nichts holen"
sagt, will das Image SETZEN, nicht bloss zwei Vorgaben notieren. Mein
Entwurf trennte das kuenstlich - und hinterliess genau dadurch den
Zustand, den die Abweichungswarnung dann anmahnte. Das war die Ursache
des Hin und Her.

Die Referenz laesst sich aus Edition und Version bilden:
    enterprise 2.4.0p9 -> registry.checkmk.com/enterprise/check-mk-enterprise:2.4.0p9
    raw        2.4.0p9 -> docker.io/checkmk/check-mk-raw:2.4.0p9
Nur bei einem aus dem Tarball geladenen Image geht das nicht, da kommt
der Name aus dem Archiv.

Deshalb:
  image use --edition E --version V
bildet die Referenz und traegt CMK_IMAGE, CMK_EDITION und CMK_VERSION
ein, ohne irgendetwas herunterzuladen. Geholt wird beim naechsten "up"
durch die Runtime selbst.

Im Assistenten heisst der Weg jetzt "Nur eintragen - geholt wird beim
naechsten Start" und nutzt genau das. Damit setzen ALLE vier Wege
CMK_IMAGE; sie unterscheiden sich nur darin, ob dabei schon etwas
geholt wird. Die drei Werte bleiben dadurch von selbst stimmig, und die
Abweichungswarnung tritt im normalen Betrieb nicht mehr auf.

Geprueft: das Kommando und der Assistentenweg setzen alle drei Werte,
danach meldet "image status" keine Abweichung mehr.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:13:57 +02:00
duffyduckandClaude Opus 5 c1371da7aa Zugangsdaten: .netrc ersetzt - Kennwoerter mit Sonderzeichen kamen
verstuemmelt an

Der Download schlug trotz richtiger Zugangsdaten fehl. Ursache gefunden:
die Uebergabe lief ueber eine temporaere .netrc, deren Format die Felder
durch Leerzeichen trennt. Ein Kennwort mit Leerzeichen, #, " oder
aehnlichem kam dadurch still verstuemmelt an - curl schickte etwas
anderes als hinterlegt, der Server antwortete 401, und die Meldung
lautete "Anmeldung abgelehnt", obwohl die Daten stimmten.

Gegen einen eigens gestarteten Testserver nachgemessen, Kennwort
'Pa ss#wo"rt$1':
    ohne Anmeldung            HTTP 401
    neu, curl --config -      HTTP 200
    alt, .netrc               HTTP 401

Alle dreizehn Aufrufstellen sind auf curl_auth umgestellt, das die
Angaben ueber "curl --config -" von der Standardeingabe liest und in
Anfuehrungszeichen setzt. Beliebige Zeichen sind damit moeglich, und die
Zugangsdaten stehen weiterhin nicht in der Prozessliste - geprueft.

Ausserdem sagt der Download jetzt, WORAN es liegt: vor dem Holen wird
der Status abgefragt und 401/403 (Anmeldung), 404 (Datei gibt es nicht)
und 000 (nicht erreichbar) getrennt gemeldet. Doppelte Kandidaten
werden nicht mehr zweimal probiert.

Dazu zwei Aergernisse aus der Bedienung beseitigt:
  * Der Assistent meldete nach "nur eintragen" die Abweichung als
    Problem, obwohl der Benutzer genau das gewollt hatte. Jetzt steht
    dort schlicht, dass Edition und Version gespeichert sind und kein
    Image geholt wurde.
  * Der Dialog hinter CMK_IMAGE/EDITION/VERSION war lang und erklaerte
    mehr, als er half. Er nennt jetzt in zwei Zeilen die Lage und stellt
    die Handlung voran.

Randnotiz zur Fehlersuche: die URL selbst war nie das Problem. Der
Server liefert fuer check-mk-enterprise-docker-2.4.0p9.tar.gz ein 401,
also "vorhanden, nur geschuetzt" - und fuer check-mk-pro-... ein 404,
denn "pro" heisst die Edition erst ab 2.5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 18:11:19 +02:00
duffyduckandClaude Opus 5 e7eb1c3be9 Mehrere Dienste hinter einem Port: Pfade statt Domainnamen
Hintergrund aus der Praxis: nach aussen ist nur ein Port frei, auf dem
Server laufen aber Checkmk und Grafana und noch ein Dienst. Die Frage
war, ob sich statt eines Domainnamens auch /irgendeinname nutzen laesst.

Ja - der Proxy Manager kennt dafuer "Custom locations", und die API
nimmt sie als locations-Array entgegen. Geprueft am Schema von v2.15.1
(components/proxy-host-object.json) und an der Vorlage _location.conf,
aus der nginx den location-Block erzeugt.

  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

--location ist mehrfach angebbar, versteht /pfad=host:port, wahlweise
mit Schema (https://) und mit einem Pfad, der beim Ziel vorangestellt
wird (/alt=host:3000/basis). Ungueltige Angaben werden abgewiesen.
Ebenfalls geprueft: als --domain ist eine IP-Adresse zulaessig, ein
DNS-Name ist nicht noetig (das Muster im Schema laesst alles ausser
einer Handvoll Sonderzeichen zu).

Neu dazu "proxy show --domain X | --id N", das den Eintrag samt allen
Pfaden auflistet - noetig, weil --update den Eintrag vollstaendig
ersetzt und man die bestehenden Pfade wieder mitgeben muss.

Im Assistenten fragt die Oberflaeche nach dem Zertifikat, ob weitere
Dienste unter demselben Namen liegen sollen, und nimmt dann Pfad und
Ziel im Wechsel auf, bis ein Feld leer bleibt.

Dokumentiert als Abschnitt 10.3 in beiden Sprachfassungen, mit dem
Fallstrick, der sonst Stunden kostet: ein Dienst hinter einem Unterpfad
muss seinen Basispfad kennen. Fuer Grafana sind das root_url und
serve_from_sub_path; ohne die bleibt die Seite weiss, weil das
JavaScript unter /public statt /grafana/public gesucht wird. Checkmk
ist nicht betroffen, es liegt ohnehin unter /<site>/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:56:04 +02:00
duffyduckandClaude Opus 5 fd96126199 README: advanced_config war als "Vorgabe unten" angekuendigt, stand aber
nirgends

Die proxy-Kommandos waren dokumentiert, in der Optionstabelle verwies
"--advanced" aber auf eine Erklaerung, die es nicht gab.

Jetzt steht der Vorgabeblock woertlich in Abschnitt 10.2, mit einer
Begruendung je Zeile:
  client_max_body_size 0     grosse Agent-Uploads und Bakery-Pakete
  proxy_read_timeout 300s    lange laufende Checkmk-Ansichten
  X-Forwarded-Proto          sonst erzeugt Checkmk http://-Verweise
  X-Forwarded-For            sonst steht nur die Proxy-Adresse im Log
Dazu, dass --advanced den Block ERSETZT (nicht ergaenzt), dass
--advanced '' ihn leert, und dass der Assistent immer die Vorgabe nimmt.

Gegengeprueft, dass der Block die JSON-Kodierung unbeschadet uebersteht:
die erzeugte Nutzlast ist gueltiges JSON, advanced_config kommt mit vier
Zeilen an, und $scheme sowie $proxy_add_x_forwarded_for bleiben als
nginx-Variablen erhalten - sie werden von der Shell nicht ersetzt.
Beim Live-Test gegen die echte Instanz war genau dieser Vorgabeblock im
Einsatz; dass nginx ihn geladen hat, zeigte sich daran, dass 443
danach antwortete und 80 dorthin umleitete.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:50:02 +02:00
duffyduckandClaude Opus 5 b4efbba050 Alle Fenster ueber drei gemeinsame Stellen, Selbstpruefung dazu
Die berechnete Fenstergroesse galt bisher nur fuer die Dialoge, die ich
dafuer einzeln angefasst hatte. Eine Pruefung des ganzen Projekts zeigte
zwei Luecken:
  * in common.sh gab es neun verstreute Aufrufstellen von dialog/whiptail
  * migrate_creator.sh hatte noch durchgehend feste Groessen
    (20 76 11, 10 76, 18 76, 14 76, 22 78, 8 76)

Beide Skripte rufen dialog/whiptail jetzt nur noch ueber drei Stellen auf:
  _ui_list  Listenfenster  (menu, checklist, radiolist)
  _ui_box   Textfenster    (msgbox, yesno, inputbox, passwordbox, infobox)
  _ui_file  Dateianzeige   (textbox)
Die berechnen die Groesse selbst. Damit stimmt sie auch fuer Fenster, die
spaeter dazukommen - man muss nur eine der ui_*-Huellen benutzen.

Neu: "cmk-manage.sh selftest" haelt das nach. Geprueft werden Syntax
aller vier Skripte, Dialoge an den Engstellen vorbei, fest eingetragene
Fenstergroessen, das Muster "[ ... ] && VAR=..." und die Vollstaendigkeit
der Einstellungstabelle gegenueber .env.example.

Der Lauf fand sofort 19 Altlasten des Musters "[ ... ] && VAR=...", das
hier schon dreimal einen stillen Abbruch verursacht hat - alle in
if-Bloecke umgeschrieben und stichprobenartig geprueft, auch die Faelle
mit case-Abschluss und Array-Zuweisung. Danach laeuft die Selbstpruefung
vollstaendig durch.

Regression: alle CLI-Kommandos, zwoelf Menuefunktionen und das Rendern
von sechs Fenstern unter whiptail in einem echten Pseudo-Terminal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:48:12 +02:00
duffyduckandClaude Opus 5 9417f0c102 Dialoge passen sich an Terminal, Text und Anzahl der Eintraege an
Die Fenstergroesse war fest (22x78, Liste 13 Zeilen). Bei einem langen
Erklaertext blieb davon nur eine sichtbare Listenzeile uebrig - die
Auswahl liess sich nur noch scrollend bedienen.

ui_calc berechnet die Groesse jetzt aus Terminalgroesse, Zeilenzahl des
Textes und Anzahl sowie Breite der Eintraege; ui_calc_text macht
dasselbe fuer Meldung, Abfrage und Eingabe, ui_text nutzt fast das
ganze Terminal. Damit sind beim beanstandeten Dialog alle drei
Eintraege sichtbar statt einem, und in einem 45-Zeilen-Terminal passen
alle 13 Hauptmenue-Punkte gleichzeitig hin.

Beim Bauen gleich wieder in die bekannte Falle getappt und behoben:
"[ bedingung ] && VAR=wert" liefert 1, wenn die Bedingung nicht
zutrifft, und beendet unter "set -e" die Funktion. Die Berechnung
verwendet deshalb durchgehend if-Bloecke; das ist im Quelltext
vermerkt, damit es nicht wieder passiert.

Geprueft: Geometrie fuer den beanstandeten Dialog und fuer lange
Listen, Rendern aller Menues unter whiptail in einem echten
Pseudo-Terminal ohne Fehlermeldung, und alle Menues kehren weiterhin
sauber zurueck.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:41:19 +02:00
duffyduckandClaude Opus 5 9c99429c15 Proxy-Hosts ueber die API statt ueber den Terminal-Browser
Drei zusammenhaengende Befunde aus der Praxis, alle am laufenden
Container nachgeprueft:

1. Die Standardzugangsdaten admin@example.com/changeme stimmen nicht
   mehr. In backend/setup.js von v2.15.1 steht, dass das erste Konto
   nur angelegt wird, wenn INITIAL_ADMIN_EMAIL und
   INITIAL_ADMIN_PASSWORD gesetzt sind - sonst kommt der
   Einrichtungsassistent. Meine README war an der Stelle falsch.
   Die beiden Werte stehen jetzt als NPM_ADMIN_EMAIL/-PASSWORD in der
   .env und werden von compose und der Quadlet-Unit durchgereicht.
   Gegen einen frisch gestarteten Container geprueft: das Konto ist
   sofort da und die Anmeldung an der API liefert ein Token.

2. Die Weboberfliche laesst sich im Terminal-Browser kaum bedienen
   (JSON-Fehler bei Proxy-Hosts, keine Datei-Uploads). Da der Proxy
   Manager ohnehin lokal laeuft, gibt es jetzt

     proxy status | list | certs | add | del

   Damit legt "proxy add --domain X" in einem Zug an: Zertifikat
   erzeugen bzw. bei Let's Encrypt anfordern, hochladen, Proxy-Host
   anlegen, HTTPS erzwingen, HTTP/2 und Websockets setzen. Der Zielport
   ist frei waehlbar (--forward-port), nicht auf 5000 festgelegt.
   Im Menue unter "proxy" und in den Einstellungen unter NGINX Proxy
   Manager.

3. Let's Encrypt nimmt in 2.15 die E-Mail des angemeldeten Kontos; ein
   letsencrypt_email im Aufruf gibt es nicht mehr. Entsprechend
   umgesetzt und im Fehlerfall erklaert.

Beim Testen gegen die echte Instanz gefunden und behoben:
  - Wieder "set -e": ein grep ohne Treffer beendete das Skript still,
    "proxy add" tat daraufhin gar nichts. Vier Stellen abgesichert.
  - Die Listenantwort laesst sich nicht an "{" zerlegen, weil
    "meta":{...} ebenfalls Klammern enthaelt - dadurch fehlte das
    Schema in der Ausgabe. Die Eintraege werden jetzt einzeln geholt.
  - --update legte jedes Mal ein neues Zertifikat an. Ein vorhandener
    eigener Eintrag gleichen Namens wird jetzt wiederverwendet.

Durchgespielt: Anmeldung, Anlegen mit selbstsigniertem Zertifikat,
Liste, Zertifikatsliste, --update, Loeschen, Neuanlage mit anderem
Zielport und alle Fehlerfaelle. Gegengeprueft, dass Port 443 danach
tatsaechlich mit unserem Zertifikat antwortet (CN=checkmk.test.local)
und Port 80 per 301 dorthin umleitet.

Dokumentiert als Kapitel 10.1 bis 10.3 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:36:21 +02:00
duffyduckandClaude Opus 5 c04b3171d9 Fehlgeschlagenes Holen klar benennen, Ausweg aus dem halben Zustand
Gemeldet war "CMK_IMAGE wird nicht aktualisiert". Nachgemessen: das
Neu-Einlesen funktioniert - ein Unterprozess schreibt, load_env liest,
der Wert kommt an. Die eigentliche Ursache war, dass der Pull gegen die
Registry fehlschlug und CMK_IMAGE deshalb zu Recht unveraendert blieb.
Nur sagte der Assistent das nicht, sondern zeigte die generische
Meldung "passt nicht zu den Vorgaben" - was wie ein Anzeigefehler
aussieht.

  - Der Assistent wertet den Rueckgabewert jetzt aus und meldet
    "Image wurde NICHT geholt", nennt CMK_IMAGE unveraendert und die
    naechsten Schritte (image repos, Tarball-Weg, Zugangsdaten).
  - Edition und Version werden bei einem Fehlschlag nicht halb
    uebernommen: --remember greift erst nach erfolgreichem Holen.

Damit man aus einem bereits bestehenden halben Zustand herauskommt,
gibt es jetzt den umgekehrten Weg:

  image use REF --remember

leitet CMK_EDITION und CMK_VERSION aus der Image-Referenz ab
(check-mk-<edition>:<tag>). Im Menue steht hinter den drei Werten
entsprechend eine Auswahl: Assistent starten, Vorgaben an das
verwendete Image angleichen, oder nichts aendern.

Geprueft: Schreiben im Unterprozess und Neu-Einlesen, Ableiten der
Vorgaben aus dem Image (Warnung verschwindet danach), Assistent mit
absichtlich falschen Zugangsdaten meldet den Fehlschlag und laesst
die .env unangetastet.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:24:04 +02:00
duffyduckandClaude Opus 5 f8a8c7a2a6 image repos: herausfinden, was die Registry wirklich anbietet
"Login Succeeded" und trotzdem "unable to copy from source": der
Repository-Pfad enterprise/check-mk-enterprise war geraten, nicht
belegt. Statt weiter zu raten fragt das Werkzeug jetzt nach.

  image repos [--edition E] [--registry R] [--user/--password]

fragt zuerst /v2/_catalog ab (sperren viele Registries) und probiert
danach die ueblichen Pfade durch, je Edition und deren Aliasnamen:
  <ed>/check-mk-<ed>, check-mk-<ed>, checkmk/check-mk-<ed>,
  enterprise/check-mk-<ed>
Gemeldet wird pro Pfad der HTTP-Status samt Tag-Anzahl. Scheitert ein
"image pull" gegen eine private Registry, laeuft die Pruefung von
selbst an und zeigt gleich, was dort liegt.

Wichtig bei der Deutung und deshalb auch so beschriftet: 401 heisst
nicht "vorhanden". Docker Hub antwortet auch auf nicht existierende
Repositories mit 401. Verlaesslich sind nur 200 und 404.

Nebenbei am Versionsarchiv geklaert, dass die Editionsumbenennung erst
mit 2.5 greift:
  2.4.0p9  -> check-mk-{raw,enterprise,cloud,managed}-docker-...
  2.5.0p13 -> check-mk-{community,pro,ultimate,ultimatemt}-docker-...
Fuer 2.4 ist "--edition enterprise" also richtig.

registry_get_token nimmt jetzt einen frei waehlbaren Scope, damit auch
registry:catalog:* angefordert werden kann.

Gegen Docker Hub verifiziert: findet checkmk/check-mk-raw (2394 Tags)
und checkmk/check-mk-community (534 Tags); gegen registry.checkmk.com
ohne Zugangsdaten sauberer Fehlbericht statt Haenger.

Dokumentiert als Abschnitt 8.8 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 17:19:54 +02:00
duffyduckandClaude Opus 5 7b26042fa4 Assistent statt doppelter Abfragen beim Image-Beschaffen
Der bisherige Ablauf war umstaendlich: Version in den Einstellungen
aendern -> Warnung, dass CMK_IMAGE nicht passt -> "Image holen?" ->
und dann erneut nach Edition, Version UND Zugangsdaten fragen,
obwohl alles schon dastand.

Jetzt ein Menuepunkt "Image beschaffen" (im Image-Menue und unter
Einstellungen -> Checkmk-Image und Zugangsdaten), der in einem
Durchgang durch Edition, Version und Bezugsweg fuehrt:
  Registry holen | Tarball herunterladen | vorhandene Datei einspielen
  | nichts holen, nur eintragen
Danach stehen CMK_EDITION, CMK_VERSION und CMK_IMAGE gemeinsam richtig.

Nach Zugangsdaten wird nur noch gefragt, wenn sie fuer den gewaehlten
Weg tatsaechlich fehlen - hinterlegte werden verwendet. Wer sie neu
eingibt, kann sie gleich in der .env speichern lassen.

Die drei Werte sind in der Oberflaeche nicht mehr einzeln editierbar
(neuer Feldtyp "info"): ein Klick darauf bietet den Assistenten an.
Damit koennen sie nicht mehr auseinanderlaufen. Auf der Kommandozeile
bleibt alles wie bisher einzeln setzbar; "image pull" und
"image download" haben dafuer neu --remember, das Edition und Version
mit in die .env schreibt.

Das Image-Menue wird dadurch kuerzer: status, versions, holen, test,
use. Die frueheren Einzelpunkte pull/download/load stecken im
Assistenten.

Geprueft: mit hinterlegten Zugangsdaten vier Dialoge und keine
Nachfrage; ohne Zugangsdaten und Bezugsweg Registry wird genau einmal
nach Benutzer, Kennwort und Speichern gefragt; der Weg "nur eintragen"
fragt gar nicht. Alle Menues kehren sauber zurueck.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 16:39:26 +02:00
duffyduckandClaude Opus 5 7a93dd5dbf CMK_IMAGE gegen CMK_EDITION/CMK_VERSION pruefen
Anlass war die Frage, wozu CMK_IMAGE neben Edition und Version
ueberhaupt noch noetig ist. Antwort: es ist der einzige Wert, den
compose und die systemd-Units lesen. Edition und Version sind reine
Vorgaben fuer den Downloader und wirken erst ueber "image pull".
Ableiten laesst sich CMK_IMAGE nicht, weil dieselbe Version je nach
Bezugsweg voellig anders heisst - docker.io/..., registry.checkmk.com/...
oder localhost/... bei einem aus dem Tarball geladenen Image.

Daraus folgt eine Falle, die bisher nirgends auffiel: wer Edition auf
"enterprise" stellt, CMK_IMAGE aber auf dem Raw-Image stehen laesst,
betreibt weiter Raw. Genau dieser Zustand kam in der Praxis vor.

image_consistency_check vergleicht deshalb Name und Tag von CMK_IMAGE
mit Edition und Version und meldet Abweichungen - in "image status",
im allgemeinen "status" und im Einstellungsmenue direkt nach dem
Aendern von Edition oder Version, dort gleich mit dem Angebot, das
Image zu holen. Aus Tarballs geladene Images (localhost/...) gelten
als stimmig, solange Name und Tag passen; die Editionsaliase werden
beruecksichtigt, "pro" passt also zu check-mk-enterprise.

Die Beschriftungen in den Einstellungen sagen jetzt, wer was tut:
  CMK_IMAGE    VERWENDETES Image - setzt "image pull"
  CMK_EDITION  Edition (nur Vorgabe, wirkt ueber "image pull")
  CMK_VERSION  Version (nur Vorgabe, wirkt ueber "image pull")

Vier Faelle geprueft: abweichende Edition, abweichende Version,
stimmiger Zustand und aus Tarball geladenes Image.

Dokumentiert als Abschnitt 8.7 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:58:39 +02:00
duffyduckandClaude Opus 5 ed052cd62f Versionen auflisten, echtes Dateinamensschema, Editionsnamen entwirrt
Anlass war der Hinweis auf die tatsaechliche Download-URL. Am echten
Server nachgemessen:
    check-mk-raw-docker-2.3.0p9.tar.gz         -> 200 (frei)
    check-mk-enterprise-docker-2.3.0p9.tar.gz  -> 401 (geschuetzt)
    check-mk-pro-docker-2.3.0p9.tar.gz         -> 404
    check-mk-raw-2.3.0p9.docker.tar.gz         -> 404
Das bisher zuerst probierte Schema war also schlicht falsch.

Editionsnamen: checkmk.com zeigt nur noch Community/Pro/Ultimate/
Ultimate MT, Dateien und Repositories tragen bis 2.4 weiter
raw/enterprise/cloud/managed. Wer von "Pro" auf check-mk-pro-... schliesst,
bekommt 404. Die Editionsauswahl in der Oberflaeche nennt jetzt beide
Namen, die README hat eine Zuordnungstabelle, und intern werden beide
Varianten durchprobiert.

Neu: "image versions" listet verfuegbare Versionen aus bis zu drei
Quellen - Versionsarchiv von checkmk.com (oeffentlich, ohne
Zugangsdaten), Registry ueber /v2/<repo>/tags/list und das
Verzeichnis-Listing des Downloadportals. Mit --filter, --limit, --all,
--source und --bare fuer die nackte Liste zum Weiterverarbeiten. Am
Ende stehen die fertigen Kommandos zum Uebernehmen.

Das Archiv liefert ausserdem den EXAKTEN Dateinamen je Version und
Edition (data-versions im HTML). Der wird jetzt als erster Kandidat
verwendet, statt ihn zu raten - geprueft fuer raw, enterprise, cloud
und managed auf 2.3.0p9, der erste Kandidat fuer raw liefert am Server
HTTP 200.

In der Oberflaeche: neuer Punkt "Verfuegbare Versionen auflisten", und
beim Holen eines Images muss die Version nicht mehr abgetippt werden -
es erscheint eine Auswahlliste aus dem Archiv.

Gegen Docker Hub verifiziert: 2393 Tags korrekt eingelesen, Filter und
Sortierung stimmen.

Dokumentiert als Abschnitt 8.5 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:54:01 +02:00
duffyduckandClaude Opus 5 2f00f81179 Zugangsdaten-Test dort erreichbar, wo die Zugangsdaten stehen
Der Test lag nur im Image-Menue, eingetragen werden Benutzer und
Kennwort aber in den Einstellungen - dort hat ihn niemand vermutet.

  - Die Einstellungs-Kategorie "Checkmk-Image und Zugangsdaten" hat
    jetzt einen Eintrag ">> Zugangsdaten jetzt pruefen".
  - Nach dem Aendern eines Zugangsdaten-Feldes fragt das Menue von
    sich aus, ob gleich geprueft werden soll.

Gleiche Ueberlegung fuer die beiden anderen Kategorien, in denen eine
Einstellung allein wenig hilft:
  - npm    -> ">> Proxy Manager: Stand und Admin-Port anzeigen"
  - backup -> ">> Backup-Jobs verwalten"

Alle acht Einstellungs-Kategorien einzeln durchlaufen, alle kehren
sauber zurueck. Dokumentiert in Abschnitt 8.4 beider Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:38:23 +02:00
duffyduckandClaude Opus 5 c98caaaf35 Terminal-Browser: nicht erreichbare Startseite wird vorab gemeldet
Symptom war ein scheinbar haengender Browsh: Logo, "Waiting for Firefox
to connect...", danach schwarz. Ursache ist nicht der Browser - Browsh
laeuft (Strg+Q kehrt ins Menue zurueck) - sondern die Startseite. Auf
http://127.0.0.1:81 antwortet nichts, solange der Proxy-Manager-Container
nicht laeuft, und ein Terminal-Browser zeigt dann keine Fehlerseite,
sondern gar nichts.

cmd_browser prueft die Startseite deshalb vorher und nennt die Ursache
statt stumm zu starten. Unterschieden werden: Proxy Manager
abgeschaltet (NPM_ENABLED=off), Container fehlt, Container gestoppt,
Container laeuft aber antwortet nicht, tote Checkmk-Oberflaeche auf
Port 5000 und externe Adressen. Jeweils mit dem passenden naechsten
Kommando. Ueberspringen mit --no-check; in der Oberflaeche erscheint
dieselbe Diagnose als Dialog mit der Wahl, trotzdem zu starten.

Dabei gefunden und behoben - an drei Stellen dieselbe Falle:
curl gibt mit -w '%{http_code}' im Fehlerfall selbst schon "000" aus.
Das zusaetzliche "|| echo 000" haengte einen zweiten Wert an, sodass
der Vergleich nie zutraf. Betroffen waren die neue Erreichbarkeits-
pruefung sowie http_code() und die Registry-Erreichbarkeit im
Zugangsdaten-Test ("image test") - dort waere ein nicht erreichbarer
Endpunkt als "unerwartete Antwort" statt als "nicht erreichbar"
gemeldet worden. Jetzt wird der Fehler der Zuweisung abgefangen.

Alle vier Diagnosezweige im Terminal durchgespielt, der
Zugangsdaten-Test zur Gegenprobe erneut gegen Docker Hub gelaufen.
Dokumentiert als Abschnitt 11.3 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:32:39 +02:00
duffyduckandClaude Opus 5 2d645bcc0b Fehler in der Oberflaeche abfangen, Backups planbar machen
Der Anlass: "Backup erstellen" bei fehlendem Container beendete die
ganze TUI mit einer Fehlerzeile in der Shell.

Ursachen waren zwei, beide behoben:
  1. die() in GUI-Pfaden. Neue Helfer gui_need_container/gui_need_sites
     melden das Problem im Dialog und kehren zurueck. Interaktives wie
     Shell und Terminal-Browser laeuft jetzt ueber gui_run_interactive
     in einer Subshell mit Weiter-mit-ENTER.
  2. "set -e". Schon ein Rueckgabewert != 0 aus einer Menuefunktion
     beendete das Skript, weil Menuezweige keine Bedingung sind. 47
     "|| return" auf "|| return 0" gestellt und 37 Menuezweige mit
     "|| true" abgesichert. Ausserdem schlug ein "clear" ohne TERM fehl
     und riss alles mit - drei Aufrufe abgesichert.
Jeder Hauptmenuepunkt wurde einzeln durchlaufen und kehrt sauber zurueck.

Neu: Backup-Jobs
  Der Menuepunkt heisst jetzt "Backup erstellen / planen" mit Untermenue
  (manuell erstellen, Jobs verwalten, Automatik ein/aus, Zeitplan
  anzeigen, Job sofort ausfuehren). Dieselben Jobs liegen auch in den
  Einstellungen unter "Backup-Jobs".

  Manuelle Backups nehmen weiterhin immer BACKUP_DIR aus der .env.
  Jeder Job hat dagegen sein eigenes Zielverzeichnis, seinen eigenen
  Zeitplan, eigene Optionen und eine eigene Aufbewahrung, nach der er
  sein Zielverzeichnis selbst aufraeumt.

  Vollstaendig auch per Parameter:
    job list | status | add | set | del | enable | disable
        | run | run-all | auto [on|off]
  mit --name --sites --cron --dir --keep --no-rrds --no-logs --stop
  --disabled.

  "job auto on" erzeugt aus den aktiven Jobs /etc/cron.d/checkmk-backup,
  eine Zeile je Job mit dessen eigenem Zeitplan. Ohne root werden die
  Zeilen ausgegeben statt kommentarlos zu scheitern. Der Schalter steht
  als BACKUP_AUTO in der .env, die Jobs in backup-jobs.conf.

Nebenbei behoben: "local f; f=... tmp" fuehrte tmp als Kommando aus,
wodurch job_put und job_remove nichts schrieben.

Dokumentiert als Abschnitt 15.1 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:23:51 +02:00
duffyduckandClaude Opus 5 4bbd1de4f6 Schalter: NGINX Proxy Manager abschaltbar (externer NGINX)
Wer die HTTPS-Terminierung bereits mit einem NGINX auf einem anderen
System loest, braucht den Container nicht. NPM_ENABLED=off sorgt dafuer,
dass er gar nicht erst angelegt wird: compose bekommt dann nur noch den
Checkmk-Dienst genannt.

    NPM_ENABLED=off  ->  compose up -d checkmk
    NPM_ENABLED=on   ->  compose up -d checkmk nginx-proxy-manager

Das gilt auch fuer "pull" - abgeschaltet wird nicht einmal das Image
geladen. Beim Abschalten wird ein vorhandener Container gestoppt UND
entfernt, damit ihn weder eine Restart-Regel noch ein Reboot wieder
hochzieht.

Die Daten bleiben in jedem Fall erhalten: Konfiguration, Datenbank und
Zertifikate liegen in den Bind-Mounts unter ./data/npm, nicht im
Container. Vor dem Abschalten werden beide Verzeichnisse mit Groesse
angezeigt; beim Einschalten wird die vorhandene Konfiguration samt
Zertifikaten unveraendert wieder aufgenommen.

Bedienung:
  - Menuepunkt "Proxy Manager betreiben" unter Einstellungen -> npm
  - cmk-manage.sh npm-enable [on|off]   (ohne Argument: Stand anzeigen)
  - config set NPM_ENABLED off

"npm-enable off" gibt gleich die noetige Firewall-Regel und eine
Beispielkonfiguration fuer den externen NGINX aus - Port 5000 muss dann
fuer dessen IP erreichbar sein. Der Agent-Receiver auf Port 8000 ist
davon nicht betroffen, den sprechen die Agents ohnehin direkt an.

Damit der Schalter auch nach einem Reboot gilt, ruft die von install.sh
erzeugte systemd-Unit jetzt cmk-manage.sh auf statt compose direkt.
Bei Quadlet wird die Unit nginx-proxy-manager.container uebersprungen
und entfernt, solange der Schalter auf "off" steht.

Verifiziert mit einem compose-Stub, dass in beiden Schalterstellungen
genau die erwarteten Dienste uebergeben werden, sowie ueber das Menue.
Dokumentiert als Abschnitt 12.4 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:11:55 +02:00
duffyduckandClaude Opus 5 3dd59fb973 image test: Zugangsdaten pruefen, ohne etwas herunterzuladen
Neues Unterkommando "image test" und ein Menuepunkt im Image-Menue.
Geprueft wird in Sekunden, statt erst beim mehrere Gigabyte grossen
Download zu scheitern:

  Registry  - Erreichbarkeit, Anmeldung und ob das Konto ueberhaupt
              Zugriff auf das Repository hat. Umgesetzt ueber den
              Docker-Registry-v2-Ablauf: WWW-Authenticate auswerten,
              Token beim genannten realm holen, damit /tags/list
              abfragen. Dadurch wird "Anmeldung stimmt, aber keine
              Berechtigung" von "Anmeldung falsch" unterschieden.
  Downloads - HTTP-Basic gegen die Tarball-URLs. HTTP 404 ohne 401
              bedeutet: Zugangsdaten sind richtig, nur Version oder
              Dateiname passen nicht - das wird auch so gemeldet.

Es wird nichts gespeichert: die Zugangsdaten gehen per temporaerer
.netrc an curl und stehen damit nicht in der Prozessliste (geprueft).
Fehlt curl, weicht die Registry-Pruefung auf podman/docker login in
eine Wegwerfdatei aus (--authfile bzw. DOCKER_CONFIG), die gespeicherte
Anmeldung des Systems bleibt unberuehrt.

Beim Testen gegen die echten Dienste gefunden und behoben:
  - "docker.io" ist nicht der API-Host der Registry; angesprochen wird
    registry-1.docker.io. Vorher lieferte /v2/ nur eine 302.
  - Die Schlussauswertung zaehlte auch Pruefungen als bestanden, die
    wegen --only gar nicht gelaufen waren.

Verifiziert gegen die echten Endpunkte: Docker Hub anonym inkl.
Tag-Liste von checkmk/check-mk-raw (HTTP 200), registry.checkmk.com
und download.checkmk.com jeweils mit falschen Zugangsdaten (HTTP 401,
korrekt als abgelehnt gemeldet).

Dokumentiert als Abschnitt 8.4 in beiden Sprachfassungen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 15:06:59 +02:00
duffyduckandClaude Opus 5 8ad4a5cbd9 Verweise auf Unterabschnitte zeigen jetzt wirklich dorthin
Abschnitt 5.1 existierte, war aber praktisch unsichtbar: alle Verweise
darauf benutzten den Anker von Kapitel 5, sprangen also an den
Kapitelanfang. Dasselbe galt fuer die uebrigen Unterabschnitts-
Verweise (8.2, 10.4, 11.3, 14.2 sowie "Variante B" in Kapitel 6) -
insgesamt 13 Stellen in beiden Dateien.

Beim Nachrechnen der Anker fiel ausserdem auf, dass Leerzeichen NICHT
kollabiert werden: aus "Variante B - Podman-Quadlet" wird
"variante-b--podman-quadlet-..." mit doppeltem Bindestrich, weil der
Gedankenstrich entfaellt und zwei Leerzeichen stehen bleiben. Vier
Anker waren deshalb zunaechst weiterhin falsch und sind korrigiert.
Bestaetigt wird die Regel durch die schon vorhandenen Anker des
Inhaltsverzeichnisses (#1-ueberblick--architektur).

Zusaetzlich zur Auffindbarkeit:
  - 5.1 steht jetzt als Untereintrag im Inhaltsverzeichnis.
  - Zwei neue Zeilen in der Fehlersuche-Tabelle: die dnf-Meldung
    "not registered with an entitlement server" und der Fall, dass
    sich epel-release nicht installieren laesst.

Geprueft: in beiden Dateien loesen alle Verweise gegen alle 62 Anker
auf (## bis ####).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 13:30:08 +02:00
duffyduckandClaude Opus 5 f768183fe0 RHEL-Kapitel: Registrierung als Schritt 0, EPEL-Vorbehalt direkt daneben
Beide Hinweise standen bisher nur in Abschnitt 5.1. Wer Kapitel 5 von
oben nach unten abarbeitet, lief aber vorher schon in den dnf-Fehler.
Deshalb jetzt im Hauptablauf selbst:

  - Ein hervorgehobener "Schritt 0" gleich zu Beginn des Kapitels mit
    den Pruefbefehlen (subscription-manager status, dnf repolist) und
    der Registrierung ueber die kostenlose Developer-Subskription.
    Dazu der Hinweis, dass RHEL 9 Simple Content Access nutzt und
    "subscription-manager attach" entfaellt, sowie die Feststellung,
    dass Rocky/Alma/CentOS Stream/Fedora nichts davon brauchen.

  - Direkt beim epel-release-Befehl der Vorbehalt, dass EPEL eine
    funktionierende Subskription voraussetzt: das Paket konfiguriert
    nur die Quelle, Abhaengigkeiten kommen weiter aus BaseOS/AppStream.
    EPEL ist damit kein Ersatz fuer die Registrierung. Bleibt
    podman-compose deswegen unerreichbar, fuehrt der Quadlet-Weg aus
    Kapitel 6 ohne Compose zum Ziel.

Die Aufzaehlung dessen, was install.sh tut, entspricht jetzt dem
tatsaechlichen Ablauf: Repository-Pruefung zuerst, dialog mit Rueckfall
auf newt.

Beide Sprachfassungen gepflegt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 13:27:38 +02:00
duffyduckandClaude Opus 5 15369f829d RHEL ohne Subskription: Paketzugang dokumentiert und abgefangen
Auf einem frisch installierten RHEL liefert dnf ohne Registrierung gar
keine Pakete - weder podman noch git oder dialog. Das ist jetzt in
beiden READMEs als Kapitel 5.1 beschrieben, mit drei Wegen:

  1) kostenlose Developer Subscription for Individuals (bis 16 Systeme,
     kleine Produktivnutzung eingeschlossen). RHEL 9 nutzt Simple
     Content Access, ein "subscription-manager attach" entfaellt.
  2) Installations-DVD als lokales Repository - ohne Konto und offline,
     aber ohne Sicherheitsupdates, daher nur als Ueberbrueckung.
  3) Wechsel auf Rocky Linux oder AlmaLinux.

Dazu eine Tabelle, welche Pakete das Projekt wirklich braucht und aus
welchem Repository sie kommen, sowie der Hinweis, dass EPEL hier nicht
weiterhilft (es setzt die Basis-Repositories voraus) - in dem Fall ist
der Quadlet-Weg ohne podman-compose die Loesung.

install.sh:
  - rhel_repo_check prueft vor der Installation, ob ueberhaupt ein
    nutzbares Repository vorhanden ist, und nennt sonst die drei Wege,
    statt den nackten dnf-Fehler stehen zu lassen.
  - "dialog" ist nicht mehr zwingend: es liegt in AppStream, bei
    Fehlschlag wird "newt" (whiptail, BaseOS) versucht. Vorher brach die
    Installation ab, wenn dialog fehlte - obwohl die Skripte whiptail
    ohnehin unterstuetzen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 13:22:32 +02:00
duffyduckandClaude Opus 5 039b5b0fc5 Englische README ergaenzt, Nummerierung in der deutschen korrigiert
README_en.md als vollstaendige englische Fassung der Dokumentation, in
beiden Dateien oben aufeinander verlinkt. Die Skripte selbst bleiben
deutsch; woertliche Programmausgaben und Menue-Abbildungen stehen
deshalb auch im englischen Text unveraendert, mit kurzer Erlaeuterung.

Beim Uebersetzen aufgefallen und in README.md behoben:
  - Unterkapitel trugen nach dem Einfuegen neuer Kapitel noch die alten
    Nummern: 9.1-9.4 in Kapitel 10, 11.1/11.2 in Kapitel 14 und
    14.1-14.7 in Kapitel 17.
  - Leerer Codeblock in Kapitel 9 (Rest einer frueheren Einfuegung).
  - Verrutschte Zeile im Menue-Kasten des Hauptmenues.

Beide Dateien haben denselben Aufbau: 22 Kapitel, 27 Unterkapitel,
136 Codebloecke, 117 Tabellenzeilen; alle internen Verweise aufgeloest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 11:39:42 +02:00
duffyduckandClaude Opus 5 1693330162 Terminal-Browser, konfigurierbarer Admin-Port und Einstellungsmenue
Der NGINX Proxy Manager laesst sich jetzt auch dann einrichten, wenn
seine Oberflaeche auf Port 81 aus dem Netz nicht erreichbar ist.

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

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

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

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

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

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