home-server/services/observer-effect/README.md
2026-06-15 21:22:41 -07:00

66 lines
2.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Observer Effect — doomsday clock
A period-styled (1964) clock for running Delta Green: *Observer Effect* online.
- **Player screen** — `observer.ellie.town/` (`clock.html`): an Olympian Holobeam
Array master chronometer. Nixie tubes counting toward 22:03:37, warning lamps
that flash on each pulse, a red wash and dissonant flutes/drums as communion
nears. Read-only; safe to share with the players.
- **Handler panel** — `observer.ellie.town/control` (`control.html`): run/hold,
scrub the clock, jump to any scenario beat, set the iteration (which resets
reality to its wake point), and fire pulse / communion / text effects on the
players' screen.
## How it syncs
A tiny Rust WebSocket relay (`relay/`) holds the one authoritative clock. The
panel sends authenticated commands; every connected screen gets the new state
and free-runs the digits locally between actions. Late joiners get the current
state immediately. Served behind nginx with TLS; the relay only listens on
loopback.
## Deploy
1. DNS: point `observer.ellie.town` at the VPS (A/AAAA). ACME does the cert.
2. It's already wired into `flake.nix` (vps modules) as
`./services/observer-effect.nix`. Rebuild the VPS:
`nixos-rebuild switch --flake .#vps` (however you normally deploy).
## The control key
Commands are authenticated with a shared token in `services/secrets/observer_vps.yaml`
(sops). Enter it once in the panel's **CONTROL KEY** field (saved in that
browser). Rotate any time with `sops services/secrets/observer_vps.yaml` then
rebuild.
## Running a session
The clock starts paused at iteration I, 17:00:00 (the Agents' arrival). Drive it
by hand to match table pacing — **JUMP TO BEAT** for the scripted moments, or
**RATE ×N** + **RUN** to let it tick. Fire **PULSE** on the live shudders and
**COMMUNION** at 22:03:37; then hit **ITERATION II/III/IV** to reset reality
nearer the end as the loop tightens. **SHOW** broadcasts a line of text over the
players' screen (e.g. *"I see the throne of God."*).
## Sound effects
The player screen's pulse / communion / broadcast-text sounds are pre-rendered
mp3s in `site/sfx/`, synthesized from pure ffmpeg `lavfi` filtergraphs (no
samples). Regenerate with:
```sh
cd site/sfx && nix-shell -p ffmpeg --run ./generate.sh
```
If a file fails to load the screen falls back to an equivalent WebAudio synth.
The ambient dread drone is always synth (it's driven by the tension level).
## Local dev (no Nix)
```sh
cd relay
OBSERVER_TOKEN=test cargo run # relay on 127.0.0.1:8770
# serve ./site on :8080 and proxy /ws -> 127.0.0.1:8770, or just open
# site/clock.html and append ?, then point common.js' WS at ws://localhost:8770/ws
```
The pages connect to `wss?://<host>/ws`, so behind nginx everything is same-origin.