Published 2026-05-27 · 11 min read

Home Assistant security checklist — hardening before you expose the smart home

Home Assistant is the single highest-value target in most homelabs. It speaks to your locks, your cameras, your alarm panel, every smart plug, and increasingly your car. A compromise isn't a stolen Plex library — it's somebody opening your garage door at 3am. This is the twelve-check hardening pass to run before HA goes anywhere near the internet, and to re-run every few months because HA changes fast and the attack surface drifts with it.

For the general pre-exposure pattern this post specialises, see Before you expose a service to the web. For the wider category of Grafana / Portainer / Pi-hole / HA admin UIs that get found by Shodan within hours, see exposed admin surfaces — the #1 homelab compromise vector. Both apply here verbatim; this post is the HA-specific layer on top.

Step 1 — Decide whether HA needs to be public at all

Before any hardening, ask the only question that obviates most of it: does Home Assistant actually need a public DNS record and an open port? The answer for the overwhelming majority of users is no. You want remote access from your phone — that is not the same thing as exposing port 8123 to the entire internet.

Three good remote-access patterns, in roughly increasing order of effort:

If any of these solve your problem — and one of them almost certainly does — choose one and stop. The rest of this checklist still matters (LAN-only HA can still be pivoted to from a compromised IoT device), but the threat model collapses from "anyone on the internet" to "anyone already on my network." That is the single biggest reduction available.

Step 2 — Audit auth providers and the trusted_networks footgun

Open configuration.yaml and look at the homeassistant.auth_providers block. The default and correct setup is a single homeassistant provider — username and password, with HA's own bcrypt hashing. Anything else needs scrutiny.

homeassistant:
  auth_providers:
    - type: homeassistant
    # NOT this, ever, on an internet-facing HA:
    # - type: trusted_networks
    #   trusted_networks:
    #     - 192.168.1.0/24
    #     - 172.16.0.0/12

The trusted_networks provider tells HA "for these IP ranges, skip authentication entirely." On a LAN-only install that's fine. The footgun: the moment you put HA behind a reverse proxy, the source IP HA sees is the proxy, not the real client. If you've added the proxy's IP to trusted_networks, every request from the internet now bypasses auth. Several public HA compromises trace exactly to this misconfig.

Settle on this rule: never trust an IP range that contains an internet-facing reverse proxy. If you need a passwordless LAN experience, use the allow_bypass_login flag on a named user with strong defence-in-depth elsewhere, not blanket IP trust.

While you're in the auth UI (Settings → People → Users), audit the user list. Every user account that exists has a reachable password. Remove the test accounts. Demote anyone who doesn't need admin to a non-admin user. Force MFA on every admin account — HA supports TOTP natively.

Step 3 — Rotate long-lived access tokens

Long-lived access tokens (LLATs) are HA's bearer credentials for external integrations: Grafana scraping HA, an automation in Node-RED, the hass CLI from another host, a custom Lovelace card that calls the REST API. They never expire. They have full user permissions. If one leaks into a Git repo, a Discord paste, or a shared screenshot, the leaker is the attacker.

Audit them in your profile → Long-lived access tokens. You're looking for:

Every LLAT belongs in a secrets store on the consumer side (1Password, Bitwarden, a .env file outside Git), never in a committed config file. See Step 7 for the secrets story end-to-end.

Step 4 — Reverse proxy + TLS, never expose raw 8123

Home Assistant's built-in HTTP server is fine for LAN use, but it isn't where you want internet traffic terminating. Put it behind a reverse proxy that handles TLS, request inspection, and rate limiting. Caddy, Traefik, and Nginx Proxy Manager are the three common picks; all three do Let's Encrypt automatically.

A minimal Caddy config:

ha.example.com {
    reverse_proxy 192.168.1.50:8123 {
        header_up X-Forwarded-For {remote_host}
        header_up X-Forwarded-Proto {scheme}
    }
    encode gzip
    header Strict-Transport-Security "max-age=31536000; includeSubDomains"
}

Then tell HA to honour the proxy headers — and only the proxy:

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.1.10        # the proxy's LAN IP, nothing wider
  ip_ban_enabled: true
  login_attempts_threshold: 5

trusted_proxies must be the narrowest CIDR that contains your reverse proxy — never 0.0.0.0/0, never 10.0.0.0/8, never the IoT VLAN. If HA trusts a wider range, attackers can spoof X-Forwarded-For and bypass IP bans.

Confirm port 8123 is firewalled at the host. The only thing on your network that should be able to reach 8123 directly is the reverse proxy box. See TLS certificate expiry on self-hosted services for the renewal side; a HA reverse proxy that quietly fails to renew is the kind of outage you find out about from a confused household at 8am.

Step 5 — Supervisor add-ons are individual admin surfaces

Home Assistant OS and Supervised installs come with the add-on store: AdGuard Home, ESPHome, Zigbee2MQTT, Node-RED, File Editor, SSH & Web Terminal, Mosquitto, InfluxDB, Grafana, Frigate. Most of them ship a web UI of their own.

