Index: scripts/install.sh
===================================================================
--- scripts/install.sh	(revision 2dd1dc40db2f7dab2c095eeb309e5aaa02369b4b)
+++ scripts/install.sh	(revision bfa6fa1e058aa9b3c2821d56a16842937aeed22a)
@@ -305,36 +305,9 @@
 
 log "Update command 'klonkt-update'…"
-cat > /usr/local/bin/klonkt-update <<EOF
-#!/usr/bin/env bash
-set -euo pipefail
-D="${KLONKT_DIR}"
-B=\$(runuser -u ${KLONKT_USER} -- git -C "\$D" rev-parse HEAD 2>/dev/null || true)
-runuser -u ${KLONKT_USER} -- git -C "\$D" fetch --depth 1 origin ${KLONKT_BRANCH}
-runuser -u ${KLONKT_USER} -- git -C "\$D" checkout -qf -B ${KLONKT_BRANCH} FETCH_HEAD
-A=\$(runuser -u ${KLONKT_USER} -- git -C "\$D" rev-parse HEAD)
-if [ "\$B" = "\$A" ]; then
-  echo "Klonkt is already up to date (\$A) — nothing to do."
-  exit 0
-fi
-if ! runuser -u ${KLONKT_USER} -- git -C "\$D" diff --quiet "\$B" "\$A" -- package-lock.json 2>/dev/null; then
-  runuser -u ${KLONKT_USER} -- env HOME="\$D" bash -c "cd '\$D' && npm ci --omit=dev"
-fi
-# Restart every instance. Each directory under the data root with an .env is one
-# instance sharing this checkout. An install that has not been split yet has no
-# such directories and still runs the single klonkt.service.
-N=0
-for d in ${KLONKT_DATA_ROOT}/*/; do
-  [ -f "\$d/.env" ] || continue
-  s=\$(basename "\$d")
-  systemctl restart "klonkt@\$s" && N=\$((N+1))
-done
-if [ "\$N" = 0 ]; then
-  systemctl restart klonkt
-  echo "Klonkt updated (\$A) + restarted."
-else
-  echo "Klonkt updated (\$A) + restarted \$N instance(s)."
-fi
-EOF
-chmod +x /usr/local/bin/klonkt-update
+# Generated by the shared script so an install and a later layout migration
+# can never drift apart on what the updater restarts.
+KLONKT_DIR="$KLONKT_DIR" KLONKT_USER="$KLONKT_USER" \
+KLONKT_DATA_ROOT="$KLONKT_DATA_ROOT" KLONKT_BRANCH="$KLONKT_BRANCH" \
+  bash "$KLONKT_DIR/scripts/klonkt-refresh-updater.sh"
 ok "klonkt-update"
 
