feat(deploy): Backend auf die stabile Instanz bringen (D77)
Drei Teile, die das Frontend-Deploy nicht braucht: ein eigenes JDK 21 im Home des Servers (dort ist nur 17 installiert, und die Toolchain zu senken hiesse, Entwicklung und Produktion auseinanderlaufen zu lassen), ein systemd-User-Unit statt nohup, und die Proxy-Regel in der .htaccess — gemessen ist, dass das P-Flag auf diesem Hoster erlaubt ist und eine Verbindung 30 s durchhaelt. Der Port steht an genau einer Stelle: deploy-prod.sh setzt ihn in die Proxy-Regel, deploy-backend.sh in die Unit. Zwei Zahlen, die zueinander passen muessen, sind eine zu viel. Die JVM-Flags sind gemessen, nicht geschaetzt. Mein erster Entwurf setzte -Xmx384m; nachgemessen kam heraus, dass die Obergrenze der kleine Hebel ist: Ohne Freiraum-Verhaeltnisse behaelt der Kollektor den gewachsenen Heap, obwohl nach einem GC nur ~45 MB leben. Mit ihnen 174 MB RSS statt 291 MB ohne jede Angabe — auf einem Host mit rund 300 MB frei ist das der Unterschied zwischen "passt" und "draengt die Datenbank weiter in den Swap". Zwei Fallen sind eingebaut, weil beide nur am Ziel auffielen: systemd expandiert kein $HOME (deshalb %h), und `systemctl --user` findet ohne XDG_RUNTIME_DIR seinen Manager nicht. Geprueft bis an die SSH-Grenze: Das Jar startet mit genau den Flags der Unit in einer Sekunde, antwortet auf die Lebendprobe mit 404 und ist von aussen nicht erreichbar; die erzeugte Unit besteht systemd-analyze verify; der ganze Ablauf lief mit gestelltem ssh/rsync durch; deploy-prod.sh liefert die Proxy-Regel mit eingesetztem Port aus. Der Deploy selbst laeuft erst, wenn jemand ihn startet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
ec6fd452b7
commit
4aff995a0e
@@ -0,0 +1,81 @@
|
||||
[Unit]
|
||||
# Werkbaum — Backend als systemd-User-Unit (D77).
|
||||
#
|
||||
# Vorlage: scripts/deploy-backend.sh setzt __JAVA__, __DIR__, __XMX__ und
|
||||
# __PORT__ ein und legt die Datei als ~/.config/systemd/user/werkbaum-backend.service
|
||||
# ab. Ein User-Unit braucht kein root; dass er auch ohne offene Sitzung
|
||||
# weiterläuft, liegt an `Linger=yes` — auf der Zielumgebung gemessen gesetzt
|
||||
# (D76-Nachtrag 1). Fehlt es, hilft `loginctl enable-linger`.
|
||||
#
|
||||
# Die Pfade kommen als `%h/…` herein, nicht als `$HOME/…`: systemd expandiert
|
||||
# in `WorkingDirectory` und `EnvironmentFile` **keine** Shell-Variablen. Ein
|
||||
# `$HOME` stünde dort wörtlich, und der Dienst startete nicht — der Fehler
|
||||
# säße in einer Datei, die man nur auf dem Server zu sehen bekommt.
|
||||
Description=Werkbaum backend
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=__DIR__
|
||||
|
||||
# Zugangsdaten kommen aus einer Datei mit Modus 600, nie aus dem Repository
|
||||
# und nie aus der Unit selbst (`systemctl --user show` gäbe sie sonst preis).
|
||||
EnvironmentFile=__DIR__/env
|
||||
|
||||
# Speicher ist auf diesem Host die knappe Größe, nicht die Rechenzeit
|
||||
# (D76-Nachtrag 3): 3,9 GB gesamt, davon rund 300 MB frei, ein weiteres GB
|
||||
# liegt schon im Swap. Die cgroup-Grenze des Pakets (3147 MB) ist eine
|
||||
# Erlaubnis, keine Reservierung; bemessen wird am Freien.
|
||||
#
|
||||
# Gemessen mit 30 angelegten Dokumenten und anschließendem GC (D77):
|
||||
#
|
||||
# ohne Angaben RSS 291 MB (Heap belegt 359 MB)
|
||||
# nur -Xmx384m RSS 254 MB (Heap belegt 359 MB)
|
||||
# -Xmx192m -Xms48m + Ratios RSS 174 MB (Heap belegt 46 MB)
|
||||
# dito mit G1 statt Serial RSS 194 MB
|
||||
#
|
||||
# Der große Hebel sind NICHT die Obergrenzen, sondern die
|
||||
# Freiraum-Verhältnisse: Ohne sie behält der Kollektor den einmal gewachsenen
|
||||
# Heap, obwohl nach einem GC nur ~45 MB leben. Mit ihnen gibt er ihn zurück.
|
||||
# SerialGC statt G1 spart weitere 20 MB und kostet bei zehn Beobachtern nichts,
|
||||
# was auffiele.
|
||||
#
|
||||
# ExitOnOutOfMemoryError: lieber ein sauberer Neustart durch systemd als ein
|
||||
# Dienst, der noch läuft und nichts mehr beantwortet.
|
||||
ExecStart=__JAVA__ \
|
||||
-Xmx__XMX__ \
|
||||
-Xms48m \
|
||||
-XX:MinHeapFreeRatio=20 \
|
||||
-XX:MaxHeapFreeRatio=40 \
|
||||
-Xss512k \
|
||||
-XX:MaxMetaspaceSize=192m \
|
||||
-XX:ReservedCodeCacheSize=64m \
|
||||
-XX:MaxDirectMemorySize=64m \
|
||||
-XX:+UseSerialGC \
|
||||
-XX:+ExitOnOutOfMemoryError \
|
||||
-Dserver.port=__PORT__ \
|
||||
-Dserver.address=127.0.0.1 \
|
||||
-jar __DIR__/werkbaum-backend.jar
|
||||
|
||||
# Der Dienst lauscht nur auf 127.0.0.1 (siehe -Dserver.address): Von außen
|
||||
# kommt man ausschließlich über den Apache-Proxy, und damit gilt dessen
|
||||
# HTTPS — das Master-Passwort geht nie im Klartext über das Netz.
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
# Beim Stoppen erst freundlich fragen; ein laufender Long-Poll hält bis zu
|
||||
# 25 s, deshalb darf das Beenden etwas dauern.
|
||||
TimeoutStopSec=40
|
||||
KillSignal=SIGTERM
|
||||
|
||||
# Bewusst ohne die Sandbox-Optionen (`PrivateTmp`, `ProtectHome` und
|
||||
# Verwandte): In einem User-Unit brauchen sie unprivilegierte
|
||||
# Benutzer-Namensräume, und wo die abgeschaltet sind, startet der Dienst
|
||||
# gar nicht erst. `NoNewPrivileges` ist ein schlichtes prctl und geht immer.
|
||||
NoNewPrivileges=true
|
||||
|
||||
StandardOutput=append:__DIR__/backend.log
|
||||
StandardError=append:__DIR__/backend.log
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
Reference in New Issue
Block a user