No description
Find a file
exe-dev-bot 846a5bda22 feat(auth): implement auth layer - identity resolution (#28)
Implements the Auth Layer section of spec 002 (22 tasks). Adds `auth.go` with API key validation, root login, OTP claim, and bearer token extraction. All functions are testable independently of HTTP.

Co-authored-by: exe.dev user <exedev@kiosk.exe.xyz>
Reviewed-on: kwila/kiosk#28
Co-authored-by: exe-dev-bot <dev-bot@kwila.cloud>
Co-committed-by: exe-dev-bot <dev-bot@kwila.cloud>
2026-02-21 08:01:01 -05:00
.agents/skills feat(db): versioned migration system with auth tables (#26) 2026-02-21 06:03:54 -05:00
.forgejo/workflows ci: add pull request workflow with fmt, vet, and tests (#22) 2026-02-21 07:02:19 -05:00
cmd/kiosk-deploy feat(deploy): split deploy binary, download from releases, add CI (#8) 2026-02-12 20:39:38 -05:00
deploy ci: add pull request workflow with fmt, vet, and tests (#22) 2026-02-21 07:02:19 -05:00
specs feat(auth): implement auth layer - identity resolution (#28) 2026-02-21 08:01:01 -05:00
static feat(scheduler): add scheduled dark/light mode switching (#24) 2026-02-21 04:30:09 -05:00
testdata feat: show weekly recurring events above calendar grid (#21) 2026-02-14 15:50:25 -05:00
.gitignore feat: improve web interface (#9) 2026-02-12 20:47:18 -05:00
AGENTS.md feat(db): versioned migration system with auth tables (#26) 2026-02-21 06:03:54 -05:00
auth.go feat(auth): implement auth layer - identity resolution (#28) 2026-02-21 08:01:01 -05:00
auth_test.go feat(auth): implement auth layer - identity resolution (#28) 2026-02-21 08:01:01 -05:00
calendar.go ci: add pull request workflow with fmt, vet, and tests (#22) 2026-02-21 07:02:19 -05:00
calendar_test.go ci: add pull request workflow with fmt, vet, and tests (#22) 2026-02-21 07:02:19 -05:00
db.go feat(auth): root seeding and reset-password CLI (#27) 2026-02-21 06:48:24 -05:00
go.mod feat(auth): root seeding and reset-password CLI (#27) 2026-02-21 06:48:24 -05:00
go.sum feat(auth): root seeding and reset-password CLI (#27) 2026-02-21 06:48:24 -05:00
handlers.go feat(scheduler): add scheduled dark/light mode switching (#24) 2026-02-21 04:30:09 -05:00
handlers_test.go feat: show weekly recurring events above calendar grid (#21) 2026-02-14 15:50:25 -05:00
justfile feat(scheduler): add scheduled dark/light mode switching (#24) 2026-02-21 04:30:09 -05:00
main.go feat(auth): root seeding and reset-password CLI (#27) 2026-02-21 06:48:24 -05:00
migrations.go feat(db): versioned migration system with auth tables (#26) 2026-02-21 06:03:54 -05:00
migrations_test.go feat(db): versioned migration system with auth tables (#26) 2026-02-21 06:03:54 -05:00
README.md feat(scheduler): add scheduled dark/light mode switching (#24) 2026-02-21 04:30:09 -05:00
scheduler.go feat(scheduler): add scheduled dark/light mode switching (#24) 2026-02-21 04:30:09 -05:00
scheduler_test.go feat(scheduler): add scheduled dark/light mode switching (#24) 2026-02-21 04:30:09 -05:00
seed_test.go feat(auth): root seeding and reset-password CLI (#27) 2026-02-21 06:48:24 -05:00
updater.go feat: improve sidebar (#20) 2026-02-14 07:25:45 -05:00
updater_test.go feat(updater): auto-update binary from Forgejo releases at 2am daily (#19) 2026-02-14 04:11:13 -05:00

Kiosk

A Go web server that aggregates ICS calendar feeds and displays them on a full-screen monthly calendar. Designed for wall-mounted Raspberry Pi displays running in Chromium kiosk mode.

Features

  • Aggregates multiple ICS calendar feeds (Google Calendar, FamCal, Proton Calendar, etc.)
  • Dark-themed monthly calendar grid optimized for 1920x1080 displays
  • Auto-rotates between current and next month every 30 seconds
  • Background feed refresh every 15 minutes
  • Web-based admin UI for managing feeds - no SSH or config files needed
  • Single binary with embedded static assets and SQLite storage
  • One-command SD card setup for Raspberry Pi via interactive TUI

Quick Start

Build and run locally:

just dev
# or
go build -o kiosk . && ./kiosk -port 8000

Deploy to Raspberry Pi

Prerequisites

  • Raspberry Pi 3 or 4 (ARM64)
  • MicroSD card (8 GB+)
  • WiFi network
  • Linux host with Go installed (ext4 mounting required - macOS is not supported)

Deploy

The deploy command flashes a ready-to-boot kiosk image onto an SD card:

just deploy

The TUI walks you through four steps:

  1. SD Card - select from auto-detected removable drives
  2. WiFi SSID - your network name
  3. WiFi Password - your network password
  4. Timezone - searchable list (e.g. America/New_York)

Review the summary, press Enter, and the tool downloads the DietPi image, flashes it, downloads the latest ARM64 kiosk binary from Forgejo releases, and writes all config files and the binary to the card.

Save your password!

The deploy generates a random root password and displays it once on the success screen. This is the only way to SSH into the Pi. Copy it to your password manager immediately. If you lose it, you'll need to re-flash the SD card.

What Gets Configured

The deploy writes a DietPi image with:

  • Automated first-boot setup (no monitor/keyboard needed)
  • WiFi credentials and timezone
  • Chromium installed in kiosk mode (fullscreen, no cursor, no screensaver)
  • Kiosk binary installed at /opt/kiosk/kiosk with a systemd service
  • Chromium auto-starts pointing to http://localhost/kiosk

After deployment:

Access Address
SSH ssh root@<pi-ip> with the generated password
Admin UI http://<pi-ip>/ from any device on the network
Kiosk display Auto-starts on the Pi's connected monitor

After First Boot

  1. Insert the SD card and power on the Pi.
  2. Wait 1015 minutes — DietPi runs automated setup and installs software.
  3. The Pi reboots into the kiosk display.
  4. From another device on the network, open the admin UI (http://<pi-ip>/) and add your calendar feeds.

Feeds refresh automatically every 15 minutes. The kiosk display auto-rotates between the current and next month every 30 seconds.

Configuration Details

Systemd service — The kiosk runs as a systemd service at /etc/systemd/system/kiosk.service. It starts after networking, listens on port 80, and restarts automatically on crash (5-second delay). Working directory is /opt/kiosk/.

Database — Feed configuration is stored in SQLite at /opt/kiosk/kiosk.db, created on first run. Re-flashing the card erases it — you'll need to re-add feeds.

WiFi — The deploy writes WPA2-PSK credentials to dietpi-wifi.txt. Enterprise WiFi (EAP/802.1X) is not supported by the TUI. For enterprise networks, flash normally then edit /boot/dietpi-wifi.txt before first boot.

Image cache — The DietPi image is cached at ~/.cache/dietpi/ on the deploy host. Delete this directory to force a fresh download.

Updating Without Re-flashing

CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o kiosk-arm64 .
scp kiosk-arm64 root@<pi-ip>:/opt/kiosk/kiosk
ssh root@<pi-ip> systemctl restart kiosk

This preserves your database and feed configuration.

Troubleshooting

Pi Won't Boot

  • No activity lights: Check power supply. Pi 4 requires USB-C delivering at least 3A.
  • Rainbow screen / repeated reboots: SD card image may be corrupted. Re-flash with sudo ./kiosk-deploy.
  • Red light only, no green flashing: Pi can't read the SD card. Try a different card or re-seat it.

WiFi Not Connecting

  • SSID is case-sensitiveMyNetworkmynetwork. Re-flash if wrong.
  • WiFi country code defaults to US. For other countries, SSH in via Ethernet and edit /boot/dietpi-wifi.txt.
  • Pi 3 only supports 2.4 GHz. Pi 4 supports both bands.
  • Hidden networks are not supported.
  • Diagnose: Connect Ethernet, SSH in, check journalctl -u networking or iwconfig.

Black Screen After Boot

  • Wait the full 1015 minutes. First boot installs packages before Chromium starts.
  • If still black after 20+ minutes, SSH in and check:
    systemctl status kiosk
    cat /boot/dietpi.txt | grep AUTOSTART
    # Should show: AUTO_SETUP_AUTOSTART_TARGET_INDEX=11
    

Kiosk Service Not Running

systemctl status kiosk        # Check status
journalctl -u kiosk -f         # View logs (live)
systemctl restart kiosk        # Restart
ls -la /opt/kiosk/kiosk        # Verify binary exists
  • "exec format error": Wrong architecture. Re-flash — the deploy tool downloads the correct ARM64 binary.
  • Feeds not loading: Check journalctl -u kiosk for HTTP errors. The Pi needs internet access to fetch ICS feeds.

No Releases Found / Download Fails

  • Check internet connectivity on the deploy host.
  • Ensure a Forgejo release exists with a kiosk-arm64 asset attached.
  • If behind a proxy, ensure https://git.kwila.cloud is reachable.

Screen Blanking / Display Turns Off

DietPi kiosk mode disables screen blanking by default. If it still turns off:

DISPLAY=:0 xset s off && DISPLAY=:0 xset -dpms && DISPLAY=:0 xset s noblank

To persist, add those commands to /var/lib/dietpi/dietpi-autostart/custom.sh.

SSH Access

ssh root@<pi-ip>   # or ssh root@DietPi-Kiosk if mDNS works

Uses Dropbear (DietPi default). Password is the one shown during deploy.

Useful Logs

journalctl -u kiosk -n 50                              # Kiosk server
cat /var/tmp/dietpi/logs/dietpi-firstrun-setup.log      # First-boot setup
journalctl -b                                           # System boot

Lost Root Password

The password cannot be recovered. Re-flash the SD card with sudo ./kiosk-deploy.

Build

just build         # Build web server for current platform
just deploy        # Build and run the deploy TUI (requires sudo)
just test          # Run tests
just clean         # Remove build artifacts

To Do

  • Add items here