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
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.
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.
Stage 4b of the clan migration. Declares a clan.inventory.instances.zerotier
instance with sunken-ship as controller and phantom-ship as peer (controller
is also listed as a peer so it joins its own network). Generates the network
ID, controller identity, and per-peer identities via `clan vars generate`;
all secrets are SOPS-encrypted to the user's age key and the per-machine
age keys.
- nixos/sops/ — clan-managed SOPS state (user + per-machine age keys).
- nixos/vars/ — shared + per-machine zerotier vars; *-identity-secret
files are SOPS-encrypted, *.value files are plain public data.
- clan.core.networking.{targetHost,buildHost} = "danny@<host>" on both
servers so `clan machines update` knows where to push and build.
- mac gets `zerotier-one` installed as a homebrew cask; authorization
on the controller happens manually by node-ID in a follow-up step.
Known rough edges (to chase in later stages):
- zerotier-inventory-autoaccept.service races zerotierone.service on
first activation (connection refused against the local API). Retrying
the unit succeeds; clan upstream bug.
- Deployment must go through `clan machines update`, not plain
nixos-rebuild, or the per-host SOPS age key isn't uploaded and
zerotier-one can't decrypt its identity.
Telegram bot hub that lists mini-apps and collects feedback via ForceReply.
Code deployed via rsync to /home/danny/shipyard/; token at
~danny/.secrets/telegram-bot-token-shipyard.
Claude Code Channels replaces OpenClaw for the @HarakatBot Telegram
bridge. Uses claude.ai subscription auth via long-lived OAuth token
at /etc/claude-channels/env — sidesteps the API rate limits OpenClaw
was hitting.
Runs as danny since plugin + pairing state lives in ~/.claude.
Wraps claude in script(1) because claude needs a PTY for its
interactive session mode.
OpenClaw service disabled but config kept for easy rollback during
validation. Will be fully removed once Channels is proven stable.
Her workspace (SOUL/MEMORY/IDENTITY/etc) is preserved in
vimwiki/openclaw/workspace/.
- 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.
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.
Claude Code Channels will replace OpenClaw for the Telegram bot.
Channels uses claude.ai subscription auth instead of pay-as-you-go
API, sidestepping the rate limits Hara has been hitting.
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>
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>
Exposes navidrome via music.dannydannydanny.me.
Bypasses CGNAT — no port forwarding needed.
Token stored outside repo at ~/.secrets/cloudflare-tunnel-token.
- Enable Wake-on-LAN (magic packet) on rusty-anchor enp2s0 via systemd service
- Add vt-theme script to rusty-anchor: switches between Catppuccin Latte/Mocha
- Theme state persisted in /etc/vt-theme, applied on login via profile.d
- alacritty-sync-system-theme.sh now SSHes to rusty-anchor and pushes the
macOS light/dark change (best-effort, non-blocking, skips if unchanged)
- Add wakeonlan to phantom-ship packages (wakeonlan 00:16:cb:87:20:ba)
Adds git and nodejs to openclaw-gateway service PATH. Configures a
git credential helper that reads a fine-grained PAT from
/etc/openclaw/github-token. Creates /var/lib/openclaw/repos for
repo clones.
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>
Telegram bot via nix-openclaw NixOS module. Secrets (API key,
bot token) loaded from /etc/openclaw/ at runtime. Telegram user
ID read from gitignored openclaw-allow-from.nix.
Shares WiFi internet to rusty-anchor over ethernet via dnsmasq DHCP
and iptables NAT. Rusty-anchor gets DHCP on 10.0.0.x with phantom-ship
as gateway and DNS.
Enable home-manager on WSL, importing the shared home.nix config.
Remove duplicate packages and env vars from wsl.nix that are now
provided by home-manager (git, ripgrep, fzf, direnv, etc.).
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.