Debian Wrapper Build Environment (Monorepo) https://kioskos.io
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-04 19:17:31 -04:00
control@0f7ddeae55 v2.1.0 2026-08-04 19:17:31 -04:00
debian v2.1.0 2026-08-04 19:17:31 -04:00
docs v2.1.0 2026-08-04 19:17:31 -04:00
kiosk@5f4d221ffa v2.1.0 2026-08-04 19:17:31 -04:00
.env.example kios 2026-07-25 18:29:08 -04:00
.gitignore Debian attempt, submodule kiosk and control 2026-05-22 20:51:03 -04:00
.gitmodules Debian attempt, submodule kiosk and control 2026-05-22 20:51:03 -04:00
LICENSE Debian attempt, submodule kiosk and control 2026-05-22 20:51:03 -04:00
README.md kios 2026-07-25 18:29:08 -04:00

KioskOS

A minimal Linux distribution that boots directly into a web browser kiosk mode, managed centrally via a Django control server. Supports x86_64 (PCs, VMs) and ARM64 (Raspberry Pi 4/5) platforms. Ships as a bootable ISO built from Debian Bookworm.

[Download] <> [License] <> [AI Involvement Disclosure]


Features

  • Bootable ISO built from Debian Bookworm via Docker + debootstrap + xorriso
  • Full-screen Chromium kiosk mode — XFCE4 autostart launches Chromium in kiosk mode
  • Direct X session — autologin on tty1 → startx → XFCE4 (no display manager)
  • Centralized management via Django control server with REST API
  • Zero-touch deployment — pre-load config.json on USB to skip setup wizard
  • WiFi/LAN configuration via interactive setup wizard on first boot (or pre-configured)
  • Remote configuration updates — change target URL, refresh intervals, and more
  • System monitoring — uptime, memory, and disk usage reported to the control server
  • Multi-architecture support — x86_64 (PCs, VMs) and ARM64 (Raspberry Pi 4/5)
  • Hybrid BIOS + UEFI boot (amd64) / UEFI boot (aarch64)
  • Docker-based control server deployment with PostgreSQL and Nginx
  • REST API for full kiosk lifecycle management
  • Administrator-issued enrollment — a one-time code binds each device to a kiosk an admin created (2.0.0; devices no longer self-register)
  • Install option — Calamares installer included on the ISO for permanent installation

Architecture Overview

KioskOS consists of three main components that work together:

Component Directory Description
Control Server control/ Django + Django REST Framework API server
Kiosk Agent kiosk/ Python agent running on each kiosk device
Build System debian/ Debian-based bootable ISO builder

For a detailed architecture diagram and data flow, see docs/ARCHITECTURE.md.


Quick Start

1. Control Server Setup

# Clone the repository
git clone https://github.com/your-org/kioskOS.git
cd kioskOS

# Configure environment
cp .env.example control/.env
# Edit control/.env with your settings

# Start the server stack (PostgreSQL + Django + Nginx)
cd control
docker-compose up -d

# Create an admin user
docker-compose exec server python manage.py createsuperuser

The control server will be available at http://localhost (Nginx on port 80).

2. Building the Kiosk ISO

Prerequisites: Docker Desktop (macOS/Linux) or Docker Engine (Linux), ~10 GB free disk, Make

cd debian

# Build x86_64 ISO (PCs, VMs)
make amd64

# Build ARM64 ISO (Raspberry Pi 4/5)
make aarch64

Output ISO: debian/output/kioskos-amd64.iso

Write ISO to USB:

# Linux
sudo dd if=output/kioskos-amd64.iso of=/dev/sdX bs=4M status=progress && sync

# macOS
diskutil list
diskutil unmountDisk /dev/diskN
sudo dd if=output/kioskos-amd64.iso of=/dev/rdiskN bs=4m

3. First Boot

  1. Write the ISO to a USB drive and boot from it.
  2. Two boot options are available: "Run KioskOS (Live)" and "Install KioskOS" (via Calamares).
  3. On live boot, the setup wizard appears automatically.
  4. Follow the dialog-based TUI to configure:
    • Network — WiFi SSID/passphrase or LAN
    • Server URL — address of your control server
    • Enrollment code — the one-time code an administrator issued for this kiosk
    • Target URL — the webpage to display in kiosk mode
  5. The device redeems the code, receives its token, and opens the browser in full-screen kiosk mode.

