source: Klonkt/scripts/klonkt-refresh-updater.sh@ f434294

main
Last change on this file since f434294 was f434294, checked in by Robin <roboburr@…>, 6 weeks ago

Maskeer de oude klonkt.service bij de split, hij stond op te staan uit de dood

Op boiert.eu verscheen na de update opnieuw een /opt/klonkt/storage. Oorzaak:
de migratie deed alleen systemctl disable op klonkt.service, maar disable
haalt uitsluitend de autostart weg. Een systemctl restart klonkt start zo'n
unit alsnog, en precies dat staat in elke updater die voor de split is
gegenereerd.

De opgestane klonkt.service heeft WorkingDirectory=/opt/klonkt en geen
EnvironmentFile, terwijl zijn .env met de data mee is verhuisd naar
/var/lib/klonkt/<slug>/. Hij start dus zonder enige config, valt terug op de
ingebouwde standaardpaden en schrijft een verse lege database in de checkout.
Afhankelijk van wie de poort pakt levert dat een lege site op, of een
crashende unit die bij elke herstart de map opnieuw aanmaakt.

Disable is dus niet genoeg: de unit wordt nu ook gemaskeerd, zodat elke
aanroep hard faalt in plaats van stilletjes een tweede proces te starten.
Omkeerbaar met systemctl unmask.

Changed files:
scripts/klonkt-migrate-data.sh

  • oude unit wordt gestopt, uitgezet en gemaskeerd
  • test op list-unit-files in plaats van is-enabled, zodat een al uitgezette unit niet wordt overgeslagen

scripts/klonkt-refresh-updater.sh

  • maskeert de oude unit alsnog op een gesplitste installatie, zodat al gemigreerde servers zichzelf repareren
  • waarschuwt als er een storage/ in de checkout staat, met het commando om te controleren of er iets in zit; verwijdert nooit zelf

deploy/MULTI-INSTANCE.md

  • rollback bijgewerkt: unmask hoort er nu bij, met de reden

-robo
Co-Authored-By: Claude Fable 5 <noreply@…>

  • Property mode set to 100755
File size: 3.9 KB
Line 
1#!/usr/bin/env bash
2#
3# (Re)write /usr/local/bin/klonkt-update so it matches how this server runs.
4#
5# Why this exists: the updater is generated once at install time. A server
6# that later migrated to the split layout (klonkt@<slug> units) kept its old
7# updater, which still restarts the retired klonkt.service. Result: the code
8# on disk updates, the restart quietly fails, and the old process keeps
9# serving — half old routes, half new templates, which is how you get a 500
10# on one page and nothing in the logs that says why.
11#
12# Idempotent; safe to run any time:
13#
14# sudo bash /opt/klonkt/scripts/klonkt-refresh-updater.sh
15#
16set -euo pipefail
17
18KLONKT_DIR="${KLONKT_DIR:-/opt/klonkt}"
19KLONKT_USER="${KLONKT_USER:-klonkt}"
20DATA_ROOT="${KLONKT_DATA_ROOT:-/var/lib/klonkt}"
21# Follow whatever branch the checkout is on (stable for most self-hosters).
22BRANCH="${KLONKT_BRANCH:-$(git -C "$KLONKT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo stable)}"
23
24[ "$(id -u)" = 0 ] || { echo "run this as root (sudo)." >&2; exit 1; }
25[ -d "$KLONKT_DIR/.git" ] || { echo "no git checkout at $KLONKT_DIR" >&2; exit 1; }
26
27cat > /usr/local/bin/klonkt-update <<EOF
28#!/usr/bin/env bash
29set -euo pipefail
30D="${KLONKT_DIR}"
31B=\$(runuser -u ${KLONKT_USER} -- git -C "\$D" rev-parse HEAD 2>/dev/null || true)
32runuser -u ${KLONKT_USER} -- git -C "\$D" fetch --depth 1 origin ${BRANCH}
33runuser -u ${KLONKT_USER} -- git -C "\$D" checkout -qf -B ${BRANCH} FETCH_HEAD
34A=\$(runuser -u ${KLONKT_USER} -- git -C "\$D" rev-parse HEAD)
35if [ "\$B" = "\$A" ]; then
36 echo "Klonkt is already up to date (\$A) — nothing to do."
37 exit 0
38fi
39if ! runuser -u ${KLONKT_USER} -- git -C "\$D" diff --quiet "\$B" "\$A" -- package-lock.json 2>/dev/null; then
40 runuser -u ${KLONKT_USER} -- env HOME="\$D" bash -c "cd '\$D' && npm ci --omit=dev"
41fi
42# Restart every instance sharing this checkout: one directory with an .env
43# under the data root per instance. No instances there = the pre-split
44# single-service layout, which still runs plain klonkt.service.
45N=0
46for d in ${DATA_ROOT}/*/; do
47 [ -f "\$d/.env" ] || continue
48 s=\$(basename "\$d")
49 systemctl restart "klonkt@\$s" && N=\$((N+1))
50done
51if [ "\$N" = 0 ]; then
52 systemctl restart klonkt
53 echo "Klonkt updated (\$A) + restarted."
54else
55 echo "Klonkt updated (\$A) + restarted \$N instance(s)."
56fi
57EOF
58chmod +x /usr/local/bin/klonkt-update
59echo "klonkt-update rewritten: branch ${BRANCH}, code ${KLONKT_DIR}, instances under ${DATA_ROOT}"
60
61# On a split install the old single unit must not be startable. `disable` alone
62# does not stop `systemctl restart klonkt` from starting it, and a resurrected
63# klonkt.service has no .env (it moved with the data): it falls back to the
64# defaults and writes a fresh empty database into the checkout.
65SPLIT=0
66for d in "${DATA_ROOT}"/*/; do [ -f "$d/.env" ] && SPLIT=1 && break; done
67if [ "$SPLIT" = 1 ] && systemctl list-unit-files klonkt.service >/dev/null 2>&1; then
68 if ! systemctl is-enabled klonkt.service 2>/dev/null | grep -q masked; then
69 systemctl stop klonkt.service 2>/dev/null || true
70 systemctl disable klonkt.service 2>/dev/null || true
71 systemctl mask klonkt.service
72 echo "retired klonkt.service: stopped, disabled and masked (unmask to roll back)"
73 fi
74fi
75
76# A leftover storage/ in the checkout means something ran without the instance
77# config. Report it; never delete it unattended — only its owner can tell
78# whether it holds anything.
79if [ "$SPLIT" = 1 ] && [ -e "${KLONKT_DIR}/storage" ]; then
80 echo
81 echo "WARNING: ${KLONKT_DIR}/storage exists while instance data lives in ${DATA_ROOT}."
82 echo " Something ran without the instance .env and wrote here. Check with:"
83 echo " sqlite3 ${KLONKT_DIR}/storage/database.sqlite 'select count(*) from posts;'"
84 echo " If it is empty, it is a stray from a resurrected klonkt.service and"
85 echo " can be removed. If it is NOT empty, do not delete it: ask first."
86fi
Note: See TracBrowser for help on using the repository browser.