Ansible Guide
Purpose
Provision supported kiosk devices (Debian 12+ and Raspberry Pi OS Bookworm) for Freeboard with a profile-driven, modular workflow.
This automation is designed for production-safe operation:
- explicit profile selection
- fail-fast preflight checks
- optional high-risk roles (boot tuning, runtime)
- backup/rollback path for managed system files
Supported targets
- Debian 12+ (x86_64)
- Raspberry Pi OS 64-bit (Bookworm) on Pi 4/5
Architecture
Main playbook: ansible/playbook.yml
Roles:
kiosk_preflight: validates platform + required settingskiosk_base: service user + base directories/packageskiosk_display: X11 + Chromium dependencies/configkiosk_player:player.shdeployment +/etc/freeboard/kiosk.env+freeboard-kiosk.servicecontainer_runtime(optional): Docker installkiosk_boot_tuning(optional): splash and boot tuning
Rollback playbook: ansible/rollback.yml
Profiles
Set kiosk_profile in inventory/group vars or via -e:
player_only(default)- player + display only
- no Docker/runtime changes
- no boot tuning
appliance_with_runtime- includes
container_runtime
- includes
appliance_with_runtime_and_boot_tuning- includes runtime and boot tuning
Per-role overrides are available (kiosk_enable_* booleans).
Required config
Required variable:
kiosk_player_url(dashboard URL the device opens)
Commonly overridden:
kiosk_service_userkiosk_player_script_sourcekiosk_browser_binarykiosk_url_check_mode(none|get|head)kiosk_systemd_no_new_privileges(defaultfalsefor Xorg/startx compatibility)
If the same appliance host also runs the API/gateway compose stack, keep runtime limiter defaults aligned with production hardening:
SECURITY_LIMITER_BACKENDmust matchDB_BACKEND(postgresin release runtime)SECURITY_LIMITER_FAILURE_MODE=fail-closedREALTIME_LIMITER_FAILURE_MODE=fail-closed
For staged rollout and rollback of these security controls, follow:
Reference defaults are listed under server_runtime_env_defaults in ansible/vars.yml.
If using appliance_with_runtime profiles on 32-bit Raspberry Pi OS, pin image tags to the legacy armv7 track (latest-armv7, v*-armv7, or sha-*-armv7).
External references for container architecture constraints:
- https://docs.docker.com/engine/install/raspberry-pi-os/
- https://docs.docker.com/engine/release-notes/29/
- https://github.com/nodejs/docker-node
- https://hub.docker.com/_/node
Reference defaults: ansible/vars.yml
Inventory setup
Create inventory from the example:
cp ansible/inventory.ini.example ansible/inventory.iniThen choose one pattern:
- Control-node pattern (recommended for production):
- Set one or more remote hosts under
[kiosk](withansible_hostandansible_user).
- Self-provision pattern (single-device bootstrap):
- Use localhost with local connection:
localhost ansible_connection=local
Execution patterns
Pattern A: Control Node to Remote Kiosk Hosts (Production)
Run from your control machine (not from the Pi itself).
ANSIBLE_CONFIG=ansible/ansible.cfg ansible-playbook -i ansible/inventory.ini ansible/playbook.yml -e "kiosk_profile=player_only kiosk_player_url=http://192.168.1.20:8080/s/abc123" --check --diffApply after dry-run:
ANSIBLE_CONFIG=ansible/ansible.cfg ansible-playbook -i ansible/inventory.ini ansible/playbook.yml -e "kiosk_profile=player_only kiosk_player_url=http://192.168.1.20:8080/s/abc123"Pattern B: Self-Provision on the Kiosk Device (Single Host)
SSH into the target Pi, then run Ansible locally:
python -m venv .venv
.venv/bin/pip install -r requirements.txt
ANSIBLE_CONFIG=ansible/ansible.cfg .venv/bin/ansible-playbook -i localhost, -c local ansible/playbook.yml -e "freeboard_target_group=all kiosk_profile=player_only kiosk_player_url=http://127.0.0.1:8080/s/abc123" --check --diff
ANSIBLE_CONFIG=ansible/ansible.cfg .venv/bin/ansible-playbook -i localhost, -c local ansible/playbook.yml -e "freeboard_target_group=all kiosk_profile=player_only kiosk_player_url=http://127.0.0.1:8080/s/abc123"Notes:
freeboard_target_group=allis required in localhost mode becauselocalhost,is not in the defaultkioskgroup.- Reboot is usually not required for
player_only; usesudo systemctl restart freeboard-kiosk.serviceafter config changes if needed.
Role tags
Target selected roles/tags if needed:
preflightkiosk_basekiosk_displaykiosk_playercontainer_runtimekiosk_boot_tuning
Example:
ANSIBLE_CONFIG=ansible/ansible.cfg ansible-playbook -i ansible/inventory.ini ansible/playbook.yml -t preflight,kiosk_player -e "kiosk_player_url=http://192.168.1.20:8080/s/abc123"Quality checks
Local checks:
ansible-lint ansible/playbook.yml ansible/rollback.yml
ansible-playbook -i localhost, ansible/playbook.yml --syntax-check -e "freeboard_target_group=all kiosk_player_url=http://localhost:8080/s/demo"
ansible-playbook -i localhost, ansible/rollback.yml --syntax-check -e "freeboard_target_group=all"CI check workflow: .github/workflows/ansible-quality.yml
Service contract
The role installs:
- env file:
/etc/freeboard/kiosk.env - systemd unit:
/etc/systemd/system/freeboard-kiosk.service - script:
/opt/freeboard/player.sh(default)
player.sh now supports bounded startup probing via:
FREEBOARD_URL_CHECK_MODEFREEBOARD_URL_CHECK_TIMEOUT_SECONDSFREEBOARD_URL_CHECK_INTERVAL_SECONDSFREEBOARD_URL_CHECK_MAX_ATTEMPTS
Rollback
Rollback managed kiosk artifacts:
ANSIBLE_CONFIG=ansible/ansible.cfg ansible-playbook -i ansible/inventory.ini ansible/rollback.ymlRollback from inside the kiosk host (localhost/self-provision pattern):
ANSIBLE_CONFIG=ansible/ansible.cfg ansible-playbook -i localhost, -c local ansible/rollback.yml -e "freeboard_target_group=all"This stops the kiosk service, restores managed backups where present, removes managed service/env files, and reloads systemd.
Post-apply verification
Pattern A (control node to remote host):
ansible -i ansible/inventory.ini kiosk -b -m shell -a "systemctl is-enabled freeboard-kiosk.service && systemctl is-active freeboard-kiosk.service"
ansible -i ansible/inventory.ini kiosk -b -m shell -a "journalctl -u freeboard-kiosk.service -n 50 --no-pager"Pattern B (inside kiosk host):
sudo systemctl is-enabled freeboard-kiosk.service
sudo systemctl is-active freeboard-kiosk.service
sudo journalctl -u freeboard-kiosk.service -n 50 --no-pagerWhen kiosk_profile includes boot tuning, schedule a controlled reboot window and validate service state again after reboot.
Security notes
- Do not run kiosk devices with admin/editor credentials.
- Prefer viewer-only accounts or share-token URLs for kiosk playback.
- Keep execution mode
safefor kiosk and IoT deployments unless explicitly justified. - Keep host key checking enabled for production automation.