Commit graph

50 commits

Author SHA1 Message Date
ef383cb2f0 sunken-ship: bump navidrome 0.61.2 -> 0.62.0 for inPlaylist visibility fix
In navidrome 0.61.x, the inPlaylist/notInPlaylist smart-playlist
criteria SQL builder did not know the smart playlist owner. It only
allowed referencing PUBLIC playlists, regardless of ownership. Per
the docs, an inaccessible reference makes the rule match no tracks,
so notInPlaylist against a private playlist silently degrades to
NOT IN () (always true) - zero filtering.

Symptom: smart playlist `Unrated (de-duped)` returned 9217 tracks
including all members of `[mulbo] dupe-losers` (private, same owner).
GRIVINA "Я хочу" showed 3 copies (1 unique + 2 dupe-losers). Verified
by DB poke: same owner_id, public=0 on both playlists.

Upstream fix: navidrome/navidrome#5411 (deluan) - "Relax playlist
visibility in inPlaylist/notInPlaylist rules". Passes the smart
playlist owner identity into the criteria SQL builder so same-owner
private references work. Shipped in v0.62.0 (2026-06-08).

nixpkgs PR for this bump: NixOS/nixpkgs#529720 (tebriel), opened
2026-06-09, not yet merged. nixos-unstable still on 0.61.2. This
adds a local nixos/pkgs/navidrome/ verbatim from nixpkgs master with
just the 3 hash lines bumped, and wires services.navidrome.package
to it. REMOVE both once nixpkgs-unstable carries 0.62.x.

