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>
This commit is contained in:
2026-09-20 22:20:21 +02:00
co-authored by Claude Opus 5
parent 4456f8c3ea
commit 7d9ed10e09
3 changed files with 360 additions and 28 deletions
+70 -12
View File
@@ -2549,6 +2549,8 @@ Eine Dateiauswahl mit Verzeichnisnavigation ist eingebaut.
| `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) |
@@ -3054,25 +3056,81 @@ Danach in der Oberfläche prüfen:
## 18. Mehrere Sites in einem Container
Der Checkmk-Entrypoint legt beim Start nur die Site aus `CMK_SITE_ID` an und
startet auch nur diese. Weitere Sites (z. B. mehrere importierte) existieren im
Bind-Mount, werden aber nach einem Neustart nicht automatisch hochgefahren.
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:
Deshalb:
```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
```
Dieses Kommando wird von der systemd-Unit (`ExecStartPost`) bzw. der
Quadlet-Unit automatisch nach dem Containerstart ausgeführt und startet alle
vorhandenen 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.
> **Empfehlung:** Für sauber getrennte Umgebungen lieber je Site ein eigenes
> Projektverzeichnis mit eigener `.env` betreiben. Da beide Container im
> Host-Netzwerk laufen, kann pro Host allerdings nur **ein** Checkmk-Container
> die Ports 5000/8000 belegen – für echte Mehrfachinstanzen dann getrennte
> Hosts oder eine Bridge-Netzwerk-Variante verwenden.
### 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**.
---
+70 -11
View File
@@ -2531,6 +2531,8 @@ A file chooser with directory navigation is built in.
| `sites` | list the sites in the container |
| `site-start SITE` / `site-stop SITE` | control a single site |
| `start-all-sites` | start all sites (invoked by systemd) |
| `site-create NAME` | create another site in the container – own ports (5001, 8001, …) |
| `site-delete NAME` | remove a site and all its data |
| `backup …` | backup as a `.tar.gz` bundle |
| `list` / `verify` / `prune --keep N` | manage backups |
| `job list\|add\|set\|del\|run\|auto` | scheduled backups (own target path per job) |
@@ -3038,24 +3040,81 @@ Then check in the interface:
## 18. Several sites in one container
At startup the Checkmk entrypoint only creates – and only starts – the site
from `CMK_SITE_ID`. Further sites (e.g. several imported ones) exist in the
bind mount but are not brought up automatically after a restart.
The image's entrypoint creates only the site from `CMK_SITE_ID` and starts only
that one. Further sites can be created, though – and with the proxy in front
they sit side by side behind a single port:
Hence:
```bash
./scripts/cmk-manage.sh site-create zweite
./scripts/cmk-manage.sh site-create kunde2 --password secret123
./scripts/cmk-manage.sh sites
./scripts/cmk-manage.sh site-delete zweite
```
### 18.1 Each site gets its own ports
`omd` assigns the ports itself – everything else follows from that:
| | first site | second | third |
|---|---|---|---|
| web UI (Apache) | 5000 | 5001 | 5002 |
| **agent receiver** | 8000 | **8001** | **8002** |
| Livestatus | 6557 | 6558 | 6559 |
Two consequences:
1. **In the proxy** every site gets its path:
```bash
./scripts/cmk-manage.sh proxy edit --domain <name> --location /zweite=127.0.0.1:5001
./scripts/cmk-manage.sh proxy reload
```
It then sits next to the first one: `https://<ip>/cmk/` and
`https://<ip>/zweite/`. Checkmk copes with the prefix because the site name
is part of every address anyway – see
[chapter 10.12](#1012-adding-more-services--grafana-as-an-example).
2. **In the firewall** the agents of that site talk to a different port:
```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` prints exactly those two commands with the right port numbers,
plus a reminder about the default server for IP access if it is set up.
### 18.2 What happens during creation
Inside the container `omd create --no-tmpfs` runs – without `--no-tmpfs` it
fails, because no tmpfs can be mounted there. If the container does **not** run
in the host network, the site's Apache is additionally bound to `0.0.0.0`,
otherwise it would not be reachable from outside; in the host network
`127.0.0.1` is enough and the proxy still reaches it. Without `--password`,
`omd` generates one and prints it.
### 18.3 After a restart
```bash
sudo ./scripts/cmk-manage.sh start-all-sites
```
This command is executed automatically by the systemd unit (`ExecStartPost`)
or the Quadlet unit after the container starts, and starts every site present.
The entrypoint starts only the default site. This command is run automatically
by the systemd unit (`ExecStartPost`) or the Quadlet unit after the container
starts, and brings up all existing sites.
> **Recommendation:** for cleanly separated environments, run one project
> directory with its own `.env` per site. Note that because both containers run
> on the host network, only **one** Checkmk container per host can occupy ports
> 5000/8000 – for genuinely multiple instances use separate hosts or a
> bridge-network variant.
### 18.4 When separate projects are better
Several sites in one container share the image and version – one `omd update`
affects all of them. For cleanly separated environments (different Checkmk
versions, separate maintenance windows, different customers) a separate project
directory with its own `.env` per site is better. Since both containers run in
the host network, only **one** Checkmk container per host can occupy ports
5000/8000 – for real multiple instances use separate hosts or a bridge-network
variant.
The GUI has all of it under **Sites im Container verwalten**.
---
+220 -5
View File
@@ -75,6 +75,8 @@ KOMMANDOS - Sites
site-start SITE Site starten
site-stop SITE Site stoppen
start-all-sites alle vorhandenen Sites starten (fuer Autostart nach Reboot)
site-create NAME weitere Site im Container anlegen (eigene Ports)
site-delete NAME Site samt Daten entfernen
KOMMANDOS - Backup / Restore / Migration
backup [Optionen] Backup einer/aller Sites als .tar.gz-Bundle erzeugen
@@ -1883,6 +1885,169 @@ cmd_site_stop() {
# Wird vom systemd-Unit nach dem Start aufgerufen: alle Sites hochfahren.
# (Der Container-Entrypoint startet nur CMK_SITE_ID.)
# =====================================================================
# Weitere Sites anlegen und entfernen
#
# Der Entrypoint des Abbilds legt nur die Site aus CMK_SITE_ID an. Eine
# zweite entsteht mit "omd create" im Container - mit --no-tmpfs, denn
# ein tmpfs laesst sich dort nicht einhaengen.
#
# Die Ports vergibt omd selbst weiter: die zweite Site bekommt 5001
# statt 5000, den Agent-Receiver auf 8001 statt 8000 und Livestatus auf
# 6558. Das ist beim Proxy und bei der Firewall zu beachten - die
# Agents dieser Site sprechen 8001 an, nicht 8000.
# =====================================================================
# Einen Wert aus der site.conf lesen
site_conf_get() { # site schluessel
ct sh -c "sed -n \"s/^CONFIG_$2='\\(.*\\)'\$/\\1/p\" /omd/sites/$1/etc/omd/site.conf" 2>/dev/null
}
# Laeuft der Checkmk-Container im Host-Netz? Dann genuegt 127.0.0.1,
# denn der Proxy Manager liegt im selben Netz.
cmk_host_network() {
[ "$($RUNTIME container inspect -f '{{.HostConfig.NetworkMode}}' "$CMK_CONTAINER_NAME" 2>/dev/null)" = host ]
}
cmd_site_create() {
local name="" pass="" expose="" nostart=""
while [ $# -gt 0 ]; do
case "$1" in
--password) pass="$2"; shift 2 ;;
--expose) expose=1; shift ;;
--no-start) nostart=1; shift ;;
--help|-h)
cat <<EOF
Eine weitere Site im laufenden Container anlegen.
$SELF site-create zweite
$SELF site-create kunde2 --password geheim123
--password PW Kennwort fuer cmkadmin (sonst erzeugt omd eines und
zeigt es an)
--expose Apache der Site auf 0.0.0.0 binden. Noetig nur, wenn
der Container NICHT im Host-Netz laeuft - sonst
genuegt 127.0.0.1, und der Proxy kommt trotzdem hin.
--no-start nur anlegen, nicht starten
Die Ports vergibt omd selbst: die naechste Site bekommt 5001, den
Agent-Receiver auf 8001 und Livestatus auf 6558.
EOF
return 0 ;;
-*) die "Unbekannte Option fuer 'site-create': $1" ;;
*) name="$1"; shift ;;
esac
done
[ -n "$name" ] || die "Name fehlt: $SELF site-create <name>"
case "$name" in
*[!a-zA-Z0-9_]*) die "Ein Site-Name darf nur Buchstaben, Ziffern und _ enthalten." ;;
esac
[ "${#name}" -le 16 ] || die "Ein Site-Name darf hoechstens 16 Zeichen lang sein."
container_running "$CMK_CONTAINER_NAME" \
|| die "Der Container '$CMK_CONTAINER_NAME' laeuft nicht.
Starten: $SELF up"
if ct test -d "/omd/sites/$name" 2>/dev/null; then
die "Die Site '$name' gibt es schon. ('$SELF sites' zeigt alle)"
fi
local -a a=(omd create --no-tmpfs)
if [ -n "$pass" ]; then a+=(--admin-password "$pass"); fi
a+=("$name")
log "Lege Site '$name' an ..."
# Die Ausgabe von omd enthaelt das erzeugte Kennwort - sie gehoert
# dem Benutzer vor die Augen.
ct "${a[@]}" || die "'omd create' ist fehlgeschlagen."
# Ohne Host-Netz waere die Site von aussen nicht erreichbar
if [ -n "$expose" ] || ! cmk_host_network; then
log "Binde den Apache der Site auf 0.0.0.0 ..."
ct omd config "$name" set APACHE_TCP_ADDR 0.0.0.0 >/dev/null 2>&1 || true
fi
if [ -z "$nostart" ]; then
log "Starte Site '$name' ..."
ct omd start "$name" >/dev/null 2>&1 || warn "Die Site liess sich nicht starten."
fi
local port recv ls ip
port="$(site_conf_get "$name" APACHE_TCP_PORT)"
recv="$(site_conf_get "$name" AGENT_RECEIVER_PORT)"
ls="$(site_conf_get "$name" LIVESTATUS_TCP_PORT)"
ip="$(primary_ip)"
echo
ok "Site '$name' angelegt."
printf ' %-22s %s\n' "Oberflaeche (direkt)" "http://127.0.0.1:${port:-?}/$name/"
printf ' %-22s %s\n' "Agent-Receiver" "${recv:-?}"
printf ' %-22s %s\n' "Livestatus (falls an)" "${ls:-?}"
cat <<EOF
${C_BLD}Damit sie von aussen erreichbar wird${C_RST}
1) Pfad im Proxy anlegen - dann liegt sie neben der ersten Site:
$SELF proxy edit --domain <name-oder-id> --location /$name=127.0.0.1:${port:-5001}
$SELF proxy reload
Danach: https://${ip:-<ip>}/$name/
2) Die Agents dieser Site sprechen Port ${recv:-8001} an, nicht 8000.
In der Firewall ergaenzen:
$SELF config set FW_EXTRA_PORTS "${recv:-8001}/tcp=Agent-Receiver $name"
sudo $SELF firewall open --apply
3) Nach einem Neustart des Containers startet nur die Standard-Site.
Alle starten: $SELF start-all-sites
EOF
if grep -qsF "$NPM_DEF_START" "$(npm_custom_conf_path)" 2>/dev/null; then
log "Der Standard-Server fuer den IP-Zugang muss danach nachgezogen werden:
$SELF proxy default --domain <name> --restart"
fi
echo
return 0
}
cmd_site_delete() {
local name="" force=""
while [ $# -gt 0 ]; do
case "$1" in
--force) force=1; shift ;;
-*) die "Unbekannte Option fuer 'site-delete': $1" ;;
*) name="$1"; shift ;;
esac
done
[ -n "$name" ] || die "Name fehlt: $SELF site-delete <name>"
container_running "$CMK_CONTAINER_NAME" \
|| die "Der Container '$CMK_CONTAINER_NAME' laeuft nicht."
ct test -d "/omd/sites/$name" 2>/dev/null || die "Die Site '$name' gibt es nicht."
if [ "$name" = "${CMK_SITE_ID:-cmk}" ] && [ -z "$force" ]; then
die "'$name' ist die Standard-Site aus CMK_SITE_ID.
Der Entrypoint legt sie beim naechsten Start ohnehin neu an.
Wenn es wirklich sein soll: $SELF site-delete $name --force"
fi
warn "Die Site '$name' und ALLE ihre Daten werden entfernt."
printf ' Vorher ein Backup: %s backup --site %s\n' "$SELF" "$name"
confirm "Site '$name' wirklich loeschen?" || die "Abgebrochen."
log "Stoppe und entferne Site '$name' ..."
ct omd stop "$name" >/dev/null 2>&1 || true
# "omd rm" fragt selbst nach; das globale -f ueberspringt die Rueckfrage.
# Ohne das bleibt die Site stehen, waehrend hier Erfolg gemeldet wuerde.
ct omd -f rm --kill "$name" >/dev/null 2>&1 || true
if ct test -d "/omd/sites/$name" 2>/dev/null; then
err "Die Site '$name' ist noch da - 'omd rm' hat nicht durchgegriffen."
log "Von Hand nachsehen: $SELF omd -f rm --kill $name"
return 1
fi
ok "Site '$name' entfernt."
log "Einen Proxy-Pfad dafuer gibt es womoeglich noch:
$SELF proxy edit --domain <name> --del-location /$name"
return 0
}
cmd_start_all_sites() {
local tries=0
while ! container_running "$CMK_CONTAINER_NAME"; do
@@ -5604,16 +5769,51 @@ gui_backups_menu() {
done
}
gui_site_create() {
local name pass
name="$(ui_input "Weitere Site anlegen" \
"Name der neuen Site (Buchstaben, Ziffern, _ - hoechstens 16 Zeichen).
Sie bekommt eigene Ports: die naechste freie ab 5001 fuer die
Oberflaeche, ab 8001 fuer den Agent-Receiver. Beides muss danach im
Proxy bzw. in der Firewall nachgezogen werden - der Befehl sagt genau,
wie." "")" || return 0
[ -n "$name" ] || return 0
case "$name" in
*[!a-zA-Z0-9_]*) ui_msg "Ungueltig" "Erlaubt sind nur Buchstaben, Ziffern und _"; return 0 ;;
esac
if [ "${#name}" -gt 16 ]; then
ui_msg "Ungueltig" "Hoechstens 16 Zeichen."; return 0
fi
pass="$(ui_password "Weitere Site anlegen" "Kennwort fuer cmkadmin (leer = omd erzeugt eines):")" || return 0
local -a a=(site-create "$name")
if [ -n "$pass" ]; then a+=(--password "$pass"); fi
local f rc=0
f="$(mktemp)"
( NO_COLOR=1 cmd_site_create "${a[@]}" ) >"$f" 2>&1 || rc=$?
if [ "$rc" -eq 0 ]; then
ui_text "Site '$name' angelegt" "$f"
else
ui_text "Anlegen fehlgeschlagen" "$f"
fi
rm -f "$f"
return 0
}
gui_sites_menu() {
gui_need_container || return 0
while :; do
local sel
sel="$(ui_menu "Sites" "Sites im Container '$CMK_CONTAINER_NAME'" \
list "Sites anzeigen" \
start "Site starten" \
stop "Site stoppen" \
all "alle Sites starten" \
back "zurueck")" || return 0
list "Sites anzeigen" \
neu "Weitere Site anlegen (eigene Ports)" \
start "Site starten" \
stop "Site stoppen" \
all "alle Sites starten" \
loesch "Site samt Daten entfernen" \
back "zurueck")" || return 0
case "$sel" in
list) local f; f="$(mktemp)"; ( cmd_sites ) >"$f" 2>&1 || true; ui_text "Sites" "$f"; rm -f "$f" ;;
start) local s; s="$(gui_pick_site)" || continue; [ -n "$s" ] || continue
@@ -5621,6 +5821,19 @@ gui_sites_menu() {
stop) local s2; s2="$(gui_pick_site)" || continue; [ -n "$s2" ] || continue
ui_run "Site stoppen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV site-stop '$s2'" ;;
all) ui_run "Alle Sites starten" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV start-all-sites" ;;
neu) gui_site_create || true ;;
loesch) local s3; s3="$(gui_pick_site)" || continue; [ -n "$s3" ] || continue
if [ "$s3" = "${CMK_SITE_ID:-cmk}" ]; then
ui_msg "Standard-Site" "'$s3' ist die Site aus CMK_SITE_ID.
Der Entrypoint legt sie beim naechsten Start ohnehin neu an -
loeschen bringt hier nichts."
continue
fi
ui_yesno "Site entfernen" "Die Site '$s3' und ALLE ihre Daten entfernen?
Vorher ein Backup: backup --site $s3" || continue
ui_run "Site entfernen" bash -c "cd '$PROJECT_DIR' && '$SELF' $SELF_ENV -y site-delete '$s3'" ;;
back) return 0 ;;
esac
done
@@ -7964,6 +8177,8 @@ main() {
site-start) cmd_site_start "$@" ;;
site-stop) cmd_site_stop "$@" ;;
start-all-sites) cmd_start_all_sites ;;
site-create) cmd_site_create "$@" ;;
site-delete|site-rm) cmd_site_delete "$@" ;;
backup) cmd_backup "$@" || true ;;
list) cmd_list || true ;;
prune) cmd_prune "$@" || true ;;