docs: rewrite README with structured overview and quick start guide
Replaces the minimal project description with a comprehensive README including a component overview table, quick start instructions, common Ansible operations, and links to detailed documentation. Aligns with Red Panda Approval™ standards.
This commit is contained in:
222
docs/hass.md
Normal file
222
docs/hass.md
Normal file
@@ -0,0 +1,222 @@
|
||||
# Home Assistant
|
||||
|
||||
## Overview
|
||||
|
||||
[Home Assistant](https://github.com/home-assistant/core) is an open-source home automation platform. In the Agathos 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/)
|
||||
Reference in New Issue
Block a user