This guide covers authentication, deployment modes, and remote access for Project Aether. For prerequisites and initial setup, see the Quick Start in the README.
Aether uses HA-verified first-time setup and supports four authentication methods.
On first launch, the UI shows a setup wizard:
- Enter HA URL + token — Aether validates the connection by calling the HA API
- Set fallback password (optional) — stored as a bcrypt hash in the database
- Register a passkey — Face ID / Touch ID for quick biometric login
The HA URL and token are stored in the database (encrypted with Fernet, key derived from JWT_SECRET). Setup can only be run once; to re-run, delete the system_config DB row.
The recommended login method. After registering a passkey during setup, use Face ID, Touch ID, or Windows Hello to sign in instantly.
Configure for your domain:
WEBAUTHN_RP_ID=home.example.com # your domain (must match URL)
WEBAUTHN_RP_NAME=Aether # display name
WEBAUTHN_ORIGIN=https://home.example.com # full origin URLNote: WebAuthn requires HTTPS in production. Use Cloudflare Tunnel or Tailscale for secure remote access.
Log in using any valid Home Assistant long-lived access token. Aether validates the token against the stored HA URL (from setup) or env var fallback.
curl -X POST http://localhost:8000/api/v1/auth/login/ha-token \
-H "Content-Type: application/json" \
-d '{"ha_token": "your-long-lived-access-token"}'If you set a password during setup, use it to log in. Aether checks the DB hash first, then falls back to the AUTH_PASSWORD env var.
# Optional env var fallback (DB password from setup takes priority)
AUTH_USERNAME=admin
AUTH_PASSWORD=your-secret
JWT_SECRET=a-long-random-string # optional, auto-derived if empty
JWT_EXPIRY_HOURS=72Login via the UI or API:
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-secret"}'The JWT is returned in the response body and as an httpOnly cookie (aether_session).
For scripts, CLI tools, or external integrations:
API_KEY=your-api-keyPass via header or query parameter:
curl -H "X-API-Key: your-api-key" http://localhost:8000/api/v1/entitiesWhen no setup has been completed and neither AUTH_PASSWORD nor API_KEY is set, authentication is completely disabled for development convenience.
| Mode | Command | Description |
|---|---|---|
| Development | make run |
Infrastructure in containers, API on host with hot-reload |
| Dev + UI | make run-ui |
Above + React UI dev server with HMR |
| Production | make run-prod |
Everything containerized (Podman Compose) |
| Stop | make down |
Stop all services and containers |
| Service | Port | Description |
|---|---|---|
| Chat UI | 3000 |
React frontend |
| Aether API | 8000 |
FastAPI backend (OpenAI-compatible + native API) |
| MLflow | 5002 |
Trace viewer for agent observability |
| PostgreSQL | 5432 |
State, conversations, entities, insights |
- Install cloudflared:
brew install cloudflared - Create a tunnel:
cloudflared tunnel create aether - Configure to route to
http://localhost:3000 - Update your
.env:
WEBAUTHN_RP_ID=aether.your-domain.com
WEBAUTHN_ORIGIN=https://aether.your-domain.com
ALLOWED_ORIGINS=https://aether.your-domain.comBenefits: no port forwarding, automatic HTTPS, DDoS protection.
- Install Tailscale on your HA machine and phone
- Access via Tailscale IP:
http://100.x.y.z:3000
Benefits: zero-config VPN, no public exposure, works with HTTP (no HTTPS needed for WebAuthn on Tailscale).
- Set
AUTH_PASSWORDto a strong password - Set
JWT_SECRETto a random 32+ character string - Configure
ALLOWED_ORIGINSfor your domain - Register a passkey for passwordless login
- Use HTTPS (required for WebAuthn on public domains)
- Configuration — LLM providers, per-agent model overrides, usage tracking
- User Flows — step-by-step interaction sequences
- Architecture — system design and agent roles