Project Structure

kioskOS/
├── control/          # Django control server (API + admin)
│   ├── api/          # REST API app (models, views, serializers)
│   ├── kioskos/      # Django project settings
│   ├── nginx/        # Nginx reverse-proxy config
│   ├── Dockerfile    # Server container image
│   └── docker-compose.yml
├── kiosk/            # Kiosk agent + setup scripts
│   ├── agent/        # Python agent (check-in, config, display control)
│   └── setup/        # First-boot setup wizard (dialog-based TUI)
├── debian/           # Debian-based OS build system (primary)
│   ├── docker/       # Docker build environments (amd64, aarch64)
│   ├── scripts/      # Provisioning, ISO creation, build orchestration
│   ├── configs/      # GRUB config, package list
│   ├── overlay/      # Root filesystem overlay
│   └── Makefile      # Build targets (amd64, aarch64, all)
├── docs/             # Documentation
└── README.md

Control Server

API Endpoints

All API endpoints are prefixed with /api/v1/.

Method Path Auth Description
POST /api/v1/register/ Enrollment code Redeem a one-time code for a device token
POST /api/v1/browser-grant/ Token Mint a single-use URL that gives the browser a device session
POST /api/v1/kiosks/{uid}/enrollment-code/ Admin Issue a fresh one-time enrollment code
POST /api/v1/checkin/ Kiosk Token Kiosk periodic check-in with system stats
GET /api/v1/config/ Kiosk Token Retrieve current kiosk configuration
GET /api/v1/kiosks/ Admin List all registered kiosks
GET /api/v1/kiosks/<uid>/ Admin Retrieve kiosk details
PATCH /api/v1/kiosks/<uid>/ Admin Update kiosk settings
GET /api/v1/kiosks/<uid>/events/ Admin Retrieve kiosk event history

Docker Deployment

The control server is deployed with Docker Compose (PostgreSQL + Gunicorn + Nginx):

cd control
cp .env.example .env          # Configure environment
docker-compose up -d           # Start all services
docker-compose exec server python manage.py createsuperuser  # Create admin

The admin panel is available at http://localhost/admin/.


Building Kiosk Images

Prerequisites

  • Docker Desktop (macOS/Linux) or Docker Engine (Linux)
  • ~10 GB free disk space
  • Make

Build Commands

cd debian

# Build x86_64 ISO (PCs, VMs) — hybrid BIOS + UEFI boot
make amd64

# Build ARM64 ISO (Raspberry Pi 4/5) — UEFI boot
make aarch64

# Clean build artifacts
make clean

How It Works

The build pipeline runs entirely inside Docker containers, so it works on macOS and Linux without native build dependencies. A build container is launched with the appropriate architecture (native for amd64, QEMU-emulated for aarch64), then the base system is bootstrapped via debootstrap. The rootfs is provisioned with kiosk packages and overlay files via chroot, packaged into a squashfs, and assembled into a bootable ISO with xorriso.

Output

  • debian/output/kioskos-amd64.iso — x86_64 bootable ISO (hybrid BIOS + UEFI)
  • debian/output/kioskos-aarch64.iso — ARM64 bootable ISO (UEFI)

Boot Options

The ISO provides two boot options via GRUB:

  • Run KioskOS (Live) — Boot directly into the live kiosk environment
  • Install KioskOS — Launch the Calamares graphical installer for permanent installation

Write ISO to USB

# Linux
sudo dd if=output/kioskos-amd64.iso of=/dev/sdX bs=4M status=progress && sync

# macOS
diskutil list
diskutil unmountDisk /dev/diskN
sudo dd if=output/kioskos-amd64.iso of=/dev/rdiskN bs=4m

Desktop / Display Stack

KioskOS uses a direct X session with no display manager:

  1. Autologin — The kiosk user is automatically logged in on tty1 via a systemd getty override
  2. X launch — .bash_profile detects VT1 and runs exec startx
  3. XFCE4 session — .xinitrc disables screen blanking and runs exec startxfce4
  4. Kiosk browser — XFCE4 autostart launches Chromium in full-screen kiosk mode

LightDM is masked and not used.


Kiosk Setup

First-Boot Setup Wizard

