@le-space/rootfs 0.6.28 → 0.6.30

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.
package/README.md CHANGED
@@ -11,6 +11,8 @@ Shared rootfs contract parsing, reference profile assets, and build helpers.
11
11
  including the delayed first-start, setup endpoint, Caddy, and AutoTLS flow
12
12
  - added a `ucan-store` reference contract scaffold with documented service
13
13
  ports and consumer env expectations
14
+ - added an ephemeral `playwright-runner` profile with Node.js 24, exact
15
+ Playwright/Chromium `1.61.1`, authenticated WSS, bounded logs, and a guest TTL
14
16
 
15
17
  ## Reference assets
16
18
 
@@ -22,3 +24,5 @@ Current shared reference profiles live under:
22
24
  - `reference/orbitdb-relay/rootfs/*`
23
25
  - `reference/ucan-store/contract.json`
24
26
  - `reference/ucan-store/rootfs/*`
27
+ - `reference/playwright-runner/contract.json`
28
+ - `reference/playwright-runner/rootfs/*`
package/index.d.ts CHANGED
@@ -123,6 +123,7 @@ interface RootfsManifest {
123
123
  rootfsSizeMiB: number;
124
124
  createdAt: string;
125
125
  notes: string;
126
+ playwrightVersion?: string;
126
127
  }
