From fc8d1eea11294dd355303df6e76b8b21d16fed3e Mon Sep 17 00:00:00 2001 From: jessikitty Date: Sun, 10 May 2026 21:44:22 +1000 Subject: [PATCH] Upload files to "/" Re-uploaded Failed Files --- README.md | 202 ++++++++++++++++++++++++++++--------------- secrets_example.yaml | 14 ++- 2 files changed, 143 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index c05bdc6..719a579 100644 --- a/README.md +++ b/README.md @@ -1,119 +1,177 @@ -ha-parental-controls +# ha-parental-controls + A Home Assistant dashboard for per-user, per-device internet blocking via OPNsense firewall alias management. Assign devices to users by MAC address, block/unblock individually or per-user, and optionally enforce scheduled access windows. -How it works +--- -OPNsense maintains a firewall alias called parental_blocked -A LAN rule blocks all traffic from IPs in that alias -The HA dashboard looks up each device's current IP from device_tracker entities (provided by the OPNsense integration), then adds/removes IPs from the alias via OPNsense API +## How it works -Because devices are identified by MAC address, blocks re-apply automatically when a device reconnects with a new IP (handled by a state change listener in the dashboard). +1. OPNsense maintains a firewall alias called `parental_blocked` +2. A LAN rule blocks all traffic from IPs in that alias +3. The HA dashboard looks up each device's current IP from `device_tracker` entities (provided by the OPNsense integration), then adds/removes IPs from the alias via OPNsense API + +Because devices are identified by **MAC address**, blocks re-apply automatically when a device reconnects with a new IP (handled by a state change listener in the dashboard). + +--- + +## Step 1 — OPNsense setup + +### 1.1 Create the firewall alias -Step 1 — OPNsense setup -1.1 Create the firewall alias Firewall → Aliases → + -FieldValueNameparental_blockedTypeHost(s)DescriptionParental Controls — blocked devicesContent(leave empty — managed via API) -Save, then Apply. -1.2 Create the blocking rule -Firewall → Rules → LAN → + -FieldValueActionBlockInterfaceLANDirectioninProtocolanySourceSingle host or alias → parental_blockedDestinationanyDescriptionParental Controls — block internet -Position this rule above your default allow-all LAN rule. Save and Apply. -1.3 Create an API key -System → Access → Users → (your admin user or a dedicated user) → API Keys → + -Permissions needed: Firewall: Alias (read + write) -Note the Key and Secret — you'll need them for secrets.yaml. -Step 2 — Home Assistant setup -2.1 Add secrets to /config/secrets.yaml +| Field | Value | +|---|---| +| Name | `parental_blocked` | +| Type | `Host(s)` | +| Description | `Parental Controls — blocked devices` | +| Content | *(leave empty — managed via API)* | + +Save, then **Apply**. + +### 1.2 Create the blocking rule + +Firewall → Rules → LAN → + + +| Field | Value | +|---|---| +| Action | **Block** | +| Interface | LAN | +| Direction | in | +| Protocol | any | +| Source | Single host or alias → `parental_blocked` | +| Destination | any | +| Description | `Parental Controls — block internet` | + +Position this rule **above** your default allow-all LAN rule. Save and Apply. + +### 1.3 Create an API key + +System → Access → Users → (your admin user or a dedicated user) → API Keys → + + +Permissions needed: **Firewall: Alias** (read + write) + +Note the **Key** and **Secret** — you'll need them for secrets.yaml. + +--- + +## Step 2 — Home Assistant setup + +### 2.1 Add secrets to `/config/secrets.yaml` + Replace values with your actual OPNsense details: -yamlopnsense_alias_add_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/add/parental_blocked" + +```yaml +opnsense_alias_add_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/add/parental_blocked" opnsense_alias_del_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias_util/delete/parental_blocked" opnsense_apply_url: "https://YOUR_OPNSENSE_IP/api/firewall/alias/reconfigure" # Generate with: echo -n "APIKEY:APISECRET" | base64 opnsense_basic_auth: "Basic BASE64_OF_KEY_COLON_SECRET" +``` + To generate the base64 string on any Linux/macOS machine: -bashecho -n "your_api_key:your_api_secret" | base64 -2.2 Copy files into place -bash# From your config directory +```bash +echo -n "your_api_key:your_api_secret" | base64 +``` + +### 2.2 Copy files into place + +```bash +# From your config directory cp packages/parental_controls.yaml /config/packages/ cp www/parental_controls.html /config/www/ +``` -If you don't use packages yet, add this to /config/configuration.yaml: -yamlhomeassistant: - packages: !include_dir_named packages +> If you don't use packages yet, add this to `/config/configuration.yaml`: +> ```yaml +> homeassistant: +> packages: !include_dir_named packages +> ``` -2.3 Add the sidebar panel -Add to /config/configuration.yaml: -yamlpanel_iframe: +### 2.3 Add the sidebar panel + +Add to `/config/configuration.yaml`: + +```yaml +panel_iframe: parental_controls: title: "Parental Controls" icon: mdi:shield-account url: /local/parental_controls.html require_admin: true -2.4 Restart Home Assistant -Check for errors in Settings → System → Logs. The input_text.parental_control_config entity should now exist. +``` -Step 3 — Dashboard first run +### 2.4 Restart Home Assistant -Open the Parental Controls sidebar panel -On first load, you'll see a setup screen. Enter: +Check for errors in Settings → System → Logs. The `input_text.parental_control_config` entity should now exist. -HA URL: your HA URL (e.g. https://ha.hideawaygaming.com.au) -Long-Lived Token: from your HA Profile → Security → Long-Lived Access Tokens → Create Token +--- +## Step 3 — Dashboard first run -Click Connect +1. Open the **Parental Controls** sidebar panel +2. On first load, you'll see a setup screen. Enter: + - **HA URL**: your HA URL (e.g. `https://ha.hideawaygaming.com.au`) + - **Long-Lived Token**: from your HA Profile → Security → Long-Lived Access Tokens → Create Token +3. Click **Connect** -Your credentials are saved to browser localStorage — you won't need to enter them again on the same device. +Your credentials are saved to browser `localStorage` — you won't need to enter them again on the same device. -Usage -Adding users -Click + Add User, give them a name and pick a colour. -Adding devices -On a user card, click + Add Device. Either: +--- -Pick from the discovered devices list (devices seen by the OPNsense integration) -Or enter a MAC address manually +## Usage +### Adding users -Tip: Set DHCP static leases in OPNsense for kids' devices so their IPs stay consistent, though the dashboard handles IP changes automatically. +Click **+ Add User**, give them a name and pick a colour. -Blocking +### Adding devices -User toggle (top right of card): blocks/unblocks all devices for that user simultaneously -Device toggle (on each device row): individual device control +On a user card, click **+ Add Device**. Either: +- Pick from the **discovered devices** list (devices seen by the OPNsense integration) +- Or enter a MAC address manually + +> **Tip**: Set DHCP static leases in OPNsense for kids' devices so their IPs stay consistent, though the dashboard handles IP changes automatically. + +### Blocking + +- **User toggle** (top right of card): blocks/unblocks all devices for that user simultaneously +- **Device toggle** (on each device row): individual device control If a device is offline when you block it, the dashboard marks it blocked and will apply the firewall rule automatically when the device reconnects. -Scheduling -Expand the 🕐 Schedule section on any user card: -Enable the schedule toggle -Set block and unblock times for weekdays and weekends -Times are enforced every minute while the dashboard page is open +### Scheduling -The time range is the blocked window — e.g. 21:00 → 07:00 means blocked from 9pm until 7am (overnight ranges work correctly). -HA-native schedule enforcement (optional) -For schedules to be enforced even when the dashboard isn't open, uncomment the automation: block at the bottom of packages/parental_controls.yaml and restart HA. Note: the YAML automation requires the from_json Jinja2 filter and HA 2023.4+. +Expand the **🕐 Schedule** section on any user card: -Troubleshooting -Block doesn't seem to apply +1. Enable the schedule toggle +2. Set **block** and **unblock** times for weekdays and weekends +3. Times are enforced every minute while the dashboard page is open -Confirm the parental_blocked alias exists in OPNsense → Firewall → Aliases -Check the blocking rule is above the default LAN allow rule -Verify your API credentials: test in a browser → https://YOUR_OPNSENSE/api/firewall/alias_util/aliases — should return JSON +The time range is the **blocked** window — e.g. `21:00 → 07:00` means blocked from 9pm until 7am (overnight ranges work correctly). -Device not appearing in discovered list +#### HA-native schedule enforcement (optional) -Make sure the OPNsense integration is installed and the device has been seen recently -Try using a manual MAC entry instead +For schedules to be enforced even when the dashboard isn't open, uncomment the `automation:` block at the bottom of `packages/parental_controls.yaml` and restart HA. Note: the YAML automation requires the `from_json` Jinja2 filter and HA 2023.4+. -"Failed to save config" +--- -Check HA logs for input_text.parental_control_config errors -Ensure the package loaded correctly (no YAML errors in startup logs) +## Troubleshooting -Dashboard won't connect +**Block doesn't seem to apply** +- Confirm the `parental_blocked` alias exists in OPNsense → Firewall → Aliases +- Check the blocking rule is above the default LAN allow rule +- Verify your API credentials: test in a browser → `https://YOUR_OPNSENSE/api/firewall/alias_util/aliases` — should return JSON -Confirm the Long-Lived Token is correct -If using a self-signed cert on HA, the page may have cert warnings — trust the cert first by visiting the HA URL directly \ No newline at end of file +**Device not appearing in discovered list** +- Make sure the OPNsense integration is installed and the device has been seen recently +- Try using a manual MAC entry instead + +**"Failed to save config"** +- Check HA logs for `input_text.parental_control_config` errors +- Ensure the package loaded correctly (no YAML errors in startup logs) + +**Dashboard won't connect** +- Confirm the Long-Lived Token is correct +- If using a self-signed cert on HA, the page may have cert warnings — trust the cert first by visiting the HA URL directly diff --git a/secrets_example.yaml b/secrets_example.yaml index c355381..93e7e0a 100644 --- a/secrets_example.yaml +++ b/secrets_example.yaml @@ -1 +1,13 @@ -IyBBZGQgdGhlc2UgZW50cmllcyB0byB5b3VyIC9jb25maWcvc2VjcmV0cy55YW1sCiMgUmVwbGFjZSB3aXRoIHlvdXIgYWN0dWFsIE9QTnNlbnNlIGRldGFpbHMKCiMgWW91ciBPUE5zZW5zZSBhbGlhcyBBUEkgZW5kcG9pbnRzCiMgUmVwbGFjZSAib3Buc2Vuc2UuaGlkZWF3YXlnYW1pbmcuY29tLmF1IiB3aXRoIHlvdXIgT1BOc2Vuc2UgSVAgb3IgaG9zdG5hbWUKb3Buc2Vuc2VfYWxpYXNfYWRkX3VybDogImh0dHBzOi8vb3Buc2Vuc2UuaGlkZWF3YXlnYW1pbmcuY29tLmF1L2FwaS9maXJld2FsbC9hbGlhc191dGlsL2FkZC9wYXJlbnRhbF9ibG9ja2VkIgpvcG5zZW5zZV9hbGlhc19kZWxfdXJsOiAiaHR0cHM6Ly9vcG5zZW5zZS5oaWRlYXdheWdhbWluZy5jb20uYXUvYXBpL2ZpcmV3YWxsL2FsaWFzX3V0aWwvZGVsZXRlL3BhcmVudGFsX2Jsb2NrZWQiCm9wbnNlbnNlX2FwcGx5X3VybDogImh0dHBzOi8vb3Buc2Vuc2UuaGlkZWF3YXlnYW1pbmcuY29tLmF1L2FwaS9maXJld2FsbC9hbGlhcy9yZWNvbmZpZ3VyZSIKCiMgQmFzaWMgYXV0aCBoZWFkZXIg4oCUIGdlbmVyYXRlIHdpdGg6CiMgICBlY2hvIC1uICJZT1VSX0FQSV9LRVk6WU9VUl9BUElfU0VDUkVUIiB8IGJhc2U2NAojIFRoZW4gcGFzdGUgdGhlIHJlc3VsdCBpbiBwbGFjZSBvZiB0aGUgcGxhY2Vob2xkZXIgYmVsb3c6Cm9wbnNlbnNlX2Jhc2ljX2F1dGg6ICJCYXNpYyBSRVBMQUNFX1dJVEhfQkFTRTY0X09GX0FQSUtFWV9DT0xPTl9BUElTRUNSRVQiCg== \ No newline at end of file +# Add these entries to your /config/secrets.yaml +# Replace with your actual OPNsense details + +# Your OPNsense alias API endpoints +# Replace "opnsense.hideawaygaming.com.au" with your OPNsense IP or hostname +opnsense_alias_add_url: "https://opnsense.hideawaygaming.com.au/api/firewall/alias_util/add/parental_blocked" +opnsense_alias_del_url: "https://opnsense.hideawaygaming.com.au/api/firewall/alias_util/delete/parental_blocked" +opnsense_apply_url: "https://opnsense.hideawaygaming.com.au/api/firewall/alias/reconfigure" + +# Basic auth header — generate with: +# echo -n "YOUR_API_KEY:YOUR_API_SECRET" | base64 +# Then paste the result in place of the placeholder below: +opnsense_basic_auth: "Basic REPLACE_WITH_BASE64_OF_APIKEY_COLON_APISECRET"