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>
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>
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>
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>
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>
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>
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>
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>
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>
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>