rename.sh: aus einer Instanz die Hauptinstallation machen
Die laufenden Installationen hiessen "tesm-opus" und "tesm-license-opus" -- ein Instanzname aus der Zeit, in der sie neben der Fassung 1.x getestet wurden. Jetzt heissen sie "tesm" und "tesm-license". Umbenennen ist mehr als ein verschobenes Verzeichnis, und drei Stellen sind leicht zu uebersehen: * SITE_KEY in der Umgebungsdatei -- daraus entsteht der Name des Sitzungscookies. Bleibt er alt, heisst das Cookie weiter wie die alte Instanz: unauffaellig und falsch. * web_cert_path/web_key_path/web_acme_webroot in der Datenbank enthalten den Namen. Ein Zertifikat unter dem alten Pfad findet nginx nicht mehr. * server_name der nginx-Site. install.sh schreibt die Datei aus seiner Vorlage neu, sobald sich die alias-Pfade aendern -- und die aendern sich hier zwangslaeufig. Ohne den Namen aus der Datenbank stehen danach zwei Sites mit "server_name _" auf Port 80, und die erste gewinnt. web-setup braucht dafuer --apply; ohne ihn speichert es nur. Zwei Fehler hat erst der Lauf am System gezeigt: * Das venv wandert nicht mit. Seine Konsolenskripte tragen den absoluten Pfad im Shebang, und danach zeigt venv/bin/gunicorn auf einen Interpreter, den es nicht mehr gibt -- systemd meldet "No such file or directory" fuer eine Datei, die sichtbar da ist. Es wird jetzt verworfen und neu gebaut. * Den Zielnamen belegt nicht nur /srv/<name>, sondern auch /var/log/<name>, der ACME-Pfad und die logrotate-Datei. Der Umzug brach mitten drin ab. Jetzt wandert alles, was den Namen belegt, in ein Archiv -- geloescht wird nichts, die Units und die Site der alten Fassung liegen darin unter systemd-alt/. Ein Test vergleicht die Pfade, die install.sh unter dem Namen anlegt, mit denen, die rename.sh kennt. Genau diese Luecke war der zweite Fehler; ohne den Test faellt der naechste erst wieder auf einem Server auf. Version 2.0.6. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm"
|
name = "tesm"
|
||||||
version = "2.0.5"
|
version = "2.0.6"
|
||||||
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
description = "TESM -- Verwaltung und Ueberwachung von PoE-Endgeraeten und Aruba-Switchen"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -0,0 +1,359 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# Benennt eine Installation um -- aus einer Instanz wird die Hauptinstallation
|
||||||
|
# (oder umgekehrt).
|
||||||
|
#
|
||||||
|
# sudo bash deploy/rename.sh --app tesm --from tesm-opus --to tesm
|
||||||
|
# sudo bash deploy/rename.sh --app tesm-license --from tesm-license-opus \
|
||||||
|
# --to tesm-license
|
||||||
|
#
|
||||||
|
# Der Name steckt an mehr Stellen, als man beim Verschieben eines Verzeichnisses
|
||||||
|
# erwartet, und drei davon sind leicht zu vergessen:
|
||||||
|
#
|
||||||
|
# * ``SITE_KEY`` in der Umgebungsdatei -- daraus entsteht der Name des
|
||||||
|
# Sitzungscookies. Bleibt er alt, heisst das Cookie weiter wie die alte
|
||||||
|
# Instanz.
|
||||||
|
# * ``web_cert_path``/``web_key_path``/``web_acme_webroot`` in der Datenbank.
|
||||||
|
# Sie enthalten den Namen; ein Zertifikat unter dem alten Pfad findet nginx
|
||||||
|
# nach dem Umzug nicht mehr.
|
||||||
|
# * ``server_name`` der nginx-Site. install.sh schreibt die Datei neu, sobald
|
||||||
|
# sich die alias-Pfade aendern -- und die aendern sich hier zwangslaeufig.
|
||||||
|
# Ohne den Namen aus der Datenbank stuenden danach zwei Sites mit ``_`` auf
|
||||||
|
# Port 80 und die erste gewinnt.
|
||||||
|
#
|
||||||
|
# Belegt der Zielname noch eine Installation der Fassung 1.x, wird sie beiseite
|
||||||
|
# geschoben: Verzeichnis nach ``<ziel>-<suffix>``, ihre systemd-Units und ihre
|
||||||
|
# nginx-Site als Kopie hinein. Danach ist der Name frei und nichts auf dem
|
||||||
|
# System zeigt mehr ins Leere.
|
||||||
|
#
|
||||||
|
# Alle angemeldeten Benutzer werden abgemeldet: das Sitzungscookie heisst
|
||||||
|
# danach anders.
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
APP=""
|
||||||
|
FROM=""
|
||||||
|
TO=""
|
||||||
|
SUFFIX="sonnet5"
|
||||||
|
ASSUME_YES=0
|
||||||
|
DRY_RUN=0
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
COLOR_OK=$'\033[32m'; COLOR_WARN=$'\033[33m'; COLOR_ERR=$'\033[31m'; COLOR_OFF=$'\033[0m'
|
||||||
|
step() { printf '\n%s==>%s %s\n' "$COLOR_OK" "$COLOR_OFF" "$*"; }
|
||||||
|
warn() { printf '%s !!%s %s\n' "$COLOR_WARN" "$COLOR_OFF" "$*"; }
|
||||||
|
fail() { printf '%s !!%s %s\n' "$COLOR_ERR" "$COLOR_OFF" "$*" >&2; exit 1; }
|
||||||
|
info() { printf ' %s\n' "$*"; }
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'USAGE'
|
||||||
|
Verwendung: rename.sh --app <tesm|tesm-license> --from <alt> --to <neu> [Optionen]
|
||||||
|
|
||||||
|
--app <name> Welche Anwendung (Pflicht)
|
||||||
|
--from <name> Bisheriger Installationsname, z.B. tesm-opus (Pflicht)
|
||||||
|
--to <name> Neuer Installationsname, z.B. tesm (Pflicht)
|
||||||
|
--suffix <text> Namenszusatz fuer eine beiseite geschobene Installation
|
||||||
|
der Fassung 1.x (Vorgabe: sonnet5)
|
||||||
|
--dry-run Nur zeigen, was geschehen wuerde
|
||||||
|
--yes Keine Rueckfrage
|
||||||
|
USAGE
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--app) APP="${2:?}"; shift 2 ;;
|
||||||
|
--from) FROM="${2:?}"; shift 2 ;;
|
||||||
|
--to) TO="${2:?}"; shift 2 ;;
|
||||||
|
--suffix) SUFFIX="${2:?}"; shift 2 ;;
|
||||||
|
--dry-run) DRY_RUN=1; shift ;;
|
||||||
|
--yes|-y) ASSUME_YES=1; shift ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) usage; fail "unbekannte Option: $1" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "$APP" == "tesm" || "$APP" == "tesm-license" ]] || { usage; fail "--app fehlt oder ist unbekannt"; }
|
||||||
|
[[ -n "$FROM" && -n "$TO" ]] || { usage; fail "--from und --to sind Pflicht"; }
|
||||||
|
[[ "$FROM" != "$TO" ]] || fail "--from und --to sind gleich"
|
||||||
|
[[ "$TO" =~ ^[a-z0-9-]{1,32}$ ]] || fail "ungueltiger Zielname: $TO"
|
||||||
|
[[ "$TO" == "$APP" || "$TO" == "$APP-"* ]] || fail "der Zielname muss mit '$APP' beginnen"
|
||||||
|
[[ "$(id -u)" -eq 0 ]] || fail "bitte mit sudo ausfuehren"
|
||||||
|
[[ -f "$SCRIPT_DIR/install.sh" ]] || fail "install.sh fehlt neben diesem Skript"
|
||||||
|
[[ -d "/srv/$FROM" ]] || fail "/srv/$FROM gibt es nicht"
|
||||||
|
[[ -f "/srv/$FROM/data/app.db" ]] || fail "/srv/$FROM sieht nicht nach einer Installation dieser Fassung aus"
|
||||||
|
|
||||||
|
ENV_PREFIX="TESM_"
|
||||||
|
[[ "$APP" == "tesm-license" ]] && ENV_PREFIX="TESM_LICENSE_"
|
||||||
|
|
||||||
|
# Alles, was den Namen traegt. Reihenfolge: erst Daten, dann Konfiguration.
|
||||||
|
VERSCHIEBEN=(
|
||||||
|
"/srv/$FROM:/srv/$TO"
|
||||||
|
"/var/log/$FROM:/var/log/$TO"
|
||||||
|
"/etc/tesm/$FROM.env:/etc/tesm/$TO.env"
|
||||||
|
"/var/www/$FROM-acme:/var/www/$TO-acme"
|
||||||
|
"/etc/tesm/certs/$FROM:/etc/tesm/certs/$TO"
|
||||||
|
)
|
||||||
|
ENTFERNEN=(
|
||||||
|
"/etc/systemd/system/$FROM.service"
|
||||||
|
"/etc/systemd/system/$FROM-monitor.service"
|
||||||
|
"/etc/nginx/sites-enabled/$FROM"
|
||||||
|
"/etc/nginx/sites-available/$FROM"
|
||||||
|
"/usr/local/bin/$FROM-admin"
|
||||||
|
"/etc/logrotate.d/$FROM"
|
||||||
|
"/etc/update-motd.d/50-$FROM"
|
||||||
|
)
|
||||||
|
|
||||||
|
# -- Webeinstellungen auslesen, bevor irgendetwas umzieht -------------------- #
|
||||||
|
# Mit dem System-Python und der Standardbibliothek: das venv zieht gleich mit
|
||||||
|
# um, und ein zusaetzliches Werkzeug (sqlite3) ist auf einem schlanken Server
|
||||||
|
# nicht garantiert.
|
||||||
|
lese_einstellung() {
|
||||||
|
python3 - "$1" "/srv/$FROM/data/app.db" <<'PY'
|
||||||
|
import sqlite3, sys
|
||||||
|
schluessel, datenbank = sys.argv[1], sys.argv[2]
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect(f"file:{datenbank}?mode=ro", uri=True)
|
||||||
|
row = conn.execute("SELECT value FROM settings WHERE key=?", (schluessel,)).fetchone()
|
||||||
|
conn.close()
|
||||||
|
except sqlite3.Error:
|
||||||
|
row = None
|
||||||
|
print((row[0] if row and row[0] is not None else "").strip())
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
DOMAIN="$(lese_einstellung web_domain || true)"
|
||||||
|
HTTPS_AN="$(lese_einstellung web_https_enabled || true)"
|
||||||
|
HSTS_AN="$(lese_einstellung web_hsts_enabled || true)"
|
||||||
|
CERT_ALT="$(lese_einstellung web_cert_path || true)"
|
||||||
|
|
||||||
|
step "Vorhaben"
|
||||||
|
info "Anwendung : $APP"
|
||||||
|
info "Alt : $FROM"
|
||||||
|
info "Neu : $TO"
|
||||||
|
info "Domain : ${DOMAIN:-(keine)}"
|
||||||
|
info "HTTPS : $([[ "$HTTPS_AN" == "1" ]] && echo "ja${CERT_ALT:+, Zertifikat $CERT_ALT}" || echo nein)"
|
||||||
|
for paar in "${VERSCHIEBEN[@]}"; do
|
||||||
|
quelle="${paar%%:*}"; ziel="${paar##*:}"
|
||||||
|
[[ -e "$quelle" ]] && info "verschieben: $quelle -> $ziel"
|
||||||
|
done
|
||||||
|
for pfad in "${ENTFERNEN[@]}"; do
|
||||||
|
[[ -e "$pfad" ]] && info "entfernen : $pfad (install.sh legt es unter dem neuen Namen neu an)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# -- Was belegt den Zielnamen? ----------------------------------------------- #
|
||||||
|
# Nicht nur das Verzeichnis unter /srv: eine Installation der Fassung 1.x
|
||||||
|
# hinterlaesst auch /var/log/<name>, /etc/logrotate.d/<name> und den
|
||||||
|
# ACME-Pfad. Der Umzug bricht sonst mitten drin ab -- live genau so passiert.
|
||||||
|
BELEGT=()
|
||||||
|
for paar in "${VERSCHIEBEN[@]}"; do
|
||||||
|
ziel="${paar##*:}"
|
||||||
|
[[ -e "$ziel" ]] && BELEGT+=("$ziel")
|
||||||
|
done
|
||||||
|
for weiteres in "/etc/logrotate.d/$TO" "/etc/update-motd.d/50-$TO"; do
|
||||||
|
[[ -e "$weiteres" ]] && BELEGT+=("$weiteres")
|
||||||
|
done
|
||||||
|
|
||||||
|
BEISEITE=""
|
||||||
|
if [[ ${#BELEGT[@]} -gt 0 ]]; then
|
||||||
|
if [[ -f "/srv/$TO/data/app.db" ]]; then
|
||||||
|
fail "/srv/$TO ist bereits eine Installation dieser Fassung. Welche gewinnt, entscheidet niemand automatisch."
|
||||||
|
fi
|
||||||
|
BEISEITE="/srv/$TO-$SUFFIX"
|
||||||
|
if [[ -e "$BEISEITE" ]]; then
|
||||||
|
# Ein vorhandenes Archiv derselben Verdraengung wird weiterbenutzt -- die
|
||||||
|
# Reste einer Installation gehoeren zusammen und nicht in ein zweites
|
||||||
|
# Verzeichnis. Alles andere unter diesem Namen bleibt unangetastet.
|
||||||
|
if [[ -f "$BEISEITE/sqlite.db" || -d "$BEISEITE/systemd-alt" ]]; then
|
||||||
|
info "Archiv $BEISEITE ist vorhanden und wird weiterbenutzt."
|
||||||
|
else
|
||||||
|
fail "$BEISEITE existiert und sieht nicht nach einem solchen Archiv aus -- bitte --suffix waehlen"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
info "Der Zielname ist belegt. Alles davon wandert nach $BEISEITE:"
|
||||||
|
for pfad in "${BELEGT[@]}"; do info " $pfad"; done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $DRY_RUN -eq 1 ]]; then
|
||||||
|
step "--dry-run: hier ist Schluss."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ $ASSUME_YES -eq 0 ]]; then
|
||||||
|
read -r -p "Fortfahren? Alle angemeldeten Benutzer werden abgemeldet. [j/N] " answer
|
||||||
|
[[ "$answer" =~ ^[jJyY]$ ]] || { echo "Abgebrochen."; exit 0; }
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- 1. Dienste anhalten ----------------------------------------------------- #
|
||||||
|
step "Dienste anhalten"
|
||||||
|
for unit in "$FROM.service" "$FROM-monitor.service"; do
|
||||||
|
if systemctl list-unit-files "$unit" --no-legend 2>/dev/null | grep -q .; then
|
||||||
|
systemctl disable --now "$unit" >/dev/null 2>&1 || true
|
||||||
|
info "$unit gestoppt und deaktiviert"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# -- 2. Zielnamen freimachen ------------------------------------------------- #
|
||||||
|
if [[ -n "$BEISEITE" ]]; then
|
||||||
|
step "Zielnamen freimachen"
|
||||||
|
# Alles wandert ins Archiv, nichts wird geloescht: unter /var/log/<name>
|
||||||
|
# liegen Protokolle, unter /srv/<name> im Zweifel eine ganze Installation.
|
||||||
|
# Die Units und die Site kommen mit -- sie zeigen auf das alte Verzeichnis
|
||||||
|
# und waeren auf dem System nur noch Fehlerquellen, im Archiv aber ein Beleg.
|
||||||
|
mkdir -p "$BEISEITE"
|
||||||
|
for pfad in "${BELEGT[@]}"; do
|
||||||
|
ziel="$BEISEITE/$(basename "$pfad")"
|
||||||
|
if [[ "$pfad" == "/srv/$TO" ]]; then
|
||||||
|
# Das Verzeichnis selbst wird das Archiv -- sein Inhalt bleibt, wie er ist.
|
||||||
|
for eintrag in "$pfad"/* "$pfad"/.[!.]*; do
|
||||||
|
[[ -e "$eintrag" ]] || continue
|
||||||
|
mv "$eintrag" "$BEISEITE/"
|
||||||
|
done
|
||||||
|
rmdir "$pfad"
|
||||||
|
info "/srv/$TO -> $BEISEITE/"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ -e "$ziel" ]]; then
|
||||||
|
ziel="$ziel-$(date +%Y%m%d-%H%M%S)"
|
||||||
|
warn "Im Archiv lag schon etwas mit diesem Namen -- ablegen als $(basename "$ziel")"
|
||||||
|
fi
|
||||||
|
mv "$pfad" "$ziel"
|
||||||
|
info "$pfad -> $ziel"
|
||||||
|
done
|
||||||
|
mkdir -p "$BEISEITE/systemd-alt"
|
||||||
|
for unit in "/etc/systemd/system/$TO.service" "/etc/systemd/system/$TO-check.service" \
|
||||||
|
"/etc/systemd/system/$TO-check.timer" "/etc/systemd/system/$TO-check-restart.service" \
|
||||||
|
"/etc/systemd/system/$TO-check-restart.timer"; do
|
||||||
|
[[ -f "$unit" ]] || continue
|
||||||
|
systemctl disable --now "$(basename "$unit")" >/dev/null 2>&1 || true
|
||||||
|
mv "$unit" "$BEISEITE/systemd-alt/"
|
||||||
|
info "$(basename "$unit") archiviert"
|
||||||
|
done
|
||||||
|
for site in "/etc/nginx/sites-enabled/$TO" "/etc/nginx/sites-available/$TO"; do
|
||||||
|
[[ -e "$site" ]] || continue
|
||||||
|
[[ -L "$site" ]] && { rm -f "$site"; continue; }
|
||||||
|
mv "$site" "$BEISEITE/systemd-alt/nginx-site"
|
||||||
|
info "nginx-Site archiviert"
|
||||||
|
done
|
||||||
|
for motd in "/etc/update-motd.d/50-$TO"; do
|
||||||
|
[[ -f "$motd" ]] && grep -q "motd_banner.py" "$motd" 2>/dev/null && rm -f "$motd" \
|
||||||
|
&& info "Banner der Fassung 1.x entfernt"
|
||||||
|
done
|
||||||
|
info "Alles Verdraengte liegt unter $BEISEITE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- 3. Umziehen ------------------------------------------------------------- #
|
||||||
|
step "Umziehen"
|
||||||
|
for paar in "${VERSCHIEBEN[@]}"; do
|
||||||
|
quelle="${paar%%:*}"; ziel="${paar##*:}"
|
||||||
|
[[ -e "$quelle" ]] || continue
|
||||||
|
[[ -e "$ziel" ]] && fail "$ziel existiert bereits -- Abbruch, damit nichts vermischt wird"
|
||||||
|
mkdir -p "$(dirname "$ziel")"
|
||||||
|
mv "$quelle" "$ziel"
|
||||||
|
info "$quelle -> $ziel"
|
||||||
|
done
|
||||||
|
|
||||||
|
# -- 4. Namen in den Dateien nachziehen -------------------------------------- #
|
||||||
|
step "Namen nachziehen"
|
||||||
|
ENV_FILE="/etc/tesm/$TO.env"
|
||||||
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
|
# Der SITE_KEY bestimmt den Namen des Sitzungscookies. Bleibt er alt, heisst
|
||||||
|
# das Cookie weiter wie die alte Instanz -- unauffaellig und falsch.
|
||||||
|
sed -i "s#^${ENV_PREFIX}SITE_KEY=.*#${ENV_PREFIX}SITE_KEY=$TO#" "$ENV_FILE"
|
||||||
|
info "SITE_KEY=$TO"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Pfade in der Datenbank, die den Namen enthalten.
|
||||||
|
python3 - "$TO" "$FROM" "/srv/$TO/data/app.db" <<'PY'
|
||||||
|
import sqlite3, sys
|
||||||
|
neu, alt, datenbank = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||||
|
schluessel = ("web_cert_path", "web_key_path", "web_acme_webroot")
|
||||||
|
try:
|
||||||
|
conn = sqlite3.connect(datenbank, timeout=5.0)
|
||||||
|
except sqlite3.Error as fehler:
|
||||||
|
print(f" Datenbank nicht schreibbar: {fehler}")
|
||||||
|
raise SystemExit(0)
|
||||||
|
try:
|
||||||
|
with conn:
|
||||||
|
for key in schluessel:
|
||||||
|
row = conn.execute("SELECT value FROM settings WHERE key=?", (key,)).fetchone()
|
||||||
|
if not row or not row[0]:
|
||||||
|
continue
|
||||||
|
wert = str(row[0])
|
||||||
|
ersetzt = wert.replace(alt, neu)
|
||||||
|
if ersetzt != wert:
|
||||||
|
conn.execute("UPDATE settings SET value=? WHERE key=?", (ersetzt, key))
|
||||||
|
print(f" {key}: {wert} -> {ersetzt}")
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
PY
|
||||||
|
|
||||||
|
# -- 5. Alte Konfiguration entfernen ----------------------------------------- #
|
||||||
|
step "Alte Konfiguration entfernen"
|
||||||
|
for pfad in "${ENTFERNEN[@]}"; do
|
||||||
|
[[ -e "$pfad" ]] || continue
|
||||||
|
rm -f "$pfad"
|
||||||
|
info "$pfad"
|
||||||
|
done
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# -- 6. Unter dem neuen Namen einrichten ------------------------------------- #
|
||||||
|
# Das venv wird verworfen und neu gebaut. Es ist abgeleiteter Zustand, und
|
||||||
|
# seine Konsolenskripte tragen den absoluten Pfad im Shebang: nach dem Umzug
|
||||||
|
# zeigt "venv/bin/gunicorn" auf einen Interpreter, den es nicht mehr gibt, und
|
||||||
|
# systemd meldet nur "No such file or directory" -- fuer eine Datei, die
|
||||||
|
# sichtbar da ist. Live auf POETEST genau so passiert.
|
||||||
|
if [[ -d "/srv/$TO/venv" ]]; then
|
||||||
|
step "venv verwerfen (Shebangs tragen den alten Pfad)"
|
||||||
|
rm -rf "/srv/$TO/venv"
|
||||||
|
info "wird von install.sh neu gebaut"
|
||||||
|
fi
|
||||||
|
|
||||||
|
step "Unter dem neuen Namen einrichten"
|
||||||
|
INSTALL_ARGS=(--app "$APP" --yes)
|
||||||
|
[[ "$TO" != "$APP" ]] && INSTALL_ARGS+=(--instance "${TO#"$APP"-}")
|
||||||
|
bash "$SCRIPT_DIR/install.sh" "${INSTALL_ARGS[@]}"
|
||||||
|
|
||||||
|
# -- 7. nginx-Site aus den Einstellungen neu schreiben ----------------------- #
|
||||||
|
# install.sh schreibt die Site aus seiner Vorlage, sobald sich die alias-Pfade
|
||||||
|
# aendern -- und die aendern sich hier zwangslaeufig. Der Name der Site steht
|
||||||
|
# aber in der Datenbank, nicht in der Vorlage. Ohne diesen Schritt stuenden
|
||||||
|
# zwei Sites mit "_" auf Port 80 und die erste gewinnt.
|
||||||
|
if [[ -n "$DOMAIN" ]]; then
|
||||||
|
step "Webserver-Konfiguration erneuern"
|
||||||
|
# --apply nicht vergessen: ohne ihn speichert web-setup nur die Einstellungen
|
||||||
|
# und laesst die Site-Datei stehen, die install.sh aus seiner Vorlage
|
||||||
|
# geschrieben hat -- mit "server_name _" und ohne TLS.
|
||||||
|
WEB_ARGS=(web-setup --apply --domain "$DOMAIN")
|
||||||
|
if [[ "$HTTPS_AN" == "1" ]]; then
|
||||||
|
WEB_ARGS+=(--https)
|
||||||
|
[[ "$HSTS_AN" == "1" ]] && WEB_ARGS+=(--hsts)
|
||||||
|
# Das Zertifikat ist mitgezogen und sein Pfad in der Datenbank nachgefuehrt
|
||||||
|
# -- "web-setup --https" laesst es dann unangetastet. Ein neues erzeugen
|
||||||
|
# wuerde nur eine weitere Browserwarnung produzieren. Nur wenn nach dem
|
||||||
|
# Umzug wirklich keines da ist, wird eines erzeugt.
|
||||||
|
CERT_NEU="${CERT_ALT//$FROM/$TO}"
|
||||||
|
if [[ -n "$CERT_NEU" && -f "$CERT_NEU" ]]; then
|
||||||
|
info "HTTPS mit dem vorhandenen Zertifikat: $CERT_NEU"
|
||||||
|
else
|
||||||
|
WEB_ARGS+=(--self-signed)
|
||||||
|
warn "Zertifikat nicht gefunden (${CERT_NEU:-keins hinterlegt}) -- es wird ein neues"
|
||||||
|
warn "selbstsigniertes erzeugt. Der Browser warnt dann einmal erneut."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if sudo -u "$APP" "/usr/local/bin/$TO-admin" "${WEB_ARGS[@]}"; then
|
||||||
|
info "Site neu geschrieben: server_name $DOMAIN"
|
||||||
|
else
|
||||||
|
warn "web-setup ist fehlgeschlagen -- bitte in der Anwendung unter"
|
||||||
|
warn "'Verwaltung -> Webserver und TLS' die Domain eintragen und uebernehmen."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -- 8. Ergebnis ------------------------------------------------------------- #
|
||||||
|
step "Fertig"
|
||||||
|
info "Verzeichnis : /srv/$TO"
|
||||||
|
info "Dienst : systemctl status $TO.service"
|
||||||
|
info "Werkzeug : $TO-admin"
|
||||||
|
info "Aktualisieren: sudo bash /srv/$TO/deploy/update.sh $APP$([[ "$TO" != "$APP" ]] && echo " latest --instance ${TO#"$APP"-}")"
|
||||||
|
[[ -n "$BEISEITE" ]] && info "Fassung 1.x : $BEISEITE (Units und Site darin unter systemd-alt/)"
|
||||||
|
echo
|
||||||
|
warn "Alle Benutzer sind abgemeldet: das Sitzungscookie heisst jetzt anders."
|
||||||
@@ -283,6 +283,51 @@ entfernt -- nur dieses, nichts anderes in dem Verzeichnis.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 4b. Installation umbenennen
|
||||||
|
|
||||||
|
Aus einer Instanz die Hauptinstallation machen (oder umgekehrt):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash deploy/rename.sh --app tesm --from tesm-opus --to tesm
|
||||||
|
sudo bash deploy/rename.sh --app tesm-license --from tesm-license-opus --to tesm-license
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Name steckt an mehr Stellen als im Verzeichnisnamen, und drei davon sind
|
||||||
|
leicht zu übersehen:
|
||||||
|
|
||||||
|
* **`SITE_KEY`** in der Umgebungsdatei -- daraus entsteht der Name des
|
||||||
|
Sitzungscookies. Bleibt er alt, heisst das Cookie weiter wie die alte
|
||||||
|
Instanz.
|
||||||
|
* **`web_cert_path`, `web_key_path`, `web_acme_webroot`** in der Datenbank. Sie
|
||||||
|
enthalten den Namen; ein Zertifikat unter dem alten Pfad findet nginx nach
|
||||||
|
dem Umzug nicht mehr.
|
||||||
|
* **`server_name`** der nginx-Site. `install.sh` schreibt die Datei aus seiner
|
||||||
|
Vorlage neu, sobald sich die `alias`-Pfade ändern -- und die ändern sich hier
|
||||||
|
zwangsläufig. Ohne den Namen aus der Datenbank stünden danach zwei Sites mit
|
||||||
|
`server_name _` auf Port 80, und die erste gewinnt.
|
||||||
|
|
||||||
|
Ausserdem wird das **venv verworfen und neu gebaut**: seine Konsolenskripte
|
||||||
|
tragen den absoluten Pfad im Shebang, und nach dem Umzug zeigt
|
||||||
|
`venv/bin/gunicorn` auf einen Interpreter, den es nicht mehr gibt. systemd
|
||||||
|
meldet dann `No such file or directory` -- für eine Datei, die sichtbar da ist.
|
||||||
|
|
||||||
|
Belegt der Zielname noch eine Installation der Fassung 1.x, wandert **alles**,
|
||||||
|
was ihn belegt, in ein Archiv `/srv/<ziel>-sonnet5`: das Verzeichnis, die
|
||||||
|
Protokolle unter `/var/log/<ziel>`, der ACME-Pfad, die logrotate-Datei, und die
|
||||||
|
systemd-Units samt nginx-Site unter `systemd-alt/`. Gelöscht wird nichts.
|
||||||
|
|
||||||
|
Ports und HTTPS bleiben, wie sie waren; ein vorhandenes Zertifikat zieht mit
|
||||||
|
und wird weiterverwendet. **Alle angemeldeten Benutzer werden abgemeldet** --
|
||||||
|
das Sitzungscookie heisst danach anders.
|
||||||
|
|
||||||
|
Danach ist auch das Aktualisieren einfacher, weil der Instanzname wegfällt:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo bash /srv/tesm/deploy/update.sh tesm
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 5. Dienste
|
## 5. Dienste
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm-core"
|
name = "tesm-core"
|
||||||
version = "2.0.5"
|
version = "2.0.6"
|
||||||
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
description = "Gemeinsames Anwendungsgeruest (Auth, RBAC, Navigation, Design-System, Migrationen) fuer TESM und TESM-Lizenzserver"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ def create_base_app(
|
|||||||
#: Seitenhintergrund. Der Lizenzserver setzt sie bewusst nicht: die
|
#: Seitenhintergrund. Der Lizenzserver setzt sie bewusst nicht: die
|
||||||
#: Funktionsliste von TESM waere dort schlicht falsch.
|
#: Funktionsliste von TESM waere dort schlicht falsch.
|
||||||
auth_tagline: str = "",
|
auth_tagline: str = "",
|
||||||
app_version: str = "2.0.5",
|
app_version: str = "2.0.6",
|
||||||
built_in_trusted_keys: tuple[str, ...] = (),
|
built_in_trusted_keys: tuple[str, ...] = (),
|
||||||
enable_license: bool = True,
|
enable_license: bool = True,
|
||||||
template_folder: str | None = None,
|
template_folder: str | None = None,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tesm-licensing"
|
name = "tesm-licensing"
|
||||||
version = "2.0.5"
|
version = "2.0.6"
|
||||||
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
description = "Ed25519-basiertes Lizenz- und Aktivierungsprotokoll fuer TESM und TESM-Lizenzserver"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = ["cryptography>=42"]
|
dependencies = ["cryptography>=42"]
|
||||||
|
|||||||
Reference in New Issue
Block a user