Expose Kubernetes applications in Home Assistant¶
Ecosystem guide — how hass_ingress works with the operator to put an independently deployed application in the Home Assistant sidebar. Not part of the operator's supported API.
Deploy applications with their own Helm chart, operator, or manifests, then use
hass_ingress to present their web
interface through Home Assistant. The application remains an ordinary Kubernetes
workload; Home Assistant provides the sidebar entry, authenticates the user, and
proxies requests through its own external URL.
Not part of the supported API
This guide shows one way to integrate the operator with another tool in the Kubernetes ecosystem. Unlike the rest of this documentation, it is not part of the operator's supported API — it reflects the state at the time of writing and may need adjusting for a different tool version or cluster setup.
Tested with: hass_ingress 1.3.2, Home Assistant 2026.9.2, operator 1.4.0-rc.0, Node-RED 5.0.7, and Kubernetes 1.34.
What this gives you¶
flowchart LR
Browser -->|Home Assistant session| HA[Home Assistant :8123]
HA -->|/api/ingress/nodered/| Ingress[hass_ingress]
Ingress -->|cluster HTTP| Service[Node-RED Service :1880]
- A sidebar entry for the application.
- Home Assistant authentication in front of the proxied application, optionally restricted to Home Assistant administrators.
- Access through the Home Assistant origin and port, without a separate public Ingress or Gateway route for the application.
- Independent application lifecycle management with Kubernetes-native tooling.
This is not a Supervisor add-on implementation. The operator does not install or
configure an application from add-on metadata, manage its updates, or provide a
SUPERVISOR_TOKEN. If the application needs the Home Assistant API, configure
its credentials separately and do not reuse the operator's bootstrap token.
Prerequisites¶
- A running Home Assistant instance with
bootstrap completed. The operator needs its
API token to register
hass_ingress. - An existing
HomeAssistantConfigurationfor the instance. - An application with an HTTP
Servicethat the Home Assistant pod can reach, or permission to deploy the Node-RED example below. - Outbound DNS and HTTPS access from the Home Assistant pod to
codeload.github.com, where the repository archive is downloaded.
The examples put Home Assistant and Node-RED in the homeassistant namespace and
name the Home Assistant resource home. Change all names consistently if your
installation differs.
Deploy the Node-RED backend¶
This deployment contains only the fields needed to start Node-RED and expose it
inside the cluster. A Service defaults to ClusterIP, so it does not create a
public Ingress or Gateway route:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-red
namespace: homeassistant
spec:
selector:
matchLabels:
app: node-red
template:
metadata:
labels:
app: node-red
spec:
containers:
- name: node-red
image: docker.io/nodered/node-red:5.0.7-24
---
apiVersion: v1
kind: Service
metadata:
name: node-red
namespace: homeassistant
spec:
selector:
app: node-red
ports:
- port: 1880
Add persistent storage for real use
This small example does not mount a volume. All flows, installed nodes, and
settings under /data are lost when the pod is replaced. For a real
installation, mount a PersistentVolumeClaim at /data as described in the
Node-RED documentation on
using a data volume.
The Service is now available to Home Assistant as
node-red.homeassistant.svc.cluster.local:1880. Keep it internal; the later
hass_ingress configuration provides the user-facing route.
Install hass_ingress¶
Install the custom integration directly from its HACS-compatible repository. A pinned tag makes upgrades deliberate and reproducible:
apiVersion: ha.homeassistant.io/v1
kind: HomeAssistantCommunityRepository
metadata:
name: hass-ingress
namespace: homeassistant
spec:
homeAssistantRef:
name: home
category: integration
repository: lovelylain/hass_ingress
ref: 1.3.2
HomeAssistantCommunityRepository is a stable v1 resource. Installing an
integration causes the operator to restart Home Assistant so that the custom
component becomes available.
Apply the resource and wait for both the repository and the restarted Home Assistant pod:
kubectl apply -f hass-ingress.yaml
kubectl wait hacr/hass-ingress -n homeassistant \
--for=condition=Ready --timeout=2m
kubectl rollout status statefulset/home -n homeassistant --timeout=5m
kubectl exec home-0 -n homeassistant -c home-assistant -- \
test -f /config/custom_components/ingress/manifest.json
Do not continue until the final command succeeds. A repository can be validated before its files are downloaded into the Home Assistant volume. If the file is missing, inspect the init container before restarting the pod:
Register the integration¶
Create its Home Assistant config entry and select YAML configuration mode:
apiVersion: ha.homeassistant.io/v1
kind: HomeAssistantIntegration
metadata:
name: ingress
namespace: homeassistant
spec:
homeAssistantRef:
name: home
domain: ingress
configuration:
mode:
value: yaml
kubectl apply -f ingress-integration.yaml
kubectl wait haint/ingress -n homeassistant \
--for=condition=Ready --timeout=2m
The config flow cannot start until Home Assistant has loaded the custom component, which is why the repository is installed and checked first.
Add the application to the sidebar¶
Add an ingress section to the spec.configuration of your existing
HomeAssistantConfiguration. Preserve the rest of that resource: it is the
source of truth for the complete configuration.yaml.
apiVersion: ha.homeassistant.io/v1
kind: HomeAssistantConfiguration
metadata:
name: home
namespace: homeassistant
spec:
homeAssistantRef:
name: home
configuration: |
default_config:
ingress:
nodered:
title: Node-RED
icon: mdi:sitemap
require_admin: true
url: http://node-red.homeassistant.svc.cluster.local:1880
nodered is the panel name and becomes part of its proxy path. The default
work_mode is ingress, which makes Home Assistant proxy the application. Keep
require_admin: true for administrative interfaces; set it to false only when
every authenticated Home Assistant user should have access.
Use the Service DNS name rather than a pod IP. For an application in another
namespace, use
<service>.<namespace>.svc.cluster.local:<port> and ensure any NetworkPolicy
allows traffic from the Home Assistant namespace.
Restrict direct backend access¶
Home Assistant authenticates the browser request, but the application Service is still directly reachable from workloads allowed by the cluster network. Do not publish a separate Ingress, Gateway route, LoadBalancer, or NodePort unless users are also meant to bypass Home Assistant.
If your cluster enforces network policies, allow only the Home Assistant pod to connect to the backend. This same-namespace example relies on the stable labels applied to operator-managed Home Assistant pods:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: node-red-from-home-assistant
namespace: homeassistant
spec:
podSelector:
matchLabels:
app: node-red
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app.kubernetes.io/name: homeassistant
app.kubernetes.io/instance: home
ports:
- protocol: TCP
port: 1880
NetworkPolicy enforcement requires a compatible CNI. Adapt both selectors when your application chart uses different labels.
Verify¶
Wait until both custom resources report ready:
kubectl get hacr hass-ingress -n homeassistant
kubectl get haint ingress -n homeassistant
kubectl get haconfig home -n homeassistant
Expected readiness indicators are:
NAME CATEGORY PHASE READY
hass-ingress integration Installed True
NAME DOMAIN READY
ingress ingress True
NAME STRATEGY READY
home auto True
Sign in to Home Assistant and select Node-RED in the sidebar. The browser URL
stays on the Home Assistant origin and the application is served below
/api/ingress/nodered/. Confirm that opening the application Service outside
that path is impossible from an untrusted network.
Compatibility limitations¶
The backend must work below a URL prefix. Applications that emit absolute URLs,
set cookies for incompatible paths, enforce their own origin, or reject proxied
WebSocket connections may need application-specific base-path settings or
hass_ingress rewrite rules. Some applications cannot be made compatible; use a
separate route with its own authentication proxy for those applications.
hass_ingress can inject headers for a backend that requires them. Store header
credentials in Home Assistant secrets.yaml through
HomeAssistantSecrets, then reference them with
!secret rather than putting credentials directly in
HomeAssistantConfiguration.
Security considerations¶
hass_ingress runs inside Home Assistant and forwards authenticated requests to
another workload. Treat its version as security-sensitive, pin spec.ref, review
changes before upgrading, and restrict the Service with network policy. An
application without its own authentication is safe only while every alternate
network path to it remains closed.
Avoid the static_token feature for normal sidebar access: it creates a URL that
bypasses Home Assistant login until the token is changed. Header-based automatic
login similarly gives the Home Assistant process possession of the backend
credential, so grant that credential only the permissions the embedded UI needs.