Admin a9e2182396 feat(config): per-service operator config + secrets (theme M1)
Services can declare an operator-configurable config block in /_manifest
(ordered array of single-key objects, pure schema: type cleartext|password,
description?, key = container env var name). Maestro:

- lib/secrets: AES-256-GCM FileStore; dedicated secrets.key (32 bytes,
  chmod 600, separate from session.key); secrets.json rows keyed
  service/field; cleartext read-write, password write-only & encrypted at
  rest, decrypted only at injection. Footure key rotation = delete the key.
- handlers/config (owner-gated via auth.RequireSession):
  GET /api/services/{service}/config (merged schema+set view, password
  values never returned), PUT/DELETE /api/services/{service}/config/{key}
  (uniform ERR_NOT_FOUND / ERR_INVALID_PAYLOAD error shape).
- start.go: injectConfigSecrets runs after injectServiceIdentity; only
  operator-set rows become env on non-oneoff services; unset fields keep
  the compose default.
- Manifest.Config carried onto Container/RegistryContainer/InstalledMetadata
  via updateInstalledMetadataFromManifest + watcher.
- Frontend: per-service Settings dialog (ServiceConfigDialog) + api
  helpers; cleartext editable, password set/unset indicator only.
- spec.yaml documents the new endpoints/schemas.
2026-08-31 00:48:51 +01:00
2026-07-29 01:36:09 +01:00
2026-08-04 22:02:50 +00:00
2026-07-29 01:33:35 +01:00
2026-07-29 01:36:09 +01:00

Maestro

Dcntrlized project coordinator service

Access & transport

The dashboard ships session cookies (instance-owner gate), so the deployment default is loopback-only: docker-compose.yaml binds 127.0.0.1:8080:8080, making the listener unreachable from the LAN unless you deliberately opt out. Maestro itself stays plaintext HTTP; TLS terminates in a reverse proxy (D6 — no TLS machinery inside the process).

Single host

Reach the UI over SSH from your workstation:

ssh -L 8080:127.0.0.1:8080 <host>
# then open http://localhost:8080

Reverse proxy (LAN / public)

Put Caddy, Traefik or nginx in front of http://127.0.0.1:8080 and terminate TLS there:

maestro.example.org {
    reverse_proxy 127.0.0.1:8080
}
  • WebSocket: the UI uses /api/ws. Caddy and Traefik proxy upgrades automatically; nginx needs explicit headers:
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
  • Cookies behind the proxy: set COOKIE_SECURE=true in Maestro's environment so both session cookies (maestro_access / maestro_refresh) are marked Secure.
  • Host header: mutating requests carry an Origin/Referer CSRF check that compares hosts. A proxy that preserves Host works unchanged; if you rewrite the host, keep forwarding X-Forwarded-* and serve the UI on the same host you proxy to.
S
Description
No description provided
Readme AGPL-3.0
618 KiB
Languages
Go 63.9%
TypeScript 32.3%
CSS 3.3%
HTML 0.3%
Dockerfile 0.2%