Changes in / [952baf3:0d5bd2c] in Klonkt


Ignore:
Files:
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • deploy/MULTI-INSTANCE.md

    r952baf3 r0d5bd2c  
    8484because the port comes from the same `.env`.
    8585
    86 **The old unit is moved aside, not deleted.** It ends up next to its old place
    87 as `klonkt.service.retired-<timestamp>`. Stopping and disabling is not enough:
    88 `systemctl restart klonkt` starts a disabled unit anyway, which is exactly what
    89 an updater generated before the split does. A resurrected `klonkt.service` no
    90 longer finds its `.env` (that moved with the data), falls back to the built-in
    91 defaults, and writes a fresh empty database into the checkout. Masking does not
    92 work here either, because the unit file sits in `/etc/systemd/system` and
    93 `systemctl mask` refuses while a real file is there.
    94 
    95 **Rolling back.** Move the data into `/opt/klonkt/storage`, restore the relative
    96 paths in `.env`, move the retired unit file back to
    97 `/etc/systemd/system/klonkt.service`, then:
    98 
    99 ```bash
    100 sudo systemctl daemon-reload
    101 sudo systemctl enable --now klonkt
    102 ```
     86**Rolling back.** The old `klonkt.service` is disabled and masked, not deleted.
     87Masked because `disable` alone does not stop `systemctl restart klonkt` from
     88starting it again, and a resurrected unit no longer finds its `.env` (that moved
     89with the data): it would fall back to the defaults and write a fresh empty
     90database into the checkout. To go back, move the data into `/opt/klonkt/storage`,
     91restore the relative paths in `.env`, then `systemctl unmask klonkt` and
     92`systemctl enable --now klonkt`.
    10393
    10494## Adding an instance
  • scripts/klonkt-migrate-data.sh

    r952baf3 r0d5bd2c  
    128128run "systemctl daemon-reload"
    129129
    130 step "Retiring $OLD_UNIT"
    131 # Stopping and disabling is NOT enough: `systemctl restart klonkt` starts a
    132 # disabled unit anyway, and that is exactly what an updater generated before
    133 # the split does. A resurrected klonkt.service no longer finds its .env (that
    134 # moved with the data), falls back to the built-in defaults, and writes a
    135 # FRESH EMPTY database into the checkout.
    136 #
    137 # Masking does not help either: the unit file lives in /etc/systemd/system,
    138 # the highest-priority directory, and `systemctl mask` refuses when a real
    139 # file is already there ("File ... already exists"). Verified, not assumed.
    140 #
    141 # So the file is moved aside. systemd then no longer knows the unit at all and
    142 # any restart fails loudly with "Unit klonkt.service not found". The file is
    143 # kept next to its old place, timestamped, so a rollback is a move back.
    144 if [ -f "/etc/systemd/system/$OLD_UNIT" ]; then
    145   run "systemctl stop $OLD_UNIT 2>/dev/null || true"
    146   run "systemctl disable $OLD_UNIT 2>/dev/null || true"
    147   RETIRED="/etc/systemd/system/${OLD_UNIT}.retired-$(date +%Y%m%d%H%M%S)"
    148   run "mv '/etc/systemd/system/$OLD_UNIT' '$RETIRED'"
    149   run "systemctl daemon-reload"
    150   say "stopped, disabled and moved aside → $RETIRED"
    151   say "roll back by moving that file back and running: systemctl daemon-reload"
    152 else
    153   say "no $OLD_UNIT unit file to retire"
     130step "Switching to klonkt@$SLUG"
     131if systemctl list-unit-files "$OLD_UNIT" >/dev/null 2>&1; then
     132  run "systemctl disable --now $OLD_UNIT"
     133  # Disable only removes the autostart link: `systemctl restart klonkt` would
     134  # still START it. That is not theoretical — an updater generated before the
     135  # split does exactly that, and the resurrected unit finds no .env (it moved
     136  # with the data), falls back to the built-in defaults and creates a FRESH
     137  # EMPTY database in the checkout. Masking makes any such call fail loudly.
     138  # Reversible: systemctl unmask klonkt.
     139  run "systemctl mask $OLD_UNIT"
     140  say "disabled and masked $OLD_UNIT (unmask to roll back)"
    154141fi
    155 
    156 step "Switching to klonkt@$SLUG"
    157142run "systemctl enable --now 'klonkt@$SLUG'"
    158143
  • scripts/klonkt-refresh-updater.sh

    r952baf3 r0d5bd2c  
    7777echo "klonkt-update rewritten: branch ${BRANCH}, code ${KLONKT_DIR}, instances under ${DATA_ROOT}"
    7878
    79 # On a split install the old single unit must not be startable at all.
    80 # `disable` is not enough (restart starts a disabled unit anyway) and `mask`
    81 # refuses while the real file sits in /etc/systemd/system, the highest-priority
    82 # directory. Moving the file aside is what actually works: systemd stops
    83 # knowing the unit, so any restart fails loudly instead of quietly starting a
    84 # second process that writes an empty database into the checkout.
     79# On a split install the old single unit must not be startable. `disable` alone
     80# does not stop `systemctl restart klonkt` from starting it, and a resurrected
     81# klonkt.service has no .env (it moved with the data): it falls back to the
     82# defaults and writes a fresh empty database into the checkout.
    8583SPLIT=0
    8684for d in "${DATA_ROOT}"/*/; do [ -f "$d/.env" ] && SPLIT=1 && break; done
    87 if [ "$SPLIT" = 1 ] && [ -f /etc/systemd/system/klonkt.service ]; then
    88   systemctl stop klonkt.service 2>/dev/null || true
    89   systemctl disable klonkt.service 2>/dev/null || true
    90   RETIRED="/etc/systemd/system/klonkt.service.retired-$(date +%Y%m%d%H%M%S)"
    91   if mv /etc/systemd/system/klonkt.service "$RETIRED"; then
    92     systemctl daemon-reload
    93     echo "retired klonkt.service → $RETIRED (move it back + daemon-reload to roll back)"
    94   else
    95     echo "WARNING: could not move /etc/systemd/system/klonkt.service aside."
    96     echo "         Until you do, any 'systemctl restart klonkt' starts a second"
    97     echo "         process that writes an empty database into ${KLONKT_DIR}."
     85if [ "$SPLIT" = 1 ] && systemctl list-unit-files klonkt.service >/dev/null 2>&1; then
     86  if ! systemctl is-enabled klonkt.service 2>/dev/null | grep -q masked; then
     87    systemctl stop klonkt.service 2>/dev/null || true
     88    systemctl disable klonkt.service 2>/dev/null || true
     89    systemctl mask klonkt.service
     90    echo "retired klonkt.service: stopped, disabled and masked (unmask to roll back)"
    9891  fi
    9992fi
  • src/services/ActivityPubService.js

    r952baf3 r0d5bd2c  
    14351435  const pem = actor && actor.publicKey && actor.publicKey.publicKeyPem;
    14361436  if (!pem) return null;
    1437   // Bind the key to the actor it speaks for. Without this we hand back whatever
    1438   // `id` the fetched document claims, so anyone could host a document carrying a
    1439   // VICTIM's id next to their OWN public key, sign with their own private half,
    1440   // and be believed: the victim's server is never contacted. The caller decides on
    1441   // `verified.id`, so the identity has to come from where the key was FETCHED,
    1442   // never from what the document says about itself.
    1443   // Adds conditions only, and there is no exemption list on purpose: an
    1444   // "unless it's a known peer" escape hatch is exactly the door this closes.
    1445   // Note this does not narrow what we accept in practice, since the line above
    1446   // already requires the embedded publicKey object (an array or a bare URI
    1447   // reference never worked here).
    1448   const key = actor.publicKey;
    1449   try {
    1450     if (new URL(p.keyId).host !== new URL(actor.id).host) return null;   // same origin as the key
    1451     if (key.id && key.id !== p.keyId) return null;                       // this key, not a neighbour's
    1452     if (key.owner && key.owner !== actor.id) return null;                // and it belongs to this actor
    1453   } catch { return null; }                                               // unparseable id or keyId
    14541437  const hs = (p.headers || '(request-target) host date').split(/\s+/);
    14551438  // Behind a reverse proxy the raw Host header is the backend bind (e.g. localhost:3000, when
Note: See TracChangeset for help on using the changeset viewer.