Commits
Pairing an Xbox Wireless Controller over Bluetooth (LE HoG) on stock
bluez 5.86 failed with "Connection terminated due to authentication
failure" on every connection attempt after pair. Enable xpadneo so the
hid_xpadneo driver handles the controller, and add two bluez tweaks
that resolve the LE auth loop:
* JustWorksRepairing = always: accept fresh pairings without requiring
a manual remove of the prior bond.
* Privacy = device: pin the host BT address so the controller's stored
bond key isn't invalidated when bluez rotates resolvable addresses.
Assisted-by: Claude Code (claude-opus-4-7[1m])
Upstream 634a4408c061 ("Bluetooth: btmtk: validate WMT event SKB
length before struct access"), backported into 7.0.7, rejects the
shorter WMT FUNC_CTRL events MT7925 firmware actually sends, leaving
hci0 stuck DOWN with "Failed to send wmt func ctrl (-22)".
Apply upstream e3ac0d9f1a20 ("Bluetooth: btmtk: accept too short
WMT FUNC_CTRL events") on top of linux_latest until the fix is
backported into linux-7.0.y stable. Remove this override once nixpkgs
ships a kernel that already contains the fix.
Assisted-by: Claude Code (claude-opus-4-7[1m])
Was killing remote tmux sessions the moment all ssh clients detached —
the actual cause of "tmux dies when everyone disconnects from neoprism".
Linger/KillUserProcesses were red herrings; tmux itself was tearing
the sessions down from inside.
Assisted-by: Claude Code (claude-opus-4-7)
Without lingering, systemd-logind tears down user@1337.service when the
last session disconnects, killing tmux along with the user slice. The
KillUserProcesses=no setting only prevents logind from explicitly killing
scope leftovers — it does not keep the user manager alive.
Assisted-by: Claude Code (claude-opus-4-7)
nixpkgs nginx is compiled with /tmp/nginx_* as temp paths. Combined
with systemd PrivateTmp, host-side cleanup of /tmp can leave nginx
with missing temp dirs after restart, breaking large POSTs (e.g.
matrix /keys/upload) and federation PUTs. Move to /var/cache/nginx,
which is auto-created via the systemd unit's CacheDirectory=nginx.
Assisted-by: Claude Code (claude-opus-4-7)
Confused agents that did plain `ipfs add` of files already on disk
caused ~9G of blockstore/filestore duplication and ~10G of
blockstore-only content. Shadow the CLI with a wrapper that rejects
`add` calls missing --nocopy; the kubo daemon and pin-watcher use
absolute store paths so they keep working.
Assisted-by: Claude Code (claude-opus-4-7)
Pin-watcher was creating MFS entries for aria2 control files that get
deleted once the download finishes, leaving orphans in the index. Also
ensure the cid-map file is world-readable after creation and after
reconcile rewrites it.
Assisted-by: Claude Code (claude-opus-4-7)
Upstream NixOS tinc module's preStart chowns hosts/ and invitations/
but not the network dir itself, so tincr can't persist the per-peer
address bootstrap cache it tries to write under /etc/tinc/retiolum/
addrcache/. The save fails with "Permission denied" (debug-only), the
cache stays empty, and retries to peers without a live meta-conn fall
back to DNS instead of the last-known address. Drop this tmpfiles rule
once nixpkgs#520533 lands.
Assisted-by: Claude Code (claude-opus-4-7)
New extension queries /api/tags at startup and registers every model
under a single "ollama" provider via the OpenAI-compat layer. Endpoint
points at neoprism.r:11434 — reachable from retiolum via the c-base-ai
autossh tunnel.
settings-env.patch also patches SettingsManager.reload() so the
PI_SETTINGS_FILE merge survives resourceLoader.reload() — without this
the bundled extensions list was being wiped after initial load.
Persistent autossh tunnel via tunnel.c-base.org exposing
ai.cbrp3.c-base.org:11434 on neoprism, reachable from retiolum at
neoprism.r:11434. ssh key generated by clan vars; pubkey must be
installed on tunnel.c-base.org under lassulus before the tunnel comes up.
PR Mic92/tincr#5 (merged 2026-05-11) removes the auto-purge in
on_del_edge that drove reachability oscillation in mixed
tincr/tinc-1.1pre18 meshes.
On top, pin Lassulus/tincr@a25eec05 which adds udp_addr clearing on
ENETUNREACH/EHOSTUNREACH/EAFNOSUPPORT/EADDRNOTAVAIL — without it,
IPv4-only hosts retry the same broken cached IPv6 udp_addr forever
when a peer's wire-advertised contact is v6 only. Submitted upstream
as Mic92/tincr#6.
Under load, the swaymsg get_tree subprocess could time out, the host
returned an empty windows list, and the extension treated that as "no
Firefox windows anywhere" — restoring a window for a workspace that
already had one. Distinguish query failure from a genuinely empty
result and skip restoration when state is unknown.
Adds `s say "..."` which speaks via flite TTS and posts a desktop
notification. The notify skill documents when to use it; the wrapper
registers the skill and allows `s` in Bash so calls don't prompt.
Upstream creates /var/lib/mautrix-discord at mode 0770 owned by
mautrix-discord:mautrix-discord, but only adds matrix-synapse to the
mautrix-discord-registration supplementary group. That left synapse
unable to traverse the directory to read discord-registration.yaml,
crashing matrix-synapse on startup.
dhtclient only announces to the DHT. lassie (and IPNI/cid.contact)
never learned about neoprism's pins, so all fetchIpfs calls fell back
to archive.org. autoclient keeps DHT client mode but also pushes
provider records to IPNI via HTTP, making content discoverable by
lassie without a fallbackUrl.
ns1.first-ns.de, robotns2.second-ns.de, robotns3.second-ns.com
tincr is wire-compatible with tinc 1.1pre18 (ExperimentalProtocol=yes,
Ed25519 only). Wrap the package with a /sbin -> bin symlink so
krebs.tinc's ${tincPackage}/sbin/tincd path resolves, and override
tincPackage. Existing peers all have Ed25519 keys; RSA keys in host
files are warned about and ignored.
The script was previously SSH_ASKPASS-only (raw PIN on stdout), which
broke rbw and gpg-agent: they speak the Assuan protocol over stdin/stdout
and could not parse the output ('failed to read password from pinentry').
Dispatch by argv:
- no args, or first arg starts with '-' (real pinentry flags like
--timeout 0 --ttyname ... --display ... --no-global-grab) -> Assuan mode
- bare prompt arg (SSH_ASKPASS convention used by ssh-tpm-agent)
-> raw PIN on stdout (existing behaviour)
Assuan mode handles SETTITLE/SETPROMPT/SETDESC/SETERROR/SETKEYINFO/OPTION/
RESET/NOP/BYE, percent-decodes incoming descriptions for the rofi -mesg,
and percent-encodes the D-line PIN.
Kernel-keyring caching is scoped to SSH_ASKPASS mode only; rbw and
gpg-agent do their own caching, and sharing one keyring slot across
unrelated secrets handed back the wrong PIN to whichever caller asked
second.
tools.kagi-search: default to 'rbw get kagi.com -f session_link'
Matches the actual vault layout (a kagi.com login with a session_link
field) instead of expecting a separate 'kagi-session-link' entry.
Bump the Workspace widget's characterCount to 20 so workspace names
fit (was capped at 2). Vertical bars are still capped to 2 chars by
noctalia regardless of this value.
When gpg-agent is reachable and the user has a secret encryption
subkey ([E] ssb), emit the age-plugin-gpg default identity
(AGE-PLUGIN-GPG-1H40XPM, the bech32 of an empty body for the gpg
plugin). gpg-agent caches the passphrase / smartcard PIN, so this is
more frictionless than the yubikey path; we therefore place it above
yubikey/solo2 but below se/tpm.
Set programs.gnupg.agent.enableSSHSupport = true so the
gpg-agent-ssh.socket unit is created and gpg-agent (in --supervised
mode) actually receives the ssh listen fd. The module also exports
SSH_AUTH_SOCK system-wide via environment.extraInit; we don't want
that, so unset it again with mkAfter. Users opt in per command via:
SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" ssh ...
nixpkgs's autotools elinks 0.19.1 fails against gettext 0.23.1
(autopoint refuses bare AM_GNU_GETTEXT, then autoheader fails on
HAVE_ALLOCA). Carry the meson-based build from upstream nixpkgs
PR #515347 locally until it lands; tools.mutt now consumes
self.packages.<system>.elinks instead of pkgs.elinks.
Inlines the libcss/libdom propagatedBuildInputs adjustments from the
same PR, scoped to this elinks build only — no global overlay.
age-plugin-gpg lets a gpg key (via gpg-agent + keygrip) act as an age
recipient/identity, so adding the corresponding age1gpg1... line to
.age-recipients makes every passage secret encryptable to gpg as well.
Caveat: gpg keygrips end up as plaintext in the encrypted file.
Newer nixpkgs renders 'settings.enable-ssh-support = true' as
'enable-ssh-support true', which gpg-agent rejects with 'argument not
expected' since it's a boolean flag. Use "" instead so the keyValue
formatter emits a bare 'enable-ssh-support ' line gpg-agent accepts.
Existing preHook only dumped matrix-synapse; the per-bridge postgres
DBs (mautrix-{whatsapp,signal,telegram,discord}) and heisenbridge's
sqlite state weren't covered. Losing them = relogin everywhere and
orphaned portal rooms.
Used via nixpkgs.overlays so per-module insecure-package permits compose
cleanly — nixpkgs.config.permittedInsecurePackages merges via
recursiveUpdate, so list values from multiple modules clobber each other.
Switch jitsi over as the first consumer.
Pairing an Xbox Wireless Controller over Bluetooth (LE HoG) on stock
bluez 5.86 failed with "Connection terminated due to authentication
failure" on every connection attempt after pair. Enable xpadneo so the
hid_xpadneo driver handles the controller, and add two bluez tweaks
that resolve the LE auth loop:
* JustWorksRepairing = always: accept fresh pairings without requiring
a manual remove of the prior bond.
* Privacy = device: pin the host BT address so the controller's stored
bond key isn't invalidated when bluez rotates resolvable addresses.
Assisted-by: Claude Code (claude-opus-4-7[1m])
Upstream 634a4408c061 ("Bluetooth: btmtk: validate WMT event SKB
length before struct access"), backported into 7.0.7, rejects the
shorter WMT FUNC_CTRL events MT7925 firmware actually sends, leaving
hci0 stuck DOWN with "Failed to send wmt func ctrl (-22)".
Apply upstream e3ac0d9f1a20 ("Bluetooth: btmtk: accept too short
WMT FUNC_CTRL events") on top of linux_latest until the fix is
backported into linux-7.0.y stable. Remove this override once nixpkgs
ships a kernel that already contains the fix.
Assisted-by: Claude Code (claude-opus-4-7[1m])
Without lingering, systemd-logind tears down user@1337.service when the
last session disconnects, killing tmux along with the user slice. The
KillUserProcesses=no setting only prevents logind from explicitly killing
scope leftovers — it does not keep the user manager alive.
Assisted-by: Claude Code (claude-opus-4-7)
nixpkgs nginx is compiled with /tmp/nginx_* as temp paths. Combined
with systemd PrivateTmp, host-side cleanup of /tmp can leave nginx
with missing temp dirs after restart, breaking large POSTs (e.g.
matrix /keys/upload) and federation PUTs. Move to /var/cache/nginx,
which is auto-created via the systemd unit's CacheDirectory=nginx.
Assisted-by: Claude Code (claude-opus-4-7)
Confused agents that did plain `ipfs add` of files already on disk
caused ~9G of blockstore/filestore duplication and ~10G of
blockstore-only content. Shadow the CLI with a wrapper that rejects
`add` calls missing --nocopy; the kubo daemon and pin-watcher use
absolute store paths so they keep working.
Assisted-by: Claude Code (claude-opus-4-7)
Upstream NixOS tinc module's preStart chowns hosts/ and invitations/
but not the network dir itself, so tincr can't persist the per-peer
address bootstrap cache it tries to write under /etc/tinc/retiolum/
addrcache/. The save fails with "Permission denied" (debug-only), the
cache stays empty, and retries to peers without a live meta-conn fall
back to DNS instead of the last-known address. Drop this tmpfiles rule
once nixpkgs#520533 lands.
Assisted-by: Claude Code (claude-opus-4-7)
New extension queries /api/tags at startup and registers every model
under a single "ollama" provider via the OpenAI-compat layer. Endpoint
points at neoprism.r:11434 — reachable from retiolum via the c-base-ai
autossh tunnel.
settings-env.patch also patches SettingsManager.reload() so the
PI_SETTINGS_FILE merge survives resourceLoader.reload() — without this
the bundled extensions list was being wiped after initial load.
PR Mic92/tincr#5 (merged 2026-05-11) removes the auto-purge in
on_del_edge that drove reachability oscillation in mixed
tincr/tinc-1.1pre18 meshes.
On top, pin Lassulus/tincr@a25eec05 which adds udp_addr clearing on
ENETUNREACH/EHOSTUNREACH/EAFNOSUPPORT/EADDRNOTAVAIL — without it,
IPv4-only hosts retry the same broken cached IPv6 udp_addr forever
when a peer's wire-advertised contact is v6 only. Submitted upstream
as Mic92/tincr#6.
Under load, the swaymsg get_tree subprocess could time out, the host
returned an empty windows list, and the extension treated that as "no
Firefox windows anywhere" — restoring a window for a workspace that
already had one. Distinguish query failure from a genuinely empty
result and skip restoration when state is unknown.
Upstream creates /var/lib/mautrix-discord at mode 0770 owned by
mautrix-discord:mautrix-discord, but only adds matrix-synapse to the
mautrix-discord-registration supplementary group. That left synapse
unable to traverse the directory to read discord-registration.yaml,
crashing matrix-synapse on startup.
tincr is wire-compatible with tinc 1.1pre18 (ExperimentalProtocol=yes,
Ed25519 only). Wrap the package with a /sbin -> bin symlink so
krebs.tinc's ${tincPackage}/sbin/tincd path resolves, and override
tincPackage. Existing peers all have Ed25519 keys; RSA keys in host
files are warned about and ignored.
The script was previously SSH_ASKPASS-only (raw PIN on stdout), which
broke rbw and gpg-agent: they speak the Assuan protocol over stdin/stdout
and could not parse the output ('failed to read password from pinentry').
Dispatch by argv:
- no args, or first arg starts with '-' (real pinentry flags like
--timeout 0 --ttyname ... --display ... --no-global-grab) -> Assuan mode
- bare prompt arg (SSH_ASKPASS convention used by ssh-tpm-agent)
-> raw PIN on stdout (existing behaviour)
Assuan mode handles SETTITLE/SETPROMPT/SETDESC/SETERROR/SETKEYINFO/OPTION/
RESET/NOP/BYE, percent-decodes incoming descriptions for the rofi -mesg,
and percent-encodes the D-line PIN.
Kernel-keyring caching is scoped to SSH_ASKPASS mode only; rbw and
gpg-agent do their own caching, and sharing one keyring slot across
unrelated secrets handed back the wrong PIN to whichever caller asked
second.
tools.kagi-search: default to 'rbw get kagi.com -f session_link'
Matches the actual vault layout (a kagi.com login with a session_link
field) instead of expecting a separate 'kagi-session-link' entry.
When gpg-agent is reachable and the user has a secret encryption
subkey ([E] ssb), emit the age-plugin-gpg default identity
(AGE-PLUGIN-GPG-1H40XPM, the bech32 of an empty body for the gpg
plugin). gpg-agent caches the passphrase / smartcard PIN, so this is
more frictionless than the yubikey path; we therefore place it above
yubikey/solo2 but below se/tpm.
Set programs.gnupg.agent.enableSSHSupport = true so the
gpg-agent-ssh.socket unit is created and gpg-agent (in --supervised
mode) actually receives the ssh listen fd. The module also exports
SSH_AUTH_SOCK system-wide via environment.extraInit; we don't want
that, so unset it again with mkAfter. Users opt in per command via:
SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)" ssh ...
nixpkgs's autotools elinks 0.19.1 fails against gettext 0.23.1
(autopoint refuses bare AM_GNU_GETTEXT, then autoheader fails on
HAVE_ALLOCA). Carry the meson-based build from upstream nixpkgs
PR #515347 locally until it lands; tools.mutt now consumes
self.packages.<system>.elinks instead of pkgs.elinks.
Inlines the libcss/libdom propagatedBuildInputs adjustments from the
same PR, scoped to this elinks build only — no global overlay.