Commit Graph
100 Commits
Author SHA1 Message Date
Gabriel Fontes 49a929063e fix(home/aerc): reload configuration on change 2026-08-14 14:18:57 -03:00
Gabriel Fontes 8db3f50867 fix(nixos/kdeconnect): scope ports to the tailnet
1714-1764 is a wide range to leave open on machines that join networks they
don't control.

Assisted-by: pi (claude-opus-5)
2026-08-13 17:34:49 -03:00
Gabriel Fontes baef0c6c8a fix(ubuntu/network): wait for any interface, not all
The generic ethernet rule makes an unplugged enp44s0 managed, so
networkd-wait-online blocked on it for the full 120s timeout and delayed
wg-quick@wg0. NixOS pairs its generic DHCP networks with --any for the same
reason.

Assisted-by: pi (claude-opus-5)
2026-08-13 17:16:15 -03:00
Gabriel Fontes c19ed9a3a7 fix(hosts/wireless): disable Wi-Fi Direct
Its control socket never gets ctrl_interface_group applied (upstream never
copies the field when creating the P2P device), so with the daemon running as
root the socket is root-only. wpa_gui scans the directory, hits p2p-dev-*
first and gives up before reaching the real interface.

Assisted-by: pi (claude-opus-5)
2026-08-13 17:07:51 -03:00
Gabriel Fontes cc5bd4b3c8 refactor(hosts): rename system-manager to ubuntu
The tree is heavily Ubuntu-coupled: masking netplan's generator and Ubuntu's
own wpa_supplicant units, apt packages in cloud-init, /etc/dbus-1 policy.

