Changes in / [0d5bd2c:952baf3] in Klonkt
- Files:
-
- 1 added
- 4 edited
-
deploy/MULTI-INSTANCE.md (modified) (1 diff)
-
scripts/klonkt-migrate-data.sh (modified) (1 diff)
-
scripts/klonkt-refresh-updater.sh (modified) (1 diff)
-
src/services/ActivityPubService.js (modified) (1 diff)
-
test/ap-signature-keyid-binding.test.js (added)
Legend:
- Unmodified
- Added
- Removed
-
deploy/MULTI-INSTANCE.md
r0d5bd2c r952baf3 84 84 because the port comes from the same `.env`. 85 85 86 **Rolling back.** The old `klonkt.service` is disabled and masked, not deleted. 87 Masked because `disable` alone does not stop `systemctl restart klonkt` from 88 starting it again, and a resurrected unit no longer finds its `.env` (that moved 89 with the data): it would fall back to the defaults and write a fresh empty 90 database into the checkout. To go back, move the data into `/opt/klonkt/storage`, 91 restore the relative paths in `.env`, then `systemctl unmask klonkt` and 92 `systemctl enable --now klonkt`. 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 ``` 93 103 94 104 ## Adding an instance -
scripts/klonkt-migrate-data.sh
r0d5bd2c r952baf3 128 128 run "systemctl daemon-reload" 129 129 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" 154 fi 155 130 156 step "Switching to klonkt@$SLUG" 131 if systemctl list-unit-files "$OLD_UNIT" >/dev/null 2>&1; then132 run "systemctl disable --now $OLD_UNIT"133 # Disable only removes the autostart link: `systemctl restart klonkt` would134 # still START it. That is not theoretical — an updater generated before the135 # split does exactly that, and the resurrected unit finds no .env (it moved136 # with the data), falls back to the built-in defaults and creates a FRESH137 # 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)"141 fi142 157 run "systemctl enable --now 'klonkt@$SLUG'" 143 158 -
scripts/klonkt-refresh-updater.sh
r0d5bd2c r952baf3 77 77 echo "klonkt-update rewritten: branch ${BRANCH}, code ${KLONKT_DIR}, instances under ${DATA_ROOT}" 78 78 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. 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. 83 85 SPLIT=0 84 86 for d in "${DATA_ROOT}"/*/; do [ -f "$d/.env" ] && SPLIT=1 && break; done 85 if [ "$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)" 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}." 91 98 fi 92 99 fi -
src/services/ActivityPubService.js
r0d5bd2c r952baf3 1435 1435 const pem = actor && actor.publicKey && actor.publicKey.publicKeyPem; 1436 1436 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 1437 1454 const hs = (p.headers || '(request-target) host date').split(/\s+/); 1438 1455 // 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.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)