4.4 KiB
4.4 KiB
Parental Controls Dashboard with OPNsense Alias Blocking
Date: 2026-05-18 Project: ha-parental-controls Status: resolved Tags: home-assistant, opnsense, firewall-alias, dhcp, websocket, rest_command, input_text, dashboard
Context
Jess wanted a Home Assistant panel to block and unblock internet access per child and per device, backed by the OPNsense firewall, with optional scheduled access windows. The first version (2026-05-10) worked in principle but hit a series of problems over the following week: WebSocket timeouts on load, broken HA auth handshake, config too large for a single input_text, OPNsense rejecting alias updates, and tablets needing credentials entered on every device.
Key Decisions
- OPNsense firewall alias (
parental_blocked) + one LAN block rule — HA only adds/removes IPs from the alias; no per-device firewall rules to manage. - Identify devices by MAC, resolve to current IP at block time — blocks re-apply automatically when a device reconnects with a new IP.
- Standalone HTML panel (
panel_iframe) instead of Lovelace cards — the UI (users, devices, toggles, schedules) is too interactive for core cards. - Device discovery/status from an OPNsense DHCP lease REST sensor rather than
device_trackerentities alone — gives hostnames, addresses and expiry in one place. - Config persisted in HA, chunked across 12
input_textentities (12 × 255 = 3060 chars) — a singleinput_textwith max 10000 is invalid (HA caps at 255), and HA storage means config is shared across devices, unlike localStorage. - REST API for initial state load, WebSocket for live updates — loading all states over WS timed out; WS timeout raised to 60s.
- OPNsense
alias_utilcalls use a JSON payload — the API rejects form-encoded bodies. - Auto-detect HA URL from
window.location.origin— works over HTTP, HTTPS, LAN IP or domain without configuration. - Optional token in a
CONFIGblock in the HTML so the panel works on every device without per-device setup. Trade-off: this contradicts the project principle of no hardcoded credentials — the repo copy must stay blank (CONFIG_HA_TOKEN = ''), and the token is only filled in on the HA host's copy.
Technical Details
- Files:
packages/parental_controls.yaml(rest_commands, scripts, sensors,input_textchunks, optional schedule automation),www/parental_controls.html(panel),secrets_example.yaml. - Secrets used:
opnsense_alias_add_url,opnsense_alias_del_url,opnsense_apply_url(/api/firewall/alias/reconfigure),opnsense_basic_auth(base64 of key:secret),opnsense_leases_url. Values<redacted>. - OPNsense API key needs Firewall: Alias read/write.
- DHCP sensor:
sensor.home_dhcp_leases_lan, data underattributes.Leases(capital L) withaddress/hostname/expires. - HA WS auth: send the auth message with raw
ws.send()— the helpersend()waits for aresult, but HA replies to auth withauth_ok/auth_invalid. lastSaveTimeguard prevents the display blanking when theinput_textstate echo arrives right after a save.- Panel added via
panel_iframeat/local/parental_controls.html,require_admin: true.
Code Changes
packages/parental_controls.yaml— rest_commands (JSON payload), DHCP lease REST sensor, 12 chunkedinput_textentities, scripts, optional schedule automation.www/parental_controls.html— REST initial load + WS updates, WS auth fix, DHCP-based discovery and HA/DHCP status indicators, chunkedparseCfg/saveCfg, save-error handling,lastSaveTimeguard, URL auto-detect, optional CONFIG token.secrets_example.yaml,README.md— setup docs.
Open Questions / Next Steps
- Schedules only run while the panel is open in a browser. For reliable enforcement, move schedule logic into an HA automation (the package has an optional one) so it runs server-side.
- Consider an HA-side way to supply the token (e.g. trusted network auth or a proxy) so the HTML never needs a hardcoded token.
- Overlaps with
opnsense-device-control,ha-device-assignmentand the newerhomenet-guardrails— decide which is canonical going forward.
Artifacts
bd49964— Auto-detect URL from page origin4142d1c— Fix empty display after save + OPNsense JSON payload fix8a5fe10/cf8d7ee— Chunked storage (12×255)4ecdda5— Redesign on OPNsense DHCP lease sensor5593d14— WS auth viaws.send()76b67d3— REST initial load, 60s WS timeout