After deploy: smart playlist songCount 9217 -> 7101, GRIVINA dupes
3 -> 1. Confirmed via direct API fetch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-09 18:21:34 +02:00
DannyDannyDanny
e43a5eb880 sunken-ship: add ffmpeg to mulbo-server PATH
quality.py's spectral-rolloff probe shells out to ffmpeg to extract
a 30s PCM clip. Without ffmpeg on PATH, subprocess fails silently
and get_or_compute_rolloff returns 0.0 — picker degrades to bitrate
ranking (which is what we were trying to fix). Add ffmpeg via
systemd unit `path = with pkgs; [ ffmpeg ];`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 12:40:45 +02:00
DannyDannyDanny
dc7ef47681 sunken-ship: add numpy to mulbo-server env
For FFT-based spectral-rolloff analysis (quality.py) used by the
chromaprint-dupe winner picker. Effective bitrate alone can't tell
a real lossless file from a re-encoded-128kbps-MP3-saved-as-WAV;
spectral rolloff catches the upsampled fakes (rolloff < 17kHz =
came from lossy source).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-04 12:35:22 +02:00
DannyDannyDanny
09d25a1899 sunken-ship: add mutagen to mulbo-server env
The /enrich/revert endpoint shipped in 20_mulbo commit 5d4e9466 calls
enrich.write_tags, which imports mutagen. The main mulbo-server's
pythonEnv only had fastapi/uvicorn/python-multipart — first revert
attempt 500'd with "ModuleNotFoundError: No module named 'mutagen'".
(The enrich oneshot has its own env with mutagen; that's why batch
enrichment worked.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 19:17:05 +02:00
DannyDannyDanny
b2df891b20 sunken-ship: PurgeMissing = always (valid value; 'missing' was rejected by navidrome 0.61.2)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 10:35:59 +02:00
DannyDannyDanny
8fcb43f279 sunken-ship: navidrome Scanner.PurgeMissing = missing
Stops `missing=1` rows accumulating in media_file. After Phase 7
dedupe, Navidrome's watcher minted ~4k track IDs for files briefly
present in /home/danny/music/.mulbo-quarantine; after rm -rf'ing
the quarantine, those rows stayed flagged-missing forever — and
Substreamer's cached queue then hit 500s on every play attempt
("Internal Server Error: open /srv/music/.mulbo-quarantine/...: no
such file or directory").

Cleaned the 4135 quarantine rows manually via SQL; this config
prevents recurrence. Trade-off: missing rows used to preserve
play-history across "file disappeared, came back" cycles. We prefer
client-cache hygiene.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 10:35:07 +02:00
Danny
1204584ae4 fitness-bot: ExecStartPost runs set-bot-presence.py
Re-publishes the bot's menu button + description on every restart
so @BBBot's chat experience stays in sync with $WEBAPP_URL. Errors
are non-fatal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 12:01:56 +02:00
Danny
cda9c4cf0f sunken-ship: drop python-telegram-bot from fitness-bot pythonEnvs
bot.py was deleted upstream — neither prod nor shipyard launches a
polling bot anymore. server.py only needs python-dotenv + aiohttp.
Also refresh the prod section's comment + service description to
reflect the Mini-App-only architecture.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 11:51:20 +02:00
DannyDannyDanny
2e9441f367 Retire dotfiles-rebuild, switch to dm-pull-deploy push timer
- Drop modules/dotfiles-rebuild.nix and its imports in clan.nix;
  sunken-ship + phantom-ship no longer ship the legacy 15-min
  rebuild-from-git timer.
- Add dm-pull-deploy-push systemd timer on sunken-ship: every 15min
  runs dm-send-deploy to announce origin/main rev via data-mesher
  gossip (sunken is the dm-pull-deploy push node).
- Fix mulbo-pull service path: add openssh so 'git fetch' over an
  SSH remote stops failing with 'cannot run ssh'.
- vps-relay authorized_keys: rename Mac key comment to mac-admin,
  add sunken-ship's actual ed25519 key for ZT mesh debugging.
- home.nix: add cinny-desktop (Matrix client).
- neovim: enable cursorline.
2026-05-20 19:31:22 +02:00
DannyDannyDanny
40cc62f65b sunken-ship: chromaprint on PATH for mulbo-server-enrich
AcoustID needs fpcalc -plain output (re-fingerprinted on-demand
since tracks_index stores -raw for dedup). chromaprint added
alongside the existing yt-dlp.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 16:02:42 +02:00
Danny
83dd92d738 shipyard staging gets a stable URL: b3.dannydannydanny.me
Drop the cloudflared Quick Tunnel (URL changed on every restart →
unworkable for shipyard's apps.json). Move to the same pattern
every other tenant uses:

- vps-relay Caddy: new virtualHost b3.dannydannydanny.me →
  reverse_proxy to sunken-ship's ZT IPv6 :8081.
- sunken-ship: open port 8081 on the zt+ firewall interface
  (was 8080 + 8091, now 8080 + 8081 + 8091).
- fitness-bot-shipyard service: set WEBAPP_URL=https://b3...
  so start.py skips its own tunnel attempt; drop pkgs.cloudflared
  from path now that nothing in the unit needs it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 14:00:39 +02:00
Danny
067bab125b sunken-ship: shipyard staging uses shipyard_poc_bot token
shipyard_poc_bot is the shared "POC slot" Telegram bot that hosts
whatever experiment is currently being staged; B3Bot staging is
just the current tenant. Repoint EnvironmentFile and
ConditionPathExists at /home/danny/.secrets/shipyard_poc_bot.env.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 13:12:09 +02:00
DannyDannyDanny
851ee8ea1d sunken-ship: mulbo-server-enrich oneshot (Phase 7.5)
Companion oneshot for mulbo-server. python312 env adds mutagen
(tag writeback); pkgs.yt-dlp on PATH for SoundCloud lookups.
Same User/SupplementaryGroups/EnvironmentFile/StateDirectory as
mulbo-server-backfill. TimeoutSec=8h covers a full library pass.

Trigger:           sudo systemctl start mulbo-server-enrich
Follow:            journalctl -fu mulbo-server-enrich

Add MULBO_ACOUSTID_KEY to /home/danny/.secrets/mulbo-server-navidrome
to enable the AcoustID source; the yt-dlp + filename sources need
no keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 13:01:05 +02:00
Danny
fb99ef3cff sunken-ship: add fitness-bot-shipyard staging instance
Mirrors the prod fitness-bot setup but watches origin/staging,
runs in /home/danny/tg_fitness_bot_shipyard, listens on port 8081,
and loads its bot token from
/home/danny/.secrets/bigbiggerbiggestbot-shipyard.env via
EnvironmentFile (separate from prod's secrets file).

ConditionPathExists keeps the service from start-looping until the
secrets file is written. No WEBAPP_URL set, so start.py boots an
ephemeral cloudflared Quick Tunnel; the bot updates its Telegram
menu button to that URL on every start (same as prod was originally).

Pull-timer fires every 15 min on the :13/28/43/58 offset to spread
load against the existing fitness-bot-pull (:07/15) and
mulbo-server-pull (:11/15) timers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 12:48:26 +02:00
DannyDannyDanny
c5cabe7531 sunken-ship: MULBO_MUSIC_WRITE_ROOT for mulbo-server dedup
/srv/music is RO bind-mount; deletes/quarantines have to go through
the underlying /home/danny/music. New env var separates the read-side
(MUSIC_ROOT, used for hashing) from the write-side (MUSIC_WRITE_ROOT,
used for unlink + move-to-quarantine).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 22:43:46 +02:00
DannyDannyDanny
4525e73f1a sunken-ship: mulbo-server-backfill systemd oneshot
Companion oneshot for mulbo-server: populates the dedup index
(tracks_index) from Navidrome's existing 15k tracks. Without it,
GET /tracks/by-hash misses for every existing offshore track and
the upload path duplicates content.

Inherits same User/SupplementaryGroups as the running service.
chromaprint added to PATH for fpcalc. TimeoutSec=8h covers full
274 GB hashing run with headroom.

Triggered manually — not auto-scheduled:
  sudo systemctl start mulbo-server-backfill
  journalctl -fu mulbo-server-backfill

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 22:30:10 +02:00
DannyDannyDanny
73d4225f9b sunken-ship: grant mulbo-server read on navidrome.db
mulbo-server's /folders endpoint reads navidrome.db directly because
the Subsonic API's path field is tag-virtual (not real fs paths).

Three pieces:
- services.navidrome UMask = 0027 (force) so future DB writes are
  group-readable; default was 0077.
- tmpfiles z-rules to chmod 0640 the existing navidrome.db, -wal, -shm
  (created under the old umask).
- mulbo-server gets SupplementaryGroups=[navidrome] so the unit's
  process can read those files.

Trade-off: couples mulbo-server to Navidrome's schema (specifically
media_file.id + media_file.path). Acceptable given Navidrome 0.61.1
has been stable on these columns; we'll catch breakage at the /health
navidrome_db_readable probe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 15:06:51 +02:00
DannyDannyDanny
4debab6f69 sunken-ship: mulbo-server creds via EnvironmentFile + MULBO_MUSIC_ROOT
Adds:
- MULBO_MUSIC_ROOT=/srv/music (for the /folders fs walk)
- EnvironmentFile=/home/danny/.secrets/mulbo-server-navidrome (creds
  for Subsonic API calls — file is mode 600, owned by danny, not in
  source control)

Required for the new /folders endpoint and the upcoming POST /tracks
which needs to call search3.view + startScan.view.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 21:22:37 +02:00
DannyDannyDanny
1744d776e2 sunken-ship: mulbo-server systemd service + pull timer + ZT port 8091
Phase 5 of the mulbo Navidrome-pivot — companion HTTP service co-
located with Navidrome that owns uploads + the dedup index + the
real on-disk folder layout (which Navidrome's tag-virtual API can't
expose). Wire spec lives in the mulbo repo at 20_mulbo/SERVER_API.md.

Runs as `danny` so writes pass through to /home/danny/music/mulbo-
uploads via the existing /srv/music ro bind-mount — no mount changes
needed. Bound to [::]:8091 (8090 was taken by escape-hormuz on
phantom-ship); firewall scopes it to the ZT mesh, same trick bbbot
uses on 8080.

Pulls the python-projects repo via SSH using sunken-ship's id_ed25519
(registered as a read-only deploy key on the repo). Auto-pull timer
runs every 15 min, offset from fitness-bot-pull and dotfiles-rebuild.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 21:11:05 +02:00
DannyDannyDanny
b8bc17f385 feat(servers): declare SSH authorizedKeys + root mac admin trust 🔑
Move the imperative SSH-key-related scars accumulated during the
clan/VPS rollout into nix config so future installs and rebuilds
reproduce the same state:

- danny@sunken-ship + danny@phantom-ship: trust the mac admin key
  (id_ed25519_<host> on Daniel-Macbook-Air) and the host's own
  self-loopback key (used by clan ssh-ng:// nix-copy-closure back
  to the same host during `clan machines update`).
- root@sunken-ship + root@phantom-ship: trust the mac admin key so
  `clan machines update` can run its SOPS-key upload step that
  SSHes to root@<host> to write /var/lib/sops-nix/key.txt.

Existing key files (~/.ssh/id_ed25519 on each host) stay where they
are; the keypair was generated once during initial bootstrap and the
public side is now declared above. Reinstalls would regenerate and
need the pubkey re-pinned here.
2026-04-25 13:30:40 +02:00
DannyDannyDanny
644420481e fix(sunken-ship): bbbot 8080 only allowed on ZT interface 🔐 2026-04-25 13:26:37 +02:00
DannyDannyDanny
3b5288a48c feat(sunken-ship): bbbot bind dual-stack so VPS Caddy reaches it via ZT IPv6 🪢 2026-04-25 13:17:27 +02:00
DannyDannyDanny
bce34985eb feat(sunken-ship): open firewall :8080 for bbbot via vps-relay 🔓 2026-04-25 13:15:59 +02:00
DannyDannyDanny
914a825587 feat(sunken-ship): trust danny for nix remote builds 🏗️ 2026-04-24 13:47:38 +02:00
DannyDannyDanny
47fc658523 feat(clan): add vps-relay + strip bbbot cloudflared 🚢
Stage 4.5: declare a Hetzner-hosted reverse-proxy VPS as a clan machine.

- nixos/hosts/vps-relay.nix: Debian→NixOS cx23 in hel1. Caddy at public
  80/443 reverse-proxies navidrome.dannydannydanny.me and
  bbbot.dannydannydanny.me over ZT to sunken-ship.
- nixos/disko-cloud.nix: simple GPT + ext4 root, no LUKS — cloud provider
  has physical disk anyway and there's no operator at boot.
- flake-modules/clan.nix: register vps-relay as an inventory machine,
  zerotier peer, internet networking target at its clan-generated ZT
  IPv6, and add vps-relay.clan to clanHostsModule /etc/hosts.
- sunken-ship fitness-bot: drop pkgs.cloudflared from PATH + set
  WEBAPP_URL=https://bbbot.dannydannydanny.me. Paired with the bbbot
  upstream patch (start.py honors env WEBAPP_URL and skips cloudflared
  when set) — once the 15-min fitness-bot-pull timer pulls that change,
  bbbot will stop churning trycloudflare.com URLs.

Vars (zerotier identity/ip + sops machine key) generated on sunken-ship
because clan's hermetic sandbox on macOS fails to run the zerotier
identity generator (same workaround as for data-mesher earlier).

VPS install flow: Hetzner-created Debian box, then `clan machines
install vps-relay --target-host root@<public-ipv4>` reinstalls to
NixOS; subsequent updates go over ZT.
2026-04-24 13:43:21 +02:00
DannyDannyDanny
0cd4947282 feat(sunken-ship): retire Cloudflare Tunnel for navidrome ☁️💥
Stage 4d of the clan migration. Navidrome is now reachable only over
the ZeroTier mesh (port 4533 on sunken-ship's ZT IPv6 address, or via
the sunken-ship-zt SSH alias). Dropped:

- systemd.services.cloudflare-tunnel
- clan.core.vars.generators.cloudflare-tunnel
- cloudflared from environment.systemPackages
- vars/per-machine/sunken-ship/cloudflare-tunnel/

Manual follow-ups still needed on sunken-ship:
- rm /home/danny/.secrets/cloudflare-tunnel-token  (old unmanaged token)
- delete the tunnel itself in the Cloudflare Zero Trust dashboard
- unlink the DNS record music.dannydannydanny.me if it was separate
2026-04-20 10:36:15 +02:00
DannyDannyDanny
7d3fd2d8cf feat(sunken-ship): migrate cloudflare-tunnel-token to clan vars 🔐
Declare a clan.core.vars.generators.cloudflare-tunnel generator that
prompts for the tunnel token on first run and stores it SOPS-encrypted
under vars/per-machine/sunken-ship/cloudflare-tunnel/tunnel-token.
systemd.services.cloudflare-tunnel ExecStart now reads the decrypted
secret at runtime from \${config.clan.core.vars...path} (lives at
/run/secrets/vars/...) instead of the unmanaged
/home/danny/.secrets/cloudflare-tunnel-token file.

Stage 4c of the clan migration. The tunnel itself is slated for
retirement in 4d — ZeroTier-only access after that. Cloudflare token
was rotated during this migration; old value no longer valid.
2026-04-19 21:07:02 +02:00
DannyDannyDanny
88c51399d0 refactor(nix): move flake to repo root 🚚
clan-cli silently ignores the `?dir=` URL parameter when resolving a
flake source, so with the flake at nixos/flake.nix `clan machines
update` fails with "flake.nix does not exist". Move the flake tree up
so the repo root contains flake.nix, flake.lock, flake-modules/, lib/,
modules/, sops/, and vars/. Host-specific NixOS modules stay in
nixos/{hosts,home,fish.nix,neovim.nix,…}; flake-module paths updated
accordingly.

- dotfiles-rebuild flakeRef is now "${dotfilesDir}#<host>" (was
  "${dotfilesDir}/nixos#<host>").
- CLAUDE.md build commands + clan section updated. nixupdate fish alias
  updated. sunken-ship hostsfile comment updated.
- Existing /etc/dotfiles checkouts on the servers will pick up the new
  layout on the next `dotfiles-rebuild` timer tick; the rebuild service
  was pre-updated via rsync so its flakeRef matches before the pull.

Also includes 4b follow-through: zerotier identities are now live on
both servers (sunken-ship=d553a2de33 controller, phantom-ship=6c048abbdc
peer) and IPv6 ping across the ZT mesh works.
2026-04-19 15:19:59 +02:00
DannyDannyDanny
975b2a3ee9 refactor(nix): auto-load flake-modules + extract shared dotfiles-rebuild 🌳
- Add import-tree input; flake.nix now auto-loads every file under
  ./flake-modules so new hosts/features drop in without editing flake.nix.
- Extract the duplicated dotfiles-rebuild service, timer, and
  safe.directory wiring into nixos/modules/dotfiles-rebuild.nix, exposed
  via flake.nixosModules.dotfiles-rebuild.
- sunken-ship and phantom-ship now pull it in from their flake-modules;
  hostname-specific flakeRef is derived from config.networking.hostName.
2026-04-18 18:00:54 +02:00
DannyDannyDanny
5e7b76bdcf fix(servers): declare safe.directory in /etc/gitconfig 🔒
The dotfiles-rebuild service runs as root, but /etc/dotfiles is owned
by `danny`. The GIT_CONFIG_* env vars in the service unit only affect
the git CLI — nix/libgit2 reads safe.directory from /etc/gitconfig.
After a recent nixpkgs bump libgit2 now enforces this strictly, so the
service was failing to evaluate the flake.

Enable programs.git and set programs.git.config.safe.directory =
[ dotfilesDir ] on both sunken-ship and phantom-ship so the trust is
persistent and Nix-managed.
2026-04-18 17:29:11 +02:00
DannyDannyDanny
a36b90e656 fix(sunken-ship): set fsType=none on /srv/music bind mount
nixos-rebuild was failing with "fsType accessed but has no value
defined" on newer nixpkgs. Bind mounts need fsType=none explicitly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:35:27 +02:00
DannyDannyDanny
5db45664ab feat(sunken-ship): auto-pull fitness bot from GitHub every 15 min
New fitness-bot-pull service + timer, modeled on dotfiles-rebuild.
Checks origin/main for new commits, pulls + restarts the service if
the HEAD moved. Offset by 7 min from dotfiles-rebuild to avoid
overlap.

Code now lives at github.com/DannyDannyDanny/bigbiggerbiggestbot
(cloned to /home/danny/tg_fitness_bot). workouts.db is gitignored
so it's preserved across pulls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-17 14:33:15 +02:00
DannyDannyDanny
be6dde6f0a feat(sunken-ship): add cloudflare tunnel for external access 🌐
Exposes navidrome via music.dannydannydanny.me.
Bypasses CGNAT — no port forwarding needed.
Token stored outside repo at ~/.secrets/cloudflare-tunnel-token.
2026-04-06 21:19:38 +02:00
DannyDannyDanny
76f63f0ae3 fix(sunken-ship): move navidrome music folder to /srv/music — ProtectHome bypass 🎵 2026-04-06 15:36:07 +02:00
DannyDannyDanny
c31ca7d473 feat(sunken-ship): add navidrome user to users group for music dir access 🎵 2026-04-06 14:46:24 +02:00
DannyDannyDanny
4bccb6e6a8 fix(sunken-ship): add audioconvert to uxplay pipeline — fixes ALAC format error 🎵
feat(home): add uhk-agent for UHK keyboard configuration 🎹
2026-04-06 11:55:06 +02:00
DannyDannyDanny
4d6b64dee9 fix: add nixos-rebuild to dotfiles-rebuild PATH on sunken-ship 🔧 2026-04-04 11:26:09 +02:00
DannyDannyDanny
49165590a6 feat: add fitness bot systemd service to sunken-ship
Code deployed separately via rsync (private repo, not referenced here).
Expects code at /home/danny/tg_fitness_bot/ and token at
~/.secrets/bigbiggerbiggestbot.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 12:15:51 +02:00
DannyDannyDanny
33e2e327b5 fix(nixos): increase UxPlay ALSA buffer to reduce audio chop 🐛
WiFi jitter causes underruns with default buffer. Set buffer-time
to 200ms for smoother playback.
2026-03-31 10:01:22 +02:00
DannyDannyDanny
384b84fec2 fix(nixos): enable nix-ld on sunken-ship for Claude Code 🐛
The Claude Code remote CLI is a dynamically linked binary that
fails on NixOS without a standard ld-linux stub. nix-ld provides it.
2026-03-30 23:52:03 +02:00
DannyDannyDanny
657e250f75 fix(nixos): quote UxPlay alsasink GStreamer pipeline arg 🔧 2026-03-30 16:17:14 +02:00
DannyDannyDanny
cea6913cf3 fix(nixos): route UxPlay audio directly to ALSA on sunken-ship 🔊
Drop PipeWire (WirePlumber fails to detect ALSA cards without a
graphical session). Use GStreamer alsasink with plughw:USB,0 to
output directly to the Scarlett Solo.
2026-03-30 16:16:18 +02:00
DannyDannyDanny
84715596f5 feat(nixos): add PipeWire and fix UxPlay audio on sunken-ship 🔊
Enable PipeWire with ALSA/PulseAudio compat so GStreamer can output
audio. Move UxPlay to a user service with linger so it can reach
PipeWire. Add danny to audio group, add alsa-utils for debugging.
2026-03-30 15:49:35 +02:00
DannyDannyDanny
ee2fa1e5f1 feat(nixos): add UxPlay systemd service on sunken-ship 🔊
Audio-only AirPlay receiver that starts at boot, advertises as
"sunken-ship", and auto-restarts on failure.
2026-03-30 15:44:00 +02:00
DannyDannyDanny
e2b820aac0 feat(nixos): add UxPlay AirPlay receiver to sunken-ship 📡
Enable Avahi for mDNS discovery and open firewall ports for
AirPlay mirroring (TCP 7000-7100, UDP 5353/6000-6001/7011).
2026-03-30 15:38:27 +02:00
DannyDannyDanny
d8e5cbe26a fix(nixos): add safe.directory for dotfiles-rebuild service 🔧
Git refuses to operate on /etc/dotfiles owned by danny when the
service runs as root. Pass safe.directory via environment variables.
2026-03-30 14:20:31 +02:00
DannyDannyDanny
463249961e fix(nixos): replace removed light option and harden char-count script
Restore flake checks by removing deprecated `programs.light` from sunken-ship and switching to brightnessctl guidance. Also clean up flake formatting and make the Raycast char-count script safer for empty input.

Made-with: Cursor
2026-03-24 12:58:40 +01:00
DannyDannyDanny
a114d2fc0c feat(sunken-ship): enable wireless networking support 2026-03-08 12:47:32 +01:00
DannyDannyDanny
424ba82399 feat(sunken-ship): pwless ssh access 🔒 2026-03-08 12:05:25 +01:00
DannyDannyDanny
1338fb1b68 Rename nixos-server to sunken-ship
- Rename hosts/nixos-server.nix -> sunken-ship.nix, nixos-server-hardware.nix -> sunken-ship-hardware.nix
- Flake: nixos-server -> sunken-ship, update module path
- Set networking.hostName = sunken-ship in server configs
- Update AGENTS.md, nixos/readme.md, docs/ssh-and-secrets.md, TODO.md

Made-with: Cursor
2026-03-01 12:44:28 +01:00
Renamed from nixos/hosts/nixos-server.nix (Browse further)