Publish LumaOps source
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
# LumaOps architecture
|
||||
|
||||
## System shape
|
||||
|
||||
LumaOps is a single-container, local-first control plane around the imported
|
||||
OpenRGB 1.0rc3 hardware engine.
|
||||
|
||||
```text
|
||||
Browser
|
||||
│ HTTP / SSE on WEB_PORT (bridge default 1223)
|
||||
▼
|
||||
FastAPI application ───── SQLite + encrypted connector secrets
|
||||
│
|
||||
├── command service ─── audit, idempotency, rate limits, locks
|
||||
│ │
|
||||
│ └── connector registry
|
||||
│ ├── OpenRGB connector ── SDK v5 TCP ── OpenRGB Core
|
||||
│ ├── WLED connector HTTP/UDP (optional)
|
||||
│ ├── Home Assistant REST/WS (optional)
|
||||
│ └── future connectors
|
||||
│
|
||||
└── built React application
|
||||
|
||||
Container supervisor
|
||||
├── OpenRGB: 127.0.0.1:6742 only
|
||||
└── FastAPI: APP_HOST:APP_PORT
|
||||
```
|
||||
|
||||
Only the internal `APP_PORT` is mapped to `WEB_PORT`; the defaults are
|
||||
`1223:8080`. The OpenRGB SDK has no authentication or encryption and is never a
|
||||
public container port.
|
||||
|
||||
## Repository boundaries
|
||||
|
||||
- The imported OpenRGB tree remains at the repository root.
|
||||
- `lumaops/backend` contains the FastAPI package and Python tests.
|
||||
- `lumaops/frontend` contains the React/TypeScript application.
|
||||
- `lumaops/backend/src/lumaops_backend/migrations` contains ordered SQLite migrations.
|
||||
- `docker` contains entrypoint/supervision, health, and Unraid assets.
|
||||
- `docs` contains LumaOps operational and design documentation.
|
||||
- A minimal OpenRGB core patch is isolated and documented separately.
|
||||
|
||||
## Runtime lifecycle
|
||||
|
||||
1. Tini becomes PID 1 and forwards container signals.
|
||||
2. The LumaOps supervisor creates persistent directories and validates their
|
||||
permissions.
|
||||
3. It starts OpenRGB with an explicit loopback address and persistent config
|
||||
path, then captures OpenRGB output in `/logs/openrgb.log`.
|
||||
4. It starts FastAPI regardless of whether hardware detection succeeds.
|
||||
5. FastAPI runs migrations, creates an application instance ID/keyfile if
|
||||
needed, and starts the connector registry.
|
||||
6. The OpenRGB connector negotiates SDK protocol 5 and synchronizes inventory.
|
||||
7. A device-list event or reconnect schedules another read-only inventory sync.
|
||||
8. On SIGTERM/SIGINT, FastAPI stops accepting work, connector tasks are
|
||||
cancelled, OpenRGB receives SIGTERM, and the supervisor waits before a
|
||||
bounded SIGKILL fallback.
|
||||
|
||||
An OpenRGB failure degrades hardware functions but does not take down the web
|
||||
application. The supervisor restarts OpenRGB with bounded backoff. Repeated
|
||||
failure opens a circuit and surfaces a recovery action in Diagnostics.
|
||||
|
||||
## Backend modules
|
||||
|
||||
The application follows ports-and-adapters boundaries rather than exposing SDK
|
||||
types through the API:
|
||||
|
||||
- `connectors.base`: normalized capabilities, inventory, state, health, errors,
|
||||
and connector contract.
|
||||
- `connectors.openrgb.protocol`: bounded SDK-v5 parser and serializer.
|
||||
- `connectors.openrgb.adapter`: connection, handshake, request correlation,
|
||||
reconnect, profile operations, and change events.
|
||||
- `connectors.mock`: deterministic test/development implementation that can be
|
||||
enabled only by an explicit non-production setting.
|
||||
- `services.inventory`: stable identities and reconciliation.
|
||||
- `services.commands`: validation, emergency stop, idempotency, locks, rate
|
||||
limiting, execution records, and audit.
|
||||
- `services.scenes`: capture/apply/preview and compensating rollback.
|
||||
- `services.automations`: schedule evaluation, cooldown, conflict keys, and run
|
||||
history.
|
||||
- `services.setup`: read-only environment and hardware checks.
|
||||
- `services.diagnostics`: redacted support bundle generation.
|
||||
- `api`: versioned resource routers under `/api/v1`, plus SSE.
|
||||
|
||||
## Connector contract
|
||||
|
||||
Every connector exposes:
|
||||
|
||||
- lifecycle: `start`, `stop`, `test`, and `health`;
|
||||
- discovery and inventory without implicit writes;
|
||||
- normalized capabilities and current state;
|
||||
- validated `set_state` operations;
|
||||
- optional profile/preset operations;
|
||||
- timeouts, bounded retries, rate limits, and normalized error categories;
|
||||
- a configuration schema whose secret fields are explicitly marked;
|
||||
- an inventory-change event callback.
|
||||
|
||||
The UI operates only on normalized devices and capability flags. It never
|
||||
contains an OpenRGB packet, WLED segment, or Home Assistant service-call path.
|
||||
|
||||
## Device identity and ownership
|
||||
|
||||
An inventory record has an immutable internal UUID. A connector provides a
|
||||
candidate fingerprint from the most durable available fields, in priority
|
||||
order: connector ID, hardware serial, stable location/path, MAC/IP plus model,
|
||||
then a guarded composite of vendor/model/name. The `device_identities` table
|
||||
persists all observed aliases so a controller moving to another discovery index
|
||||
keeps its UUID.
|
||||
|
||||
`controller_index` is volatile routing data and is updated during each OpenRGB
|
||||
sync. Before every write, the adapter compares the stored fingerprint with the
|
||||
current controller at that index. Mismatch cancels the command and triggers a
|
||||
resync.
|
||||
|
||||
One physical light has one management owner: OpenRGB, native connector, Home
|
||||
Assistant, or unmanaged. Possible duplicates are surfaced for administrator
|
||||
resolution and are never written through two connectors concurrently.
|
||||
|
||||
## Normalized capability model
|
||||
|
||||
Capabilities are explicit booleans plus ranges:
|
||||
|
||||
- power and restore;
|
||||
- RGB, colour temperature, and brightness;
|
||||
- effect/mode, speed, direction, and multiple colours;
|
||||
- per-zone, per-segment, and per-LED control;
|
||||
- presets/profiles;
|
||||
- read-only or experimental state.
|
||||
|
||||
Commands are intersected with capabilities. Unsupported properties result in a
|
||||
422 response before any connector is called. Brightness, speed, indices,
|
||||
colours, list lengths, and update frequency are range-checked twice: at the API
|
||||
boundary and in the connector.
|
||||
|
||||
## Command path and safety
|
||||
|
||||
Every mutation follows this path:
|
||||
|
||||
```text
|
||||
API validation
|
||||
→ authentication/CSRF policy
|
||||
→ idempotency lookup
|
||||
→ emergency-stop/read-only/block policy
|
||||
→ stable identity resolution
|
||||
→ capability validation
|
||||
→ connector + device locks
|
||||
→ token-bucket rate limit
|
||||
→ connector timeout/circuit breaker
|
||||
→ result + audit record + realtime event
|
||||
```
|
||||
|
||||
Commands have UUIDs and record request ID, actor, target, sanitized desired
|
||||
state, start/end time, duration, result, and normalized error. Secret values and
|
||||
raw environment data are never command payloads.
|
||||
|
||||
The emergency stop cancels queued effects, prevents new hardware writes, and
|
||||
sends one bounded all-off attempt only when the administrator requests it. It
|
||||
does not loop on failing hardware.
|
||||
|
||||
## Scenes and rollback
|
||||
|
||||
LumaOps scenes are application-level, versioned desired-state documents. They
|
||||
can contain OpenRGB devices, connector devices, groups, and explicit off
|
||||
entries. OpenRGB profiles remain separate objects.
|
||||
|
||||
Scene application first resolves targets and snapshots retrievable prior state.
|
||||
Commands then execute in deterministic connector/device order. If a required
|
||||
item fails, already changed devices receive compensating commands where their
|
||||
prior state is known. The result reports applied, skipped, failed, and rolled
|
||||
back targets; rollback is best effort and never hides the original failure.
|
||||
|
||||
## Automation model
|
||||
|
||||
Rules store a trigger document, action list, timezone, enabled state, cooldown,
|
||||
and conflict key. MVP trigger types are time, weekday, manual, webhook, and
|
||||
device online/offline. Sunrise/sunset becomes active once coordinates are
|
||||
configured. Temperature and Home Assistant events use the same trigger
|
||||
interface when a provider exists.
|
||||
|
||||
A single scheduler claims due rules transactionally. The conflict key prevents
|
||||
overlapping runs for the same scene/group/device. All attempts create an
|
||||
`automation_runs` record, including skipped cooldown/conflict decisions.
|
||||
|
||||
## Data and migrations
|
||||
|
||||
SQLite uses foreign keys, WAL mode, a busy timeout, UTC timestamps, and explicit
|
||||
transactions. Ordered SQL migrations are recorded in `schema_migrations`.
|
||||
Before a migration marked destructive, the runner creates a timestamped online
|
||||
backup in `/data/backups` and aborts if that backup fails.
|
||||
|
||||
Core tables cover settings, connectors, encrypted secrets, devices, identity
|
||||
aliases, rooms, groups, membership/tags, scenes/items, automations/runs,
|
||||
commands/results, audit events, health samples, discovery runs, ignored
|
||||
devices, idempotency keys, and setup state.
|
||||
|
||||
Soft deletion is used for user-managed resources and history-bearing inventory.
|
||||
High-volume health and activity history has a configurable retention policy.
|
||||
|
||||
## API and realtime updates
|
||||
|
||||
REST resources live below `/api/v1`. Responses carry `X-Request-ID`; failures
|
||||
use one stable shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "device_offline",
|
||||
"message": "Het apparaat is niet bereikbaar.",
|
||||
"request_id": "...",
|
||||
"details": {},
|
||||
"recovery": ["Controleer de connector", "Voer een nieuwe scan uit"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
List endpoints use `limit`, `offset`, filtering, and documented sort fields.
|
||||
Writes that could be retried accept `Idempotency-Key`. Server-Sent Events at
|
||||
`/api/v1/events` distribute health, inventory, command, and audit changes.
|
||||
|
||||
FastAPI also serves the compiled SPA and its hashed assets. API and health paths
|
||||
are excluded from SPA fallback.
|
||||
|
||||
## Configuration and secrets
|
||||
|
||||
Non-secret settings come from environment variables and the settings table;
|
||||
environment values win for deployment-critical addresses and paths. Connector
|
||||
secrets are encrypted with Fernet-compatible authenticated encryption using a
|
||||
persistent key from `LUMAOPS_SECRET_KEY` or `/config/lumaops/secret.key`.
|
||||
|
||||
The keyfile is created with mode 0600 when absent. Losing it makes connector
|
||||
secrets unrecoverable but does not corrupt inventory, scenes, or audit data.
|
||||
Rotation decrypts all values in one transaction using the old key and reencrypts
|
||||
them with the new key after a backup.
|
||||
|
||||
## Health model
|
||||
|
||||
`/health/live` reports only whether the web process can serve requests.
|
||||
`/health/ready` verifies database access and migrations. `/api/v1/health`
|
||||
aggregates the supervisor heartbeat, OpenRGB process, SDK protocol/connection,
|
||||
database, connectors, and persistent-directory writability.
|
||||
|
||||
Aggregate states are `healthy`, `degraded`, and `unhealthy`. Missing hardware or
|
||||
SDK is degraded, not a web-process crash. The container healthcheck treats a
|
||||
working but degraded application as alive while exposing the degradation in the
|
||||
detailed API.
|
||||
|
||||
## Deployment invariants
|
||||
|
||||
- x86_64 Linux and one production image.
|
||||
- No compiler, source tree, npm cache, or build tool in the runtime stage.
|
||||
- `/config`, `/data`, and `/logs` are persistent and writable.
|
||||
- No default `privileged: true`; only explicit device mappings.
|
||||
- Bridge networking by default; documented host mode for LAN discovery.
|
||||
- No SaaS dependency and no automatic reverse-proxy or external exposure.
|
||||
- Mock mode is rejected when `LUMAOPS_ENV=production` and is visibly marked in
|
||||
every page when explicitly enabled elsewhere.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Back-up en herstel
|
||||
|
||||
Een volledige LumaOps-back-up bevat drie consistente onderdelen:
|
||||
|
||||
- /data met lumaops.db en beheerde databaseback-ups;
|
||||
- /config/openrgb met OpenRGB-instellingen, profielen en plugins;
|
||||
- /config/lumaops met secret.key.
|
||||
|
||||
Zonder secret.key zijn versleutelde connectorsecrets niet herstelbaar. Bewaar de sleutel samen met de database in een versleutelde, toegangsgelimiteerde back-up. Deel diagnostiekexports niet als back-up; die bevatten bewust geen secrets.
|
||||
|
||||
## Back-up
|
||||
|
||||
Stop voor een volledig consistente bestandssnapshot kort de container:
|
||||
|
||||
docker compose stop lumaops
|
||||
tar -C /mnt/user/appdata -czf /mnt/user/backups/lumaops-YYYYMMDD-HHMMSS.tgz lumaops
|
||||
docker compose start lumaops
|
||||
|
||||
De UI maakt atomair een SQLite-herstelpunt via de SQLite backup API. Gebruik dat vóór configuratiewijzigingen, maar kopieer periodiek ook beide configmappen.
|
||||
|
||||
## Herstel
|
||||
|
||||
1. Stop LumaOps.
|
||||
2. Maak een veiligheidskopie van de huidige appdata.
|
||||
3. Herstel alle drie de onderdelen met dezelfde eigenaar PUID/PGID.
|
||||
4. Start de container.
|
||||
5. Controleer migrations, SDK health, inventaris en connectorsecrets.
|
||||
|
||||
Een databaseback-up uit de UI maakt vóór restore automatisch een extra safety-back-up en controleert SQLite-integriteit. Roteer de encryptiesleutel alleen met een expliciete decrypt/re-encryptmigratie; simpelweg secret.key vervangen maakt bestaande ciphertext onleesbaar.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Connectoren ontwikkelen
|
||||
|
||||
Alle hardware- en netwerkbronnen implementeren de connectorcontracten onder lumaops/backend/src/lumaops_backend/connectors. De rest van backend en frontend werkt alleen met genormaliseerde Device, DeviceState, Capabilities en ConnectorHealth-objecten.
|
||||
|
||||
Een connector levert minimaal id, kind, configuratieschema, start/stop, discovery, inventory, state lezen/schrijven, connectietest, health en identify. Fouten worden vertaald naar stabiele LumaOps-foutcategorieën. Secrets worden via SecretStore versleuteld en verschijnen nooit in configschema, logs of responses.
|
||||
|
||||
Ontwikkelvolgorde:
|
||||
|
||||
1. Voeg modellen en adapter toe zonder merkcode in de UI.
|
||||
2. Normaliseer stabiele identiteit met bron, vendor/model, serienummer, locatie of netwerkidentiteit; gebruik nooit alleen een lijstindex.
|
||||
3. Declareer capabilities conservatief en stuur geen niet-ondersteunde velden.
|
||||
4. Voeg timeouts, begrensde reconnect-backoff, rate limiting en health toe.
|
||||
5. Schrijf contracttests, parserfixtures en fouttests.
|
||||
6. Registreer de connector in ConnectorRegistry en toon hem automatisch via /api/v1/connectors.
|
||||
|
||||
OpenRGB is de referentie-implementatie. De packetcodec is geïsoleerd in connectors/openrgb/protocol.py en de async I/O in adapter.py. Een nieuwe connector mag die binaire details niet naar services lekken.
|
||||
|
||||
WLED en Home Assistant zijn de eerste geplande uitbreidingen. Detecteer dubbele eigenaars voor WLED via DDP/E1.31 en laat owner één van openrgb, native, home_assistant of unmanaged zijn. MQTT, ESPHome, HTTP en remote agents passen in hetzelfde contract.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# OpenRGB Core-wijzigingen
|
||||
|
||||
LumaOps beperkt wijzigingen aan OpenRGB Core tot de onderstaande twee patches.
|
||||
|
||||
## Gecontroleerd afsluiten in headless modus
|
||||
|
||||
`startup/main_FreeBSD_Linux_MacOS.cpp` installeert handlers voor SIGINT en SIGTERM.
|
||||
|
||||
De headless server installeert handlers voor SIGINT en SIGTERM. De handler zet alleen een sig_atomic_t-vlag; de normale applicatiedraad roept daarna NetworkServer::StopServer aan. Daardoor kan Tini/supervisor de SDK-server gecontroleerd stoppen zonder async-signal-unsafe netwerk- of Qt-code in de signal handler.
|
||||
|
||||
## Veilige fallback voor HID-interfaceherkenning
|
||||
|
||||
`ResourceManager.cpp` en `ResourceManager.h` voegen een losse vergelijking zonder
|
||||
interface-index toe wanneer een detector geen exacte HID-interface vindt. De fallback
|
||||
wordt alleen automatisch geregistreerd als precies één detector overeenkomt. Bij nul of
|
||||
meerdere kandidaten verandert er niets; zo kan een ambigu apparaat nooit stilzwijgend
|
||||
aan de verkeerde detector worden gekoppeld.
|
||||
|
||||
Deze patch ondersteunt hardware waarvan de door Linux gemelde interface-index afwijkt,
|
||||
waaronder de geteste Aura- en geheugencontrollers. De bestaande exacte match blijft
|
||||
altijd de eerste keuze.
|
||||
|
||||
Bij iedere upstreamupdate moeten beide patches opnieuw worden beoordeeld. Verwijder een
|
||||
forkpatch zodra upstream gelijkwaardig gedrag implementeert.
|
||||
@@ -0,0 +1,52 @@
|
||||
# Hardwaretoegang
|
||||
|
||||
OpenRGB praat rechtstreeks met USB, HID, SMBus/I²C en soms seriële controllers. Geef LumaOps alleen de benodigde nodes.
|
||||
|
||||
## USB
|
||||
|
||||
De Compose-standaard geeft /dev/bus/usb door. Inventariseer op Unraid met:
|
||||
|
||||
lsusb
|
||||
find /dev/bus/usb -maxdepth 2 -type c -ls
|
||||
|
||||
OpenRGB gebruikt de ingebouwde 60-openrgb.rules als referentie. In een container zijn expliciete device mappings en hostpermissies bepalend. Koppel stabiele fysieke apparaten bij voorkeur aan bus/VID/PID/serienummer; de LumaOps UUID is niet alleen op OpenRGB controller-index gebaseerd.
|
||||
|
||||
## I²C en SMBus
|
||||
|
||||
Laad op de host eerst i2c-dev en de chipsetdriver, bijvoorbeeld i2c-i801 voor veel Intel-systemen of i2c-piix4 voor sommige AMD-systemen:
|
||||
|
||||
modprobe i2c-dev
|
||||
modprobe i2c-i801
|
||||
ls -l /dev/i2c-*
|
||||
i2cdetect -l
|
||||
|
||||
Voeg daarna uitsluitend de benodigde adapter toe:
|
||||
|
||||
devices:
|
||||
- /dev/i2c-0:/dev/i2c-0
|
||||
|
||||
Adapterindices kunnen na hardware- of kernelwijzigingen veranderen. Controleer i2cdetect -l na een Unraid-update. Voer geen willekeurige i2cset-opdrachten uit; de OpenRGB-detectielogica is de enige hardwarelaag.
|
||||
|
||||
## LumaOps op de Widefrog Unraid-host
|
||||
|
||||
De huidige host gebruikt deze beperkte hardwaretoegang:
|
||||
|
||||
- `/dev/hidraw0`: ASUSTeK AURA LED Controller `0b05:18f3`;
|
||||
- `/dev/i2c-0`: Intel I801 SMBus voor Corsair Vengeance RGB DDR4;
|
||||
- `/dev/bus/usb`: USB-transport voor ondersteunde OpenRGB-apparaten.
|
||||
|
||||
Voer als root eenmalig `scripts/unraid-hardware-setup.sh` uit. Het script installeert een minimale udev-regel, geeft alleen deze apparaten toegang voor de Unraid-groep `users` en registreert zichzelf idempotent in `/boot/config/go`. Daarna kan de niet-root LumaOps-container de apparaten gebruiken zonder privileged modus of een volledige `/dev`-mount.
|
||||
|
||||
## Serieel
|
||||
|
||||
Voor controllers op /dev/ttyUSB0 of /dev/ttyACM0 voegt men de specifieke node als read/write device toe. Controleer dialout/uucp-groepsrechten op de host. Mount nooit standaard de volledige /dev-map.
|
||||
|
||||
## Diagnoseprofiel
|
||||
|
||||
Alleen wanneer een device in privileged mode wel werkt:
|
||||
|
||||
docker compose -f docker-compose.yml -f docker/compose.diagnostic.yml up -d
|
||||
|
||||
Stop eerst de normale container. Het diagnoseprofiel is onveilig en tijdelijk. Identificeer de ontbrekende node/permissie, stop het profiel en keer terug naar expliciete devices. Voeg geen brede capabilities toe zonder aantoonbare noodzaak.
|
||||
|
||||
De eerste fysieke schrijfactie hoort een statische, gematigde kleur op één niet-experimenteel apparaat te zijn. Gebruik geen snelle effecten tijdens validatie.
|
||||
@@ -0,0 +1,67 @@
|
||||
# OpenRGB upstream synchroniseren
|
||||
|
||||
De repository heeft `origin` voor deze LumaOps-repo en `upstream` voor de officiële OpenRGB GitLab-repository. Tag `upstream-openrgb-1.0rc3` markeert de originele baseline.
|
||||
|
||||
Eisen:
|
||||
|
||||
- OpenRGB blijft de core hardware-engine en volgt upstream-architectuur.
|
||||
- Forkwijzigingen blijven minimaal.
|
||||
- Afwijkingen t.o.v. upstream worden gelogd in [CORE_PATCHES](docs/CORE_PATCHES.md) en [SOURCE_AUDIT](docs/SOURCE_AUDIT.md).
|
||||
|
||||
1. Controleer de upstream-remote.
|
||||
|
||||
```bash
|
||||
git remote -v
|
||||
git fetch --tags upstream
|
||||
```
|
||||
|
||||
2. Maak een onderhoudsbranch.
|
||||
|
||||
```bash
|
||||
git switch -c maintenance/openrgb-VERSIE
|
||||
```
|
||||
|
||||
3. Breng upstream binnen via een gecontroleerde merge.
|
||||
|
||||
```bash
|
||||
git merge --no-commit upstream/master
|
||||
```
|
||||
|
||||
4. Valideer dat alleen geautoriseerde core-bestanden afwijken.
|
||||
|
||||
```bash
|
||||
OPENRGB_BASELINE_TAG=upstream-openrgb-1.0rc3 ./scripts/openrgb-upstream-guard.sh
|
||||
```
|
||||
|
||||
Of op Windows:
|
||||
|
||||
```powershell
|
||||
$env:OPENRGB_BASELINE_TAG="upstream-openrgb-1.0rc3"
|
||||
.\scripts\openrgb-upstream-guard.ps1
|
||||
```
|
||||
|
||||
Deze controle draait automatisch in CI via:
|
||||
- `/.github/workflows/openrgb_upstream_compat_guard.yml` op `pull_request` en `push` voor `main`/`master`.
|
||||
|
||||
5. Voer daarna de inhoudelijke review uit op:
|
||||
- `NetworkProtocol.*`
|
||||
- `NetworkServer.*`
|
||||
- `PluginManager.*`
|
||||
- `RGBController.*`
|
||||
- `SettingsManager.*`
|
||||
- `ProfileManager.*`
|
||||
- `cli.*`
|
||||
- alle controller- en detectorregistraties.
|
||||
|
||||
6. Pas de forkpatch (headless stop-handler) opnieuw toe of verwijder hem als upstream dat gedrag inmiddels bevat.
|
||||
|
||||
7. Bepaal compatibiliteitstesten:
|
||||
- compileer OpenRGB-core,
|
||||
- draai backend/frontendtests,
|
||||
- bouw de container,
|
||||
- voer read-only inventarisatie uit op hardware,
|
||||
- voer daarna minimaal één non-destructieve kleuractie op fysiek apparaat uit.
|
||||
|
||||
8. Als stap 4 mislukt, stop en onderzoek de drift direct.
|
||||
|
||||
Gebruik nooit een blinde subtree-overschrijving.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Public release boundary
|
||||
|
||||
De ontwikkelrepository bevat in oudere commits interne deployment-URL's en mag
|
||||
daarom niet met volledige historiek openbaar worden gemaakt. Publiceer in plaats
|
||||
daarvan een gecontroleerde, parentless bronexport van een gereviewde releasecommit:
|
||||
|
||||
```sh
|
||||
bash scripts/export-public-source.sh /path/to/new-lumaops-public
|
||||
gitleaks git /path/to/new-lumaops-public --config /path/to/new-lumaops-public/.gitleaks.toml --redact
|
||||
```
|
||||
|
||||
De export neemt de actuele getrackte bron op, verwijdert de private automatische
|
||||
deploymentworkflow, weigert runtime-secrets, bekende interne markers en onverwacht
|
||||
grote bestanden, en schrijft een SHA-256-manifest. Het resultaat heeft één rootcommit
|
||||
zonder ouders en tagt die als `public-release-baseline`, zodat de upstream-guard ook
|
||||
toekomstige publieke bijdragen kan begrenzen. Controleer daarna de manifest-, test-, build-, lint- en secretscan
|
||||
voordat de nieuwe publieke remote wordt toegevoegd.
|
||||
|
||||
Het vaste securitycontact is `security@itworx.tech`. Voor de eerste release
|
||||
moeten alleen de publieke project- en support-URL nog naar de definitieve naam
|
||||
van de nieuwe publieke exportrepository wijzen; de private ontwikkelrepository
|
||||
blijft daarvan gescheiden.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Ontwerp voor LumaOps Agent
|
||||
|
||||
Het MVP bevat geen agent. Een handmatig remote OpenRGB SDK-endpoint past later in de connectorlaag, maar het kale SDK-protocol hoort nooit over internet: het biedt geen TLS, authenticatie of autorisatie.
|
||||
|
||||
De geplande agent draait op Windows of Linux naast een lokale OpenRGB-instance. Hij maakt zelf een uitgaande TLS-verbinding naar de hub, gebruikt een afzonderlijk revocable token, rapporteert genormaliseerde inventory/health en accepteert alleen schema-gevalideerde opdrachten. De hub bewaart geen OS- of OpenRGB-beheerderswachtwoorden.
|
||||
|
||||
Vereiste eigenschappen:
|
||||
|
||||
- device-bound identiteit en tokenrotatie;
|
||||
- TLS met certificate validation en optionele pinning;
|
||||
- command-idempotency, sequence numbers en deadlines;
|
||||
- lokale allowlist, rate limiter en kill switch;
|
||||
- offline veilige toestand en begrensde reconnect-backoff;
|
||||
- audit aan agent- en hubzijde;
|
||||
- geen inkomende luisterpoort op de remote host;
|
||||
- versie/capability negotiation voor rolling upgrades.
|
||||
|
||||
Datamodel: agent, agent_connection, connector_instance en device_identity blijven afzonderlijk. Apparaten behouden hun interne UUID wanneer een agent reconnect of controllerindices wijzigen. Compromittering van één token mag geen andere agent of centrale beheerrechten ontsluiten.
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
# Security model
|
||||
|
||||
LumaOps controls hardware. Treat its web access, persistent configuration, and
|
||||
connector credentials as administrator-level assets.
|
||||
|
||||
## Safe defaults
|
||||
|
||||
- OpenRGB binds only to `127.0.0.1:6742`; Docker never publishes 6742.
|
||||
- Authentication is enabled for the default LAN bind and requires a unique
|
||||
administrator token of at least 32 characters.
|
||||
- Bridge networking, unprivileged runtime users, and selected device mappings
|
||||
are preferred over host networking or privileged mode.
|
||||
- Inventory and discovery do not write to devices.
|
||||
- Mock mode cannot start in production.
|
||||
- Unknown, blocked, read-only, or identity-mismatched devices reject writes.
|
||||
- Mutations are rate-limited, locked per device, time-bounded, and audited.
|
||||
|
||||
## OpenRGB SDK boundary
|
||||
|
||||
The SDK has no authentication, authorization, or TLS. Anyone who can reach it
|
||||
can control attached hardware. Never add a compose `ports` entry for 6742 and
|
||||
never bind it to a LAN address. A manually configured remote SDK endpoint is
|
||||
accepted only with a persistent warning and is suitable solely for a protected
|
||||
LAN or tunnel.
|
||||
|
||||
## Application access
|
||||
|
||||
Authentication is mandatory for a production process that binds to a non-loopback
|
||||
address. Authenticated mode uses an HttpOnly, Secure (when HTTPS), SameSite cookie
|
||||
and a separate CSRF token for state-changing requests. The administrator token can
|
||||
also be supplied as an API bearer token and must be stored outside source control.
|
||||
|
||||
`TRUSTED_PROXIES` is empty by default. Forwarded headers are honored only from
|
||||
explicit proxy addresses. Setting `EXTERNAL_ACCESS=true` without authentication
|
||||
is a startup error.
|
||||
|
||||
TLS terminates at an administrator-managed reverse proxy. LumaOps does not
|
||||
provision DNS, certificates, port forwarding, or Nginx Proxy Manager.
|
||||
|
||||
## Secrets at rest
|
||||
|
||||
Connector secrets are authenticated-encrypted with the persistent LumaOps key.
|
||||
Use one of:
|
||||
|
||||
1. `LUMAOPS_SECRET_KEY` supplied through a protected container secret; or
|
||||
2. `/config/lumaops/secret.key`, generated on first start with restrictive
|
||||
permissions.
|
||||
|
||||
Back up the key with appdata and store a second protected offline copy. If it is
|
||||
lost, encrypted connector credentials cannot be recovered and must be entered
|
||||
again. Database contents, device metadata, scenes, and audit records remain
|
||||
usable.
|
||||
|
||||
OpenRGB may place Hue or Espurna credentials directly in
|
||||
`/config/openrgb/OpenRGB.json`. Protect and back up that directory as sensitive
|
||||
data too.
|
||||
|
||||
Key rotation creates a database backup, decrypts and reencrypts every connector
|
||||
secret inside one transaction, verifies all ciphertext, atomically replaces the
|
||||
keyfile, and then removes the old key only when the administrator confirms the
|
||||
backup.
|
||||
|
||||
## Logging and diagnostics
|
||||
|
||||
Structured logging redacts known secret field names, authorization/cookie
|
||||
headers, query tokens, encryption keys, and connector credentials. Do not enable
|
||||
raw HTTP or SDK packet logging in production. Request, connector, device, and
|
||||
command identifiers are logged instead.
|
||||
|
||||
The diagnostic bundle uses an allowlist. It includes versions, health,
|
||||
redacted schema-level configuration, device metadata, device-node visibility,
|
||||
and recent normalized errors. It excludes environment dumps, database files,
|
||||
cookies, access tokens, secret ciphertext, raw OpenRGB settings, serial numbers
|
||||
unless explicitly selected, and arbitrary log tails.
|
||||
|
||||
## Hardware risk controls
|
||||
|
||||
- Validate controller identity immediately before writes.
|
||||
- Clamp neither invalid input nor unknown enum values silently; reject them.
|
||||
- Respect advertised mode and zone capabilities.
|
||||
- Limit realtime updates and stop effects when the backend connection ends.
|
||||
- Use a static low-brightness colour for first physical validation.
|
||||
- Do not unload host drivers, change ACPI policy, flash firmware, or probe SMBus
|
||||
addresses destructively.
|
||||
- Treat user plugins as trusted native code with the same privileges as OpenRGB.
|
||||
|
||||
The temporary privileged compose profile exists only to diagnose permissions.
|
||||
After identifying the required `/dev/bus/usb`, hidraw, I2C, or serial nodes,
|
||||
return to explicit mappings and remove privileged access.
|
||||
|
||||
## Vulnerability reporting and updates
|
||||
|
||||
Never publish live deployment values, environment files or diagnostic exports.
|
||||
Review OpenRGB upstream changes, Python/npm lockfiles, and base-image security updates
|
||||
regularly. Build an updated image from source, run the complete test/smoke suite,
|
||||
back up appdata, and then replace the running container. Never update OpenRGB in
|
||||
place inside a running container.
|
||||
@@ -0,0 +1,274 @@
|
||||
# LumaOps source audit
|
||||
|
||||
Status: completed on 2026-07-14 against the imported OpenRGB 1.0rc3 source tree.
|
||||
|
||||
## Scope and method
|
||||
|
||||
The supplied archive was imported unchanged as commit `a15d499` and tagged
|
||||
`upstream-openrgb-1.0rc3` before LumaOps work started. The audit covered the
|
||||
build definition, command-line startup, SDK client/server implementation,
|
||||
protocol structures, settings and profile persistence, plugin loading, Linux
|
||||
hardware access, and the network-lighting controllers named in the project
|
||||
brief.
|
||||
|
||||
The imported tree contains 2,237 tracked files, including 1,045 C++ sources,
|
||||
943 headers, 37 Qt UI definitions, 189 controller directories, and 201 detector
|
||||
implementations. OpenRGB vendors or embeds several dependencies, including
|
||||
hidapi, libusb, mbedTLS, httplib, hueplusplus, libe131, mdns, and nlohmann JSON.
|
||||
|
||||
Files reviewed in detail include:
|
||||
|
||||
- `README.md`, `CONTRIBUTING.md`, `LICENSE`, and `OpenRGB.pro`
|
||||
- all required documents under `Documentation/`
|
||||
- `NetworkServer.*`, `NetworkClient.*`, and `NetworkProtocol.*`
|
||||
- `PluginManager.*`, `SettingsManager.*`, and `ProfileManager.*`
|
||||
- `cli.*`, `ResourceManager.*`, and platform startup sources
|
||||
- the controller and detector sources for the network protocols listed below
|
||||
|
||||
## Confirmed versions
|
||||
|
||||
| Component | Version | Source of truth |
|
||||
| --- | --- | --- |
|
||||
| OpenRGB | 1.0rc3 | `OpenRGB.pro` sets `SUFFIX = 1.0rc3` |
|
||||
| SDK protocol | 5 | `NetworkProtocol.h` sets `OPENRGB_SDK_PROTOCOL_VERSION 5` |
|
||||
| Plugin API | 4 | `OpenRGBPluginInterface.h` sets `OPENRGB_PLUGIN_API_VERSION 4` |
|
||||
|
||||
The LumaOps adapter must negotiate protocol 5. A peer that returns a different
|
||||
version is reported as incompatible instead of silently interpreting a newer or
|
||||
older packet layout.
|
||||
|
||||
## Licensing and contribution constraints
|
||||
|
||||
OpenRGB is distributed under GPL-2.0. The source files commonly use the
|
||||
`GPL-2.0-or-later` SPDX identifier. All upstream license files, copyright
|
||||
notices, and SPDX headers remain intact. LumaOps is part of the combined work
|
||||
and is therefore also published under GPL-2.0-or-later in this repository.
|
||||
|
||||
`CONTRIBUTING.md` makes the human contributor responsible for submitted code
|
||||
and disallows AI authorship or co-authorship metadata. Commits use the existing
|
||||
repository identity and do not add AI attribution trailers.
|
||||
|
||||
Anyone distributing a LumaOps image must make the corresponding source,
|
||||
including the exact OpenRGB modifications and build instructions, available
|
||||
under the GPL. Merely running the software privately does not trigger source
|
||||
distribution obligations.
|
||||
|
||||
## Build and headless operation
|
||||
|
||||
### Upstream Linux build
|
||||
|
||||
`Documentation/Compiling.md` describes a qmake/Qt 5 build. The significant
|
||||
Debian/Ubuntu build dependencies are Qt 5 development tools, a C++ toolchain,
|
||||
pkg-config, libusb, hidapi, and mbedTLS. The upstream sequence is equivalent to:
|
||||
|
||||
```sh
|
||||
mkdir build
|
||||
cd build
|
||||
qmake ../OpenRGB.pro
|
||||
make -j"$(nproc)"
|
||||
```
|
||||
|
||||
OpenRGB is still linked with Qt libraries in a headless build, but it creates a
|
||||
`QApplication` only when the GUI flag is selected. It therefore runs without an
|
||||
X11/Wayland display when started in server mode.
|
||||
|
||||
### Verified headless command
|
||||
|
||||
The CLI parser and platform startup code confirm this production command:
|
||||
|
||||
```sh
|
||||
openrgb \
|
||||
--server \
|
||||
--server-host 127.0.0.1 \
|
||||
--server-port 6742 \
|
||||
--config /config/openrgb \
|
||||
--noautoconnect
|
||||
```
|
||||
|
||||
The directory passed to `--config` must exist before startup. `--server-host`
|
||||
must always be explicit because OpenRGB otherwise defaults to `0.0.0.0`.
|
||||
`--nodetect` must not be supplied: it would defeat the required local hardware
|
||||
inventory. Starting with no server/CLI action would select the graphical UI.
|
||||
|
||||
The Linux startup path initializes `ResourceManager`, starts the internal
|
||||
server, waits for device detection, and then remains in
|
||||
`WaitWhileServerOnline()`. There is one upstream gap relevant to containers:
|
||||
SIGINT/SIGTERM handlers are registered only in the GUI startup branch. LumaOps
|
||||
therefore carries a small isolated patch that installs the same shutdown handler
|
||||
for headless server mode. This lets the supervisor stop OpenRGB cleanly instead
|
||||
of relying on the operating system's abrupt default termination.
|
||||
|
||||
The production container must verify at runtime that port 6742 is listening on
|
||||
loopback and must never publish or expose it through Docker.
|
||||
|
||||
## SDK protocol audit
|
||||
|
||||
The SDK is an unauthenticated binary TCP protocol. It is appropriate only as an
|
||||
internal process boundary in the same container; it is not an internet or LAN
|
||||
security boundary.
|
||||
|
||||
Packets start with a 16-byte header:
|
||||
|
||||
1. magic bytes `ORGB`;
|
||||
2. 32-bit device index;
|
||||
3. 32-bit packet ID;
|
||||
4. 32-bit payload length.
|
||||
|
||||
The implementation serializes the protocol's integers and packed structures in
|
||||
the native little-endian layout used by the x86_64 target. Notable request IDs
|
||||
are controller count (`0`), controller data (`1`), protocol negotiation (`40`),
|
||||
client name (`50`), device-list-changed (`100`), rescan (`140`), profile list and
|
||||
operations (`150`-`153`), and plugin operations (`200`-`201`). Update requests
|
||||
cover mode, device/zone/LED colours, custom mode, resizing zones, and segment
|
||||
changes.
|
||||
|
||||
Protocol 5 adds zone flags, controller flags, effects-only zones, alternative
|
||||
LED names, and segment-clear/add operations. The controller-data response is a
|
||||
nested variable-length structure containing strings, modes, zones, segments,
|
||||
LEDs, and colours. This makes strict bounds checking mandatory.
|
||||
|
||||
The internal adapter will enforce:
|
||||
|
||||
- exact-length reads and the `ORGB` magic value;
|
||||
- protocol-5 negotiation before normal traffic;
|
||||
- a configurable hard maximum packet size (default 16 MiB);
|
||||
- bounded collection counts and bounded, NUL-terminated strings;
|
||||
- controller, zone, LED, mode, speed, brightness, and colour validation;
|
||||
- controller identity checks instead of trusting a stale device index;
|
||||
- one serialized write queue plus per-device locks;
|
||||
- connection and command timeouts, bounded reconnect backoff, and cancellation;
|
||||
- no write side effects during inventory;
|
||||
- safe handling of device-list change notifications and OpenRGB restarts.
|
||||
|
||||
The server source also checks controller indexes and validates declared payload
|
||||
sizes for update packets. LumaOps performs the same checks before transmitting,
|
||||
so malformed application input never reaches OpenRGB.
|
||||
|
||||
### Existing Python client evaluation
|
||||
|
||||
The current `openrgb-python` package was inspected at upstream commit
|
||||
`dbbe58336268e273e2604f6f10b9e2f2003d6d84`. It still declares protocol version
|
||||
4, does not implement the protocol-5 surface required by this release, does not
|
||||
provide the required rescan request, and contains receive paths that use a
|
||||
single unbounded socket read for a declared packet length. Its repository also
|
||||
does not provide the parser/serialization test coverage required here.
|
||||
|
||||
Decision: LumaOps uses a small first-party SDK protocol-5 adapter behind a
|
||||
connector interface. No other application layer imports packet structures.
|
||||
This keeps the binary protocol auditable and lets tests replay captured and
|
||||
synthetic packets without replacing the real production adapter.
|
||||
|
||||
## Settings, profiles, and plugins
|
||||
|
||||
On Linux, OpenRGB normally stores data under `$XDG_CONFIG_HOME/OpenRGB` or
|
||||
`$HOME/.config/OpenRGB`. With the verified command above, all OpenRGB-owned
|
||||
state is instead rooted at `/config/openrgb`:
|
||||
|
||||
| Data | Location |
|
||||
| --- | --- |
|
||||
| Main settings | `/config/openrgb/OpenRGB.json` |
|
||||
| Normal profiles | `/config/openrgb/*.orp` |
|
||||
| Controller size profile | `/config/openrgb/sizes.ors` |
|
||||
| User plugins | `/config/openrgb/plugins/` |
|
||||
| System plugins | build-time platform directory, normally `/usr/lib/openrgb/plugins` |
|
||||
|
||||
Profiles match controller identity fields rather than relying only on discovery
|
||||
order. Profile deletion removes the corresponding profile file. Settings are
|
||||
written directly as JSON and OpenRGB itself does not make an atomic backup, so
|
||||
LumaOps backs up the OpenRGB directory together with its own data before
|
||||
restores, migrations, or destructive maintenance.
|
||||
|
||||
Plugin enablement is stored in the `Plugins` section of `OpenRGB.json`. A plugin
|
||||
must match Plugin API 4 exactly. User-supplied plugins execute native code in the
|
||||
OpenRGB process and are therefore treated as trusted administrator extensions,
|
||||
not as sandboxed add-ons.
|
||||
|
||||
Some network-controller configuration is also stored in `OpenRGB.json`. It can
|
||||
include credentials such as a Philips Hue username/client key or Espurna API
|
||||
key. `/config/openrgb` must therefore receive the same restrictive filesystem
|
||||
permissions, backup handling, and diagnostic redaction as LumaOps secrets.
|
||||
|
||||
LumaOps state is deliberately separate under `/config/lumaops` and `/data` so
|
||||
OpenRGB upstream files and application migrations have independent lifecycles.
|
||||
|
||||
## Existing OpenRGB network support
|
||||
|
||||
The audit distinguishes automatic discovery from controllers that are created
|
||||
from manually saved settings even when their source class is named a detector.
|
||||
|
||||
| Family | Existing OpenRGB path | Transport and discovery notes |
|
||||
| --- | --- | --- |
|
||||
| DDP | DDP network controller | Manual target stored in settings; UDP, default port 4048 |
|
||||
| E1.31/sACN | E1.31 controller | Manual unicast/multicast configuration; standard E1.31 UDP transport |
|
||||
| Philips Hue | Hue controller via hueplusplus | Bridge discovery plus manual bridge data; REST/entertainment setup; username and client key are persistent secrets |
|
||||
| Philips WiZ | WiZ controller | UDP port 38899 |
|
||||
| Nanoleaf | Nanoleaf controller | HTTP API for setup/state and external-control UDP streaming; external port may be negotiated, with 60222 used by supported paths |
|
||||
| LIFX | LIFX controller | LAN protocol over UDP port 56700 |
|
||||
| Govee | Govee controller | LAN discovery multicast `239.255.255.250:4001`, local discovery port 4002, control UDP port 4003 |
|
||||
| TP-Link Kasa | Kasa controller | Local TCP protocol on port 9999 |
|
||||
| Yeelight | Yeelight controller | LAN discovery/manual target; TCP port 55443 |
|
||||
| Espurna | Espurna controller | Manual IP/port/API key; HTTP-style API over TCP |
|
||||
| Elgato lighting | Key Light and Light Strip controllers | Local HTTP/TCP API on port 9123 |
|
||||
|
||||
Host networking may be needed for broadcast, multicast, or mDNS discovery on an
|
||||
Unraid host. Bridge networking remains the default. A host-network deployment
|
||||
still binds the SDK to `127.0.0.1`; only the LumaOps web port is intended for LAN
|
||||
access.
|
||||
|
||||
Native WLED and Home Assistant connectors remain outside OpenRGB and use the
|
||||
same LumaOps capability model. Duplicate ownership is prevented by assigning
|
||||
one management owner per physical device.
|
||||
|
||||
## Hardware access on Linux and Unraid
|
||||
|
||||
### USB
|
||||
|
||||
OpenRGB needs access to hidraw/libusb devices. A normal Linux installation can
|
||||
install generated udev rules at `/usr/lib/udev/rules.d/60-openrgb.rules`. In a
|
||||
container, the host kernel still owns udev and permissions. The supported
|
||||
deployment passes `/dev/bus/usb` explicitly and, where needed, selected hidraw
|
||||
devices. Running the whole container as privileged or mounting all of `/dev` is
|
||||
not the production default.
|
||||
|
||||
### SMBus/I2C
|
||||
|
||||
The host loads `i2c-dev` plus its chipset driver, commonly `i2c-i801` on Intel
|
||||
or `i2c-piix4` on AMD. Only discovered `/dev/i2c-*` nodes that are actually
|
||||
needed are passed through. Some boards require vendor-specific modules; some
|
||||
kernel/ACPI workarounds can be unsafe and are documented as diagnostics rather
|
||||
than enabled automatically. SPD-related controllers can conflict with kernel
|
||||
memory sensor drivers, so LumaOps does not unload modules or write to SMBus as
|
||||
part of inventory.
|
||||
|
||||
### Serial devices
|
||||
|
||||
Optional serial controllers use individually mapped `/dev/ttyUSB*` or
|
||||
`/dev/ttyACM*` devices. Their group/permission requirements remain host-specific.
|
||||
|
||||
The first-run inventory is read-only. Actual validation starts with one selected
|
||||
device, a static low-intensity colour, and a low command frequency.
|
||||
|
||||
## Architectural conclusions
|
||||
|
||||
1. Preserve the upstream source layout and keep LumaOps under `lumaops/`,
|
||||
`docker/`, `docs/`, and `tests/`.
|
||||
2. Carry only the documented headless signal patch and unambiguous HID-interface
|
||||
fallback in OpenRGB Core; keep all other policy, persistence, connectors, and UI
|
||||
work outside the core.
|
||||
3. Build OpenRGB from the imported source in the production multi-stage image.
|
||||
4. Run OpenRGB and FastAPI under a real init/supervisor; serve the built React
|
||||
application from FastAPI so only one web port is public.
|
||||
5. Use an internal protocol-5 adapter for production and a clearly marked mock
|
||||
adapter only for tests and intentional development mode.
|
||||
6. Store stable LumaOps UUIDs from a fingerprint of durable identity fields plus
|
||||
persisted identity aliases; never expose discovery order as identity.
|
||||
7. Keep OpenRGB at `127.0.0.1:6742`, including under host networking, and reject
|
||||
non-loopback production configuration unless an administrator explicitly
|
||||
opts into the documented remote-endpoint risk.
|
||||
8. Treat both `/config/openrgb` and `/config/lumaops` as sensitive persistent
|
||||
state and redact them from diagnostics.
|
||||
9. Model connector capabilities generically so WLED, Home Assistant, MQTT,
|
||||
remote agents, and future protocols do not require brand-specific UI paths.
|
||||
|
||||
This audit clears the project to proceed with the LumaOps architecture and MVP
|
||||
implementation while retaining OpenRGB 1.0rc3 as the actual hardware engine.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Testen
|
||||
|
||||
Backend:
|
||||
|
||||
cd lumaops/backend
|
||||
python -m ruff format --check src tests
|
||||
python -m ruff check src tests
|
||||
python -m mypy src
|
||||
python -m pytest
|
||||
|
||||
Frontend:
|
||||
|
||||
cd lumaops/frontend
|
||||
npm ci
|
||||
npm run lint
|
||||
npm run test
|
||||
npm run build
|
||||
npm audit
|
||||
|
||||
Productie:
|
||||
|
||||
docker compose build --pull
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
docker exec lumaops /opt/venv/bin/python /opt/lumaops/healthcheck.py
|
||||
|
||||
Gebruik CONNECTOR_MODE=mock uitsluitend met LUMAOPS_ENV=test of development. De Settings-validatie weigert mockmodus in productie en de UI toont een permanente waarschuwing. Fysieke tests beginnen met inventory en daarna één statische kleur op lage frequentie.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Probleemoplossing
|
||||
|
||||
## Webapp niet bereikbaar
|
||||
|
||||
Controleer `docker compose ps`, de externe poort 1223/`WEB_PORT`, de interne `APP_PORT` (standaard 8080) en `/logs/backend.log`. De rootfilesystem is read-only; `/config`, `/data`, `/logs`, `/tmp` en `/run` moeten schrijfbaar zijn. Controleer PUID/PGID en appdata-eigenaarschap.
|
||||
|
||||
## OpenRGB of SDK offline
|
||||
|
||||
Bekijk /logs/openrgb.log en /logs/supervisor.log. De supervisor herstart OpenRGB met begrensde backoff; de webapp blijft beschikbaar en health wordt degraded. Controleer dat alleen 127.0.0.1:6742 gebruikt wordt:
|
||||
|
||||
docker exec lumaops python -c "import socket; print(socket.create_connection(('127.0.0.1',6742),2))"
|
||||
|
||||
Publiceer 6742 niet om het probleem te omzeilen. Controleer versie 1.0rc3 en SDK-protocol 5.
|
||||
|
||||
## Geen USB- of I²C-apparaten
|
||||
|
||||
Doorloop de setupwizard opnieuw. Vergelijk host- en containerinventaris. Voeg /dev/bus/usb of alleen de benodigde /dev/i2c-* toe. Laad i2c-dev plus chipsetdriver op de host. Gebruik het privileged diagnoseprofiel alleen kort om een permissieverschil te bevestigen.
|
||||
|
||||
## Network lights niet gevonden
|
||||
|
||||
Bridge networking laat niet elk broadcast/multicast/mDNS-protocol door. Test de host-network override. Houd OPENRGB_HOST op 127.0.0.1. Controleer VLAN/firewall en of discovery is ingeschakeld.
|
||||
|
||||
## Login werkt niet via HTTP
|
||||
|
||||
Secure cookies vereisen HTTPS. Gebruik een reverse proxy met TLS. Alleen voor tijdelijke LAN-diagnose kan SECURE_COOKIES=false. EXTERNAL_ACCESS=true zonder AUTH_ENABLED wordt bij startup geweigerd.
|
||||
|
||||
## Database of secrets
|
||||
|
||||
SQLite-integriteitsfouten: stop de container en herstel een gecontroleerde back-up. Een ontbrekende secret.key kan niet cryptografisch worden gereconstrueerd; herstel dezelfde sleutel of configureer connectorsecrets opnieuw.
|
||||
|
||||
## Diagnosepakket
|
||||
|
||||
Download /api/v1/diagnostics/export via de UI. Het pakket bevat versies, schema zonder geheimen, hardwaretoegang, SDK-status, inventory, health en recente fouten. Request-id uit een foutmelding koppelt frontend, API en logs.
|
||||
@@ -0,0 +1,59 @@
|
||||
# LumaOps op Unraid
|
||||
|
||||
## Voorbereiding
|
||||
|
||||
LumaOps bouwt één image met OpenRGB Core, de FastAPI-backend en de statische React-app. De veilige standaard is bridge networking, een read-only rootfilesystem en alleen expliciete hardwaredevices. Alle Linux-capabilities worden verwijderd, behalve CHOWN, SETUID en SETGID die de root-entrypoint kort nodig heeft om volumes en PUID/PGID in te stellen; na de overstap draait de applicatie als Unraid nobody/users via PUID=99 en PGID=100.
|
||||
|
||||
Maak appdata aan:
|
||||
|
||||
mkdir -p /mnt/user/appdata/lumaops/{openrgb,config,data,logs}
|
||||
|
||||
Kloon de repository, kopieer .env.example naar .env en bouw:
|
||||
|
||||
git clone REPOSITORY-URL
|
||||
cd LumaOps
|
||||
cp .env.example .env
|
||||
# Genereer een unieke token met: openssl rand -base64 32
|
||||
# en vervang LUMAOPS_ADMIN_TOKEN in .env.
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
docker compose ps
|
||||
|
||||
Pas in docker-compose.yml de hostpaden aan naar /mnt/user/appdata/lumaops wanneer Compose vanuit een andere map draait. Voor de Unraid GUI kan docker/unraid-lumaops.xml als templatebasis worden gebruikt. Bij een lokale build blijft Repository lumaops:0.1.0.
|
||||
|
||||
## Netwerkmodi
|
||||
|
||||
Bridge is standaard en publiceert alleen de webinterface: extern `WEB_PORT=1223` naar intern `APP_PORT=8080`. Open dus `http://UNRAID-IP:1223`. Poort 6742 ontbreekt doelbewust bij `ports`.
|
||||
|
||||
Voor OpenRGB-netwerkcontrollers die UDP broadcast, multicast of mDNS nodig hebben:
|
||||
|
||||
docker compose -f docker-compose.yml -f docker/compose.host-network.yml up -d
|
||||
|
||||
De override verwijdert de webpoortmapping omdat host networking die niet gebruikt. LumaOps luistert dan rechtstreeks op `WEB_PORT` (standaard 1223). `OPENRGB_HOST` blijft 127.0.0.1, ook in host mode.
|
||||
|
||||
## Bijwerken
|
||||
|
||||
git fetch origin
|
||||
git pull --ff-only origin main
|
||||
docker compose build --pull
|
||||
docker compose up -d --remove-orphans
|
||||
docker image prune
|
||||
|
||||
Maak vooraf een appdata-back-up. Databaseback-ups in de UI vervangen geen kopie van de volledige appdata. Een rollback gebruikt een vorige Git-commit/tag en daarna dezelfde build/up-opdrachten.
|
||||
|
||||
## Productiecontrole
|
||||
|
||||
docker compose ps
|
||||
docker inspect --format "{{json .State.Health}}" lumaops
|
||||
docker exec lumaops /opt/venv/bin/python /opt/lumaops/healthcheck.py
|
||||
docker exec lumaops sh -c "ss -ltn 2>/dev/null || true"
|
||||
|
||||
Verwacht: web bereikbaar op hostpoort 1223, SDK alleen op 127.0.0.1:6742 en health healthy. Een ontbrekend hardwaredevice mag de webapp niet neerhalen; readiness wordt degraded/unhealthy met hersteladvies.
|
||||
|
||||
## Authenticatie
|
||||
|
||||
Login staat standaard aan en vereist een unieke `LUMAOPS_ADMIN_TOKEN` van minstens
|
||||
32 tekens. Voor rechtstreekse HTTP-toegang op een vertrouwd LAN blijft
|
||||
`SECURE_COOKIES=false`; zet dit op `true` achter HTTPS. Zet bij internettoegang ook
|
||||
`EXTERNAL_ACCESS=true` en voeg alleen bekende proxyadressen toe aan
|
||||
`TRUSTED_PROXIES`. Publiceer LumaOps nooit rechtstreeks zonder TLS.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Verificatierapport 0.1.0
|
||||
|
||||
Dit rapport beschrijft de lokale releasecontrole van LumaOps op 15 juli 2026. De
|
||||
geteste OCI-image is `lumaops:0.1.0` voor x86_64 Linux.
|
||||
|
||||
## Resultaten
|
||||
|
||||
- De volledige OpenRGB 1.0rc3 Core compileert in de multi-stage Docker-build.
|
||||
- Een schone productiecontainer migreert SQLite naar `0001_initial` en start
|
||||
gezond met een echte OpenRGB SDK-protocol-5-verbinding.
|
||||
- De webinterface is op de host uitsluitend gepubliceerd als `1223:8080`.
|
||||
- De SDK-listener is uitsluitend `127.0.0.1:6742`; poort 6742 is niet door
|
||||
Docker gepubliceerd. Een rauwe SDK-v5-handshake is succesvol uitgevoerd.
|
||||
- Het rootfilesystem is read-only. Alleen `/config`, `/data`, `/logs`, `/tmp`
|
||||
en `/run` zijn schrijfbaar gemaakt.
|
||||
- OpenRGB en de backend draaien na de entrypoint als UID 1000 in de rooktest.
|
||||
De runtime-image bevat geen gcc, g++, make, qmake of cmake.
|
||||
- De ingebouwde container-healthcheck rapporteert `healthy`.
|
||||
- Een opgeslagen instelling blijft na een containerrestart aanwezig.
|
||||
- Na een geforceerde beëindiging van OpenRGB bleef `/health/live` HTTP 200
|
||||
geven; de supervisor startte OpenRGB opnieuw en de connector herstelde.
|
||||
- Een normale containerstop eindigde met exitcode 0 en stopte backend en
|
||||
OpenRGB gecontroleerd.
|
||||
- Een schone testcontainer met de expliciete mockadapter vond twee apparaten.
|
||||
Set-state, inventarisverversing, scène capture/apply/duplicate/export en het
|
||||
auditlog zijn via de versie-API uitgevoerd.
|
||||
|
||||
## Geautomatiseerde kwaliteitscontroles
|
||||
|
||||
Backend:
|
||||
|
||||
ruff format --check . # 34 bestanden correct geformatteerd
|
||||
ruff check . # geslaagd
|
||||
mypy src # 31 bronbestanden, geen fouten
|
||||
pytest # 14 geslaagd
|
||||
|
||||
Frontend:
|
||||
|
||||
npm run lint # geslaagd, nul waarschuwingen
|
||||
npm test # 3 geslaagd
|
||||
npm run build # TypeScript en Vite geslaagd
|
||||
npm audit # 0 kwetsbaarheden
|
||||
|
||||
De productiefrontend gaf HTTP 200. De componenttests dekken onder meer de
|
||||
genormaliseerde inventaris, filtering en de snelle kleuractie via de echte
|
||||
versie-API-contracten.
|
||||
|
||||
## Compose- en templatecontrole
|
||||
|
||||
`docker compose config` is uitgevoerd voor de standaard-, host-network- en
|
||||
diagnostische varianten. Standaard is alleen hostpoort 1223 gepubliceerd. In
|
||||
host mode luistert de webapp rechtstreeks op 1223. De diagnostische override is
|
||||
bewust privileged en is niet de productieconfiguratie. Het Unraid XML-template
|
||||
is als XML geparseerd en verwijst eveneens naar poort 1223.
|
||||
|
||||
## Grenzen van deze controle
|
||||
|
||||
Er zijn geen fysieke RGB-apparaten of Unraid-hostdevice-nodes aan deze
|
||||
ontwikkelmachine gekoppeld. De echte Core en SDK zijn met nul controllers
|
||||
getest; hardwarewrites zijn uitsluitend tegen de expliciete mockadapter gedaan.
|
||||
Volg daarom vóór productiegebruik de niet-destructieve inventariscontrole uit
|
||||
`HARDWARE_ACCESS.md`, en test daarna één ondersteund apparaat met een
|
||||
statische kleur en lage commandofrequentie.
|
||||
Reference in New Issue
Block a user