Assisted-by: pi (claude-opus-5)
2026-08-13 16:44:51 -03:00
Gabriel Fontes 4da7e34d42 refactor(hosts): move shared config into hosts/common
Assisted-by: pi (claude-opus-5)
2026-08-13 16:37:39 -03:00
Gabriel Fontes fc9ab65dd1 fix(hosts/wireless): disable wpa_supplicant hardening
The sandbox binds secretsFile into the unit's namespace, so a secret that
can't be decrypted kills the daemon along with the control socket needed to
connect by hand and fix it. It also breaks wpa_gui (nixpkgs#475438).

Tradeoff: the daemon runs as root again, as it does on most distros.

Assisted-by: pi (claude-opus-5)
2026-08-13 16:36:09 -03:00
Gabriel Fontes a587e539e9 feat(system-manager): port networking.wireless and generic DHCP
Run the upstream NixOS wpa_supplicant module under system-manager through a
compat shim. system-manager already reuses nixpkgs' systemdUtils,
environment.etc and userborn, so the unit, the generated config and the
wpa_supplicant user come out unchanged; only four NixOS-only options needed
stubbing, two of which are re-expressed on top of environment.etc.

Extract the wireless config to hosts/wireless.nix so both trees share one
source: they sit at the same depth, so every path resolves identically.
electra's generated wpa_supplicant.conf is now byte-identical to atlas'
except for the country line.

Take over networkd from netplan on electra with the same generic match rules
NixOS uses, which also covers ethernet and USB tethering, neither of which
was configured before. netplan is neutered by masking its generator rather
than uninstalling it, since purging netplan.io would take cloud-init,
ubuntu-minimal and ubuntu-server-minimal with it.

Assisted-by: pi (claude-opus-5)
2026-08-13 16:36:09 -03:00
Gabriel Fontes 91005fcfb9 chore(hosts): move wifi secrets from nixos to hosts 2026-08-13 15:09:51 -03:00
Gabriel Fontes 0ed723235b feat(home): add Atelier/bin to PATH 2026-08-13 14:53:05 -03:00
Gabriel Fontes 2b8b2d9c71 feat(hosts/electra): declare uidmap deb 2026-08-13 14:26:55 -03:00
Gabriel Fontes df734b3f5e feat(home/electra): add juju and glab 2026-08-13 12:21:14 -03:00
Gabriel Fontes 6741355646 feat(home/aerc): theme from colorscheme, sort folders, wire filters
Generate an aerc styleset from config.colorscheme.colors, matching how
tmux, zathura and the rest are themed. Keys are quoted throughout since
unquoted dotted names build nested attrsets and fail the module's type
check.

Home Manager writes the whole aerc.conf, so aerc's shipped filters never
applied: bring back colorize, calendar and html, and point the viewer at
less. Pin the mailbox order per account instead of taking plain
alphabetical, and fold subfolders under their parent.

Assisted-by: pi (claude-opus-5)
2026-08-12 21:11:25 -03:00
Gabriel Fontes 31ffe6195c feat(home): distinguish host wallpapers
Give each host a wallpaper whose derived colorscheme sits at its own position on an evenly spaced hue wheel:
- Atlas: aenami-dawn; Celaeno: mountain-yellow-red
- Alcyone: autumn-leaves-orange; Pleione: plains-flowers-green-red
- Electra: aenami-northern-lights; Merope: aenami-bright-planet
- Maia: deer-lunar-fantasy; Taygeta: nebula-purple-pink

Reserve the remaining turquoise position for a future asterope host, and regenerate the website colorscheme data.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 19:44:02 -03:00
Gabriel Fontes c8247e3fdc fix(projects/website): restore listing title hover underline
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 15:19:07 -03:00
Gabriel Fontes b5be716f85 feat(projects/website): update sesos paper 2026-08-12 12:41:15 -03:00
Gabriel Fontes c167c08809 fix(projects/website): update constellation connections
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 12:36:36 -03:00
Gabriel Fontes b2e31f3cca refactor(projects/website): simplify stylesheet cascade
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 12:26:03 -03:00
Gabriel Fontes ae6361afa1 refactor(projects/website): centralize style tokens
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 12:22:27 -03:00
Gabriel Fontes ac15815de9 refactor(projects/website): modularize stylesheet structure
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 12:17:51 -03:00
Gabriel Fontes aedb99a2b1 chore(projects/website): remove unused sass code
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 12:15:49 -03:00
Gabriel Fontes 05725a71ef fix(projects/website): remove dead colorscheme page 2026-08-12 12:08:48 -03:00
Gabriel Fontes 8ee7b0446c feat(projects/website): collapse design paper appendix
Keep the appendix heading visible while placing its sustainability fragment table in a details disclosure that is collapsed by default.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:58:59 -03:00
Gabriel Fontes 4806800c88 fix(projects/website): remove duplicate figure border
Let the publication figure styling provide the frame instead of drawing a second border inside the relations SVG.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:52:23 -03:00
Gabriel Fontes cf32e51c6e fix(projects/website): refine publication navigation
Keep the publications navigation item selected on paper pages and align their DOI links with the publication listing while removing the redundant back link.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:44:05 -03:00
Gabriel Fontes b07eb924a7 fix(projects/website): improve paper figures in dark mode
Render publication figures on a stable light surface so their original colors and labels remain legible regardless of the site theme.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:39:52 -03:00
Gabriel Fontes e6a7ea04b1 feat(projects/website): add paper web editions
Publish complete Markdown editions of both papers with linked citations, references, tables, original figures, appendices, acknowledgments, and scholarly citation metadata. Include the sustainability fragment table and the updated SESoS ecosystem figure while preserving the PDFs as versions of record.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:39:52 -03:00
Gabriel Fontes 527fc899ca refactor(projects/website): replace link glow with starlight accents
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:15:00 -03:00
Gabriel Fontes 0a7121b071 fix(projects/website): refine section heading rhythm
Assisted-by: pi (gpt-5.6-sol)
2026-08-12 11:04:42 -03:00
Gabriel Fontes abcec31b41 feat(projects/site): remove telegram link 2026-08-12 03:51:16 -03:00
Gabriel Fontes 80a00cb29d fix(projects/website): move feed link to footer
Move the RSS link from its brittle absolute position above the blog listing into the global social footer, and remove the obsolete positional selector.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:49:23 -03:00
Gabriel Fontes 0c9471a4f2 fix(projects/website): update source link
Point the footer source link at the website path in the Foundry monorepo.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:46:42 -03:00
Gabriel Fontes f37f6314f2 fix(projects/website): brighten ambient sparks
Increase spark core size, palette contrast, halo, and shimmer range so the ambient layer remains subtle but actually visible.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:41:33 -03:00
Gabriel Fontes 6cbfc9e959 feat(projects/website): add ambient star sparks
Layer sparse palette-tinted sparks behind the site with slow staggered shimmer, no pointer interaction, and explicit reduced-motion and print fallbacks.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:40:04 -03:00
Gabriel Fontes b5901a4eaa fix(projects/website): move atlas a bit right 2026-08-12 03:40:04 -03:00
Gabriel Fontes b3744d9d8e fix(projects/website): smooth theme selection ring
Replace the aliased circular outline with an inset antialiased shadow ring and a faint outer glow for both selection and keyboard focus.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:33:10 -03:00
Gabriel Fontes 5a32f05d7f fix(projects/website): outline selected theme star
Apply the constellation control's circular focus outline to the active palette as a persistent selection indicator.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:28:05 -03:00
Gabriel Fontes 7ff867ed2f feat(projects/website): adopt star glyph motif
Use conventional hash markers for heading permalinks, frame the site identity with decorative stars, and render constellation points as luminous star glyphs while preserving their 48px controls and interaction behavior.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:26:08 -03:00
Gabriel Fontes 832fb45016 feat(projects/website): add heading permalinks
Add accessible self-links to rendered h2-h6 headings without embedding HTML in Markdown. Reveal the star marker on hover or keyboard focus, keep it visible on touch devices, and omit it from print.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:22:30 -03:00
Gabriel Fontes d693b272c8 feat(projects/website): extend constellation interactions
Carry the constellation's glow and motion into links, navigation, and form controls, add palette-lit structural rules, and glint anchored headings on arrival. Respect reduced-motion preferences throughout.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:16:28 -03:00
Gabriel Fontes a17674d086 fix(projects/website): restore light background tint
Mix native light surfaces with each scheme's primary role instead of its near-white primary container, preserving a distinct atmospheric tint across all eight themes.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:06:31 -03:00
Gabriel Fontes 2464495974 refactor(projects/website): consume mode-aware colorschemes
Adopt the new top-level colorscheme structure and emit each scheme's native dark and light Material roles directly. Remove the manual light-role remapping and obsolete print scheme, update the legacy colorscheme page, and promote Electra to an interactive constellation theme.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 03:00:01 -03:00
Gabriel Fontes 2784bfa85c refactor: expose colorscheme set in flake 2026-08-12 02:48:54 -03:00
Gabriel Fontes 6e5547495d feat: rename mgc to electra, add to schemes 2026-08-12 02:42:14 -03:00
Gabriel Fontes 69c71bee0a fix(projects/website): refine pleiades geometry
Align the seven theme stars more closely with the Pleiades reference and add muted, non-interactive Electra and Sterope stars to complete the cluster.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 02:38:34 -03:00
Gabriel Fontes 4169d2760f fix(projects/website): adapt star previews to color mode
Give each constellation star dark and light preview roles from its own palette, switching automatically with prefers-color-scheme.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 02:34:34 -03:00
Gabriel Fontes e7822d39d0 fix(projects/website): restore tinted backgrounds
Mix each selected palette into the light and dark surface hierarchy so theme changes affect the page atmosphere again without altering semantic role mapping.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 02:31:39 -03:00
Gabriel Fontes 427d49a420 feat(projects/website): follow system color mode
Expose each selected scheme as a stable palette, then map that same palette to dark or light semantic roles according to prefers-color-scheme. Preserve constellation selection, persistence, live system changes, and the dedicated print palette without adding a mode switch.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 02:28:46 -03:00
Gabriel Fontes 4a005875c8 fix(projects/website): tweak header padding 2026-08-12 02:17:26 -03:00
Gabriel Fontes 9d85420a7a refactor(projects/website): decrease h1, remove _ suffix 2026-08-12 02:13:17 -03:00
Gabriel Fontes de85f5bb62 refactor(projects/website): simplify constellation caption
Remove the explanatory heading and current-theme readout, leaving only a quiet centered invitation beneath the constellation.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 02:07:28 -03:00
Gabriel Fontes 4ed4983e55 feat(projects/website): add pleiades theme selector
Replace the colorscheme select with a full-width Pleiades constellation whose seven accessible, touch-friendly star buttons preview and apply their matching themes. Keep active state, persistence, keyboard labels, reduced motion, and JavaScript-disabled behavior in sync.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 02:04:14 -03:00
Gabriel Fontes beadd19c5a fix(projects/website): center document prose
Center narrow non-listing prose within the shared content shell while keeping page titles aligned across routes.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 01:53:05 -03:00
Gabriel Fontes 7059ac0c09 fix(projects/website): stabilize page title alignment
Keep every page article at the shared content width while constraining only non-listing prose sections to the narrower reading measure.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 01:52:03 -03:00
Gabriel Fontes ba0206d450 refactor(projects/website): soften document rhythm
Narrow document pages to a comfortable reading measure, tighten the masthead and heading rhythm, reduce display scale, and use regular Fira Sans for friendlier section headings while preserving full-width archive layouts.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 01:50:47 -03:00
Gabriel Fontes 2248d605d8 feat(projects/website): redesign site
Replace Water.css with a classless technical-editorial design for the about, blog, publications, CV, and post pages. Add responsive document and listing layouts, Fira Sans Condensed display typography, semantic page regions, and a persistent JavaScript-gated colorscheme picker.

Assisted-by: pi (gpt-5.6-sol)
2026-08-12 01:43:52 -03:00
Gabriel Fontes fecb27979c chore(projects/website): regenerate colorschemes
Assisted-by: pi (gpt-5.6-sol)
2026-08-11 19:46:22 -03:00
Gabriel Fontes 8709fe0b7a feat(jagex-auth): accept pasted authentication responses
Allow authorization to consume either a raw ID token or the complete Jagex successful-login URL from stdin when no desktop URL handler is available.

Assisted-by: pi (gpt-5.6-sol)
2026-08-11 18:21:29 -03:00
Gabriel Fontes 15a19e5db0 refactor(jagex-auth): adopt rs hub authentication flow
Replace the legacy chained OAuth flow with the official launcher beta's single ID-token exchange and game session API. Register the rshub callback and permit its narrowly scoped qutebrowser handoff.

Assisted-by: pi (gpt-5.6-sol)
2026-08-11 18:16:59 -03:00
Gabriel Fontes 1ad2dd7564 fix(hosts/merope/sabnzbd): drop MemoryHigh, register for oomd swap kills
MemoryHigh is enforced by reclaim, and reclaiming anonymous pages means
writing them to swap. Holding sabnzbd near 4G resident therefore pushed 5.2G
into the 8G swapfile: the limit did not contain the growth, it converted a
RAM problem into swap exhaustion, which is the failure that actually
threatens the box. Without it sabnzbd grows in RAM, where oomd's pressure
rule can see it stall.

ManagedOOMSwap=kill registers this unit alone as a swap-monitoring
candidate. oomd ranks swap candidates by usage, so scoping it here means the
early trigger at 90% swap can only ever select sabnzbd, while jellyfin's
cold pages stay ineligible. The pressure rule on system.slice remains the
broader net for anything else.

Assisted-by: pi (claude-opus-5)
2026-08-11 10:12:46 -03:00
Gabriel Fontes 06c59fbf2a feat(hosts/merope): replace earlyoom with systemd-oomd
earlyoom only acts when available memory AND free swap are both under
threshold. During the 2026-08-11 swap exhaustion, swap crossed 5% at 02:14
but RAM did not until 06:10, so it watched the swapfile drain to zero for
four hours. It then sent 88 SIGTERMs without landing a kill: SIGKILL
escalation is gated at half the threshold (2.5%), RAM bottomed at 4.74%,
and sabnzbd's graceful shutdown took 12 minutes under thrash.

systemd-oomd was already running but monitoring zero cgroups, since every
unit defaults to ManagedOOMSwap=auto. It acts on PSI stall time, which does
not distinguish waiting on reclaim from waiting on swap I/O, and it SIGKILLs
the cgroup rather than negotiating. Candidates are ranked by reclaim
activity, so a service holding cold pages in swap is picked last rather
than first.

Set on system.slice directly because systemd.oomd.enableSystemSlice
hardcodes ManagedOOMSwap=kill, which would rank jellyfin's ~1.2G of cold
swap ahead of whatever is actually thrashing.

Assisted-by: pi (claude-opus-5)
2026-08-11 10:10:16 -03:00
Gabriel Fontes 61e044f1fa fix(hosts/merope/sabnzbd): restart after out-of-memory kills
earlyoom SIGTERMed sabnzbd at 06:10 after it grew to 4.2G resident plus
5.2G of swap, exhausting the box's 8G swapfile. sabnzbd caught the signal,
saved its queue and exited 0 twelve minutes later, and with Restart=no it
stayed dead for the next three and a half hours.

Restart=on-failure would not have helped: the graceful shutdown path is a
clean exit.

Assisted-by: pi (claude-opus-5)
2026-08-11 10:02:48 -03:00
Gabriel Fontes 8869064076 chore(hosts/merope/sabnzbd): drop timeout setting
No need to, I thought the issue was server timeout, but it actually was unaiv. artc.
2026-08-10 23:42:27 -03:00
Gabriel Fontes f884d8e087 fix(hosts/merope/sabnzbd): fix paths 2026-08-10 23:16:38 -03:00
Gabriel Fontes 9c5a9b074b fix(hosts/merope/sabnzbd): trim article retry cost
Every server was on defaults: timeout=60, and max_art_tries=3 across six
servers. That is up to eighteen rounds, each willing to wait a minute,
before SAB concludes an article is gone. Nothing legitimate takes that
long -- TLS handshakes to all six hosts complete in under a second.

Drop timeout to 20s and max_art_tries to 2. This is a straightforward
reduction in the cost of the failure path, not a fix for any particular
incident.

Explicitly not addressed: a stall found while investigating, where the
queue sat at ~0.13 MB/s with every server idle -- eweka and blocknews
holding ten established connections each with no article assigned to any
of them, and frugal at zero of thirty. Nothing was requesting articles at
all. An earlier draft of this commit blamed connections blocked on
timeouts and marked the blocknews pair optional; the connection dump
showed those sockets were idle rather than busy, so both the mechanism and
the remedy were wrong and have been dropped. Root cause still unknown.

Assisted-by: pi (claude-opus-5)
2026-08-10 23:13:42 -03:00
Gabriel Fontes 4d28bb9a29 fix(hosts/merope/sabnzbd): deprioritise cpu and io
par2/unrar routinely take a full core each and the media disk hits 83%
utilisation during a grab, both competing with jellyfin direct play and
library scans. sabnzbd was still at the default weight of 100, tied with
jellyfin, while the *arrs sit at 50.

Drop it to 20 so its pipeline yields under contention and keeps the whole
box when nothing else wants it. Children inherit the cgroup weight, so
this covers par2 and unrar without touching sabnzbd's own nice setting.

Assisted-by: pi (claude-opus-5)
2026-08-10 22:03:26 -03:00
Gabriel Fontes e3673ed9cd fix(grafana): use dashboard range for disk discovery
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 20:49:36 -03:00
Gabriel Fontes e14a866cce fix(grafana): hide hosts dashboard variables
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 20:24:33 -03:00
Gabriel Fontes 76a2e37f88 fix(grafana): update hosts dashboard layout
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 20:20:22 -03:00
Gabriel Fontes 92a74d1f92 fix(mgc): set root home during bootstrap
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 18:15:20 -03:00
Gabriel Fontes 41508a8f14 fix(system-manager): provide D-Bus session config
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 18:04:31 -03:00
Gabriel Fontes bb979ec2eb fix(mgc): run Nix installer as cloud-init root
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 18:04:31 -03:00
Gabriel Fontes b9f055458b refactor(mgc): wrap bootstrap in attended autoinstall
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 18:04:31 -03:00
Gabriel Fontes 7ee2e76610 fix(mgc): enforce local-only login during bootstrap
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 18:04:31 -03:00
Gabriel Fontes cebd2a2273 refactor(mgc): replace installer with cloud-init config
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 18:04:31 -03:00
Gabriel Fontes 699c87621d refactor(alcyone/grafana): rebuild hosts dashboard
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 14:18:46 -03:00
Gabriel Fontes 2378d52ec0 fix(hosts): un-exclude partitions from node exporter 2026-08-10 13:38:57 -03:00
Gabriel Fontes 331dbb57b6 feat(alcyone/grafana): enable section-level variables
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 12:48:25 -03:00
Gabriel Fontes a6c9d512f2 fix(hosts/merope): remove speedtest exporter
Had memory leaks
2026-08-10 12:29:30 -03:00
Gabriel Fontes 561e34e976 feat(hosts/merope/sabnzbd): tune down memoryhigh to 4gb 2026-08-10 12:18:49 -03:00
Gabriel Fontes 4c7f42f4f6 fix(hosts/merope/sabnzbd): explicitly set cache_limit 2026-08-10 12:17:40 -03:00
Gabriel Fontes fcb65ede67 refactor(alcyone/grafana): migrate internet speed dashboard to v2
Strip generated resource metadata and v2 defaults while retaining the schema-required wrappers and dashboard behavior.

Assisted-by: pi (gpt-5.6-sol)
2026-08-10 12:01:40 -03:00
Gabriel Fontes 303ad14dde feat(hosts/alcyone/grafana): use bps for network rather than Bps 2026-08-10 12:00:54 -03:00
Gabriel Fontes b3c51812b9 feat(hosts/alcyone/grafan): don't hardcode rate intervals 2026-08-10 12:00:25 -03:00
Gabriel Fontes 07b1560191 refactor(alcyone/grafana): migrate hosts dashboard to v2
Strip generated resource metadata and v2 defaults while retaining the schema-required wrappers and dashboard behavior.

Assisted-by: pi (gpt-5.6-sol)
2026-08-10 11:52:29 -03:00
Gabriel Fontes 1d469dfd07 feat(hosts/alcyone/grafana): add internet speed dashboard 2026-08-10 11:38:16 -03:00
Gabriel Fontes 6a09a748c6 feat(merope): add speedtest prometheus exporter
Scrape the exporter from alcyone every five minutes.

Assisted-by: pi (gpt-5.6-sol)
2026-08-10 10:55:07 -03:00
Gabriel Fontes 4e33a17a53 fix(hosts/merope/sabnzbd): persist state 2026-08-10 10:37:44 -03:00
Gabriel Fontes 6fc5103fb0 refactor(hosts/merope/sabnzbd): migrate to new settings format 2026-08-10 10:35:58 -03:00
Gabriel Fontes 69c67d5377 fix(hosts/merope/sabnzbd): incrrease memory ceil 2026-08-10 10:09:33 -03:00
Gabriel Fontes 112735b62a fix(hosts/merope): tune sabnzbd to lower memory usage 2026-08-10 09:55:01 -03:00
Gabriel Fontes b1a569a2cc Revert "feat(hosts/merope/sabnzbd): revert connection limits, pause on pp"
This reverts commit 3425a71fa4.
2026-08-10 09:54:20 -03:00
Gabriel Fontes 654ea00bfd feat(grafana): add host network panels
Assisted-by: pi (gpt-5.6-sol)
2026-08-10 02:56:38 -03:00
Gabriel Fontes edfbd0f3a4 fix(hosts/merope/sabznbd): remove pause_on_post_processing 2026-08-10 02:41:58 -03:00
Gabriel Fontes 3425a71fa4 feat(hosts/merope/sabnzbd): revert connection limits, pause on pp 2026-08-10 02:25:04 -03:00
Gabriel Fontes d5c0787ba0 perf(merope/sabnzbd): negotiate ChaCha20 instead of AES
The Cortex-A72 in the BCM2711 implements no ARMv8 crypto extensions, so
TLS runs entirely in software. Measured on merope: AES-256-GCM manages
53 MB/s per core against 208 MB/s for ChaCha20-Poly1305, roughly 4x.

All six providers default to TLS_AES_256_GCM_SHA384 and all six accept
ChaCha20, so at the 43 MB/s this box was pulling, about 0.8 of a core was
going to decryption alone -- on a machine already sitting at 93% CPU with
the network only a third utilised and the disks coasting. Usenet
throughput here is bounded by the cipher, not by bandwidth or IO.

Setting ssl_ciphers makes SABnzbd cap the connection at TLS 1.2, since
Python never exposed SSL_CTX_set_ciphersuites() for the 1.3 suites. That
costs an extra handshake round trip, amortised across long-lived
connections, and an unencrypted certificate that SNI already gives away.
ECDHE preserves forward secrecy and ChaCha20-Poly1305 is the same AEAD
1.3 would have picked.

Preferred over exporting OPENSSL_CONF, which reaches the same cipher
while keeping TLS 1.3: this is the supported knob, so when upstream can
select 1.3 ciphersuites the cap lifts on its own, whereas overriding a
library's config file to reorder one list is the kind of thing that
breaks silently.

Assisted-by: pi (claude-opus-5)
2026-08-10 01:57:13 -03:00
Gabriel Fontes 532a35ba7a docs(todo): drop the merope reorg plan, it is done
/srv/media is now a single btrfs subvolume on the media disk holding the
libraries and both staging trees, so imports are same-filesystem renames.
426 torrents were re-pointed through the deluge UI and are seeding without
a recheck, and the M.2 went from 164G to 39G used.

The layout is described by hardware-configuration.nix, deluge.nix and
sabnzbd.nix better than prose could, so the plan has nothing left to say.

Two follow-ups it was carrying, recorded here rather than kept as a file:
copying across filesystems flattened every reflink between the music
library and the torrent payloads, so those trees hold 170 GiB where they
held ~124 and duperemove would reclaim it; and the media filesystem has
still never been scrubbed.

Assisted-by: pi (claude-opus-5)
2026-08-10 01:17:27 -03:00
Gabriel Fontes 517bde3aa7 feat(hosts/merope): update media mountpoints 2026-08-10 01:08:54 -03:00
Gabriel Fontes 4feb27b4f6 docs(todo): rewrite as status and actions
Both documents had accreted a running commentary -- findings, then
corrections to those findings, then corrections to the corrections. That
is a changelog, and it is the wrong shape for something read mid-migration
at 2am.

Rewritten to carry only current state and what remains to be done. The
boot-chain work, the swap incident, the USB 2.0 discovery and the
successive revisions of the throughput numbers are all gone; git holds
that history if anyone wants it.

The migration is now a runbook rather than a description: what can be done
in advance without downtime, what needs the media stack stopped and
roughly how long each step takes, and what must wait until the result is
proven.

Documents the reflink structure between music and torrents, measured
rather than assumed. Both trees cost ~124 GiB today and ~170 GiB once
copied, because reflinks cannot cross filesystems. Sharing is whole-file
and strictly bimodal -- no file is fragmentarily shared, and the 23% that
sit at 90-99% differ only by a ~115 KiB tag block Lidarr rewrote after
importing -- so duperemove recovers nearly all of it afterwards. Warns
against file-level duplicate finders, which compare content rather than
extents and would trade 564 seeds for zero bytes. Replaces a fabricated
claim that music was heavily hardlinked: it has none.

Drops host SSH keys from the backup set, where they were listed as tier 1
on the false premise that sops needs them. Every creation rule already
lists the GPG key as a recipient beside the per-host age keys.

Corrects the claim that alcyone needs no dumps: firefly and headscale are
both sqlite there, and only its postgres (roundcube) is excluded.

Assisted-by: pi (claude-opus-5)
2026-08-09 23:46:04 -03:00
Gabriel Fontes f58c76ac59 fix(global/greetd): drop stray backslash in tuigreet command
The escape came from tuigreet's shell-quoted README example. Nix needs
no escape here, so the backslash reached greetd.toml and its command
lexer rejected \$ as an unknown escape sequence -- greetd has failed to
start on every host without regreet since e4fa2194 (2026-06-16).

Assisted-by: pi (claude-opus-5)
2026-08-09 22:11:47 -03:00