Lab Kiosk OS & Edge SaaS

Quickstart

Run the whole platform — control plane and a simulated user workstation — on one machine in about five minutes. No thin clients, no Cloudflare account, no ISO build.

Prerequisites

  • Node.js v22 or newer. The test suite uses Node's native node:sqlite, which is not available earlier.
  • pnpm v9 or newer (npm install -g pnpm).
  • A rootful Docker-compatible engine with Compose v2, for the workstation simulator.

1. Start the control plane

cd cloudflare-control
pnpm install

# Local secrets. With a D1 binding present the worker refuses to seed a default
# super admin, so this step is required rather than optional.
cp .dev.vars.example .dev.vars

Edit .dev.vars:

SUPER_ADMIN_EMAIL=admin@labkiosk.local
SUPER_ADMIN_PASSWORD=LocalDevPassword123!

Then:

pnpm dev

predev runs wrangler d1 migrations apply labkiosk-db --local first, applying every file in migrations/ to the local D1 store under .wrangler/state/v3/d1. The worker will not serve a database whose migrations are missing.

The platform is now on http://localhost:8787:

SurfaceURL
Public landing pagehttp://localhost:8787/
User Portalhttp://localhost:8787/home?tenant=docker-demo
Operator Consolehttp://localhost:8787/admin?tenant=docker-demo
Super Admin consolehttp://localhost:8787/super

The ?tenant= override works here only because localhost is a recognised development host. In production the Host header is the sole authority — see Architecture Overview.


2. Create an organization

The worker creates three demo organizations at startup, one per way of testing: web-demo (the hosted site), local-demo (a local VM) and docker-demo (the Docker simulator). They are the only organizations the super admin may open.

  1. Sign in to http://localhost:8787/super with the credentials from .dev.vars.
  2. Open Console on docker-demo (this guide uses the Docker simulator; a local VM uses local-demo).
  3. Go to Settings → Workstation Enrollment Key and copy the key.

To try an ordinary organization instead, register one at http://localhost:8787/, then approve it under Tasks in /super (mark the phone verified first). Locally no email is sent: each message, including the registration code in its subject, is printed in the dev server's log. The demo names and demo itself are reserved.


3. Launch the workstation simulator

From the repository root:

docker compose up -d

Compose builds the simulator image from your working tree and tags it ghcr.io/akbhoi/labkiosk:latest. To skip the build and use the published image instead:

docker compose pull && docker compose up -d

The image bakes the client source in, so a pulled image runs main's client code rather than your edits. While working on agent.py or the extension, use docker compose up -d --build, or push files into the running container — see Workstation Simulator.

Open the simulated screen:

http://localhost:6080/vnc.html

The VNC password is random per container and printed in docker compose logs. You should see the thin-client desktop showing the first-boot setup wizard.


4. Enrol the workstation

In the noVNC window — not your host browser; the agent's API is loopback-only and the wizard is served from inside the container:

FieldValue
Organization subdomaindocker-demo
Workstation identifierPC-01
Enrollment keythe key from step 2

Click Connect & Register Workstation. Under the hood:

  1. The agent posts to http://host.docker.internal:8787/api/devices/enroll.
  2. The worker validates the key and returns a persistent device bearer token plus the organization's portal URL.
  3. The agent writes /etc/labkiosk/config.json (mode 0600) with the token, the worker URL, and the target URL.
  4. The agent writes the organization's allowlist into /etc/chromium/policies/managed/policies.json.
  5. Because Chromium reads managed policy only at startup, the agent sets pendingBrowserRestart and the watchdog relaunches the browser once — otherwise the freshly enrolled kiosk would sit on a "This page is blocked" screen.

Within three seconds PC-01 appears on the Admin console with a live thumbnail.


5. Try the operator controls

From http://localhost:8787/admin?tenant=docker-demo:

  • Lock all screens — a full-screen curtain appears in the simulator with your message.
  • Broadcast a URL — every workstation navigates there at once and stays there.
  • Reset to portal — clears the broadcast and returns the lab to the launcher.
  • Add a portal app — the card shows up on the user portal, and its host is added to the effective allowlist automatically.

→ Admin Console Guide for what each control actually does.


6. Run the checks

# Strict typecheck: src/ against Workers types, test/ against Node types
pnpm --prefix cloudflare-control run typecheck

# Integration and security suite
pnpm --prefix cloudflare-control test

Both must be clean before any change is committed. → Testing Guide


Teardown

docker compose down -v

-v discards the container's volumes, resetting the simulator to an un-enrolled first-boot state. All ephemeral state — browser profile, session cache, VNC secret — lives in /tmp and vanishes with the container.


Where to go next

GoalPage
Understand what you just ranArchitecture Overview
Build a real bootable ISOBuilding the ISO
Install onto real hardwareInstallation Guide
Deploy to Cloudflare for realProduction Deployment
Something did not workTroubleshooting

This page is wiki/Quickstart.md in the repository.