Commits
prism is decommissioned, so social.krebsco.de had no working entry
point while the hotdog container itself kept serving fine on neoprism.
DNS for social.krebsco.de still needs to be repointed to neoprism
before ACME can issue a cert.
Livestreams never played and VOD depends on companion keeping up with
YouTube's po_token and SABR changes, which it does not reliably enough to
be worth the moving parts.
Takes the residential exits with it: tinyproxy on styx and coaxmetal
existed only so neoprism could reach YouTube from a non-Hetzner address.
Leaves the generated companion key in vars/pass, matching how the
silverbullet and oauth2-proxy removals were handled.
Point at Lassulus/tincr fix/pmtu-blackhole-recovery (upstream main plus
the fix) until it lands in Mic92/tincr.
ignavia and coaxmetal sit behind the same NAT, which does not hairpin.
Once a relay hands each the other's reflexive address, every UDP probe
is answered with ICMP port unreachable, and tincr never recovers:
udp_timed_out measured from the probe send rather than the reply, so
the 10s keepalive kept pushing a 30s deadline out of reach and
udp_confirmed stayed pinned; with it pinned, discovery collapsed maxmtu
to 0 and nothing re-armed it, so every cycle re-converged to MTU 0.
Logged as "Fixing MTU of coaxmetal to 0" 201 times in 30 minutes with
the peer unusable, versus once for every healthy peer.
Also carries upstream PRs #13-#20 (riscv64, tincd-compat, default
package, systemd credential loading, multi-user.target).
Colours stay inside the terminal's ANSI palette (NNN_FCOLORS, NNN_COLORS,
bat's ansi theme, mdcat), including nnn's nerd icon table which hardcodes
xterm-256 codes, so retheming the terminal also retints a session running
on the far side of ssh.
The image previewer asks the terminal which graphics protocol it speaks
instead of letting chafa guess from inherited KITTY_* variables, which
claim kitty even where the data cannot reach a terminal and leave blank
placeholder cells behind. Frames are rendered into memory and written
with signals blocked, so preview-tui killing the previewer on a selection
change cannot truncate an escape sequence.
The kiosk account owns everything needed to test a game the way a player
meets it, and none of it is reachable from outside: sway holds seat0,
XDG_RUNTIME_DIR is 0700, the Xbox pad's evdev nodes are ACL'd to strom
(only the legacy js0 is world-readable, and SDL2 does not use it), and
/home/strom carries both the game state and the /home/strom/strom
checkout that strom-session resolves STROM_FLAKE from.
Follows the existing 2configs/{wine,review,ableton}.nix pattern.
Without an admin nobody can manage any session: sessions registered
through the keyless announce API carry no owner, so canManage was false
for every one of them and the dashboard suppressed its share and kill
controls entirely.
invidious plus invidious-companion, with every request to YouTube going
out through the residential exits on styx (primary) and coaxmetal
(backup). An nginx stream block fans 127.0.0.1:8118 into the two
tinyproxies; failover rather than round-robin, because YouTube binds
po_tokens and videoplayback URLs to the requesting address.
The companion key is generated once into a clan var and handed to
invidious as a systemd credential (the config script runs as the
DynamicUser, which cannot read /run/secrets) and to the container as an
EnvironmentFile.
default_user_preferences.local is forced on: upstream defaults it off,
which makes invidious hand the browser raw googlevideo URLs that are
minted for the exit's address, so they 403 for the client and leak the
exit IP. Playback paths additionally require a real session via
auth_request, since the bytes come off a residential line.
invidious is pinned one release ahead of our nixpkgs for the comments
parser fix; drop the override once the pin catches up.
Livestreams do not play: YouTube serves them SABR-only or with HLS
segments that 403 without a po_token, and invidious' HLS path bypasses
companion. Upstream gap, tracked in iv-org/invidious#3811 and
iv-org/invidious-companion#7.
YouTube throttles and blocks Hetzner ranges, so neoprism cannot talk to
it directly. tinyproxy listens on the retiolum address of each box and
only accepts neoprism, giving invidious a residential exit.
Bare `provider = "custom"` resolves its credential from a host-gated
candidate list and only forwards OPENAI_API_KEY when base_url points at
openai.com (upstream #28660 / GHSA-76xc-57q6-vm5m). For any other host it
substitutes the literal placeholder "no-key-required", so the llama
cluster answered 401. Use a named custom_providers entry with key_env,
which is not host-gated, and rename the env var to LLAMA_API_TOKEN.
The collab patch lived here and was applied twice (2configs/covibe.nix with the
collab-web SPA, tools/covibe without it), and the client wrapper hardcoded the
four covibe.lassul.us addresses in shell. covibe owns all of that now:
- 2configs/covibe.nix keeps only the deployment: ompPackage and webRoot come
from the module defaults (covibe.packages.${system}.omp and its SPA).
- tools/covibe passes the addresses to covibe-client.override; the CLI's own
COVIBE_* env fallbacks replace the shell script, and `covibe` in a project
directory still starts a session with arguments going to omp.
- covibe.inputs.llm-agents.follows = "llm-agents" keeps one omp revision, so the
patched omp derivation is unchanged (4nxafz2k…-omp-17.1.4.drv): no new build.
- 2configs/omp-collab-autostart.patch deleted (now covibe/nix/).
The autostart was one-shot, and an omp collab host never returns on its own:
CollabSocket treats 4001/4004/4009/4029 as fatal (no reconnect), and
CollabHost.#broadcast self-stops with "session switched" when the session id
changes — which happens seconds into a fresh session, as the first prompt
creates the real session. Observed on ignavia: hosts died 21s and 88s in
(logging one debug line, "dropping frame, socket closed" t=bye), so the
dashboard listed sessions whose room no longer existed and every browser link
answered "session ended: no such room" for the rest of a multi-hour session.
superviseAutostartCollab() now keeps hosting: it re-hosts on the same preset
room whenever the host disappears without the user asking (/collab stop and
/leave set a flag), with exponential backoff on connect failures. Because
covibe fixes the room id and key, re-hosting restores the identical link, so
QR codes already scanned keep working; retrying also recovers from a stale
4009 host once the relay's keepalive frees the dead room.
readCollabAutostartEnv() also consumes OMP_COLLAB_* from process.env: children
inherit it, so a nested omp would race the host for the same room and one of
them loses with 4009.
Rebased onto omp 17.1.4 (the previous patch only applied with fuzz) and
typechecked with tsgo.
The disko tank/radicle dataset must exist before switching on a live host; if
it is absent the zfsutil mount fails local-fs.target and drops to emergency
mode (no network). nofail degrades that to a skipped mount instead. Create the
dataset with: zfs create -o mountpoint=/var/lib/radicle -o quota=80G tank/radicle
Extend 2configs/radicle.nix into a public seed: allow-all seeding (scope=all),
listen 0.0.0.0:8776 + externalAddresses radicle.lassul.us:8776, radicle-httpd
behind an nginx vhost (radicle.lassul.us, ACME). Drop the tor proxy + onion
preferred seeds. Move the config off xerxes onto neoprism, and put the node
state on tank at /var/lib/radicle with an 80G ZFS quota (radicle has no built-in
byte quota; the dataset bounds it).
Reference pinentry-rofi (or pinentry_mac on darwin) directly in the
wrapper and write it to rbw config before unlocking, instead of relying
on a persisted store path that gets garbage-collected and breaks
'rbw unlock' with 'error spawning pinentry: No such file'.
Livestreams never played and VOD depends on companion keeping up with
YouTube's po_token and SABR changes, which it does not reliably enough to
be worth the moving parts.
Takes the residential exits with it: tinyproxy on styx and coaxmetal
existed only so neoprism could reach YouTube from a non-Hetzner address.
Leaves the generated companion key in vars/pass, matching how the
silverbullet and oauth2-proxy removals were handled.
Point at Lassulus/tincr fix/pmtu-blackhole-recovery (upstream main plus
the fix) until it lands in Mic92/tincr.
ignavia and coaxmetal sit behind the same NAT, which does not hairpin.
Once a relay hands each the other's reflexive address, every UDP probe
is answered with ICMP port unreachable, and tincr never recovers:
udp_timed_out measured from the probe send rather than the reply, so
the 10s keepalive kept pushing a 30s deadline out of reach and
udp_confirmed stayed pinned; with it pinned, discovery collapsed maxmtu
to 0 and nothing re-armed it, so every cycle re-converged to MTU 0.
Logged as "Fixing MTU of coaxmetal to 0" 201 times in 30 minutes with
the peer unusable, versus once for every healthy peer.
Also carries upstream PRs #13-#20 (riscv64, tincd-compat, default
package, systemd credential loading, multi-user.target).
Colours stay inside the terminal's ANSI palette (NNN_FCOLORS, NNN_COLORS,
bat's ansi theme, mdcat), including nnn's nerd icon table which hardcodes
xterm-256 codes, so retheming the terminal also retints a session running
on the far side of ssh.
The image previewer asks the terminal which graphics protocol it speaks
instead of letting chafa guess from inherited KITTY_* variables, which
claim kitty even where the data cannot reach a terminal and leave blank
placeholder cells behind. Frames are rendered into memory and written
with signals blocked, so preview-tui killing the previewer on a selection
change cannot truncate an escape sequence.
The kiosk account owns everything needed to test a game the way a player
meets it, and none of it is reachable from outside: sway holds seat0,
XDG_RUNTIME_DIR is 0700, the Xbox pad's evdev nodes are ACL'd to strom
(only the legacy js0 is world-readable, and SDL2 does not use it), and
/home/strom carries both the game state and the /home/strom/strom
checkout that strom-session resolves STROM_FLAKE from.
Follows the existing 2configs/{wine,review,ableton}.nix pattern.
invidious plus invidious-companion, with every request to YouTube going
out through the residential exits on styx (primary) and coaxmetal
(backup). An nginx stream block fans 127.0.0.1:8118 into the two
tinyproxies; failover rather than round-robin, because YouTube binds
po_tokens and videoplayback URLs to the requesting address.
The companion key is generated once into a clan var and handed to
invidious as a systemd credential (the config script runs as the
DynamicUser, which cannot read /run/secrets) and to the container as an
EnvironmentFile.
default_user_preferences.local is forced on: upstream defaults it off,
which makes invidious hand the browser raw googlevideo URLs that are
minted for the exit's address, so they 403 for the client and leak the
exit IP. Playback paths additionally require a real session via
auth_request, since the bytes come off a residential line.
invidious is pinned one release ahead of our nixpkgs for the comments
parser fix; drop the override once the pin catches up.
Livestreams do not play: YouTube serves them SABR-only or with HLS
segments that 403 without a po_token, and invidious' HLS path bypasses
companion. Upstream gap, tracked in iv-org/invidious#3811 and
iv-org/invidious-companion#7.
Bare `provider = "custom"` resolves its credential from a host-gated
candidate list and only forwards OPENAI_API_KEY when base_url points at
openai.com (upstream #28660 / GHSA-76xc-57q6-vm5m). For any other host it
substitutes the literal placeholder "no-key-required", so the llama
cluster answered 401. Use a named custom_providers entry with key_env,
which is not host-gated, and rename the env var to LLAMA_API_TOKEN.
The collab patch lived here and was applied twice (2configs/covibe.nix with the
collab-web SPA, tools/covibe without it), and the client wrapper hardcoded the
four covibe.lassul.us addresses in shell. covibe owns all of that now:
- 2configs/covibe.nix keeps only the deployment: ompPackage and webRoot come
from the module defaults (covibe.packages.${system}.omp and its SPA).
- tools/covibe passes the addresses to covibe-client.override; the CLI's own
COVIBE_* env fallbacks replace the shell script, and `covibe` in a project
directory still starts a session with arguments going to omp.
- covibe.inputs.llm-agents.follows = "llm-agents" keeps one omp revision, so the
patched omp derivation is unchanged (4nxafz2k…-omp-17.1.4.drv): no new build.
- 2configs/omp-collab-autostart.patch deleted (now covibe/nix/).
The autostart was one-shot, and an omp collab host never returns on its own:
CollabSocket treats 4001/4004/4009/4029 as fatal (no reconnect), and
CollabHost.#broadcast self-stops with "session switched" when the session id
changes — which happens seconds into a fresh session, as the first prompt
creates the real session. Observed on ignavia: hosts died 21s and 88s in
(logging one debug line, "dropping frame, socket closed" t=bye), so the
dashboard listed sessions whose room no longer existed and every browser link
answered "session ended: no such room" for the rest of a multi-hour session.
superviseAutostartCollab() now keeps hosting: it re-hosts on the same preset
room whenever the host disappears without the user asking (/collab stop and
/leave set a flag), with exponential backoff on connect failures. Because
covibe fixes the room id and key, re-hosting restores the identical link, so
QR codes already scanned keep working; retrying also recovers from a stale
4009 host once the relay's keepalive frees the dead room.
readCollabAutostartEnv() also consumes OMP_COLLAB_* from process.env: children
inherit it, so a nested omp would race the host for the same room and one of
them loses with 4009.
Rebased onto omp 17.1.4 (the previous patch only applied with fuzz) and
typechecked with tsgo.
The disko tank/radicle dataset must exist before switching on a live host; if
it is absent the zfsutil mount fails local-fs.target and drops to emergency
mode (no network). nofail degrades that to a skipped mount instead. Create the
dataset with: zfs create -o mountpoint=/var/lib/radicle -o quota=80G tank/radicle
Extend 2configs/radicle.nix into a public seed: allow-all seeding (scope=all),
listen 0.0.0.0:8776 + externalAddresses radicle.lassul.us:8776, radicle-httpd
behind an nginx vhost (radicle.lassul.us, ACME). Drop the tor proxy + onion
preferred seeds. Move the config off xerxes onto neoprism, and put the node
state on tank at /var/lib/radicle with an 80G ZFS quota (radicle has no built-in
byte quota; the dataset bounds it).