From 678a28c25f213001966da863f29834ac0f76694a Mon Sep 17 00:00:00 2001 From: Matteo Nastasi Date: Wed, 7 Oct 2026 09:32:33 +0000 Subject: [PATCH] write a systemd unit for the daemon instead of the sysv script "INSTALL.sh system" wrote a script into /etc/init.d. On debian 13 that script is never run: the sysv compatibility generator of systemd is gone, so nothing turns it into a service and nothing starts it at boot. Where systemd is in charge the action now writes .service in Etc, beside the nginx and nftables files, and leaves /etc/init.d alone; without systemd it installs the sysv script exactly as before. The unit is only written, and the run prints the three commands that install it, as for the other generated files. What the unit had to get right, both found by running the daemon: - -d. Without it the daemon keeps stdin in its select set, and stdin being /dev/null under systemd it reads EOF at once and exits with 22 (sac-a-push.phh, the branch that returns 22). The sysv script got away without it because screen gave the daemon a tty. - KillSignal stays SIGTERM. On SIGTERM the daemon serializes the room into /brisk-crystal.data and exits 0, and the next start reads it back, so a stop and a start keep the games. SIGINT exits with 1 and saves nothing. Restart=on-failure, so a stop asked for stays stopped while a crash comes back up; TimeoutStopSec=15, measured against the 56ms an empty room takes to serialize; ExecReload sends SIGHUP, which the daemon already treats as a reload; WorkingDirectory because the daemon reaches its own files by relative paths. The screen session and the shell loop that respawned the daemon are both gone, and its output goes to the journal, which the unit says how to silence. ngx_put is now gen_put: it is no longer only for nginx files. Checked in a container with systemd: the unit passes systemd-analyze verify, the service starts and binds the eleven ports, systemctl reload reaches the daemon without changing its pid, systemctl stop exits 0 in 50ms leaving brisk-crystal.data behind, the next start logs "ROOM FROM FILE", and a SIGKILL on the main process brings it back up (NRestarts=1). Co-Authored-By: Claude Opus 5 (1M context) --- INSTALL.sh | 110 +++++++++++++++++++++++++++++++++++++++++++--- WARNING.txt | 34 ++++++++++++++ bin/brisk-init.sh | 5 +++ 3 files changed, 144 insertions(+), 5 deletions(-) diff --git a/INSTALL.sh b/INSTALL.sh index 10fd27f..685a604 100755 --- a/INSTALL.sh +++ b/INSTALL.sh @@ -135,7 +135,7 @@ function searchetc() { # Put a freshly generated file in place: left alone when nothing changed, # otherwise the previous version is kept as .old, because these files are # also the ones somebody may have touched by hand. -function ngx_put() { +function gen_put() { local tmp dst tmp="$1" dst="$2" @@ -196,6 +196,78 @@ function fpm_front_ports() { done | sort -un } +# Whether this machine is run by systemd. A /etc/init.d script is of no use +# where it is: debian 13 dropped the sysv compatibility generator, so the +# script is never turned into a service and nothing starts it at boot. +function has_systemd() { + [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1 +} + +# The systemd unit of the daemon, written in Etc as .service, to be +# copied by hand into /etc/systemd/system/. It replaces bin/brisk-init.sh, +# which wrapped the daemon in a screen session and respawned it with a shell +# loop: Restart= is that loop, and the log goes to the journal instead of +# staying inside a screen nobody attaches to. +function systemd_unit_gen() { + local name unit_f tmp + local pfx_ws + + name="$(inst_name)" + unit_f="$etc_path/${name}.service" + pfx_ws="$(echo "$web_path" | sed 's:/*$::')" + + tmp="$(mktemp)" + cat > "$tmp" <.nft, to be copied by hand into /etc/nftables.d/. Over tcp # the daemon believes X-Real-Ip, which the bans are built on, and its control @@ -260,7 +332,7 @@ function nft_conf_gen() { echo " }" echo "}" } > "$tmp" - ngx_put "$tmp" "$nft_f" + gen_put "$tmp" "$nft_f" if [ -n "$fpm_ports" ]; then echo " php-fpm serves the front from here (port ${fpm_ports}): included" else @@ -341,7 +413,7 @@ function nginx_conf_gen() { fi echo "}" } > "$tmp" - ngx_put "$tmp" "$http_f" + gen_put "$tmp" "$http_f" # --- the nine daemon urls --- tmp="$(mktemp)" @@ -375,7 +447,7 @@ proxy_set_header Connection \$${var}_connection_upgrade; # be down together with the daemon error_page 502 503 504 ${pfx}/daemon-down.html; EOF - ngx_put "$tmp" "$inc_f" + gen_put "$tmp" "$inc_f" # --- inside the server {} --- tmp="$(mktemp)" @@ -447,7 +519,7 @@ EOF done fi } > "$tmp" - ngx_put "$tmp" "$srv_f" + gen_put "$tmp" "$srv_f" if [ -n "$ngx_ver" ]; then echo " written for the nginx found here, $ngx_ver: check it with nginx -t" @@ -649,7 +721,35 @@ if [ "$action" = "system" ]; then echo "private path: [$legal_path]" echo "system user: [$sys_user]" echo + if has_systemd; then + echo "init system: [systemd] -> a unit, written in Etc" + else + echo "init system: [no systemd] -> the sysv script, in /etc/init.d" + fi + echo read -p "press enter to continue" sure + + if has_systemd; then + # Etc is where the other generated files go; this action runs before + # the pre-check that looks it up, so it is looked up here. + etc_path="$(searchetc "$(dirname "$web_path")" Etc)" + if [ $? -ne 0 ]; then + echo "Etc directory not found above $(dirname "$web_path")" + exit 1 + fi + echo "systemd unit:" + systemd_unit_gen + echo + echo "... DONE." + echo "DON'T FORGET: the unit is only written, not installed. Copy it, then:" + echo + echo " su -c 'cp $etc_path/${scrname}.service /etc/systemd/system/'" + echo " su -c 'systemctl daemon-reload'" + echo " su -c 'systemctl enable --now ${scrname}'" + echo + exit 0 + fi + cp bin/brisk-init.sh brisk-init.sh.wrk sed -i "s@^BPATH=.*@BPATH=\"${web_path}\"@g;s@^PPATH=.*@PPATH=\"${legal_path}\"@g;s@^SSUFF=.*@SSUFF=\"${scrname}\"@g;s@^BUSER=.*@BUSER=\"${sys_user}\"@g" brisk-init.sh.wrk diff --git a/WARNING.txt b/WARNING.txt index 63f9c7c..6de382f 100644 --- a/WARNING.txt +++ b/WARNING.txt @@ -95,3 +95,37 @@ NOTES on the shape of the ProxyPass lines (checked on apache 2.4.68): Everything that is not in this list (the static pages, admin.php, usermgmt.php, the .css and the .js) is still served by apache. + + +==== 3. STARTING THE DAEMON: SYSTEMD ==== + +"INSTALL.sh system" used to write a sysv script into /etc/init.d. On debian +13 that script is never run: the sysv compatibility generator of systemd is +gone, so nothing turns it into a service and nothing starts it at boot. + +Where systemd is in charge, the action now writes a unit in Etc instead, +.service beside the other generated files, and leaves /etc/init.d +alone. It is only written: copy it, reload, enable. + + su -c 'cp /brisk.service /etc/systemd/system/' + su -c 'systemctl daemon-reload' + su -c 'systemctl enable --now brisk' + +Without systemd nothing changes: the sysv script is installed as before. + +Two things the unit does that are easy to get wrong by hand: + + - brisk-spush.php is started with -d. Without it the daemon keeps stdin + in its select set, and stdin being /dev/null under systemd it reads EOF + at once and exits with 22. The sysv script got away without it because + it wrapped the daemon in a screen session, which gave it a tty. + + - the signal of the stop stays SIGTERM. On SIGTERM the daemon serializes + the room into /brisk-crystal.data and exits 0, and the next + start picks the room up from there, so a stop and a start do not throw + the games away. SIGINT exits without saving anything. + +Restart=on-failure, not always: a stop asked for exits 0 and stays stopped, +while a crash or a SIGKILL comes back up. The screen session and the shell +loop that respawned the daemon are both gone, and the output of the daemon +goes to the journal. diff --git a/bin/brisk-init.sh b/bin/brisk-init.sh index 0c29c0e..e661b3e 100755 --- a/bin/brisk-init.sh +++ b/bin/brisk-init.sh @@ -8,6 +8,11 @@ # Short-Description: manage brisk daemon ### END INIT INFO +# NOTE: this script is for machines without systemd. Where systemd is in +# charge, "INSTALL.sh system" writes a unit in Etc instead and does not touch +# /etc/init.d: debian 13 dropped the sysv compatibility generator, so this +# script would simply never be run. See WARNING.txt. + BPATH="xx/home/nastasi/web/brisk" PPATH="xx/home/nastasi/brisk-priv" # screen suffix -- 2.47.3