# 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"
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 <name>.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" <<EOF
+# brisk ${name} - systemd unit of the brisk-spush daemon.
+# Generated by INSTALL.sh, do not edit: run "INSTALL.sh system" again instead.
+# cp ${unit_f} /etc/systemd/system/${name}.service
+# systemctl daemon-reload
+# systemctl enable --now ${name}
+
+[Unit]
+Description=Brisk daemon (${name})
+# postgresql.service in After= is simply ignored when the database is on
+# another machine or is not postgres
+After=network-online.target postgresql.service
+Wants=network-online.target
+
+[Service]
+Type=simple
+User=${sys_user}
+# the daemon reaches its own files by relative paths ("./brisk-spush.phh",
+# and "../" for Obj/), so it has to start from spush/
+WorkingDirectory=${pfx_ws}/spush
+# -d is NOT optional: without it the daemon keeps stdin in its select set,
+# and stdin being /dev/null here it reads EOF at once and exits with 22.
+# brisk-init.sh got away without it because screen gave it a tty.
+ExecStart=${pfx_ws}/spush/brisk-spush.php -d
+ExecReload=/bin/kill -HUP \$MAINPID
+# SIGTERM makes the daemon serialize the room into
+# ${legal_path}/brisk-crystal.data and exit 0, and the next start picks the
+# room up from there. SIGINT would exit without saving anything, so the
+# signal of the stop has to stay SIGTERM.
+KillSignal=SIGTERM
+# measured at 56ms on an empty room; the room of a busy evening takes longer
+# to serialize, and after this systemd resorts to SIGKILL, which saves nothing
+TimeoutStopSec=15
+# a deliberate stop exits 0 and stays stopped; a crash, or a SIGKILL, comes
+# back up
+Restart=on-failure
+RestartSec=1
+
+[Install]
+WantedBy=multi-user.target
+
+# The daemon writes a line to stdout and one to stderr every four seconds,
+# and from here they go to the journal. To keep them out of it, add
+# StandardOutput=null
+# StandardError=null
+# to [Service], and the loss is only those two lines: what matters, from the
+# refused starts to the failed admin checks, is on stderr as well.
+EOF
+ gen_put "$tmp" "$unit_f"
+}
+
# The nftables rules of the daemon machine of a split installation, written
# in Etc as <name>.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
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
fi
echo "}"
} > "$tmp"
- ngx_put "$tmp" "$http_f"
+ gen_put "$tmp" "$http_f"
# --- the nine daemon urls ---
tmp="$(mktemp)"
# 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)"
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"
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
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,
+<name>.service beside the other generated files, and leaves /etc/init.d
+alone. It is only written: copy it, reload, enable.
+
+ su -c 'cp <Etc>/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 <legal_path>/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.