127
128
  interface RootfsManifestOptions {
128
129
  createdAt?: string;
package/index.js CHANGED
@@ -274,6 +274,9 @@ function validateRootfsManifest(manifest) {
274
274
  return { manifest, valid: false, errors: ["Rootfs manifest is missing."] };
275
275
  }
276
276
  if (!manifest.version) errors.push("Rootfs manifest version is missing.");
277
+ if (manifest.profile === "playwright-runner" && !/^\d+\.\d+\.\d+$/u.test(manifest.playwrightVersion ?? "")) {
278
+ errors.push("Playwright runner manifest must expose an exact Playwright version.");
279
+ }
277
280
  if (manifest.rootfsInstallStrategy != null && manifest.rootfsInstallStrategy !== "thin" && manifest.rootfsInstallStrategy !== "prebaked") {
278
281
  errors.push('Rootfs install strategy must be "thin" or "prebaked" when provided.');
279
282
  }
@@ -345,6 +348,9 @@ function createRootfsManifest(plan, contract, options = {}) {
345
348
  createdAt: options.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
346
349
  notes: contract.manifest.notes ?? ""
347
350
  };
351
+ if (contract.rootfs.profile === "playwright-runner") {
352
+ manifest.playwrightVersion = "1.61.1";
353
+ }
348
354
  if (typeof options.rootfsSourceSizeBytes === "number" && Number.isFinite(options.rootfsSourceSizeBytes) && options.rootfsSourceSizeBytes > 0) {
349
355
  manifest.rootfsSourceSizeBytes = options.rootfsSourceSizeBytes;
350
356
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@le-space/rootfs",
3
- "version": "0.6.28",
3
+ "version": "0.6.30",
4
4
  "description": "Shared rootfs contract parsing, reference profile assets, and build helpers.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -243,6 +243,7 @@ case "${ROOTFS_PROFILE}" in
243
243
  --copy-in "${SCRIPT_DIR}/orbitdb-relay-bootstrap.service:/etc/systemd/system"
244
244
  --copy-in "${SCRIPT_DIR}/orbitdb-relay-bootstrap-refresh.service:/etc/systemd/system"
245
245
  --copy-in "${SCRIPT_DIR}/orbitdb-relay-bootstrap-refresh.timer:/etc/systemd/system"
246
+ --copy-in "${SCRIPT_DIR}/orbitdb-relay-bootstrap-deregister.service:/etc/systemd/system"
246
247
  --copy-in "${SCRIPT_DIR}/orbitdb-relay-autotls-refresh.service:/etc/systemd/system"
247
248
  --copy-in "${SCRIPT_DIR}/orbitdb-relay-bootstrap.conf:/etc/systemd/system/orbitdb-relay.service.d"
248
249
  --run-command "tar -xf /opt/$(basename "${APP_TAR}") -C /opt/orbitdb-relay"
@@ -0,0 +1,20 @@
1
+ [Unit]
2
+ Description=Best-effort Aleph bootstrap deregistration on shutdown for orbitdb-relay
3
+ After=network-online.target orbitdb-relay.service
4
+ Wants=network-online.target
5
+ ConditionPathExists=/etc/default/orbitdb-relay.ready
6
+
7
+ [Service]
8
+ Type=oneshot
9
+ RemainAfterExit=yes
10
+ Environment=ENV_FILE=/etc/default/orbitdb-relay
11
+ Environment=DESCRIBE_SCRIPT=/usr/local/sbin/orbitdb-relay-describe.py
12
+ Environment=ALEPH_BOOTSTRAP_DEREGISTER_ONLY=1
13
+ ExecStart=/bin/true
14
+ ExecStop=/usr/bin/python3 /usr/local/sbin/orbitdb-relay-bootstrap-refresh.py
15
+ StandardOutput=journal
16
+ StandardError=journal
17
+ TimeoutStopSec=25
18
+
19
+ [Install]
20
+ WantedBy=multi-user.target
@@ -476,6 +476,7 @@ def fetch_previous_hashes(
476
476
  sender: str,
477
477
  current_item_hash: str,
478
478
  now_ms: int,
479
+ deregister_all: bool = False,
479
480
  ) -> list[str]:
480
481
  stale_cutoff_ms = now_ms - (STALE_RECORD_MAX_AGE_SECONDS * 1000)
481
482
  normalized_sender = normalize_address(sender)
@@ -503,7 +504,10 @@ def fetch_previous_hashes(
503
504
  }
504
505
  if not same_publisher:
505
506
  continue
506
- if parsed["item_hash"] == current_item_hash:
507
+ if not deregister_all and parsed["item_hash"] == current_item_hash:
508
+ continue
509
+ if deregister_all:
510
+ found.append(str(parsed["item_hash"]))
507
511
  continue
508
512
  updated_at = timestamp_ms(parsed["updated_at"])
509
513
  if updated_at is not None and updated_at < stale_cutoff_ms:
@@ -556,6 +560,49 @@ def main() -> None:
556
560
  print(json_dumps({"status": "skipped", "reason": "missing publisher key"}))
557
561
  return
558
562
 
563
+ publisher_address = address_from_private_key(publisher_private_key)
564
+ now_ms = int(time.time() * 1000)
565
+ channel = env_values.get("ALEPH_BOOTSTRAP_CHANNEL", DEFAULT_CHANNEL).strip() or DEFAULT_CHANNEL
566
+ ref = env_values.get("ALEPH_BOOTSTRAP_REF", DEFAULT_REF).strip() or DEFAULT_REF
567
+ post_type = env_values.get("ALEPH_BOOTSTRAP_POST_TYPE", POST_TYPE).strip() or POST_TYPE
568
+ if post_type != POST_TYPE:
569
+ raise RuntimeError(
570
+ f"Unsupported ALEPH_BOOTSTRAP_POST_TYPE: {post_type}. Expected {POST_TYPE}."
571
+ )
572
+ api_host = env_values.get("ALEPH_BOOTSTRAP_API_HOST", DEFAULT_API_HOST).strip() or DEFAULT_API_HOST
573
+ deregister_only = os.environ.get("ALEPH_BOOTSTRAP_DEREGISTER_ONLY", "").strip().lower() in {
574
+ "1",
575
+ "true",
576
+ "yes",
577
+ }
578
+ if deregister_only:
579
+ hashes = fetch_previous_hashes(
580
+ api_host,
581
+ channel,
582
+ ref,
583
+ post_type,
584
+ publisher_address,
585
+ "",
586
+ now_ms,
587
+ deregister_all=True,
588
+ )
589
+ forget_response = broadcast_forget(
590
+ api_host, publisher_address, publisher_private_key, hashes, channel
591
+ )
592
+ print(
593
+ json_dumps(
594
+ {
595
+ "status": "forgotten" if hashes else "skipped",
596
+ "reason": None if hashes else "no matching bootstrap records",
597
+ "sender": publisher_address,
598
+ "registrationId": registration_id,
599
+ "forgottenHashes": hashes,
600
+ "forgetResponse": forget_response,
601
+ }
602
+ )
603
+ )
604
+ return
605
+
559
606
  describe = subprocess.run([DESCRIBE_SCRIPT], check=True, capture_output=True, text=True)
560
607
  metadata = json.loads(describe.stdout.strip() or "{}")
561
608
  peer_id = metadata.get("peer_id")
@@ -567,19 +614,9 @@ def main() -> None:
567
614
  metadata.get("browser_bootstrap_multiaddrs") or [], browser_only=True
568
615
  )
569
616
 
570
- publisher_address = address_from_private_key(publisher_private_key)
571
- now_ms = int(time.time() * 1000)
572
617
  now_seconds = now_ms / 1000
573
618
  profile = env_values.get("ALEPH_BOOTSTRAP_PROFILE", DEFAULT_PROFILE).strip() or DEFAULT_PROFILE
574
619
  version = env_values.get("ALEPH_BOOTSTRAP_VERSION", "").strip() or None
575
- channel = env_values.get("ALEPH_BOOTSTRAP_CHANNEL", DEFAULT_CHANNEL).strip() or DEFAULT_CHANNEL
576
- ref = env_values.get("ALEPH_BOOTSTRAP_REF", DEFAULT_REF).strip() or DEFAULT_REF
577
- post_type = env_values.get("ALEPH_BOOTSTRAP_POST_TYPE", POST_TYPE).strip() or POST_TYPE
578
- if post_type != POST_TYPE:
579
- raise RuntimeError(
580
- f"Unsupported ALEPH_BOOTSTRAP_POST_TYPE: {post_type}. Expected {POST_TYPE}."
581
- )
582
- api_host = env_values.get("ALEPH_BOOTSTRAP_API_HOST", DEFAULT_API_HOST).strip() or DEFAULT_API_HOST
583
620
  published_multiaddrs = select_compact_multiaddrs(browser_multiaddrs or multiaddrs)
584
621
  published_browser_multiaddrs: list[str] = []
585
622
  if not published_multiaddrs:
@@ -15,6 +15,8 @@ CADDY_UPSTREAM_HOST="${CADDY_UPSTREAM_HOST:-127.0.0.1}"
15
15
  CADDY_UPSTREAM_METRICS_PORT="${CADDY_UPSTREAM_METRICS_PORT:-9090}"
16
16
  AUTOTLS_REFRESH_SERVICE="${AUTOTLS_REFRESH_SERVICE:-orbitdb-relay-autotls-refresh.service}"
17
17
  BOOTSTRAP_REFRESH_TIMER="${BOOTSTRAP_REFRESH_TIMER:-orbitdb-relay-bootstrap-refresh.timer}"
18
+ BOOTSTRAP_REFRESH_SERVICE="${BOOTSTRAP_REFRESH_SERVICE:-orbitdb-relay-bootstrap-refresh.service}"
19
+ BOOTSTRAP_DEREGISTER_SERVICE="${BOOTSTRAP_DEREGISTER_SERVICE:-orbitdb-relay-bootstrap-deregister.service}"
18
20
  PUBLIC_IPV4=""
19
21
  PUBLIC_IPV6=""
20
22
  TCP_PORT=""
@@ -278,7 +280,10 @@ if [ "${START_SERVICE}" -eq 1 ]; then
278
280
  systemctl restart "${SERVICE_NAME}"
279
281
  systemctl enable "${AUTOTLS_REFRESH_SERVICE}"
280
282
  systemctl enable "${BOOTSTRAP_REFRESH_TIMER}"
283
+ systemctl enable "${BOOTSTRAP_DEREGISTER_SERVICE}"
284
+ systemctl restart "${BOOTSTRAP_DEREGISTER_SERVICE}"
281
285
  systemctl start "${BOOTSTRAP_REFRESH_TIMER}"
286
+ systemctl restart --no-block "${BOOTSTRAP_REFRESH_SERVICE}" || true
282
287
  if [ -n "${PROXY_HOSTNAME}" ]; then
283
288
  write_caddyfile "${PROXY_HOSTNAME}"
284
289
  touch "${CADDY_READY_FILE}"
@@ -0,0 +1,21 @@
1
+ # Playwright runner RootFS
2
+
3
+ This profile prebakes Node.js 24, Playwright `1.61.1`, its matching Chromium
4
+ headless shell, Caddy, and systemd units. It intentionally contains no endpoint
5
+ credential or TLS private key. The full headed Chromium bundle is omitted
6
+ because this remote CI runner only launches headless browsers.
7
+
8
+ After Aleph allocates the VM, the reusable action must inject:
9
+
10
+ - `/etc/default/playwright-runner` with `PLAYWRIGHT_RUNNER_SECRET` and the exact
11
+ `PLAYWRIGHT_VERSION=1.61.1`;
12
+ - a per-run certificate and key readable by the dedicated proxy service;
13
+ - the requested TTL override, if shorter than the default 45 minutes.
14
+
15
+ The bootstrap unit refuses to start the browser and proxy until those files are
16
+ present. Caddy protects `/version` and the websocket upgrade with the same
17
+ Bearer credential. The Playwright server only listens on `127.0.0.1:3000`.
18
+
19
+ The TTL is a last-resort shutdown, not authoritative Aleph cleanup. The owner
20
+ must still erase and FORGET the exact INSTANCE and verify scheduler
21
+ deallocation.
@@ -0,0 +1,40 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "id": "playwright-runner",
4
+ "displayName": "Ephemeral Playwright Chromium Runner",
5
+ "source": {
6
+ "repository": "NiKrause/relay-button",
7
+ "subdirectory": "packages/rootfs/reference/playwright-runner"
8
+ },
9
+ "rootfs": {
10
+ "profile": "playwright-runner",
11
+ "installMode": "prebaked",
12
+ "installDir": "/opt/playwright-runner",
13
+ "binaryPath": "/opt/playwright-runner/node_modules/.bin/playwright",
14
+ "dataDir": "/var/lib/playwright-runner",
15
+ "envFile": "/etc/default/playwright-runner"
16
+ },
17
+ "services": {
18
+ "bootstrap": "playwright-runner-bootstrap.service",
19
+ "main": "playwright-runner.service",
20
+ "autotlsRefresh": "playwright-runner-ttl.timer"
21
+ },
22
+ "ports": [
23
+ {
24
+ "port": 22,
25
+ "tcp": true,
26
+ "udp": false,
27
+ "purpose": "SSH bootstrap and diagnostics"
28
+ },
29
+ {
30
+ "port": 443,
31
+ "tcp": true,
32
+ "udp": false,
33
+ "purpose": "Authenticated Playwright WSS and version endpoint"
34
+ }
35
+ ],
36
+ "manifest": {
37
+ "copyTarget": "packages/rootfs/reference/playwright-runner/latest.json",
38
+ "notes": "Node.js 24 and Playwright 1.61.1 with matching Chromium are prebaked. A random bearer secret and per-run TLS material must be injected after boot. The image contains no reusable credential and shuts down through a bounded TTL timer."
39
+ }
40
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ admin off
3
+ auto_https disable_redirects
4
+ }
5
+
6
+ :443 {
7
+ tls /etc/playwright-runner/tls.crt /etc/playwright-runner/tls.key
8
+
9
+ @unauthorized not header Authorization "Bearer {$PLAYWRIGHT_RUNNER_SECRET}"
10
+ respond @unauthorized 401
11
+
12
+ handle /version {
13
+ header Content-Type application/json
14
+ respond `{"playwrightVersion":"{$PLAYWRIGHT_VERSION}"}` 200
15
+ }
16
+
17
+ reverse_proxy 127.0.0.1:3000
18
+ }
@@ -0,0 +1,16 @@
1
+ FROM debian:12
2
+
3
+ ENV DEBIAN_FRONTEND=noninteractive
4
+ ENV LIBGUESTFS_BACKEND=direct
5
+
6
+ RUN apt-get update \
7
+ && apt-get install -y --no-install-recommends \
8
+ ca-certificates \
9
+ curl \
10
+ libguestfs-tools \
11
+ linux-image-amd64 \
12
+ qemu-system-x86 \
13
+ qemu-utils \
14
+ && rm -rf /var/lib/apt/lists/*
15
+
16
+ WORKDIR /workspace/shared-rootfs
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ OUT_DIR="${OUT_DIR:-${SCRIPT_DIR}/../dist-rootfs}"
6
+ BASE_URL="${BASE_URL:-https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2}"
7
+ BASE_IMAGE="${OUT_DIR}/debian-12-genericcloud-amd64.qcow2"
8
+ IMAGE="${OUT_DIR}/aleph-playwright-runner.qcow2"
9
+ ROOTFS_IMAGE_SIZE="${ROOTFS_IMAGE_SIZE:-20G}"
10
+ PLAYWRIGHT_VERSION="${PLAYWRIGHT_VERSION:-1.61.1}"
11
+ HOST_UID="${HOST_UID:-}"
12
+ HOST_GID="${HOST_GID:-}"
13
+ ROOTFS_SPARSIFY_TMPDIR=""
14
+
15
+ require() {
16
+ command -v "$1" >/dev/null 2>&1 || { echo "Missing required command: $1" >&2; exit 1; }
17
+ }
18
+
19
+ for command in curl qemu-img virt-customize; do require "${command}"; done
20
+ test "${PLAYWRIGHT_VERSION}" = "1.61.1" || {
21
+ echo "playwright-runner only supports Playwright 1.61.1" >&2
22
+ exit 1
23
+ }
24
+
25
+ cleanup() {
26
+ if [ -n "${ROOTFS_SPARSIFY_TMPDIR}" ] && [ -d "${ROOTFS_SPARSIFY_TMPDIR}" ]; then
27
+ rm -rf "${ROOTFS_SPARSIFY_TMPDIR}"
28
+ fi
29
+ }
30
+ trap cleanup EXIT
31
+
32
+ mkdir -p "${OUT_DIR}"
33
+ if [ ! -f "${BASE_IMAGE}" ]; then
34
+ curl --fail --show-error --location --retry 5 --retry-all-errors \
35
+ --connect-timeout 20 --max-time 300 "${BASE_URL}" -o "${BASE_IMAGE}"
36
+ fi
37
+
38
+ cp "${BASE_IMAGE}" "${IMAGE}"
39
+ qemu-img resize "${IMAGE}" "${ROOTFS_IMAGE_SIZE}"
40
+
41
+ virt-customize \
42
+ -a "${IMAGE}" \
43
+ --network \
44
+ --mkdir /opt/playwright-runner \
45
+ --mkdir /opt/playwright-browsers \
46
+ --mkdir /etc/playwright-runner \
47
+ --mkdir /etc/systemd/journald.conf.d \
48
+ --mkdir /var/lib/playwright-runner \
49
+ --copy-in "${SCRIPT_DIR}/Caddyfile:/etc/playwright-runner" \
50
+ --copy-in "${SCRIPT_DIR}/playwright-runner-bootstrap.sh:/usr/local/sbin" \
51
+ --copy-in "${SCRIPT_DIR}/playwright-runner.service:/etc/systemd/system" \
52
+ --copy-in "${SCRIPT_DIR}/playwright-runner-proxy.service:/etc/systemd/system" \
53
+ --copy-in "${SCRIPT_DIR}/playwright-runner-bootstrap.service:/etc/systemd/system" \
54
+ --copy-in "${SCRIPT_DIR}/playwright-runner-ttl.service:/etc/systemd/system" \
55
+ --copy-in "${SCRIPT_DIR}/playwright-runner-ttl.timer:/etc/systemd/system" \
56
+ --run-command "apt-get update && apt-get install -y --no-install-recommends ca-certificates caddy curl gnupg" \
57
+ --run-command "curl -fsSL https://deb.nodesource.com/setup_24.x | bash -" \
58
+ --run-command "apt-get install -y --no-install-recommends nodejs" \
59
+ --run-command "useradd --system --home /var/lib/playwright-runner --shell /usr/sbin/nologin playwright-runner" \
60
+ --run-command "useradd --system --home /var/lib/playwright-runner --shell /usr/sbin/nologin playwright-proxy" \
61
+ --run-command "cd /opt/playwright-runner && npm init -y && npm install --omit=dev --no-audit --no-fund playwright@${PLAYWRIGHT_VERSION}" \
62
+ --run-command "cd /opt/playwright-runner && PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers ./node_modules/.bin/playwright install --with-deps --only-shell chromium" \
63
+ --run-command "chown -R playwright-runner:playwright-runner /opt/playwright-runner /opt/playwright-browsers /var/lib/playwright-runner" \
64
+ --run-command "chown -R root:playwright-proxy /etc/playwright-runner && chmod 0750 /etc/playwright-runner" \
65
+ --run-command "chmod 0755 /usr/local/sbin/playwright-runner-bootstrap.sh" \
66
+ --run-command "printf '[Journal]\\nSystemMaxUse=128M\\nRuntimeMaxUse=64M\\nMaxRetentionSec=2day\\n' >/etc/systemd/journald.conf.d/playwright-runner.conf" \
67
+ --run-command "npm cache clean --force" \
68
+ --run-command "apt-get clean && rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* /root/.npm /tmp/* /var/tmp/*" \
69
+ --run-command "systemctl enable playwright-runner-bootstrap.service"
70
+
71
+ if command -v virt-sparsify >/dev/null 2>&1; then
72
+ SPARSE_IMAGE="${IMAGE%.qcow2}.sparse.qcow2"
73
+ ROOTFS_SPARSIFY_TMPDIR="$(mktemp -d "${OUT_DIR}/virt-sparsify-tmp.XXXXXX")"
74
+ TMPDIR="${ROOTFS_SPARSIFY_TMPDIR}" virt-sparsify --check-tmpdir=continue --compress \
75
+ "${IMAGE}" "${SPARSE_IMAGE}"
76
+ mv "${SPARSE_IMAGE}" "${IMAGE}"
77
+ fi
78
+
79
+ if [ -n "${HOST_UID}" ] && [ -n "${HOST_GID}" ]; then
80
+ chown -R "${HOST_UID}:${HOST_GID}" "${OUT_DIR}"
81
+ fi
82
+
83
+ echo "Compressed RootFS size: $(stat -c '%s bytes' "${IMAGE}") ($(du -h "${IMAGE}" | cut -f1) on disk)"
84
+ echo "Playwright ${PLAYWRIGHT_VERSION} RootFS ready: ${IMAGE}"
@@ -0,0 +1,13 @@
1
+ [Unit]
2
+ Description=Validate and start the injected Playwright runner configuration
3
+ After=network-online.target
4
+ Wants=network-online.target
5
+ ConditionPathExists=/etc/default/playwright-runner
6
+
7
+ [Service]
8
+ Type=oneshot
9
+ ExecStart=/usr/local/sbin/playwright-runner-bootstrap.sh
10
+ RemainAfterExit=yes
11
+
12
+ [Install]
13
+ WantedBy=multi-user.target
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ENV_FILE=/etc/default/playwright-runner
5
+ TLS_CERT=/etc/playwright-runner/tls.crt
6
+ TLS_KEY=/etc/playwright-runner/tls.key
7
+
8
+ test -s "${ENV_FILE}"
9
+ test -s "${TLS_CERT}"
10
+ test -s "${TLS_KEY}"
11
+
12
+ set -a
13
+ # shellcheck disable=SC1090
14
+ source "${ENV_FILE}"
15
+ set +a
16
+
17
+ test "${PLAYWRIGHT_VERSION:-}" = "1.61.1"
18
+ test -n "${PLAYWRIGHT_RUNNER_SECRET:-}"
19
+
20
+ chown root:playwright-proxy "${TLS_CERT}" "${TLS_KEY}"
21
+ chmod 0644 "${TLS_CERT}"
22
+ chmod 0640 "${TLS_KEY}"
23
+
24
+ systemctl restart playwright-runner.service
25
+ systemctl restart playwright-runner-proxy.service
26
+ systemctl restart playwright-runner-ttl.timer
@@ -0,0 +1,28 @@
1
+ [Unit]
2
+ Description=Authenticated TLS proxy for the Playwright runner
3
+ After=network-online.target playwright-runner.service
4
+ Requires=playwright-runner.service
5
+ ConditionPathExists=/etc/default/playwright-runner
6
+ ConditionPathExists=/etc/playwright-runner/tls.crt
7
+ ConditionPathExists=/etc/playwright-runner/tls.key
8
+
9
+ [Service]
10
+ Type=simple
11
+ User=playwright-proxy
12
+ Group=playwright-proxy
13
+ EnvironmentFile=/etc/default/playwright-runner
14
+ ExecStart=/usr/bin/caddy run --config /etc/playwright-runner/Caddyfile --adapter caddyfile
15
+ ExecReload=/usr/bin/caddy reload --config /etc/playwright-runner/Caddyfile --adapter caddyfile
16
+ Restart=on-failure
17
+ RestartSec=2
18
+ NoNewPrivileges=true
19
+ PrivateTmp=true
20
+ ProtectSystem=strict
21
+ ProtectHome=true
22
+ AmbientCapabilities=CAP_NET_BIND_SERVICE
23
+ CapabilityBoundingSet=CAP_NET_BIND_SERVICE
24
+ StandardOutput=journal
25
+ StandardError=journal
26
+
27
+ [Install]
28
+ WantedBy=multi-user.target
@@ -0,0 +1,6 @@
1
+ [Unit]
2
+ Description=Stop an expired ephemeral Playwright runner
3
+
4
+ [Service]
5
+ Type=oneshot
6
+ ExecStart=/usr/bin/systemctl poweroff
@@ -0,0 +1,10 @@
1
+ [Unit]
2
+ Description=Maximum lifetime for an ephemeral Playwright runner
3
+
4
+ [Timer]
5
+ OnActiveSec=45min
6
+ AccuracySec=1min
7
+ Unit=playwright-runner-ttl.service
8
+
9
+ [Install]
10
+ WantedBy=timers.target
@@ -0,0 +1,26 @@
1
+ [Unit]
2
+ Description=Ephemeral Playwright 1.61.1 browser server
3
+ After=network-online.target
4
+ Wants=network-online.target
5
+ ConditionPathExists=/etc/default/playwright-runner
6
+
7
+ [Service]
8
+ Type=simple
9
+ User=playwright-runner
10
+ Group=playwright-runner
11
+ EnvironmentFile=/etc/default/playwright-runner
12
+ Environment=PLAYWRIGHT_BROWSERS_PATH=/opt/playwright-browsers
13
+ WorkingDirectory=/opt/playwright-runner
14
+ ExecStart=/opt/playwright-runner/node_modules/.bin/playwright run-server --host 127.0.0.1 --port 3000
15
+ Restart=on-failure
16
+ RestartSec=2
17
+ NoNewPrivileges=true
18
+ PrivateTmp=true
19
+ ProtectSystem=strict
20
+ ProtectHome=true
21
+ ReadWritePaths=/var/lib/playwright-runner
22
+ StandardOutput=journal
23
+ StandardError=journal
24
+
25
+ [Install]
26
+ WantedBy=multi-user.target
@@ -1,6 +1,6 @@
1
1
  [Unit]
2
2
  Description=Best-effort Aleph bootstrap deregistration on shutdown for uc-go-peer
3
- After=network-online.target
3
+ After=network-online.target uc-go-peer.service
4
4
  Wants=network-online.target
5
5
  ConditionPathExists=/etc/default/uc-go-peer.ready
6
6