• v2.1.0 b9a5f8ada6

    v2.1.0 Stable

    kaisa released this 2026-08-04 23:17:31 +00:00 | 0 commits to main since this release

    Highlights

    • Remote shell jobs — administrators can queue arbitrary shell commands
      (or one-click presets) against a kiosk from the admin UI; the device runs
      them as root and reports back the exit code and output. Off by default,
      per device.
    • Touchscreens now follow screen rotation — touch input is re-mapped
      with xinput map-to-output after every rotation, at cold boot, and when
      a USB touchscreen reconnects.
    • Agent startup crash fixed — the 2.0.0 agent could crash on launch
      with "'http' is not a package" due to a sys.path shadowing bug.
    • Image fixes for real-world hardware — NTP time sync for devices with
      dead RTC batteries, and AMD GPU firmware so rotation works on AMD APUs.

    No breaking changes. 2.0.0 agents keep working against a 2.1.0 server —
    they simply ignore the new jobs field in check-in responses. Remote shell
    jobs require a 2.1.0 agent and an explicit per-kiosk opt-in.

    Upgrading already-deployed kiosks: the agent package now depends on
    xinput and x11-xserver-utils, so apt install --only-upgrade kioskos-agent pulls the touch-mapping tools onto devices imaged before they
    were in the ISO. For the image-level fixes (time sync, AMD firmware) run the
    one-shot scripts/hotfix-amd-firmware-timesync.sh
    on each device — idempotent, and it reboots only when the GPU fix requires it.


    Control (Django control server)

    Remote shell jobs

    • New KioskJob model and full job lifecycle: pending → running → succeeded / failed / timed_out, plus cancelled (before delivery),
      expired (not delivered within the 1-hour TTL — a device unplugged for a
      fortnight must not come back and run last month's upgrade), and lost
      (delivered but no result within timeout + grace, e.g. the command rebooted
      the device).
    • Jobs are pulled, not pushed: the server holds them until the device's
      next check-in, so the feature works for kiosks behind NAT on customer
      networks. Delivery latency is bounded by the check-in interval.
    • Each job is handed out exactly once — rows are claimed with a
      compare-and-swap on status, so two racing check-ins cannot both be told
      to run the same command. Up to 5 jobs are delivered per check-in.
    • Named presets for routine fleet operations: update all packages,
      upgrade the agent, restart the agent, reboot, report disk usage, tail the
      agent journal. reboot and restart_agent detach and delay so the job
      can report success before taking the agent down with it.
    • Off by default: a new per-kiosk shell_enabled flag gates both
      queueing and delivery. The agent runs jobs as root, so the capability is
      granted deliberately per device, never fleet-wide.
    • Kiosk detail page grew a shell job panel: queue a preset or a custom
      command, watch status, and read captured stdout/stderr; jobs not yet
      delivered can be cancelled.
    • Expired/lost transitions are applied lazily on the check-in and job-list
      paths — the deployment has no worker process, and check-in is the only
      clock the server can rely on.
    • Every queue, delivery, and completion is recorded as a KioskEvent
      (new job event type), so the audit trail shows what ran where, who
      asked for it, and how it ended. The created_by admin is kept even if
      the account is later deleted.
    • Output is truncated server-side at 64 kB per stream (keeping the tail,
      where failures explain themselves) as a backstop behind the agent's own
      32 kB cap.
    • Test suite extended with full coverage of queueing, claiming, result
      reporting, cancellation, expiry/lost reaping, and permission boundaries.

    KioskOS Agent (kioskos-agent 2.1.0)

    Remote shell jobs

    • New agent/shell.py job runner: jobs execute on a dedicated worker
      thread, one at a time — a ten-minute package upgrade must not freeze the
      check-in loop, which is also the dead-browser watchdog; serial execution
      keeps two apt runs from fighting over the dpkg lock.
    • Commands run via bash -c in their own process group (a timeout
      SIGTERMs, then SIGKILLs the whole tree, not just the shell), with stdin
      closed (anything that prompts fails fast instead of hanging) and a fixed
      environment (DEBIAN_FRONTEND=noninteractive, sane PATH,
      LC_ALL=C.UTF-8).
    • Captured output is capped at 32 kB per stream, keeping the tail.
    • Results that cannot be posted (device offline) are held and retried
      on later check-ins, bounded to the 50 most recent.
    • Device-side veto: a new shell_enabled key in
      /etc/kioskos/config.json (default true) lets an operator mark a
      device as never accepting remote commands regardless of what the control
      server says; refused jobs report exit code 126 so the admin sees a reason
      instead of a job that silently never finishes.
    • On shutdown the runner stops taking new jobs but lets a running job
      finish — interrupting an upgrade mid-dpkg would be worse than losing
      the result. New test module tests/test_shell.py.

    Touchscreen rotation (2.0.1)

    • Fixed touch input staying in the panel's native orientation after screen
      rotation: set_orientation() now re-maps every calibratable touch device
      onto the rotated output via xinput map-to-output. Touch devices are
      identified by the libinput Calibration Matrix property, so mice and
      other relative pointers are never affected.
    • The agent package now depends on xinput and x11-xserver-utils — the
      tools display.py actually shells out to — so upgrading the package
      pulls them onto devices imaged before they were added to the ISO.

    Startup crash & self-update fixes (2.0.2)

    • Fixed an agent crash on startup (No module named 'http.client'; 'http' is not a package): the service ran with
      WorkingDirectory=/opt/kioskos/agent, and python -m puts the working
      directory first on sys.path, so the agent's own http.py shadowed the
      stdlib http package that requests imports. The service now runs from
      /opt/kioskos and sets PYTHONSAFEPATH=1 so the working directory can
      never leak onto sys.path again.
    • Self-update now refreshes all apt sources instead of only the kioskos
      repo — dependencies introduced by a new agent version come from the
      Debian repos, which ISO-imaged devices have no cached lists for — and
      tolerates a skewed clock during the refresh (dead RTC batteries make apt
      reject Release files as "not valid yet").

    Multi-display & cold-boot touch mapping (2.0.3)

    • Touch devices are no longer all mapped to the primary output: one display
      gets every touch device (the common kiosk); equal counts of touch devices
      and displays are paired deterministically (device IDs ascending, outputs
      left-to-right); a count mismatch falls back to the primary output with a
      warning. Mirrored layouts share one rectangle, so any pairing is correct
      there.
    • Fixed touch mapping not applied on cold boot: the agent rotates the
      screen as soon as the X socket exists — before Xorg has enumerated input
      devices via udev — so there was nothing to map yet. A startup thread now
      polls for touch devices and maps them as soon as they appear, and the
      check-in loop re-applies mappings every cycle, so a USB touchscreen that
      reconnects mid-session heals within one interval instead of staying on
      the identity matrix.

    KioskOS OS (image & build system)

    • systemd-timesyncd added to the image and enabled at provision time:
      kiosks often have dead RTC batteries, and a skewed clock breaks both apt
      ("Release file not valid yet") and TLS to the control server.
    • firmware-amd-graphics added: without it the amdgpu driver cannot
      load on AMD APUs, X falls back to the EFI framebuffer, and screen
      rotation is unavailable.
    • xinput added for the agent's touch-input remapping.
    • New one-shot hotfix script
      (kiosk/scripts/hotfix-amd-firmware-timesync.sh) brings already-deployed
      devices in line with the image fixes above — idempotent, fleet-friendly
      over SSH, and reboots only when the GPU fix requires it (--no-reboot to
      suppress).
    • Calamares installer branding now reports the real product version
      (2.1.0 — it had still claimed 1.0.0).
    • ARCHITECTURE.md documents the full remote shell job design (lifecycle,
      the two-switch permission model, endpoints, and device-side execution).

    Protocol (agent ↔ server API v1)

    New in check-in responses

    • jobs: an array of {id, command, timeout, preset} shell jobs
      claimed by this check-in. Each job appears in exactly one response.
      Absent/empty for kiosks without shell_enabled; older agents ignore it.

    New endpoints

    Endpoint Auth Purpose
    POST /api/v1/jobs/{id}/result/ device token Device reports exit_code, stdout, stderr, duration_seconds, timed_out.
    POST /api/v1/kiosks/{uid}/jobs/ admin session Queue a job (command or preset, plus optional timeout, expires_in).
    GET /api/v1/kiosks/{uid}/jobs/ admin session Job history for a device, filterable by status.
    GET /api/v1/jobs/{id}/ admin session One job with its captured output.
    POST /api/v1/jobs/{id}/cancel/ admin session Cancel an undelivered job (409 once it has been handed out).
    GET /api/v1/job-presets/ admin session Named commands offered by the UI.

    Security model

    • The result endpoint is scoped to the reporting device — a kiosk can
      only close out a job that was handed to it, so a leaked device token
      cannot forge results for the rest of the fleet.
    • Queueing requires an admin session; a device token is refused, so a
      compromised kiosk cannot queue work for itself.
    • Two switches, both required: the server-side per-kiosk shell_enabled
      flag (default off, checked at queue time and delivery time) and the
      device-side shell_enabled config key (default on, the operator's veto).
    Downloads
  • v2.0.0 9e81ed2010

    v2.0.0 Stable

    kaisa released this 2026-07-26 03:28:30 +00:00 | 2 commits to main since this release

    ⚠️ Breaking changes & upgrade notes

    2.0.0 is a breaking release. Devices no longer self-register.

    • An administrator now creates each kiosk in the control server and issues a
      one-time enrollment code, which the device redeems for its auth token.
    • Agents older than 2.0.0 cannot enroll against a 2.0.0 server.
    • Already-enrolled devices keep their tokens and keep checking in, but must
      be re-imaged (or upgraded and re-enrolled) to obtain browser sessions
      — kiosk pages now authenticate to terminal APIs through a device-session
      cookie that only 2.0.0 agents can obtain.
    • The standalone kioskos-browser.service unit is gone. Upgrading via
      install.sh disables and removes the legacy unit, its generated
      start-browser.sh launcher, and browser.env. The agent is now the only
      browser launcher.

    Upgrade path: deploy the 2.0.0 control server first (existing devices
    continue to check in), then roll out 2.0.0 images/agents and enroll each
    device with a fresh code.


    Protocol (agent ↔ server API v1)

    Breaking

    • POST /api/v1/register/ now requires enrollment_code. Anonymous
      self-registration is removed; every other field in the request is
      self-asserted, recorded for inventory only, and never trusted. Unknown,
      expired, and redeemed codes all return the same 403.

    New endpoints

    Endpoint Auth Purpose
    POST /api/v1/browser-grant/ device token Mint a single-use URL (2-minute expiry) that sets an HttpOnly device-session cookie and redirects to the target page. Off-origin next= values are discarded.
    GET /api/v1/setup/status/ · POST /api/v1/setup/ public (one-shot) First-boot onboarding: report whether an admin exists / create the first admin.
    POST /api/v1/auth/login/ · /logout/ · GET /auth/me/ session Admin UI session authentication.
    POST /api/v1/kiosks/{uid}/enrollment-code/ admin session Issue a fresh one-time enrollment code.
    POST /api/v1/kiosks/{uid}/command/ admin session Queue a one-shot reload_browser / restart_browser command.

    Response & field changes

    • Registration, check-in, and config responses now carry
      screen_orientation (normal / left / right / inverted —
      values pass straight through to xrandr --rotate).
    • Check-in responses carry command: the pending one-shot command,
      delivered exactly once (the server clears the slot in the same request).
      Empty string when none is queued. Delivery latency is bounded by
      checkin_interval (default 60 s).
    • config_updated is derived from admin config_update events newer than
      the device's last_seen_at.

    Security model

    • Devices authenticate with Authorization: Token <token>; the token is
      minted only by redeeming an enrollment code and never enters the browser.
    • Admin endpoints use session auth with CSRF protection; registration,
      login, and setup are rate-limited.

    Control (Django control server)

    New admin web UI

    • Complete Angular + PrimeNG single-page admin interface replacing raw API
      usage: login page, kiosk list with live online/offline/unenrolled status,
      kiosk detail with a full configuration form, and an event history table.
    • Kiosk lifecycle from the UI: create (returns an enrollment code to hand to
      the installer), edit, delete, re-issue enrollment codes, and queue
      remote browser actions.
    • First-boot onboarding page: a fresh install walks the operator through
      creating the initial admin account.

    Enrollment & authentication

    • One-time enrollment codes (XXXX-XXXX-XXXX): human-typeable alphabet
      that drops easily-misread characters (O/0, I/1, S/5, Z/2), 7-day expiry,
      single-use, and unique per kiosk. Re-issuing a code never invalidates a
      working device token, so it cannot knock a kiosk offline.
    • Registration rejects unknown, expired, and already-redeemed codes with an
      identical response, so the endpoint cannot be used to probe which codes
      exist.
    • First-boot setup endpoint (/api/v1/setup/) is open only while no admin
      exists, then permanently closed.
    • Session-based auth endpoints for the admin UI (/auth/login/,
      /auth/logout/, /auth/me/) with CSRF protection.
    • Rate limiting on registration, login, and setup endpoints.

    Device management features

    • Browser session grants: the server mints single-use, short-lived grant
      URLs that give the kiosk browser an HttpOnly device-session cookie —
      the device token itself never reaches the browser.
    • Screen orientation per kiosk (normal, left, right, inverted),
      editable in the admin UI and delivered to the device with every
      registration and check-in response.
    • One-shot remote commands: admins can queue reload_browser or
      restart_browser from the kiosk detail page. The command is delivered on
      the device's next check-in and cleared atomically, so it fires exactly
      once; queueing a new command replaces a pending one.
    • Every admin config change and queued command is recorded as a kiosk event
      and drives the config_updated flag on the next check-in.

    Operations

    • Dockerfile and entrypoint reworked: migrations, static file collection,
      and Gunicorn startup are handled on container boot.
    • Test suite expanded to 47 tests covering enrollment, check-in, commands,
      orientation, onboarding, and admin auth.

    KioskOS Agent (kioskos-agent 2.0.0)

    Enrollment & sessions

    • Registration redeems the admin-issued enrollment code; the agent no longer
      invents its own identity. Clear operator-facing errors distinguish a
      missing code from a rejected one.
    • Registration is retried from the check-in loop rather than only at
      startup, since it can now legitimately fail on a bad or expired code.
    • Before each browser launch the agent exchanges its token for a browser
      grant URL
      , giving kiosk pages a device session without ever exposing
      the token to Chromium. If the grant cannot be obtained the agent falls
      back to the plain URL (a visible page beats a blank screen) and marks the
      launch degraded.

    Reliability (white-screen fixes)

    • The agent waits for the X display before the first browser launch —
      previously Chromium could start into a not-yet-existing display and die
      with nothing to relaunch it.
    • A degraded launch is self-healing: on the first successful check-in
      after launching without a session (network still coming up, grant
      refused), the agent restarts the browser with a fresh grant instead of
      waiting for a URL change. A degraded first launch also triggers an
      immediate check-in rather than sleeping a full interval.
    • Dead-browser watchdog: every check-in cycle (even while offline) the
      agent relaunches Chromium if its process has died — including browsers
      that outlived an agent restart.
    • Stale Chromium SingletonLock files are removed before launch and the
      user-data directory ownership is corrected, eliminating silent
      fails-to-display after crashes.

    Display & kiosk behavior

    • Screen orientation is applied with xrandr — at boot before the
      browser launches (so the fullscreen window sizes itself to the rotated
      geometry) and at runtime on change, followed by a browser restart. The
      setting persists locally and survives offline reboots.
    • Remote commands: reload_browser performs a SIGHUP page reload;
      restart_browser kills and relaunches Chromium with a fresh session.
    • Chromium now launches with kiosk printing enabled and media-stream
      permission prompts auto-accepted.

    Setup wizard

    • The wizard cannot complete without a saved configuration: cancelling
      or failing any step returns to the previous menu or offers a restart, and
      the .setup-complete marker is written only after the config is
      confirmed and saved. DHCP and static-IP failures now offer
      retry / go back / continue-anyway, matching the existing WiFi flow.
    • New kioskos-setup command re-runs the TUI wizard from any console,
      VT, or SSH session and restarts the agent on success; the wizard prints
      that recovery hint on any abnormal exit.

    Security

    • /etc/kioskos/config.json is written 0600 with atomic replace — since
      2.0.0 it holds a real credential that gates terminal APIs.
    • Single browser launcher: the legacy kioskos-browser.service +
      start-browser.sh path is removed (it raced the agent, restarting old
      browser instances the agent had just killed).

    KioskOS OS (image & build system)

    Installer & first boot

    • The GRUB "Install KioskOS" entry no longer runs the TUI setup wizard
      or the agent inside the live installer session — configuration made there
      landed in the tmpfs overlay and never propagated into the installed
      system, and a registration attempt would have burned the one-time
      enrollment code. Setup now runs on the installed system's first boot.
    • USB config preload (kioskos-preload): first boot searches a
      KIOSKOS-CONFIG-labeled partition, removable media, and /boot for a
      pre-provisioned kioskos-config.json, validates it, applies the network
      settings, and skips the wizard — enabling zero-touch mass deployment.
    • The setup service no longer marks setup complete on its own
      (ExecStartPost removed); completion is owned by the wizard itself.

    Boot ordering & session

    • kioskos-agent.service now orders after network-online.target
      (with NetworkManager-wait-online enabled), so the browser is not
      launched against a dead network.
    • Mouse cursor auto-hides after 10 seconds of inactivity
      (unclutter-xfixes), in kiosk mode only — the installer session keeps a
      normal cursor.
    • The dead XFCE autostart browser entry and browser.env were removed from
      the overlay; the agent is the single browser launcher.

    Build system

    • GRUB packages switched to the -bin variants (grub-pc-bin,
      grub-efi-amd64-bin, grub-efi-arm64-bin) to avoid postinst conflicts
      inside the chroot build, for both amd64 and aarch64.
    • Intel/AMD CPU microcode included on amd64 images.
    • Added x11-xserver-utils (provides xset/xrandr) and
      unclutter-xfixes to the image package set.
    • The overlay-shipped /etc/kioskos/config.json is locked to
      root:root 0600 in the image.
    • Documentation (README, ARCHITECTURE.md) updated to match the real
      boot flow and 2.0.0 security model.
    Downloads
  • v1.0.0 999fb9c601

    v1.0.0 Stable

  • v0.1.0 14a789f418

    v0.1.0 Stable