Skip to main content

LapEE bundler quickstart

This guide gets a laptop online as a PermawebOS paid bundler node.

It uses the signed LapEE runtime image and the bundler profile.

What You Need

  • A target x86_64 UEFI laptop.
  • TPM 2.0.
  • The release-provided LapEE runtime image, hash, and signature material.
  • The release-provided LapEE provisioner image and instructions.
  • A local LapEE source checkout for the Makefile image helpers.
  • Docker Desktop or another Docker runtime.
  • jq for command-line JSON checks.
  • A USB stick for the runtime image.
  • The bundler profile.
  • Optional WiFi credentials if the laptop will not use Ethernet.

Use lapee-usb.img by default. Use the no-TME image only for hardware that cannot satisfy the memory-encryption gate.

1. Provision The Laptop

Run the LapEE provisioner on the target laptop before booting the runtime image. The provisioner prepares the firmware Secure Boot policy for the release key or exact UKI hash.

This is a firmware-owner action. Know how to recover the laptop firmware before changing Secure Boot policy.

2. Download and Verify The Runtime Image

Download a LapEE image here.

To verify, use the hash and signature material published with the release. For a SHA-256 file:

sha256sum -c lapee-usb.img.sha256

On macOS:

shasum -a 256 -c lapee-usb.img.sha256

Do not write an image whose release hash does not match.

3. Stage The Image

Run the remaining image commands from the LapEE source repo root. Put the verified image at the default path used by the Makefile helpers:

mkdir -p build/images
cp /path/to/lapee-usb.img build/images/lapee-usb.img

4. Prepare config.json

Copy the bundler profile to a local config.json beside the Makefile:

cp /path/to/lapee-bundler-devices/profile/lapee.json config.json

That profile enables remote device loading, pins the trusted device signer, maps the published Forge package IDs, and installs the paid-bundler startup hook.

Set bundler-beneficiary to your own address to receive AO tokens for bundling data.

If you have release-provided operator config to preserve, merge it first and the paid-bundler profile second:

jq -S -s '.[0] * .[1]' \
/path/to/release-config.json \
/path/to/lapee-bundler-devices/profile/lapee.json \
> config.json

Put release-image config first and the paid-bundler profile second. The profile wins when both define the same role key.

Do not put secrets in config.json. It is public operator config and appears in the measured node message.

5. Optional WiFi

If Ethernet is available, prefer Ethernet. If WiFi is needed, create wifi.conf beside the Makefile as exactly two lines:

SSID
WPA2-PSK

wifi.conf is plaintext secret material. Do not commit it.

6. Apply Operator Inputs

With Docker running, inject config.json and optional wifi.conf into the staged image:

make operator-config-apply IMAGE=build/images/lapee-usb.img

This uses the tooling container to edit the FAT ESP. It does not rebuild LapEE, and it does not rebuild or re-sign EFI/Boot/BootX64.efi.

After this step, build/images/lapee-usb.img contains any staged WiFi password. Do not share the modified image if it contains wifi.conf.

7. Write The USB

make write-image DEV=/dev/diskN IMAGE=build/images/lapee-usb.img

Use the whole removable disk, not a partition. On Linux this is usually /dev/sdX; on macOS it is usually /dev/diskN. The target device is erased.

8. Boot

Boot the target laptop from the prepared USB stick.

Expected behavior:

  • The splash appears.
  • Networking comes up.
  • PermawebOS starts on port 8734.
  • The splash shows a node URL and QR code.

If the splash appears stuck at Starting HyperBEAM, probe the node from another machine before assuming boot failed:

curl -fsS -H 'accept: application/json' \
http://<node-ip>:8734/~measurement@1.0/info

9. Smoke Check

Set the node URL from the splash:

export NODE_URL=http://<node-ip>:8734

Check the measured node and the paid-bundler profile:

curl -fsS -H 'accept: text/plain' "$NODE_URL/~meta@1.0/info/address"
curl -fsS -H 'accept: text/plain' "$NODE_URL/~meta@1.0/info/lapee-profile"
curl -fsS -H 'accept: text/plain' "$NODE_URL/~meta@1.0/info/load-remote-devices"
curl -fsS \
-H 'accept: application/json' \
-H 'accept-bundle: true' \
"$NODE_URL/~meta@1.0/info/trusted-device-signers" \
| jq '[to_entries[] | select(.key | test("^[0-9]+$")) | .value]'
curl -fsS \
-H 'accept: application/json' \
-H 'accept-bundle: true' \
"$NODE_URL/~measurement@1.0/boot" > boot-measurement.json
curl -fsS -H 'accept: application/json' "$NODE_URL/~tpm@2.0a/info"
curl -fsS -H 'accept: application/json' "$NODE_URL/~ao-payment@1.0/info"
curl -fsS -H 'accept: application/json' "$NODE_URL/~bundler-settlement@1.0/info"
curl -fsS -H 'accept: application/json' "$NODE_URL/~arweave-byte-pricing@1.0/quote?resource=arweave-bytes&amount=1"
curl -fsS -H 'accept: text/html' "$NODE_URL/~hyperbuddy@1.0/index" >/dev/null

Expected profile value:

aopayment-bundler

Use explicit accept headers for machine-readable checks. Browser requests may open HyperBuddy or HTML views.

trusted-device-signers is an AO json@1.0 list, encoded as numeric object keys such as "1", "2", and so on. The jq filter above renders the plain JSON signer array.

Public Reachability

Public reachability is external routing, not config.json: DNS, a tunnel, router port forwarding, or a reverse proxy must point at the node HTTP port. Clients and dashboards still need to health-check the public URL.