223 lines
7.7 KiB
Markdown
223 lines
7.7 KiB
Markdown
# Home Assistant
|
|
|
|
## Overview
|
|
|
|
[Home Assistant](https://github.com/home-assistant/core) is an open-source home automation platform. In the Ouranos sandbox it runs as a native Python application inside a virtual environment, backed by PostgreSQL for state recording and fronted by HAProxy for TLS termination.
|
|
|
|
**Host:** Oberon
|
|
**Role:** container_orchestration
|
|
**Port:** 8123
|
|
**URL:** https://hass.ouranos.helu.ca
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────┐ HTTPS ┌──────────────┐ HTTP ┌──────────────┐
|
|
│ Client │────────▶│ HAProxy │────────▶│ Home │
|
|
│ │ │ (Titania) │ │ Assistant │
|
|
└──────────┘ │ :443 TLS │ │ (Oberon) │
|
|
└──────────────┘ │ :8123 │
|
|
└──────┬───────┘
|
|
│
|
|
┌─────────────────┼─────────────────┐
|
|
│ │ │
|
|
┌────▼─────┐ ┌──────▼──────┐ ┌─────▼─────┐
|
|
│PostgreSQL│ │ Alloy │ │ Prometheus│
|
|
│(Portia) │ │ (Oberon) │ │(Prospero) │
|
|
│ :5432 │ │ scrape │ │ remote │
|
|
│ recorder │ │ /api/prom │ │ write │
|
|
└──────────┘ └─────────────┘ └───────────┘
|
|
```
|
|
|
|
## Ansible Deployment
|
|
|
|
### Playbook
|
|
|
|
```bash
|
|
cd ansible
|
|
ansible-playbook hass/deploy.yml
|
|
```
|
|
|
|
### Files
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `hass/deploy.yml` | Main deployment playbook |
|
|
| `hass/configuration.yaml.j2` | Home Assistant configuration |
|
|
| `hass/requirements.txt.j2` | Python package pinning |
|
|
| `hass/hass.service.j2` | Systemd service unit |
|
|
|
|
### Variables
|
|
|
|
#### Host Variables (`host_vars/oberon.incus.yml`)
|
|
|
|
| Variable | Description | Value |
|
|
|----------|-------------|-------|
|
|
| `hass_user` | System user | `hass` |
|
|
| `hass_group` | System group | `hass` |
|
|
| `hass_directory` | Install directory | `/srv/hass` |
|
|
| `hass_media_directory` | Media storage | `/srv/hass/media` |
|
|
| `hass_port` | HTTP listen port | `8123` |
|
|
| `hass_version` | Pinned HA release | `2026.2.0` |
|
|
| `hass_db_host` | PostgreSQL host | `portia.incus` |
|
|
| `hass_db_port` | PostgreSQL port | `5432` |
|
|
| `hass_db_name` | Database name | `hass` |
|
|
| `hass_db_user` | Database user | `hass` |
|
|
| `hass_db_password` | Database password | `{{ vault_hass_db_password }}` |
|
|
| `hass_metrics_token` | Prometheus bearer token | `{{ vault_hass_metrics_token }}` |
|
|
|
|
#### Host Variables (`host_vars/portia.incus.yml`)
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `hass_db_name` | Database name on Portia |
|
|
| `hass_db_user` | Database user on Portia |
|
|
| `hass_db_password` | `{{ vault_hass_db_password }}` |
|
|
|
|
#### Vault Variables (`group_vars/all/vault.yml`)
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `vault_hass_db_password` | PostgreSQL password for hass database |
|
|
| `vault_hass_metrics_token` | Long-Lived Access Token for Prometheus scraping |
|
|
|
|
## Configuration
|
|
|
|
### PostgreSQL Recorder
|
|
|
|
Home Assistant uses the `recorder` integration to persist entity states and events to PostgreSQL on Portia instead of the default SQLite. Configured in `configuration.yaml.j2`:
|
|
|
|
```yaml
|
|
recorder:
|
|
db_url: "postgresql://hass:<password>@portia.incus:5432/hass"
|
|
purge_keep_days: 30
|
|
commit_interval: 1
|
|
```
|
|
|
|
The database and user are provisioned by `postgresql/deploy.yml` alongside other service databases.
|
|
|
|
### HTTP / Reverse Proxy
|
|
|
|
HAProxy on Titania terminates TLS and forwards to Oberon:8123. The `http` block in `configuration.yaml.j2` configures trusted proxies so HA correctly reads `X-Forwarded-For` headers:
|
|
|
|
```yaml
|
|
http:
|
|
server_port: 8123
|
|
use_x_forwarded_for: true
|
|
trusted_proxies:
|
|
- 10.0.0.0/8
|
|
```
|
|
|
|
### HAProxy Backend
|
|
|
|
Defined in `host_vars/titania.incus.yml` under `haproxy_backends`:
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Subdomain | `hass` |
|
|
| Backend | `oberon.incus:8123` |
|
|
| Health path | `/api/` |
|
|
| Timeout | 300s (WebSocket support) |
|
|
|
|
The wildcard TLS certificate (`*.ouranos.helu.ca`) covers `hass.ouranos.helu.ca` automatically — no certificate changes required.
|
|
|
|
## Authentication
|
|
|
|
Home Assistant uses its **native `homeassistant` auth provider** (built-in username/password). HA does not support OIDC/OAuth2 natively, so Casdoor SSO integration is not available.
|
|
|
|
On first deployment, HA will present an onboarding wizard to create the initial admin user.
|
|
|
|
## Monitoring
|
|
|
|
### Prometheus Metrics
|
|
|
|
Home Assistant exposes Prometheus metrics at `/api/prometheus`. The Alloy agent on Oberon scrapes this endpoint with bearer token authentication and remote-writes to Prometheus on Prospero.
|
|
|
|
| Setting | Value |
|
|
|---------|-------|
|
|
| Metrics path | `/api/prometheus` |
|
|
| Scrape interval | 60s |
|
|
| Auth | Bearer token (Long-Lived Access Token) |
|
|
|
|
**⚠️ Two-Phase Metrics Bootstrapping:**
|
|
|
|
The `vault_hass_metrics_token` must be a Home Assistant **Long-Lived Access Token**, which can only be generated from the HA web UI after the initial deployment:
|
|
|
|
1. Deploy Home Assistant: `ansible-playbook hass/deploy.yml`
|
|
2. Complete the onboarding wizard at `https://hass.ouranos.helu.ca`
|
|
3. Navigate to **Profile → Security → Long-Lived Access Tokens → Create Token**
|
|
4. Store the token in vault: `vault_hass_metrics_token: "<token>"`
|
|
5. Redeploy Alloy to pick up the token: `ansible-playbook alloy/deploy.yml`
|
|
|
|
Until the token is created, the Alloy hass scrape will fail silently.
|
|
|
|
### Loki Logs
|
|
|
|
Systemd journal logs are collected by Alloy's `loki.source.journal` and shipped to Loki on Prospero.
|
|
|
|
```bash
|
|
# Query in Grafana Explore
|
|
{job="systemd", hostname="oberon"} |= "hass"
|
|
```
|
|
|
|
## Operations
|
|
|
|
### Start / Stop
|
|
|
|
```bash
|
|
sudo systemctl start hass
|
|
sudo systemctl stop hass
|
|
sudo systemctl restart hass
|
|
```
|
|
|
|
### Health Check
|
|
|
|
```bash
|
|
curl http://localhost:8123/api/
|
|
```
|
|
|
|
### Logs
|
|
|
|
```bash
|
|
journalctl -u hass -f
|
|
```
|
|
|
|
### Version Upgrade
|
|
|
|
1. Update `hass_version` in `host_vars/oberon.incus.yml`
|
|
2. Run: `ansible-playbook hass/deploy.yml`
|
|
|
|
The playbook will reinstall the pinned version via pip and restart the service.
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
| Symptom | Cause | Resolution |
|
|
|---------|-------|------------|
|
|
| Service won't start | Missing Python deps | Check `pip install` output in deploy log |
|
|
| Database connection error | Portia unreachable | Verify PostgreSQL is running: `ansible-playbook postgresql/deploy.yml` |
|
|
| 502 via HAProxy | HA not listening | Check `systemctl status hass` on Oberon |
|
|
| Metrics scrape failing | Missing/invalid token | Generate Long-Lived Access Token from HA UI (see Monitoring section) |
|
|
|
|
### Debug Mode
|
|
|
|
```bash
|
|
# Check service status
|
|
sudo systemctl status hass
|
|
|
|
# View recent logs
|
|
journalctl -u hass --since "5 minutes ago"
|
|
|
|
# Test database connectivity from Oberon
|
|
psql -h portia.incus -U hass -d hass -c "SELECT 1"
|
|
```
|
|
|
|
## References
|
|
|
|
- [Home Assistant Documentation](https://www.home-assistant.io/docs/)
|
|
- [Home Assistant GitHub](https://github.com/home-assistant/core)
|
|
- [Recorder Integration](https://www.home-assistant.io/integrations/recorder/)
|
|
- [Prometheus Integration](https://www.home-assistant.io/integrations/prometheus/)
|
|
- [HTTP Integration](https://www.home-assistant.io/integrations/http/)
|