pinnace 0.3.1 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,7 +28,7 @@
28
28
  * operator's client and as the box's periodic agent, so the record/warm/mirror/
29
29
  * status logic has a single implementation (no bash/TS drift). Kubo still owns
30
30
  * pinning (`dag/import --pin-roots`) + provider-record freshness
31
- * (`Provide.Interval`); the pinnace timers own ONLY IPNS republish/export,
31
+ * (`Provide.Strategy`); the pinnace timers own ONLY IPNS republish/export,
32
32
  * replica mirror/fallback, gateway warm, and status. The reference bash is used
33
33
  * here as the BEHAVIOURAL SPEC of what each timer must do, not as code to emit.
34
34
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-init.d.ts","sourceRoot":"","sources":["../../src/provision/cloud-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gCAAgC,CAAC;AAE7D,8DAA8D;AAC9D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC;AAEjC,yEAAyE;AACzE,eAAO,MAAM,cAAc,EAAE,SAAS,QAAQ,EAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC9B,mDAAmD;IACnD,IAAI,EAAE,QAAQ,CAAC;IACf,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC3B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC/B,mEAAmE;IACnE,IAAI,EAAE,QAAQ,CAAC;IACf,6CAA6C;IAC7C,SAAS,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,0EAA0E;IAC1E,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAAC;CAClD;AA8cD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAWjC,CAAC;AAOF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAUhE"}
1
+ {"version":3,"file":"cloud-init.d.ts","sourceRoot":"","sources":["../../src/provision/cloud-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gCAAgC,CAAC;AAE7D,8DAA8D;AAC9D,MAAM,MAAM,QAAQ,GAAG,SAAS,CAAC;AAEjC,yEAAyE;AACzE,eAAO,MAAM,cAAc,EAAE,SAAS,QAAQ,EAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC9B,mDAAmD;IACnD,IAAI,EAAE,QAAQ,CAAC;IACf,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;IAClB,gFAAgF;IAChF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,SAAS,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC3B,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC/B,mEAAmE;IACnE,IAAI,EAAE,QAAQ,CAAC;IACf,6CAA6C;IAC7C,SAAS,EAAE,WAAW,CAAC;CACvB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC5B,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,0EAA0E;IAC1E,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAAC;CAClD;AAoeD;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,YAWjC,CAAC;AAOF;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAUhE"}
@@ -10,7 +10,7 @@ const DEFAULT_KUBO_VERSION = 'v0.38.1';
10
10
  * the same agent. Overridable per-box via {@link ProvisionInput.pinnaceVersion}.
11
11
  * `pinnace@0.1.0` is the first published release (npm, public, OIDC provenance).
12
12
  */
13
- const DEFAULT_PINNACE_VERSION = '0.3.1';
13
+ const DEFAULT_PINNACE_VERSION = '0.3.3';
14
14
  /**
15
15
  * The pinned Node.js major the box installs via NodeSource (`setup_<this>.x`).
16
16
  * Node 22 is a current active LTS; Node 20 (the old literal) is the OLDEST LTS
@@ -236,12 +236,19 @@ write_files:
236
236
  install -d -o ipfs -g ipfs /var/lib/ipfs
237
237
 
238
238
  export IPFS_PATH=/var/lib/ipfs/.ipfs
239
+ # HOME must be passed to every sudo -u ipfs invocation: sudo does not
240
+ # inherit it, and the ipfs binary aborts (Error: HOME is not defined) since
241
+ # it resolves HOME/.config/ipfs for the nopfs denylists. Without this,
242
+ # ipfs init fails under set -e and aborts this whole script before the
243
+ # datadir/config are set up (the box then crash-loops). Point it at the
244
+ # ipfs user home (the datadir root).
245
+ IPFS_HOME=/var/lib/ipfs
239
246
  if [ ! -f "$IPFS_PATH/config" ]; then
240
247
  # 'server' profile disables local-network announce (good for a datacenter box)
241
- sudo -u ipfs env IPFS_PATH="$IPFS_PATH" ipfs init --profile server
248
+ sudo -u ipfs env IPFS_PATH="$IPFS_PATH" HOME="$IPFS_HOME" ipfs init --profile server
242
249
  fi
243
250
 
244
- cfg() { sudo -u ipfs env IPFS_PATH="$IPFS_PATH" ipfs config "$@"; }
251
+ cfg() { sudo -u ipfs env IPFS_PATH="$IPFS_PATH" HOME="$IPFS_HOME" ipfs config "$@"; }
245
252
 
246
253
  # --- Reachability: bind API + gateway to localhost only (NEVER public) ---
247
254
  cfg Addresses.API "/ip4/127.0.0.1/tcp/5001"
@@ -250,12 +257,12 @@ write_files:
250
257
  # --- Discoverability: keep provider records fresh so gateways find us ---
251
258
  cfg --json Routing.AcceleratedDHTClient true
252
259
  cfg Routing.Type "auto"
253
- # Re-announce everything we serve; interval well under the record expiry.
254
- # (Kubo 0.38 uses Provide.*; the pre-0.38 keys FATAL the daemon at boot.)
255
- # Provide.Interval is a DURATION value Kubo requires as JSON. Without --json,
256
- # setting it errors (not found / maybe use --json) and, under set -e, aborts
257
- # this whole setup script (leaving the box half-provisioned).
258
- cfg --json Provide.Interval '"12h"'
260
+ # Re-announce everything we serve via the Kubo 0.38 Provide.* config (the
261
+ # pre-0.38 keys FATAL the daemon at boot). Only Provide.Strategy is set: on
262
+ # Kubo 0.38.1 the interval sub-key is not a settable config path (ipfs
263
+ # config errors "not found / maybe use --json" even WITH --json), and under
264
+ # set -e that aborts this whole setup script. It is optional with a sane
265
+ # built-in default, so we leave it unset.
259
266
  cfg Provide.Strategy "all"
260
267
 
261
268
  # --- Resource hygiene for a small box ---
@@ -291,12 +298,20 @@ write_files:
291
298
  User=ipfs
292
299
  Group=ipfs
293
300
  Environment=IPFS_PATH=/var/lib/ipfs/.ipfs
294
- # Guarantee the datadir exists (owned by ipfs) BEFORE the sandboxed daemon
295
- # starts: ReadWritePaths=/var/lib/ipfs requires the path to exist at unit
296
- # start, so a missing datadir otherwise fails namespace setup with
297
- # 226/NAMESPACE and crash-loops. The leading '+' runs this as root, outside
298
- # the sandbox; it is idempotent.
299
- ExecStartPre=+/usr/bin/install -d -o ipfs -g ipfs /var/lib/ipfs
301
+ # HOME must point at the ipfs user's home (inside ReadWritePaths). Kubo's
302
+ # nopfs plugin resolves \$HOME/.config/ipfs/denylists; with HOME unset it
303
+ # falls back under /home/ipfs, which ProtectHome=true HIDES, so the daemon
304
+ # dies at startup with "denylists: permission denied". Setting HOME here
305
+ # keeps that lookup inside the writable datadir.
306
+ Environment=HOME=/var/lib/ipfs
307
+ # NOTE: the datadir /var/lib/ipfs is created by a runcmd step BEFORE this
308
+ # unit is enabled (see runcmd) — NOT via ExecStartPre. ReadWritePaths=
309
+ # /var/lib/ipfs makes systemd set up the mount namespace (referencing that
310
+ # path) BEFORE running any Exec* line, including ExecStartPre — even an
311
+ # ExecStartPre=+ one — so if the path is missing, namespace setup fails
312
+ # with 226/NAMESPACE and the ExecStartPre can never create it (a catch-22).
313
+ # The path must therefore exist before the unit starts, guaranteed outside
314
+ # the unit.
300
315
  ExecStart=/usr/local/bin/ipfs daemon --migrate=true --enable-gc
301
316
  Restart=on-failure
302
317
  RestartSec=5
@@ -398,7 +413,14 @@ runcmd:
398
413
  - ufw allow 443/tcp
399
414
  - ufw --force enable
400
415
 
401
- # Install + start Kubo
416
+ # Install + start Kubo.
417
+ # Create the datadir FIRST, unconditionally, before anything that needs it.
418
+ # This MUST happen outside the ipfs.service unit: that unit's
419
+ # ReadWritePaths=/var/lib/ipfs makes systemd fail namespace setup
420
+ # (226/NAMESPACE) if the path is missing, before any ExecStartPre could create
421
+ # it. And it must not depend on ipfs-setup.sh reaching its own mkdir (that
422
+ # script can abort early). So we guarantee it here, first.
423
+ - install -d -o ipfs -g ipfs /var/lib/ipfs
402
424
  - /usr/local/sbin/ipfs-setup.sh
403
425
  - systemctl daemon-reload
404
426
  - systemctl enable --now ipfs.service
@@ -1 +1 @@
1
- {"version":3,"file":"cloud-init.js","sourceRoot":"","sources":["../../src/provision/cloud-init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cloud-init.js","sourceRoot":"","sources":["../../src/provision/cloud-init.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinnace",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "license": "AGPL-3.0-only",
5
5
  "description": "Self-host a static website on IPFS across one or more self-owned Kubo nodes.",
6
6
  "repository": {
@@ -28,7 +28,7 @@
28
28
  * operator's client and as the box's periodic agent, so the record/warm/mirror/
29
29
  * status logic has a single implementation (no bash/TS drift). Kubo still owns
30
30
  * pinning (`dag/import --pin-roots`) + provider-record freshness
31
- * (`Provide.Interval`); the pinnace timers own ONLY IPNS republish/export,
31
+ * (`Provide.Strategy`); the pinnace timers own ONLY IPNS republish/export,
32
32
  * replica mirror/fallback, gateway warm, and status. The reference bash is used
33
33
  * here as the BEHAVIOURAL SPEC of what each timer must do, not as code to emit.
34
34
  *
@@ -164,7 +164,7 @@ const DEFAULT_KUBO_VERSION = 'v0.38.1';
164
164
  * the same agent. Overridable per-box via {@link ProvisionInput.pinnaceVersion}.
165
165
  * `pinnace@0.1.0` is the first published release (npm, public, OIDC provenance).
166
166
  */
167
- const DEFAULT_PINNACE_VERSION = '0.3.1';
167
+ const DEFAULT_PINNACE_VERSION = '0.3.3';
168
168
  /**
169
169
  * The pinned Node.js major the box installs via NodeSource (`setup_<this>.x`).
170
170
  * Node 22 is a current active LTS; Node 20 (the old literal) is the OLDEST LTS
@@ -416,12 +416,19 @@ write_files:
416
416
  install -d -o ipfs -g ipfs /var/lib/ipfs
417
417
 
418
418
  export IPFS_PATH=/var/lib/ipfs/.ipfs
419
+ # HOME must be passed to every sudo -u ipfs invocation: sudo does not
420
+ # inherit it, and the ipfs binary aborts (Error: HOME is not defined) since
421
+ # it resolves HOME/.config/ipfs for the nopfs denylists. Without this,
422
+ # ipfs init fails under set -e and aborts this whole script before the
423
+ # datadir/config are set up (the box then crash-loops). Point it at the
424
+ # ipfs user home (the datadir root).
425
+ IPFS_HOME=/var/lib/ipfs
419
426
  if [ ! -f "$IPFS_PATH/config" ]; then
420
427
  # 'server' profile disables local-network announce (good for a datacenter box)
421
- sudo -u ipfs env IPFS_PATH="$IPFS_PATH" ipfs init --profile server
428
+ sudo -u ipfs env IPFS_PATH="$IPFS_PATH" HOME="$IPFS_HOME" ipfs init --profile server
422
429
  fi
423
430
 
424
- cfg() { sudo -u ipfs env IPFS_PATH="$IPFS_PATH" ipfs config "$@"; }
431
+ cfg() { sudo -u ipfs env IPFS_PATH="$IPFS_PATH" HOME="$IPFS_HOME" ipfs config "$@"; }
425
432
 
426
433
  # --- Reachability: bind API + gateway to localhost only (NEVER public) ---
427
434
  cfg Addresses.API "/ip4/127.0.0.1/tcp/5001"
@@ -430,12 +437,12 @@ write_files:
430
437
  # --- Discoverability: keep provider records fresh so gateways find us ---
431
438
  cfg --json Routing.AcceleratedDHTClient true
432
439
  cfg Routing.Type "auto"
433
- # Re-announce everything we serve; interval well under the record expiry.
434
- # (Kubo 0.38 uses Provide.*; the pre-0.38 keys FATAL the daemon at boot.)
435
- # Provide.Interval is a DURATION value Kubo requires as JSON. Without --json,
436
- # setting it errors (not found / maybe use --json) and, under set -e, aborts
437
- # this whole setup script (leaving the box half-provisioned).
438
- cfg --json Provide.Interval '"12h"'
440
+ # Re-announce everything we serve via the Kubo 0.38 Provide.* config (the
441
+ # pre-0.38 keys FATAL the daemon at boot). Only Provide.Strategy is set: on
442
+ # Kubo 0.38.1 the interval sub-key is not a settable config path (ipfs
443
+ # config errors "not found / maybe use --json" even WITH --json), and under
444
+ # set -e that aborts this whole setup script. It is optional with a sane
445
+ # built-in default, so we leave it unset.
439
446
  cfg Provide.Strategy "all"
440
447
 
441
448
  # --- Resource hygiene for a small box ---
@@ -471,12 +478,20 @@ write_files:
471
478
  User=ipfs
472
479
  Group=ipfs
473
480
  Environment=IPFS_PATH=/var/lib/ipfs/.ipfs
474
- # Guarantee the datadir exists (owned by ipfs) BEFORE the sandboxed daemon
475
- # starts: ReadWritePaths=/var/lib/ipfs requires the path to exist at unit
476
- # start, so a missing datadir otherwise fails namespace setup with
477
- # 226/NAMESPACE and crash-loops. The leading '+' runs this as root, outside
478
- # the sandbox; it is idempotent.
479
- ExecStartPre=+/usr/bin/install -d -o ipfs -g ipfs /var/lib/ipfs
481
+ # HOME must point at the ipfs user's home (inside ReadWritePaths). Kubo's
482
+ # nopfs plugin resolves \$HOME/.config/ipfs/denylists; with HOME unset it
483
+ # falls back under /home/ipfs, which ProtectHome=true HIDES, so the daemon
484
+ # dies at startup with "denylists: permission denied". Setting HOME here
485
+ # keeps that lookup inside the writable datadir.
486
+ Environment=HOME=/var/lib/ipfs
487
+ # NOTE: the datadir /var/lib/ipfs is created by a runcmd step BEFORE this
488
+ # unit is enabled (see runcmd) — NOT via ExecStartPre. ReadWritePaths=
489
+ # /var/lib/ipfs makes systemd set up the mount namespace (referencing that
490
+ # path) BEFORE running any Exec* line, including ExecStartPre — even an
491
+ # ExecStartPre=+ one — so if the path is missing, namespace setup fails
492
+ # with 226/NAMESPACE and the ExecStartPre can never create it (a catch-22).
493
+ # The path must therefore exist before the unit starts, guaranteed outside
494
+ # the unit.
480
495
  ExecStart=/usr/local/bin/ipfs daemon --migrate=true --enable-gc
481
496
  Restart=on-failure
482
497
  RestartSec=5
@@ -578,7 +593,14 @@ runcmd:
578
593
  - ufw allow 443/tcp
579
594
  - ufw --force enable
580
595
 
581
- # Install + start Kubo
596
+ # Install + start Kubo.
597
+ # Create the datadir FIRST, unconditionally, before anything that needs it.
598
+ # This MUST happen outside the ipfs.service unit: that unit's
599
+ # ReadWritePaths=/var/lib/ipfs makes systemd fail namespace setup
600
+ # (226/NAMESPACE) if the path is missing, before any ExecStartPre could create
601
+ # it. And it must not depend on ipfs-setup.sh reaching its own mkdir (that
602
+ # script can abort early). So we guarantee it here, first.
603
+ - install -d -o ipfs -g ipfs /var/lib/ipfs
582
604
  - /usr/local/sbin/ipfs-setup.sh
583
605
  - systemctl daemon-reload
584
606
  - systemctl enable --now ipfs.service