Merge pull request 'deploy: Skript zum Einrichten des Portals auf 131' (#424) from feat/skript-131-portal into main
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Failing after 1m5s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Successful in 4s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Successful in 3s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Failing after 19s
CI / Web (dms-browser) (push) Failing after 1m27s
CI / Web (pdf-viewer) (push) Failing after 1m5s
CI / Web (shl) (push) Failing after 12s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Failing after 2s
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Failing after 1m5s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Successful in 4s
CI / Connect Security-Test-Gate (QA-01 AC4, Merge-Gate) (push) Successful in 3s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Failing after 19s
CI / Web (dms-browser) (push) Failing after 1m27s
CI / Web (pdf-viewer) (push) Failing after 1m5s
CI / Web (shl) (push) Failing after 12s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Failing after 2s
This commit was merged in pull request #424.
This commit is contained in:
commit
52a6a4bfd7
2 files changed
+195
-1
No files matched your search
Executable
+193
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env bash
|
||||
# Richtet das Portal auf 131 ein (Dienst, nginx 8450, Firewall, CORS am Core,
|
||||
# Audience "portal", Neubau von Portal und Login). Als root auf 131 ausfuehren:
|
||||
# scp deploy/131-portal-einrichten.sh root@192.168.1.131:/root/ && ssh root@192.168.1.131 'bash /root/131-portal-einrichten.sh'
|
||||
# Idempotent; geaenderte Dateien werden vorher nach $BAK gesichert. Geheimnisse
|
||||
# werden nur zwischen Dateien kopiert und nie ausgegeben.
|
||||
set -euo pipefail
|
||||
|
||||
HOST=192.168.1.131
|
||||
INSTALL=/opt/nexarch-web/portal
|
||||
ACCOUNT=/opt/nexarch-web/account
|
||||
SRC=/root/nexarch-code
|
||||
BAK=/root/portal-einrichten-$(date +%Y%m%d-%H%M%S)
|
||||
NGINX_SITE=/etc/nginx/sites-available/nexarch-gui
|
||||
mkdir -p "$BAK"
|
||||
|
||||
say() { printf '\n== %s\n' "$*"; }
|
||||
fail() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
[ "$(id -u)" = 0 ] || fail "als root ausfuehren"
|
||||
[ -f "$NGINX_SITE" ] || fail "$NGINX_SITE fehlt"
|
||||
[ -f /etc/nftables.conf ] || fail "/etc/nftables.conf fehlt"
|
||||
[ -f /etc/nexarch/policy-api.env ] || fail "/etc/nexarch/policy-api.env fehlt"
|
||||
[ -d "$INSTALL/web/portal/.next" ] || fail "Portal-Build unter $INSTALL fehlt"
|
||||
grep -qE 'include\s+/etc/nginx/conf\.d/\*\.conf' /etc/nginx/nginx.conf || fail "nginx.conf bindet conf.d nicht ein"
|
||||
nginx -t </dev/null 2>&1 | tail -1
|
||||
|
||||
say "1/8 Quellstand"
|
||||
git -C "$SRC" fetch -q origin </dev/null
|
||||
git -C "$SRC" checkout -q --detach origin/main </dev/null
|
||||
git -C "$SRC" log --oneline -1 </dev/null
|
||||
|
||||
say "2/8 Portal-Env /etc/nexarch/web-portal.env"
|
||||
if [ -f /etc/nexarch/web-portal.env ]; then
|
||||
echo "vorhanden, bleibt unveraendert"
|
||||
else
|
||||
tok=$(grep '^NEXARCH_POLICY_SERVICE_TOKEN=' /etc/nexarch/policy-api.env | cut -d= -f2-)
|
||||
[ -n "$tok" ] || fail "NEXARCH_POLICY_SERVICE_TOKEN fehlt in policy-api.env"
|
||||
umask 077
|
||||
{
|
||||
echo "PORTAL_POLICY_API_URL=http://127.0.0.1:8093"
|
||||
echo "PORTAL_CORE_API_URL=http://127.0.0.1:8099"
|
||||
echo "PORTAL_STATUS_API_URL=http://127.0.0.1:8084"
|
||||
echo "PORTAL_TOKEN_AUDIENCE=portal"
|
||||
echo "PORTAL_POLICY_SERVICE_TOKEN=$tok"
|
||||
} > /etc/nexarch/web-portal.env
|
||||
chown root:nexarch /etc/nexarch/web-portal.env
|
||||
chmod 640 /etc/nexarch/web-portal.env
|
||||
unset tok
|
||||
echo "angelegt (root:nexarch 640)"
|
||||
fi
|
||||
|
||||
say "3/8 Core: Audience portal"
|
||||
ENVF=/etc/nexarch/account-api.env
|
||||
cp -p "$ENVF" "$BAK/account-api.env"
|
||||
if grep -q '^NEXARCH_ACCOUNT_MODULE_AUDIENCES=' "$ENVF"; then
|
||||
grep -E '^NEXARCH_ACCOUNT_MODULE_AUDIENCES=.*(^|[=,])portal(,|$)' "$ENVF" >/dev/null || sed -i -E 's/^(NEXARCH_ACCOUNT_MODULE_AUDIENCES=.*)$/\1,portal/' "$ENVF"
|
||||
else
|
||||
echo 'NEXARCH_ACCOUNT_MODULE_AUDIENCES=dms,portal' >> "$ENVF"
|
||||
fi
|
||||
grep '^NEXARCH_ACCOUNT_MODULE_AUDIENCES=' "$ENVF"
|
||||
echo "Hinweis: mit mehr als einer Audience lehnt der Core Anfragen ohne ?module= ab. Auf 131 nutzt bisher kein Frontend eine Sitzung (geprueft), das Portal setzt module=portal."
|
||||
|
||||
say "4/8 nginx: CORS am Core (8443) und Block 8450"
|
||||
cp -p "$NGINX_SITE" "$BAK/nexarch-gui"
|
||||
cat > /etc/nginx/conf.d/nexarch-cors-map.conf <<'MAP'
|
||||
map $http_origin $nexarch_cors_origin {
|
||||
default "";
|
||||
"~^https://192\.168\.1\.131:(8444|8445|8446|8447|8448|8449|8450)$" $http_origin;
|
||||
}
|
||||
MAP
|
||||
cat > /etc/nginx/snippets-nexarch-cors.conf <<'SNIP'
|
||||
if ($request_method = OPTIONS) {
|
||||
add_header Access-Control-Allow-Origin $nexarch_cors_origin always;
|
||||
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
||||
add_header Access-Control-Allow-Headers "Content-Type" always;
|
||||
add_header Access-Control-Allow-Credentials "true" always;
|
||||
add_header Content-Length 0;
|
||||
return 204;
|
||||
}
|
||||
add_header Access-Control-Allow-Origin $nexarch_cors_origin always;
|
||||
add_header Access-Control-Allow-Credentials "true" always;
|
||||
SNIP
|
||||
python3 - "$NGINX_SITE" <<'PY'
|
||||
import re, sys
|
||||
p = sys.argv[1]
|
||||
s = open(p).read()
|
||||
inc = " include /etc/nginx/snippets-nexarch-cors.conf;\n"
|
||||
for loc in ("/auth/", "/account/"):
|
||||
pat = " location %s {\n" % loc
|
||||
first = s.index(pat) # erster Treffer = Block auf 8443
|
||||
after = first + len(pat)
|
||||
if inc not in s[after:after + len(inc) + 1]:
|
||||
s = s[:after] + inc + s[after:]
|
||||
if "listen 8450 ssl;" not in s:
|
||||
s = s.rstrip("\n") + """
|
||||
|
||||
# NEXARCH Web - Portal
|
||||
server {
|
||||
listen 8450 ssl;
|
||||
http2 on;
|
||||
server_name _;
|
||||
ssl_certificate /etc/ssl/archivmail/archivmail.crt;
|
||||
ssl_certificate_key /etc/ssl/archivmail/archivmail.key;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3057;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
"""
|
||||
open(p, "w").write(s)
|
||||
PY
|
||||
if nginx -t </dev/null 2>&1; then
|
||||
echo "nginx -t ok (Reload folgt nach der Firewall)"
|
||||
else
|
||||
cp -p "$BAK/nexarch-gui" "$NGINX_SITE"; rm -f /etc/nginx/conf.d/nexarch-cors-map.conf /etc/nginx/snippets-nexarch-cors.conf
|
||||
fail "nginx -t fehlgeschlagen, Aenderung zurueckgenommen"
|
||||
fi
|
||||
|
||||
say "5/8 Firewall: Port 8450"
|
||||
cp -p /etc/nftables.conf "$BAK/nftables.conf"
|
||||
grep -q '8449, 8450' /etc/nftables.conf || sed -i 's/8448, 8449 }/8448, 8449, 8450 }/' /etc/nftables.conf
|
||||
grep -q '8450' /etc/nftables.conf || fail "8450 konnte nicht in nftables.conf eingetragen werden"
|
||||
nft -c -f /etc/nftables.conf </dev/null || { cp -p "$BAK/nftables.conf" /etc/nftables.conf; fail "nft-Pruefung fehlgeschlagen, zurueckgenommen"; }
|
||||
nft -f /etc/nftables.conf </dev/null
|
||||
systemctl reload nginx </dev/null
|
||||
|
||||
say "6/8 Dienst nexarch-web-portal"
|
||||
sed "s#__INSTALL_DIR__#$INSTALL#g" "$SRC/deploy/systemd/nexarch-web-portal.service.tmpl" > /etc/systemd/system/nexarch-web-portal.service
|
||||
systemctl daemon-reload </dev/null
|
||||
|
||||
build_app() { # build_app <verzeichnis-mit-web/> <app> <env...>
|
||||
local base=$1 app=$2; shift 2
|
||||
local dir="$base/web/$app"
|
||||
[ -d "$dir" ] || fail "$dir fehlt"
|
||||
tar czf "$BAK/$app-next.tgz" -C "$dir" .next
|
||||
rsync -a --delete --exclude node_modules --exclude .next "$SRC/web/shl/" "$base/web/shl/"
|
||||
rsync -a --delete --exclude node_modules --exclude .next "$SRC/web/$app/" "$dir/"
|
||||
chown -R nexarch:nexarch "$base/web/shl" "$dir"
|
||||
mkdir -p "$base/.home"; chown nexarch:nexarch "$base/.home"
|
||||
local lock; lock=$(sha256sum "$dir/package-lock.json" | cut -d' ' -f1)
|
||||
if [ ! -d "$dir/node_modules" ] || [ "$(cat "$dir/node_modules/.nexarch-lock" 2>/dev/null)" != "$lock" ]; then
|
||||
runuser -u nexarch -- env HOME="$base/.home" NPM_CONFIG_CACHE="$base/.home/.npm" bash -c "cd '$dir' && npm ci --no-audit --no-fund && echo $lock > node_modules/.nexarch-lock" </dev/null > "$BAK/$app-npm.log" 2>&1 \
|
||||
|| { tail -5 "$BAK/$app-npm.log"; fail "npm ci $app fehlgeschlagen (Log: $BAK/$app-npm.log)"; }
|
||||
fi
|
||||
if [ -d "$dir/node_modules/@nexarch/shl" ] && [ ! -L "$dir/node_modules/@nexarch/shl" ]; then
|
||||
rm -rf "$dir/node_modules/@nexarch/shl"; ln -s ../../../shl "$dir/node_modules/@nexarch/shl"
|
||||
fi
|
||||
if [ -e "$base/web/shl/node_modules" ] && [ ! -L "$base/web/shl/node_modules" ]; then
|
||||
mv "$base/web/shl/node_modules" "$BAK/$app-shl-node_modules"
|
||||
fi
|
||||
[ -e "$base/web/shl/node_modules" ] || ln -s "../$app/node_modules" "$base/web/shl/node_modules"
|
||||
if runuser -u nexarch -- env HOME="$base/.home" NPM_CONFIG_CACHE="$base/.home/.npm" "$@" bash -c "cd '$dir' && npx next build --webpack" </dev/null > "$BAK/$app-build.log" 2>&1; then
|
||||
echo "Build $app ok"
|
||||
else
|
||||
tail -5 "$BAK/$app-build.log"
|
||||
rm -rf "$dir/.next"; tar xzf "$BAK/$app-next.tgz" -C "$dir"
|
||||
fail "Build $app fehlgeschlagen, alter Stand zurueckgestellt (Log: $BAK/$app-build.log)"
|
||||
fi
|
||||
}
|
||||
|
||||
say "7/8 Neubau Portal und Login aus origin/main"
|
||||
build_app "$INSTALL" portal NEXT_PUBLIC_CORE_API_BASE=https://$HOST:8443 NEXT_PUBLIC_LOGIN_URL=https://$HOST:8443/ NEXT_PUBLIC_TOKEN_MODULE=portal
|
||||
if [ -d "$ACCOUNT/web/account" ]; then
|
||||
build_app "$ACCOUNT" account NEXT_PUBLIC_PORTAL_URL=https://$HOST:8450/
|
||||
systemctl restart nexarch-web-account </dev/null
|
||||
else
|
||||
echo "UEBERSPRUNGEN: $ACCOUNT/web/account fehlt"
|
||||
fi
|
||||
systemctl enable --now nexarch-web-portal </dev/null
|
||||
systemctl restart nexarch-web-portal </dev/null
|
||||
|
||||
say "8/8 account-api und Pruefung"
|
||||
systemctl reset-failed nexarch-account-api </dev/null || true
|
||||
systemctl restart nexarch-account-api </dev/null || true
|
||||
sleep 4
|
||||
for u in nexarch-account-api nexarch-web-portal nexarch-web-account nexarch-policy-api nginx; do printf '%-28s %s\n' "$u" "$(systemctl is-active $u </dev/null || true)"; done
|
||||
if ! systemctl is-active --quiet nexarch-account-api; then
|
||||
echo "account-api laeuft nicht. Ursache:"
|
||||
journalctl -u nexarch-account-api -n 5 --no-pager </dev/null | cut -c1-200
|
||||
echo "Bei SQLSTATE 28P01: Passwort der DB-Rolle nexarch_core und DSN in /etc/nexarch/account-api.env abgleichen, dann: systemctl reset-failed nexarch-account-api && systemctl restart nexarch-account-api"
|
||||
fi
|
||||
printf 'Portal 3057 : %s\n' "$(curl -s -o /dev/null -m 8 -w '%{http_code}' http://127.0.0.1:3057/ </dev/null)"
|
||||
printf 'Portal 8450 : %s\n' "$(curl -sk -o /dev/null -m 8 -w '%{http_code}' https://127.0.0.1:8450/ </dev/null)"
|
||||
printf 'CORS 8443 : %s\n' "$(curl -sk -m 8 -i -X OPTIONS https://127.0.0.1:8443/auth/module-token -H 'Origin: https://192.168.1.131:8450' -H 'Access-Control-Request-Method: POST' </dev/null | tr -d '\r' | grep -i '^access-control-allow-origin' || echo 'kein Header')"
|
||||
echo
|
||||
echo "Sicherungen: $BAK"
|
||||
echo "Test im Browser: https://$HOST:8443/login (Anmeldung), danach Weiterleitung auf https://$HOST:8450/"
|
||||
@@ -4,7 +4,8 @@
|
||||
- Code: `/opt/nexarch-web/portal/web/{portal,shl}`, Eigentümer `nexarch`. Der Benutzer hat kein Home; für `npm ci` HOME und `NPM_CONFIG_CACHE` auf `/opt/nexarch-web/portal/` setzen.
|
||||
- Build mit `NEXT_PUBLIC_CORE_API_BASE=https://192.168.1.131:8443`, `NEXT_PUBLIC_LOGIN_URL=https://192.168.1.131:8443/`, `NEXT_PUBLIC_TOKEN_MODULE=portal`.
|
||||
- Unit-Vorlage: `deploy/systemd/nexarch-web-portal.service.tmpl` (Port 3057). Env-Datei `/etc/nexarch/web-portal.env` mit `PORTAL_POLICY_API_URL`, `PORTAL_CORE_API_URL`, `PORTAL_STATUS_API_URL` und dem Secret `PORTAL_POLICY_SERVICE_TOKEN` (legt der Betreiber an).
|
||||
- Offen: nginx-Block (Port 8450) und nft-Regel für den Zugriff von außen.
|
||||
- Einrichten in einem Schritt: `deploy/131-portal-einrichten.sh` (als root auf 131: Env-Datei aus dem Policy-Token, Unit, nginx-Block 8450, nft-Regel, Audience `portal`, CORS am Core, Neubau von Portal und Login). Das Skript sichert jede geänderte Datei nach `/root/portal-einrichten-<Zeit>` und nimmt nginx- und nft-Änderungen bei Prüffehlern zurück.
|
||||
- CORS: Der Core (8443) liefert auf 131 selbst keine CORS-Header; Frontends auf anderen Ports (8444–8450) brauchen sie für `/auth/module-token`. Das Skript trägt sie in nginx ein (`/etc/nginx/conf.d/nexarch-cors-map.conf`, Ursprünge `https://192.168.1.131:8444–8450`).
|
||||
- Voraussetzung für Anmeldung: `nexarch-account-api` läuft (Passwort der DB-Rolle muss zur DSN in `account-api.env` passen; bei Authentifizierungsfehler beendet sich der Dienst mit Exit 2 und startet nicht neu).
|
||||
|
||||
## 204 (Dev/Test, Demo `nexarch-portal-live`)
|
||||
|
||||
Reference in new issue
Block a user