[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 # Nach fuenf Fehlstarts in fuenf Minuten gibt systemd auf. Ohne diese Grenze # laeuft ein kaputtes Deployment endlos im Kreis: `is-active` sagt dann # dauerhaft „activating", das Log waechst, und der eigentliche Fehler steht # irgendwo weit oben. Mit ihr endet es sichtbar in „failed". StartLimitIntervalSec=300 StartLimitBurst=5 [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