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:
| Surface | URL |
|---|---|
| Public landing page | http://localhost:8787/ |
| User Portal | http://localhost:8787/home?tenant=docker-demo |
| Operator Console | http://localhost:8787/admin?tenant=docker-demo |
| Super Admin console | http://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.
- Sign in to
http://localhost:8787/superwith the credentials from.dev.vars. - Open Console on
docker-demo(this guide uses the Docker simulator; a local VM useslocal-demo). - 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 onagent.pyor the extension, usedocker 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:
| Field | Value |
|---|---|
| Organization subdomain | docker-demo |
| Workstation identifier | PC-01 |
| Enrollment key | the key from step 2 |
Click Connect & Register Workstation. Under the hood:
- The agent posts to
http://host.docker.internal:8787/api/devices/enroll. - The worker validates the key and returns a persistent device bearer token plus the organization's portal URL.
- The agent writes
/etc/labkiosk/config.json(mode0600) with the token, the worker URL, and the target URL. - The agent writes the organization's allowlist into
/etc/chromium/policies/managed/policies.json. - Because Chromium reads managed policy only at startup, the agent sets
pendingBrowserRestartand 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
| Goal | Page |
|---|---|
| Understand what you just ran | Architecture Overview |
| Build a real bootable ISO | Building the ISO |
| Install onto real hardware | Installation Guide |
| Deploy to Cloudflare for real | Production Deployment |
| Something did not work | Troubleshooting |