On first boot, the kiosk launches a dialog-based TUI setup wizard that guides you through:

  1. Network configuration — Connect to WiFi (SSID + passphrase) or use wired LAN
  2. Server URL — Enter the address of your control server (e.g., http://192.168.1.100)
  3. Enrollment code — The one-time code for this kiosk, e.g. ABCD-EFGH-JKLM. Dashes and letter case are ignored.
  4. Target URL — The webpage to display in kiosk mode (e.g., https://example.com/display)

Once complete, the device redeems the code with the control server and launches Chromium in full-screen kiosk mode.

Getting an Enrollment Code

Since 2.0.0 a device cannot register itself. Before setting up a device:

  1. In the control server, create the kiosk (name it after where it will live).
  2. The server shows a one-time code once — write it down or copy it.
  3. Type it into the setup wizard on the device.

Codes are single-use and expire after seven days. If one is lost or expires, issue a new one from the kiosk's row; that does not disturb any device already enrolled against it. To move a kiosk to replacement hardware, issue a fresh code and set up the new device — then regenerate the token to cut the old one off.

Zero-Touch Deployment (Pre-loaded Config)

For bulk deployments, you can skip the setup wizard entirely by pre-loading a config.json file onto the USB drive before booting the kiosk.

How It Works

  1. The ISO includes a small FAT32 partition labeled KIOSKOS-CONFIG
  2. On first boot, the kioskos-preload service searches for config.json on:
    • The KIOSKOS-CONFIG partition (recommended)
    • /boot/config.json or /boot/efi/config.json (boot/EFI partition)
    • /config.json (root filesystem)
  3. If a valid config is found, it is copied to /etc/kioskos/config.json, network settings are applied, and the setup wizard is skipped.

Preparing a USB Drive

The config partition works with the ISO image. A FAT32 config partition is automatically included during the build — just burn the ISO and drop config.json onto the partition.

Manual (any OS — macOS, Windows, Linux):

  1. Burn the KioskOS ISO to the USB drive
  2. The USB will show a small FAT32 volume named KIOSKOS-CONFIG
    • On macOS: it appears in Finder as a removable drive
    • On Windows: it appears in Explorer with its label
    • On Linux: it auto-mounts or use udisksctl mount -b /dev/sdX3
  3. Copy your config.json to the root of that partition
  4. Eject / unmount and boot the kiosk

Config File Format

The config.json must contain at least server_url, enrollment_code and target_url:

{
    "server_url": "https://control.example.com",
    "enrollment_code": "ABCD-EFGH-JKLM",
    "target_url": "https://display.example.com",
    "refresh_interval": 300,
    "checkin_interval": 60,
    "network": {
        "type": "wifi",
        "wifi_ssid": "MyNetwork",
        "wifi_password": "MyPassword"
    }
}

Network type can be dhcp, wifi, or static. For static IP, include static_ip (with CIDR), static_gateway, and static_dns in the network object.

Because enrollment codes are single-use, zero-touch deployment needs one code per device — a shared config.json will enroll the first device to boot and be rejected by the rest. The file also carries a credential: keep the USB drive with the same care as the device, and note that /etc/kioskos/config.json is written 0600 on the kiosk.

Re-Running Setup

To reconfigure a kiosk, SSH into the device (or connect a keyboard) and run:

sudo /opt/kioskos/setup/setup.sh

To force reconfiguration, remove the setup marker first:

sudo rm /etc/kioskos/.setup-complete
sudo systemctl restart kioskos-setup.service

Development

Running the Control Server Locally

cd control
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

The development server will be available at http://localhost:8000.

Running Tests

cd control
python manage.py test

Configuration

  • Control Server: Copy .env.example to control/.env and adjust values for your environment (database, secret key, CORS, etc.).
  • Kiosk Agent: See kiosk/config.json.example for the agent configuration format.

AI Involvement Disclosure

This project uses Kilocode and GLM-5 by Z.ai as part of the dev chain. All code generated by GLM-5 was manually reviewed by a human before deployment.

Documentation is still scrappy, AI generated in some places, and needs some review before considering it stable as well.

DO YOUR DUE DILIGENCE!!!! Validate this codebase before blindly trusting it with your production systems.


License

This project is licensed under the MIT License. See LICENSE for details.