# HomeOS Self-built smart-home control plane — single household, self-hosted, LAN-first. Laravel 13 · Livewire v3 · Tailwind v4 · PostgreSQL 17 + TimescaleDB · Redis/Horizon · Reverb. Everything runs in Docker; the host needs **only Docker** (no PHP/Composer/Node). Authoritative spec: [`handoff.md`](handoff.md) · conventions: [`rules.md`](rules.md) · guide: [`CLAUDE.md`](CLAUDE.md). ## First-run setup ```bash cp .env.example .env # dev defaults work as-is docker compose build # build the app image docker compose run --rm app bash docker/app/bootstrap.sh # deps + key + assets + migrate/seed bash docker/mosquitto/gen-passwd.sh # broker credentials (fills empty MQTT_*_PASSWORD) docker compose up -d # start the full stack ``` > `docker compose up` alone is **not** the first command — `vendor/`, `node_modules`, > `public/build` and the Mosquitto passwd file are not committed, so the steps above > must run first. Then open **http://localhost** and sign in with the seeded dev admin: - **admin@homeos.local** / **homeos-dev** ← change this for anything but local dev. ### Production `.env.example` ships **development** defaults. For a real deployment you **must**: - set `APP_ENV=production` and `APP_DEBUG=false` (otherwise exceptions are exposed and the demo household is seeded into your real database); - set strong values for `DB_PASSWORD`, the `REVERB_APP_*` keys and `HOMEOS_ADMIN_PASSWORD` (seeding aborts if the admin password is unset outside local/testing), and run `php artisan key:generate`. The demo seeder (`DemoHomeSeeder`) only runs in local/testing. ## Everyday commands (in-container, R8) ```bash docker compose exec app php artisan … # artisan docker compose exec app composer … # composer docker compose exec app npm run build # rebuild assets (or `npm run dev` for HMR) docker compose exec app php artisan test # test suite docker compose logs -f app # logs ``` ## Add-ons On-demand integrations, managed under **Add-ons** in the sidebar. ### Ring (cloud, opt-in) Ring has no local API, so HomeOS bridges it via [ring-mqtt](https://github.com/tsightler/ring-mqtt). The bridge is part of the stack, so it **starts automatically** with `docker compose up -d` — no manual step. Then: 1. In HomeOS → **Add-ons → Ring → Install → Einrichten**, click **Open bridge UI** (**http://:${RING_UI_PORT:-55123}**) and sign in with your Ring account (email + password + 2FA). The bridge mints and stores the refresh token — HomeOS never handles Ring's OAuth. 2. Ring devices (doorbell, cameras, sensors) appear automatically under **Devices**, tagged **Cloud**. ## Install as an app (PWA) HomeOS ships a web manifest + service worker, so it installs to a tablet/phone home screen ("Add to Home Screen") and runs full-screen. Use the **Steuerung** (`/panel`) tab as the tablet control surface. Install requires HTTPS in production (localhost is exempt for testing). ## Services & ports | Service | Role | Host port | |---|---|---| | `app` | php-fpm + nginx + supervisor | `${APP_PORT:-80}` | | `reverb` | websockets (proxied same-origin via nginx `/app`) | `${REVERB_HOST_PORT:-6001}` | | `horizon` · `scheduler` | queue workers · cron (presence, metrics, automations) | — | | `mqtt-listener` | subscribes the bus, dispatches ingest jobs | — | | `mosquitto` | MQTT broker (auth + per-client ACLs) | `${MQTT_HOST_PORT:-1883}` | | `discovery` | mDNS/SSDP sidecar (host network) | — | | `ring-mqtt` | Ring bridge — **opt-in** (`--profile addons`) | `${RING_UI_PORT:-55123}` | | `db` | PostgreSQL 17 + TimescaleDB | `127.0.0.1:${DB_HOST_PORT:-5432}` | | `redis` | cache / queue | — | All ports and `HOST_UID`/`HOST_GID` are env-driven in `.env`.