@le-space/rootfs 0.6.28 → 0.6.29
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 +4 -0
- package/index.d.ts +1 -0
- package/index.js +6 -0
- package/package.json +1 -1
- package/reference/playwright-runner/README.md +21 -0
- package/reference/playwright-runner/contract.json +40 -0
- package/reference/playwright-runner/rootfs/Caddyfile +18 -0
- package/reference/playwright-runner/rootfs/Dockerfile.rootfs +16 -0
- package/reference/playwright-runner/rootfs/build-rootfs-image.sh +84 -0
- package/reference/playwright-runner/rootfs/playwright-runner-bootstrap.service +13 -0
- package/reference/playwright-runner/rootfs/playwright-runner-bootstrap.sh +26 -0
- package/reference/playwright-runner/rootfs/playwright-runner-proxy.service +28 -0
- package/reference/playwright-runner/rootfs/playwright-runner-ttl.service +6 -0
- package/reference/playwright-runner/rootfs/playwright-runner-ttl.timer +10 -0
- package/reference/playwright-runner/rootfs/playwright-runner.service +26 -0
- package/reference/uc-go-peer/rootfs/__pycache__/uc-go-peer-describe.cpython-312.pyc +0 -0
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
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
|
@@ -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,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
|