Two settings on every add-on warrant attention:

Check from the HA host:

ss -tlnp | grep -v '127.0.0.1\|::1'

Anything bound to 0.0.0.0 or your LAN IP is an exposed admin surface. For each one, decide: does it need to be reachable outside HA Ingress at all? If not, set the add-on's network config to leave the port blank — HA will only expose it via the authenticated Ingress proxy.

The SSH & Web Terminal add-on deserves a special mention. The community version supports SSH key authentication and a hardened sshd config; the "official" version is friendlier but historically defaults less strictly. Either way, disable password auth and only allow specific keys. See SSH key hygiene for homelabs for the audit.

Step 6 — HACS and custom integrations are a supply chain

HACS — the Home Assistant Community Store — pulls integrations directly from arbitrary GitHub repositories. It is enormously useful and it is also the single largest source of supply-chain risk in a typical HA install. Custom integrations run in the HA process. They have full access to HA's secrets, every entity, every connected device.

Treat them accordingly:

The same logic applies to custom Lovelace cards, themes, and AppDaemon apps. Any code you didn't write that runs inside HA can read every token, every API key, every camera feed. Audit it like you would a server-side dependency.

Step 7 — Move every secret out of YAML and Git

configuration.yaml, automation YAML, script YAML — none of these should contain a single literal API key, password, or token. Everything goes through secrets.yaml with !secret references:

# secrets.yaml — NEVER committed
mqtt_password: "long-random-string"
notify_pushover_token: "azGD..."
spotify_client_secret: "1c2d..."

# configuration.yaml — safe to commit
mqtt:
  broker: 127.0.0.1
  password: !secret mqtt_password

notify:
  - platform: pushover
    api_key: !secret notify_pushover_token

Add secrets.yaml, known_devices.yaml, and the entire .storage/ directory to .gitignore the moment you initialise the repo. Audit existing history with trufflehog before pushing to a public remote:

trufflehog filesystem /config
trufflehog git file:///path/to/your/ha-config.git

If anything leaked, assume the secret is burned. Rotate the credential at the upstream service, then rewrite Git history with git filter-repo and force-push. Future you will not enjoy the rotation, but past-you's mistake is bounded from here.

Step 8 — Segment IoT devices on their own VLAN

Most smart-home gear is shipped by manufacturers whose security maturity is measurably worse than a typical Linux distro. Cheap Zigbee plugs, off-brand IP cameras, Wi-Fi smart bulbs — these run vendor firmware that is rarely patched and frequently phoning home to servers you can't audit. Putting Home Assistant on the same flat LAN is asking for lateral movement.

The pattern that works:

pfSense, OPNsense, UniFi, and Mikrotik all do VLAN-tagged networks at the homelab price point. Spend the weekend; it pays back the first time a Wi-Fi camera firmware turns out to phone home to a server in a jurisdiction you weren't expecting.

Step 9 — Backups, encryption, and a restore drill

Home Assistant accumulates state — automations, dashboards, device registrations, historical data — that is genuinely hard to rebuild. Loss is not catastrophic the way a stolen credential is, but a corrupted SD card on a Pi after eighteen months of accreted config will ruin a weekend.

The Backups feature (Supervisor → Backups) handles the local snapshot. The parts that are easy to skip:

Step 10 — Stay current on HA Core, OS, and base images

Home Assistant Core releases approximately monthly. Major breaking changes ship on a predictable schedule; security fixes do not. HA OS, Supervisor, and the add-on base images update independently. Falling more than two releases behind on Core is the most common drift pattern.

The cadence that works at homelab scale:

The "set it and forget it" HA install — three years on the same Core release, OS untouched since flash — is overwhelmingly common and overwhelmingly the install that compromises catch out. HA Core has had real CVEs over the years; staying current is the only sustainable defence.

Common mistakes

Where Noxen fits in

Noxen is a Mac-native agentless scanner for the Linux hosts running your homelab — including the HA OS host, the Pi running Supervised HA, or the VM serving HA Container. It flags exposed Home Assistant admin surfaces among roughly seventy services it detects (Grafana, Portainer, Frigate, Plex, *arr, Pi-hole, Mosquitto, the lot), checks SSH and TLS hygiene on every host, and matches the installed package set against a signed daily CVE feed.

Run it on a schedule and it surfaces drift the morning after: port 8123 became reachable, a new add-on opened a host port, an SSH config edit re-enabled passwords. $79 one-time at noxen.app. For the wider rhythm see the 30-minute homelab security baseline.

Try Noxen$79 one-time, agentless, diff-from-yesterday reports for the boxes that run your smart home.

Scan the boxes that run your smart home

Noxen runs nightly agentless audits over SSH and shows only what changed since the last scan — exposed Home Assistant or add-on UIs, new CVEs, SSH and TLS drift. Mac-native control plane, no agents on the targets.

Buy Noxen — $79 one-time Download free trial