# Ubuntu Based Kiosk **Current Version:** 2.7.0 (check script header for latest version) **Built with Claude Sonnet 4.6 AI assistance** **License:** GPL v3 - Keep derivatives open source **Repository:** https://github.com/outis1one/ubuntu-based-kiosk/ --- ## Target Systems - Ubuntu 24.04+ Server (minimal install recommended) - Raspberry Pi 4+ (with or without touchscreen) - *untested* - Laptops, desktops, all-in-ones, 2-in-1s - Touch support optional (works with keyboard/mouse) --- ## ⚠️ Security Notice **This is NOT suitable for secure locations or public kiosks.** - Do NOT use as a replacement for hardened kiosk solutions - Designed for home/office/trusted environments only - Use entirely at your own risk - No warranty or security guarantees provided --- ## Purpose Home/office kiosk for reusing old hardware, displaying: - Self-hosted services (Immich, MagicMirror2, Home Assistant, Plex, Jellyfin, Emby) - Web dashboards and digital signage - Photo slideshows and family calendars - Video conferencing (Jitsi, Zoom, Google Meet) - Any web-based content --- ## Quick Install ```bash # Install Ubuntu 24.04 Server # ***Do not use "kiosk" as a user name when installing, the script creates a restricted user named kiosk and the script will not install if the sudo user/user name when setting up the system is "kiosk".*** # Configure WiFi if no ethernet available # Enable SSH during installation # Download and run the installer wget https://github.com/outis1one/ubuntu-based-kiosk/raw/main/ubuntu-based-kiosk.sh chmod +x ubuntu-based-kiosk.sh && ./ubuntu-based-kiosk.sh ``` The installer will guide you through configuration during setup. --- ## Offline / Air-Gapped Download If the kiosk machine can't reach GitHub directly (no browser, restrictive proxy, or you just prefer to grab the script on another computer and carry it over via USB), download it ahead of time instead of using the `curl`/`wget` one-liner above. > **Note:** This only avoids needing internet access *to fetch the script*. The installer itself still requires the kiosk machine to have internet access while it runs — it uses `apt` to install packages, pulls Node.js from NodeSource, and runs `npm install` to fetch Electron (~120MB). There is currently no fully air-gapped/offline package bundle. **On a machine with internet access:** ```bash # Option A: download just the installer script wget https://github.com/outis1one/ubuntu-based-kiosk/raw/main/ubuntu-based-kiosk.sh # Option B: download the whole repo as a ZIP (includes install.sh, addon scripts, and older archived installer versions) wget https://github.com/outis1one/ubuntu-based-kiosk/archive/refs/heads/main.zip unzip main.zip ``` Copy the downloaded `.sh` file (or the extracted ZIP contents) to a USB drive, then on the kiosk machine: ```bash # Mount the USB drive and copy the script over, then: chmod +x ubuntu-based-kiosk.sh ./ubuntu-based-kiosk.sh ``` The kiosk machine still needs a working internet connection (ethernet, or WiFi configured during Ubuntu install) for the script to complete. --- ## Core Features ### Multi-Site Management - **Single or multiple sites** with independent configurations - **Named sites** - Optional friendly names for easy identification in navigation menu - **Auto-rotation** - Sites rotate automatically based on duration - **Manual sites** - Duration = 0, accessible via swipe only, trigger inactivity timeout - **Hidden sites** - Duration = -1, PIN-protected access, trigger inactivity timeout - **Home URL** - Auto-return after inactivity on manual or hidden sites - **Pause functionality** - Temporarily pause rotation (configurable per-site) - **Navigation menu** - Quick access to all sites via key icon (top-left hot corner) ### Touch Controls - **2-finger horizontal swipe** - Switch between sites - **3-finger down swipe** - Toggle hidden tabs (PIN required to show, swipe again to hide) - **1-finger swipe** (dual mode) - Navigate within page (arrow keys) - **On-screen keyboard** - Auto-shows on text fields or click keyboard icon - **Navigation menu** - Click key icon (top-left) to access site list and gesture cheat sheet ### On-Screen Keyboard - **HTML-based keyboard** with full QWERTY layout - **Auto-show on text fields** (optional) - **30-second auto-close** after inactivity - **Shift/Caps Lock support** - **Special characters** via shift keys - Works alongside physical keyboard ### Password Protection & Lockout (all are optional) - **Session lockout** after configured inactivity - **Scheduled lockout** at specific time daily - **Display wake lockout** - Require password after display schedule - **Boot password** option - Require password on system startup - **Full screen blocking** during lockout (no content visible) ### Navigation Security - **Restricted** - Exact URL only, no link clicking - **Same-origin** - Links within same domain only (recommended) - **Open** - Unrestricted browsing (trusted environments only) ### Scheduling System (all are optional) - **Power schedule** - Auto-shutdown and RTC wake (hardware dependent) - **Display schedule** - Turn display off/on at specific times - **Quiet hours** - Mute audio or stop Squeezelite during hours - **Electron reload** - Periodic restart to prevent memory leaks ### Media Playback Intelligence - **Auto-detects playing media** (HTML5 video/audio, YouTube, Plex, Jellyfin, Emby) - **Pauses rotation** during media playback - **Grace period** after media stops - **Respects user activity** while watching --- ## Optional Add-ons ### Authentication #### Authelia Auto-Login (SSO) Automatically authenticates the kiosk against a self-hosted [Authelia](https://www.authelia.com) instance on every startup. The Authelia password is **not stored in plain text** — it is encrypted with AES-256-CBC using a key derived from the machine's unique `/etc/machine-id`, so the encrypted blob is useless on any other machine. **Access via menu:** `Addons → 5. Authelia Auto-Login` After running the addon it prints the full server-side setup, but the summary is below. ##### Kiosk side (SSH in and run the installer) ```bash ssh user@kiosk-machine ./ubuntu-based-kiosk.sh # Addons → 5. Authelia Auto-Login # Enter your Authelia URL, username, and password when prompted ``` ##### Authelia server side (Dockerized) **Step 1 — Generate the argon2 password hash** (run on your Docker host): ```bash docker run --rm authelia/authelia:latest \ authelia crypto hash generate argon2 \ --password 'yourpassword' ``` Copy the `$argon2id$...` output — that is your hash. **Step 2 — Add a kiosk user** to `~/docker/authelia/config/users.yml`: ```yaml kiosk: displayname: "Kiosk Display" password: '$argon2id$v=19$m=65536,t=3,p=4$' email: kiosk@local.com groups: - kiosk ``` **Step 3 — MERGE into `~/docker/authelia/config/configuration.yml`** (do not replace your existing config): **access_control** — Find your **existing** `access_control:` block and add the kiosk rule as the **first** rule inside it. > **Do NOT create a second `access_control:` block.** YAML silently ignores duplicate keys — Authelia will never see the kiosk rule and the kiosk will get a white screen. Authelia reads rules top-down — first match wins. The kiosk rule **must** sit above any `two_factor` wildcard rule, otherwise the wildcard matches first. **Why `one_factor`?** The kiosk authenticates via the API (`/api/firstfactor` — password only). TOTP and WebAuthn require an interactive second step that is impossible from a script, so the kiosk group must use `one_factor`. *Before (your existing config):* ```yaml access_control: default_policy: deny rules: - domain: '*.yourdomain.com' policy: two_factor ``` *After (add kiosk rule above the two_factor rule — same block, not a new one):* ```yaml access_control: default_policy: deny rules: - domain: '*.yourdomain.com' # kiosk first — one_factor only subject: 'group:kiosk' policy: one_factor - domain: '*.yourdomain.com' # existing rule stays below policy: two_factor ``` **session** — Keep your existing session block as-is; no changes needed. The kiosk re-authenticates via API on every startup so session expiry barely matters for it. If you do **not** yet have a session block, add: ```yaml session: expiration: 8h inactivity: 1h remember_me: 7d cookies: - domain: yourdomain.com authelia_url: https://auth.yourdomain.com ``` **Step 4 — Restart Authelia:** ```bash docker compose restart authelia ``` ##### How it works On every kiosk startup, Electron calls Authelia's `/api/firstfactor` endpoint with `keepMeLoggedIn: true` **before** any sites load. Authelia responds with a `Set-Cookie` header that Electron absorbs into its default session. All BrowserViews then load with that session cookie already present. Because Electron's session persists to disk across reboots (`/home/kiosk/.config/kiosk-app/`), the cookie also survives restarts — the API call on startup just refreshes or extends it. ##### Authelia vs HTTP Basic Auth Both can be used at the same time — they serve different purposes: | Method | Where configured | When to use | |--------|-----------------|-------------| | **Authelia SSO** | `Addons → Authelia Auto-Login` (global) | Sites protected by an Authelia reverse proxy | | **HTTP Basic Auth** | Per-site username/password in tab config | Sites that show a browser popup asking for credentials | --- ### Communication - **Easy Asterisk Intercom** - Voice communication and intercom system - Downloads latest version from Easy Asterisk repository - Automatic update detection and installation - Configuration preservation during updates - Full Asterisk PBX integration - SIP/PJSIP support for IP phones and softphones ### Audio - **Lyrion Music Server (LMS)** - Formerly Logitech Media Server - **Squeezelite Player** - Network audio player for LMS - **PipeWire audio** - Modern Linux audio stack - **Volume controls** - Hardware button support ### Printing - **CUPS printing system** - **Network printer sharing** - **IPP Everywhere support** - **PDF printing** via cups-pdf ### Remote Access - **VNC** - x11vnc for remote desktop - **WireGuard VPN** - Config paste support - **Tailscale VPN** - Auth key support - **Netbird VPN** - Setup key support ### Advanced - **Emergency WiFi Hotspot** - Auto-starts if no internet after boot (configurable during install) - **Virtual Console Access** - Ctrl+Alt+F1-F8 terminal login (can enable/disable during install) - **Complete Uninstall** - Full system cleanup and kiosk removal - **SSH remote access** - For configuration and troubleshooting --- ## What This Script Installs ### Core Components - **Electron** v42.x (Chromium-based app framework) - **Node.js** v20.x with npm - **Openbox** - Lightweight window manager - **LightDM** - Display manager with autologin - **xorg** - X11 server and utilities - **unclutter** - Hide mouse cursor - **Hardware acceleration** - VAAPI, Mesa drivers ### Audio Stack - **PipeWire** - Modern audio/video server - **PipeWire-Pulse** - PulseAudio compatibility - **WirePlumber** - Session manager - **ALSA** utilities ### System Services - **systemd-timesyncd** - NTP time sync - **acpid** - Power button handling - **ufw** - Uncomplicated Firewall - **Network Manager** or netplan for networking ### Development Tools - **build-essential** - GCC, make, etc. - **Python 3** with evdev for PTT - **jq** - JSON processing - **curl / git** - Downloading and version control - **net-tools** - Legacy networking utilities (ifconfig, netstat, etc.) - **ncdu** - Disk usage analyzer for troubleshooting --- ## System Behavior ### Security & Lockdown - **Autologin** as kiosk user - **Virtual consoles** (Ctrl+Alt+F1-F8) - Optional, configurable during install - **X server key combinations disabled** (Ctrl+Alt+Backspace) - **Right-click disabled** in kiosk app - **Screen blanking disabled** with schedule awareness - **DPMS management** - Aggressive keep-alive with schedule respect ### Audio Management - **PipeWire watchdog** - Auto-restart if audio fails - **Volume persistence** - Speakers 100%, Mic 100% and unmuted - **Quiet hours aware** - Respects audio schedules - **User services** - Audio runs under kiosk user ### Network - **WiFi configuration** - WPA2, netplan-based - **Multi-method WiFi scan** - nmcli, iw, wpa_cli fallbacks - **Watchdog support** - Auto-revert bad WiFi configs - **Emergency hotspot** - Fallback if no internet --- ## Maintenance & Troubleshooting ### Service Management ```bash # Restart kiosk display sudo systemctl restart lightdm # View Electron logs sudo tail -f /home/kiosk/electron.log # Check service status systemctl status lightdm systemctl status squeezelite sudo systemctl --user -M kiosk@ status pipewire ``` ### Common Issues **No display after boot:** ```bash # Check LightDM status sudo journalctl -u lightdm -n 50 # Verify kiosk user id kiosk # Check X11 authorization sudo -u kiosk DISPLAY=:0 xdpyinfo ``` **External monitor/TV (HDMI) shows nothing, or shows a cropped/scaled picture:** Any connected display beyond the primary is mirrored automatically at the **primary's exact resolution** (not the external display's own native resolution) — both at kiosk login/boot (via Openbox autostart) and live when plugged/unplugged afterward (via a udev rule that triggers `kiosk-hotplug.service`). Both paths call the same `/usr/local/bin/kiosk-mirror-display.sh`. If the external display doesn't natively list the primary's resolution (e.g. a 1366x768 laptop panel mirrored to a 1920x1080-native TV), a matching mode is generated on the fly with `cvt` and forced onto the output — most monitors/TVs accept a close, non-native CVT timing without issue, but a few strict ones may reject it (see below). ```bash # List outputs and check if the external display is detected sudo -u kiosk DISPLAY=:0 XAUTHORITY=/home/kiosk/.Xauthority xrandr # Look for your output (e.g. HDMI1/HDMI2/HDMI-1) as "connected" with a mode list. # Check what the mirroring logic actually did (native mode vs. forced CVT mode, or failures) journalctl | grep "KIOSK:" | tail -20 # Check whether the hotplug handler fired sudo journalctl -u kiosk-hotplug.service -n 20 # Manually re-trigger it sudo systemctl start kiosk-hotplug.service # Run the mirroring logic by hand for more verbose output sudo -u kiosk DISPLAY=:0 XAUTHORITY=/home/kiosk/.Xauthority bash -x /usr/local/bin/kiosk-mirror-display.sh ``` If the output shows `disconnected`, it's a cabling/port/EDID issue, not software — try a different cable/port or a monitor known to work. If a forced CVT mode is rejected by the display (blank screen only after mirroring runs, works fine before), that display's EDID doesn't accept out-of-spec timings — you'll need to manually pick one of its natively listed modes instead: ```bash sudo -u kiosk DISPLAY=:0 XAUTHORITY=/home/kiosk/.Xauthority xrandr --output HDMI2 --mode 1360x768 --same-as eDP1 ``` **No sound over HDMI (audio only from laptop/built-in speakers):** Whenever an external display is connected/mirrored, `kiosk-audio-route.sh` switches PipeWire's default sink to whichever sink's name contains `hdmi`, and moves any already-playing audio stream onto it. It's called at kiosk login (after PipeWire is confirmed ready) and by `kiosk-hotplug.service` on every plug/unplug — see `/usr/local/bin/kiosk-mirror-display.sh` above for the display side of the same hotplug event. ```bash # List sinks and confirm an HDMI one exists (name will contain "hdmi") sudo -u kiosk pactl list sinks short # Check what the routing logic actually did journalctl | grep "KIOSK: audio routed\|KIOSK: failed to route" | tail -10 # Check current default sink sudo -u kiosk pactl get-default-sink # Manually re-trigger routing sudo systemctl start kiosk-hotplug.service # Force it by hand if needed (replace with your sink name from the list above) sudo -u kiosk pactl set-default-sink alsa_output.pci-0000_00_1f.3.hdmi-stereo ``` If no sink name contains `hdmi`, the audio codec on that HDMI port either isn't exposed by ALSA/PipeWire on this hardware, or the monitor/TV doesn't report HDMI audio support in its EDID (common on monitors that only do video) — in that case there's no PipeWire-side fix, audio has to come from the laptop speakers or a separate cable. **Audio not working:** ```bash # Check PipeWire (use menu: Advanced → Audio Diagnostics) sudo -u kiosk pactl info # Restart audio sudo systemctl restart lightdm ``` **Touch not working:** ```bash # List input devices xinput list # Check Electron logs for touch events sudo tail -f /home/kiosk/electron.log | grep TOUCH # Test gestures (should show in logs): # - 3-finger UP = "[TOUCH] 3-finger UP - show hidden tab" # - 3-finger DOWN = "[TOUCH] 3-finger DOWN - return to normal tabs" # - 2-finger HORIZONTAL = "[MANUAL] User switched tab..." ``` **Hidden sites not showing:** ```bash # Check PIN file exists ls -la /home/kiosk/kiosk-app/.jitsi-pin # View current PIN sudo cat /home/kiosk/kiosk-app/.jitsi-pin # Check for hidden sites in config sudo jq '.tabs[] | select(.duration == -1)' /home/kiosk/kiosk-app/config.json # Check if inactivity timeout is working on hidden tabs sudo tail -f /home/kiosk/electron.log | grep HOME # Should show: "[HOME] HIDDEN IDLE: Xm Ys / Ym Ys" ``` **Inactivity prompt not appearing:** ```bash # Check home tab configuration sudo jq '.homeTabIndex, .inactivityTimeout' /home/kiosk/kiosk-app/config.json # Watch for inactivity logging sudo tail -f /home/kiosk/electron.log | grep HOME # Manual site: "[HOME] 🏠 MANUAL IDLE: 1m 45s / 2m 0s" # Hidden site: "[HOME] 🏠 HIDDEN IDLE: 1m 45s / 2m 0s" # Prompt shown: "[HOME] 🔔 *** SHOWING PROMPT NOW (hidden tab) ***" ``` **Keyboard not appearing:** ```bash # Check keyboard button setting sudo grep enableKeyboardButton /home/kiosk/kiosk-app/config.json # View keyboard events sudo tail -f /home/kiosk/electron.log | grep KEYBOARD ``` ### Adding Printers to CUPS **1. Access CUPS Web Interface:** ``` http://:631/admin ``` Login with the username and password you used during Ubuntu installation. **2. Click "Add Printer"** **3. Find Your Printer URI** CUPS needs a device URI to connect to your printer. Here's how to find it: **For Network Printers (Most Common):** From Windows, find the printer's URI: 1. Right-click printer → **Printer Properties** → **Ports** tab 2. Look for the checked port, note the format: **HP Network Printers:** - Windows shows: `IP_192.168.1.100` or similar - CUPS URI: `hp:/net/?ip=192.168.1.100` - Alternative: `socket://192.168.1.100:9100` **Generic Network Printers (IPP):** - Windows shows: `http://192.168.1.100/ipp/print` or similar - CUPS URI: `ipp://192.168.1.100/ipp/print` - Alternative: `http://192.168.1.100:631/ipp/print` **Generic Network Printers (Socket/JetDirect):** - Windows shows: `Standard TCP/IP Port` on `192.168.1.100` - CUPS URI: `socket://192.168.1.100:9100` - Port 9100 is standard for HP JetDirect protocol **USB Printers:** - CUPS auto-detects these - URI looks like: `usb://HP/LaserJet%20P1102` - Select from "Local Printers" list in CUPS **4. Select Driver** After entering URI, CUPS will ask for a driver: - Search for your printer model - If not found, try "Generic PCL" or "Generic PostScript" - For HP printers, install `hplip`: `sudo apt install hplip` **5. Set as Default (Optional)** Administration → Set Default Printer **6. Print Test Page** Printers → Your Printer → Maintenance → Print Test Page **Quick Reference - Common URIs:** ```bash # HP Network Printer hp:/net/HP_LaserJet_P3015?ip=192.168.1.100 # Generic Network (Socket/JetDirect - Port 9100) socket://192.168.1.100:9100 # Generic Network (IPP) ipp://192.168.1.100/ipp/print # Shared Windows Printer smb://WORKGROUP/COMPUTER/PrinterName ``` **Troubleshooting:** - **Printer not responding:** Check firewall, ensure kiosk can ping printer IP - **Wrong driver:** Try Generic PostScript or PCL drivers - **Authentication failed:** Verify Windows printer sharing is enabled - **Can't find printer:** Use `lpinfo -v` to list all available devices --- ## Touch Gesture Quick Reference | Gesture | Fingers | Direction | Action | |---------|---------|-----------|--------| | Swipe | 2 | Left/Right | Switch between sites | | Swipe | 1 | Left/Right | Navigate within page (arrow keys) | | Swipe | 3 | Down | Toggle hidden tabs (PIN required) | **Keyboard Shortcuts:** - `Ctrl+Tab` or `Ctrl+]` - Next tab - `Ctrl+Shift+Tab` or `Ctrl+[` - Previous tab - `Alt+Right/Left` - Next/Previous tab - `F10` or `Ctrl+H` - Toggle hidden tabs - `Escape` - Return to normal tabs (from hidden) - `Ctrl+Alt+Delete` or `Ctrl+Alt+P` - Power menu - `Ctrl+K` - Toggle keyboard --- ### Menu System Access ```bash # Run installer script again to access menu ./ubuntu-based-kiosk.sh # Menu structure: # 1. Core Settings - Sites, WiFi, schedules, passwords, full reinstall, complete uninstall # 2. Addons - Authelia Auto-Login, Easy Asterisk Intercom, LMS, CUPS, VNC, VPNs # 3. Advanced - Diagnostics, logs, Electron updates, virtual consoles, emergency hotspot # 4. Restart Kiosk Display ``` ### Installing Easy Asterisk Intercom The Easy Asterisk Intercom addon provides voice communication capabilities to your kiosk system. **Access the addon menu:** ```bash ./ubuntu-based-kiosk.sh # Select: 2) Addons # Then: 4) Easy Asterisk Intercom ``` **Features:** - **Automatic installation** - Downloads and installs the latest version from the Easy Asterisk repository - **Update detection** - Checks for newer versions and prompts to update - **Safe re-runs** - Can be run multiple times without breaking existing configurations - **Config preservation** - Automatically backs up and restores configurations during updates - **Full Asterisk PBX** - Complete telephony features including SIP, extensions, voicemail **Installation behavior:** - **First install:** Downloads latest version from https://github.com/outis1one/easy-asterisk - **Already installed (latest):** Prompts to re-run installation (preserves configs) - **Update available:** Prompts to update and shows version difference - **All scenarios:** Configuration files in `/etc/asterisk/` and installation settings are preserved **Managing Easy Asterisk:** ```bash # Check installation status systemctl status asterisk # View Asterisk console asterisk -rvvv # Restart Asterisk systemctl restart asterisk # Configure intercom (rerun installation to update) ./ubuntu-based-kiosk.sh # Select: 2) Addons → 4) Easy Asterisk Intercom ``` **Installation location:** - Installation files: `/opt/easy-asterisk/` - Configuration: `/etc/asterisk/` - Version tracking: `/opt/easy-asterisk/.version` - Config backups: `/opt/easy-asterisk/config_backup/` ### Updating Electron ```bash # Via menu: Advanced → Manual Electron Update (RECOMMENDED) # The menu option automatically: # - Creates backup before updating # - Shows rollback instructions # - Handles permissions correctly # Or manually: cd /home/kiosk/kiosk-app sudo -u kiosk npm install electron@latest sudo systemctl restart lightdm ``` **Rollback if update fails:** The menu update creates automatic backups in `/home/kiosk/electron-backup-/` ```bash # 1. Stop display sudo systemctl stop lightdm # 2. Find your backup (most recent) ls -lt /home/kiosk/electron-backup-* | head -1 # 3. Restore backup files (replace timestamp with your backup) BACKUP=/home/kiosk/electron-backup- sudo cp $BACKUP/package.json /home/kiosk/kiosk-app/ sudo cp $BACKUP/package-lock.json /home/kiosk/kiosk-app/ 2>/dev/null || true # 4. Remove failed install and reinstall previous version sudo rm -rf /home/kiosk/kiosk-app/node_modules/electron cd /home/kiosk/kiosk-app && sudo -u kiosk npm install --unsafe-perm # 5. Fix permissions sudo chown root:root /home/kiosk/kiosk-app/node_modules/electron/dist/chrome-sandbox sudo chmod 4755 /home/kiosk/kiosk-app/node_modules/electron/dist/chrome-sandbox # 6. Restart display sudo systemctl start lightdm ``` --- ## Configuration Files ### Main Config `/home/kiosk/kiosk-app/config.json` ```json { "autoswitch": true, "swipeMode": "dual", "allowNavigation": "same-origin", "homeTabIndex": 0, "inactivityTimeout": 120, "enablePauseButton": true, "enableKeyboardButton": true, "enablePasswordProtection": false, "tabs": [ { "url": "https://example.com", "duration": 180, "username": "", "password": "" } ] } ``` ### Key Config Values - **duration**: `>0` = auto-rotate (seconds), `0` = manual only, `-1` = hidden - **swipeMode**: `"dual"` = 2-finger nav + 1-finger arrows, `"standard"` = 2-finger only - **allowNavigation**: `"restricted"` | `"same-origin"` | `"open"` - **homeTabIndex**: Tab to return to after inactivity (`-1` = disabled) - **inactivityTimeout**: Seconds before showing "still here?" prompt - **lockoutTimeout**: Minutes of inactivity before lockout (0 = disabled) - **lockoutAtTime**: Daily lockout time in `"HH:MM"` format - **requirePasswordOnBoot**: `true` = password required on system startup **Note:** Config files may contain `lockoutActiveStart` and `lockoutActiveEnd` fields from earlier versions. These are not currently functional and are ignored by the application. ### Hidden Sites PIN `/home/kiosk/kiosk-app/.jitsi-pin` The PIN file controls access to hidden sites (duration = -1): - **Default:** `1234` - **Configure via:** Main Menu → Core Settings → Sites → Configure Hidden Sites PIN - **Disable PIN:** Set content to `NOPIN` to allow any entry - **Custom PIN:** 4-8 digits ```bash # Set custom PIN echo "5678" | sudo -u kiosk tee /home/kiosk/kiosk-app/.jitsi-pin # Disable PIN protection echo "NOPIN" | sudo -u kiosk tee /home/kiosk/kiosk-app/.jitsi-pin ``` --- ## Advanced Features ### Site Duration Modes **Auto-Rotate (duration > 0):** - Site displays for specified seconds - Auto-advances to next rotation site - Pause button available - Respects media playback **Manual Only (duration = 0):** - Site accessible via swipe - Never auto-rotates - No pause button (not needed) - Can be set as Home URL - Triggers inactivity timeout (returns to home after idle time) **Hidden (duration = -1):** - Toggle visibility via 3-finger down swipe + PIN, or F10 key - Also use Escape key to return to normal tabs - PIN stored in `/home/kiosk/kiosk-app/.jitsi-pin` - Default PIN: 1234 (configurable via Sites menu) - PIN can be 4-8 digits or disabled completely - Hidden from normal rotation - **Triggers inactivity timeout** (returns to home after idle time, just like manual sites) #### Why Use Hidden Tabs? Hidden tabs are perfect for scenarios where you need access to sensitive or private content on a shared/public kiosk: **Private Communication:** - Video conferencing (Jitsi Meet, Zoom, Google Meet) - Private messaging or chat applications - Internal communication tools for staff only - Conference room scheduling interfaces **Administrative Access:** - Server administration panels (Proxmox, TrueNAS, router interfaces) - Security camera feeds - Home automation controls (Home Assistant, OpenHAB) - Network monitoring dashboards **Content Management:** - Digital signage content editors - Photo album management (Immich, PhotoPrism) - Media server administration (Plex, Jellyfin) - Calendar and scheduling updates **Secure Entertainment:** - Personal streaming accounts (prevent others from accessing your watch history) - Gaming platforms or cloud gaming services - Adult content controls (parental access only) - Personal social media (Facebook, Instagram, etc.) **Business Use Cases:** - Employee time tracking systems - Inventory management interfaces - Point-of-sale backend access - Staff scheduling and shift management **Example Scenarios:** 1. **Reception Kiosk:** Public-facing sites rotate (directory, weather, news), but staff can swipe up with PIN to access appointment scheduling, visitor management, or internal messaging. 2. **Family Room Display:** Displays photo slideshows, calendar, and weather, but parents can PIN-access streaming services, smart home controls, or security cameras. 3. **Digital Signage:** Publicly shows announcements and menus, but managers can PIN-access the content management system to make updates. 4. **Conference Room Display:** Shows meeting schedules and company news, but attendees can PIN-access video conferencing or presentation tools. The hidden tab system provides a balance between public accessibility and private functionality without needing to physically access a terminal or reconfigure the system. #### Why Use Named Sites? Named sites provide user-friendly labels that make navigation and management easier, especially when dealing with multiple similar URLs or complex web addresses. **Benefits:** - **Easier Navigation:** Click "Photo Gallery" instead of remembering "https://immich.mydomain.com:2283" - **Better Organization:** Quickly identify sites in the navigation menu without parsing URLs - **User-Friendly:** Non-technical users can find sites by name instead of domain - **Cleaner Display:** "Home Assistant" is more readable than "http://192.168.1.50:8123" - **Professional Appearance:** Business kiosks benefit from descriptive names over technical URLs **Use Cases:** **Home/Family Kiosks:** - "Photo Albums" instead of "https://photoprism.local:2342" - "Weather" instead of "https://weather.com" - "Security Cameras" instead of "http://192.168.1.100:8000" - "Smart Home" instead of "http://homeassistant.local:8123" **Business Kiosks:** - "Employee Portal" instead of "https://portal.company.com/employees" - "Time Clock" instead of "https://timekeeping.company.com/punch" - "Inventory System" instead of "http://10.0.0.50:8080/inventory" - "Customer Service" instead of "https://crm.company.com/support" **Digital Signage:** - "Dashboard 1" through "Dashboard 5" for rotating content - "Announcements" instead of "https://cms.local/public/announcements" - "Menu Board" instead of "http://192.168.1.75/menus/today" **Multi-Location Setups:** - "Building A Reception" and "Building B Reception" for identical URL structures - "Floor 1 Display" through "Floor 10 Display" for elevator kiosks - "East Wing" and "West Wing" for hospital navigation Names are completely optional - if left blank, the URL will be displayed as usual. Configure names during initial setup or update them later via: Core Settings → Sites → Update site names. ### Inactivity Extensions When "Are you still here?" prompt appears (on manual or hidden sites): - **"Yes, I'm still here"** - Reset all timers, stay on current page - **Time extensions** (15m, 30m, 1h, 2h) - Pause rotation and inactivity - **"No, go home"** - Return to home URL immediately - Extensions pause BOTH rotation and lockout timers - Maximum extension: 4 hours (safety timeout) **Triggers on:** - Manual sites (duration = 0) after inactivity timeout - Hidden sites (duration = -1) after inactivity timeout - Does NOT trigger on auto-rotating sites (duration > 0) - they use pause button instead ### Lockout Behavior **Triggers:** - Inactivity timeout expires (if configured) - Scheduled lockout time reached (if configured) - Display schedule wake-up (if password-on-wake enabled) - System boot (if requirePasswordOnBoot enabled) **During Lockout:** - Full black screen (no content visible) - All browser views detached for security - Password prompt displayed - Limited power menu (no Reload option to prevent bypass) - Rotation and timers paused **After Unlock:** - Returns to previous site - Timers reset - Normal operation resumes ### Media Detection Detects and pauses for: - HTML5 `