personal configs and automations
  • Python 76.6%
  • Shell 22.6%
  • JavaScript 0.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
mysticalsoap 902e38e664
system: WAN egress shaper on enp5s0 (HTB + CAKE, gluetun in Bulk)
The uplink queue sits in the ISP modem, so nothing host-side saw it
fill; a sustained upload collapsed the link for every LAN device
(docker#156). Measured 2026-10-08 from the raw link with a 75 MB
upload: 41 Mbit/s at the NIC against a ~43.5 Mbit ceiling, RTT to
1.1.1.1 14 ms idle / 27 ms avg, 54 ms max under load. With the shaper
at 38 Mbit: 36 Mbit/s sustained, 12.6 ms avg / 17.7 ms max loaded,
same as idle. gluetun's seeding moved to the Bulk tin and yielded to
the upload during the test.

HTB rather than a root CAKE because enp5s0 carries LAN traffic too;
a root shaper would cap Jellyfin to a TV at the uplink rate. The DSCP
rule lives in its own nft table because aqomui's firewall path runs
iptables -F/-X on mangle, which would wipe a mangle-table mark.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-08 17:24:03 -04:00
_helper/docs docs: KWin decoration edits don't repaint open windows 2026-10-08 09:34:20 -04:00
bash bash: nano as the default editor 2026-09-20 22:55:06 -04:00
bin backup-configs: mirror daemon.json and the ufw rule files 2026-10-08 15:38:53 -04:00
config ssh: vps alias for the relay host 2026-09-20 22:00:34 -04:00
cursors cursors: borderless — rim merged into body 2026-09-06 11:42:06 -04:00
easyeffects/db updated some setup stuff from reinstall experience 2026-04-12 23:31:57 -04:00
fish backup-configs: updated kde/kwinoutputconfig.json, kde/kdeglobals, kde/plasmarc, kde/konsole-keytabs, bash/bashrc, config/starship.toml, packages/pacman.txt, packages/aur.txt (2026-09-05 15:05) 2026-09-05 15:05:02 -04:00
git switch login shell to zsh, track its config 2026-08-17 14:08:51 -04:00
icons/yamis-overrides yamis-overrides: drop the Mahjong Soul tile — games stay colorful 2026-09-05 22:52:24 -04:00
kde backup-configs: updated system/docker/daemon.json, system/ufw/*, kde/plasma-org.kde.plasma.desktop-appletsrc, packages/pacman.txt (2026-10-08 15:40) 2026-10-08 15:40:38 -04:00
packages backup-configs: updated system/docker/daemon.json, system/ufw/*, kde/plasma-org.kde.plasma.desktop-appletsrc, packages/pacman.txt (2026-10-08 15:40) 2026-10-08 15:40:38 -04:00
system system: WAN egress shaper on enp5s0 (HTB + CAKE, gluetun in Bulk) 2026-10-08 17:24:03 -04:00
systemd remove the legacy sync unit copies too 2026-09-07 19:31:51 -04:00
wallpapers backup-configs: updated kde/kscreenlockerrc (2026-09-05 21:06) 2026-09-05 21:06:34 -04:00
.gitignore fastfetch: split logo pipeline for hand edits 2026-09-06 15:49:04 -04:00
README.md system: WAN egress shaper on enp5s0 (HTB + CAKE, gluetun in Bulk) 2026-10-08 17:24:03 -04:00

dotfiles

Personal configuration files for CachyOS + KDE Plasma.

Playbooks and reference notes live in _helper/docs/

Layout

Path Contents Kept current by
kde/ kdeglobals, kwinrc, kwinrulesrc, kwinoutputconfig.json, plasmarc, plasmashellrc, konsolerc backup-configs
kde/konsole-keytabs/ Konsole custom keyboard schemes + modified profiles (from ~/.local/share/konsole/) backup-configs
kde/kxmlgui5-konsole/ Konsole shortcut overrides, e.g. Copy/Paste rebinds (from ~/.local/share/kxmlgui5/konsole/) backup-configs
kde/kwin-scripts/ cava-to-tv KWin script backup-configs
kde/applications/ cava-fullscreen.desktop, Proton desktop launchers manual
kde/icons/ Proton icon assets manual
config/cava/, config/kitty/ cava visualizer + kitty's cava profile backup-configs
config/ssh/config SSH client config (from ~/.ssh/config) backup-configs
git/ gitconfig (from ~/.gitconfig), config-github (per-directory override for ~/dev/github/**) backup-configs
zsh/ zshrc, p10k.zsh — the login shell backup-configs
fish/ config.fish, fish_variables — kept as the fallback shell backup-configs
easyeffects/db/ EasyEffects presets (compressor, equalizer, gate, limiter, stereotools) backup-configs
system/fstab /etc/fstab backup-configs
system/NetworkManager/dispatcher.d/ 50-shape-enp5s0, WAN egress shaper — see below manual
systemd/ user-level systemd units (~/.config/systemd/user/) — see below backup-configs
packages/ pacman.txt (explicit native installs), aur.txt (explicit foreign/AUR installs) backup-configs
bin/ backup-configs, sync-systemtray, check-claude-denylist, aur-orphans manual

check-claude-denylist

Audits Claude Code's two deny lists in ~/.claude/settings.json against what /opt/docker actually holds, so they stay correct by verification rather than by memory. Read-only; prints paths, never file contents. Exit 1 if anything needs attention.

Lives here rather than in /opt/docker because it reads personal harness config, and that repo is headed public.

Four checks, each mapping to a mistake that has actually happened:

  • overbroad — a pattern denying a git-tracked file. Tracked means deliberately not secret, so this is the blanket-.env-wildcard mistake.
  • mirror drift — permissions.deny only binds the Read tool; sandboxed Bash obeys sandbox.filesystem.denyRead instead. A path in one and not the other is a real hole. Compares coverage, not pattern text, since the two lists legitimately use different patterns for the same protection.
  • fragile ** — denyRead's ** doesn't reliably match targets 0–1 segments below its anchor. Flags those, skipping ones a per-stack literal already covers.
  • stale — a pattern matching nothing on disk. Harmless, but it means the list has drifted.

Run it after adding a service, moving a secret, or changing what the repo tracks.

backup-configs

bin/backup-configs is the sync automation: it copies each live file/dir in its MANIFEST into the repo, regenerates the package lists, and — if anything changed — commits (--push also pushes). Run it after any config change you want captured, or on a schedule.

Not covered by the manifest (edit these paths in the repo directly, or extend the manifest if they become worth automating):

  • bin/* scripts themselves
  • kde/applications/, kde/icons/ (Proton launchers/icons)

Restoring on a fresh install

Packages

sudo pacman -S --needed - < packages/pacman.txt
# then install an AUR helper if needed, e.g.:
paru -S --needed - < packages/aur.txt

KDE Plasma

Copy from kde/: kdeglobals, kwinoutputconfig.json, plasmarc, plasmashellrc, kwinrulesrc (has the Proton Mail alt-tab rule), kwinrc, konsolerc into ~/.config/.

Copy kde/konsole-keytabs/ into ~/.local/share/konsole/ and kde/kxmlgui5-konsole/ into ~/.local/share/kxmlgui5/konsole/ to restore the custom Konsole keyboard scheme and Copy/Paste shortcut rebinds.

KWin Tiling (DP-2 portrait monitor)

After a fresh install, KWin tiling on the secondary monitor resets on logout if other monitors have non-default tile layouts. Known Plasma 6.4+ regression.

Fix: Leave all other monitors at their default single-tile layout (don't configure tiling on them). Only configure tiling on DP-2. Set the 50/50 horizontal split with Super+T.

KWin Scripts

kde/kwin-scripts/<name> holds KWin scripts (currently cava-to-tv, which sends the cava/kitty TV visualizer window to the HDMI-A-1 output on open — the classic window-rule "Force screen" approach doesn't reliably win against a window that requests fullscreen immediately at launch).

  1. Install: kpackagetool6 --type KWin/Script -i kde/kwin-scripts/<name>
  2. The enabled flag (kwin4_script_<name>Enabled=true under [Plugins]) is already restored as part of kwinrc, but a freshly-installed script still needs loading for the current session: qdbus6 org.kde.KWin /Scripting loadScript ~/.local/share/kwin/scripts/<name>/contents/code/main.js <name> then qdbus6 org.kde.KWin /Scripting start
  3. It auto-loads on future logins without step 2.

Proton App Icons

  1. Copy PNGs to ~/.local/share/icons/hicolor/256x256/apps/
  2. Copy .desktop files to ~/.local/share/applications/
  3. Run gtk-update-icon-cache --force --ignore-theme-index ~/.local/share/icons/hicolor
  4. Run kbuildsycoca6 --noincremental
  5. Window rules are restored automatically via kwinrulesrc

systemd user units

systemd/ holds user-scope units (~/.config/systemd/user/, not /etc/systemd/system/):

Unit Purpose Schedule
docker-goroutine-watch.timer captures a dockerd pprof goroutine dump if the count spikes (see bin/docker-goroutine-watch.py) every 5 min

Install:

cp systemd/*.service systemd/*.timer ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now docker-goroutine-watch.timer

The CrowdSec hub update, Invidious restart, IP2Location renewal, and Docker image prune timers that used to live here moved to /opt/docker/_helper/ (each has its own directory: crowdsec-hub-update/, invidious-restart/, ip2location/, docker-image-prune/) — they operate entirely on the docker stack, so the docker repo is the more natural home. Same for the docker.service TimeoutStopSec override, now at /opt/docker/_helper/docker-service-override.conf. See that repo's Maintenance doc.

WAN egress shaper

system/NetworkManager/dispatcher.d/50-shape-enp5s0 applies HTB + CAKE on enp5s0 and an nft DSCP rule on every link-up. Why and how to verify: the docker repo's Networking § Egress shaping. NetworkManager runs only root-owned, non-world-writable scripts, so a symlink into this repo won't do:

sudo install -o root -g root -m 755 system/NetworkManager/dispatcher.d/50-shape-enp5s0 /etc/NetworkManager/dispatcher.d/
sudo /etc/NetworkManager/dispatcher.d/50-shape-enp5s0 enp5s0 up

btrfs balance (/mnt/external, run on fresh install)

Scrub timers for every btrfs filesystem, /mnt/external included, are set up from the docker repo — see its Maintenance § btrfs scrub. The balance below is external-only and not tracked as repo files — create by hand:

/etc/systemd/system/btrfs-balance-external.service:

[Unit]
Description=btrfs balance /mnt/external
ConditionPathIsMountPoint=/mnt/external

[Service]
Type=oneshot
ExecStart=/usr/bin/btrfs balance start -dusage=50 -musage=50 /mnt/external
IOSchedulingClass=idle
CPUSchedulingPolicy=idle

/etc/systemd/system/btrfs-balance-external.timer:

[Unit]
Description=Weekly btrfs balance /mnt/external

[Timer]
OnCalendar=weekly
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target

Then:

sudo systemctl enable --now btrfs-balance-external.timer

system/fstab: /mnt/external uses x-systemd.device-timeout=2,x-systemd.idle-timeout=60 to avoid a 90s hang when unplugged (fixed 2026-07-20).

sync-systemtray

Keeps systray applet layout mirrored across panels on multiple monitors. Has hardcoded containment/applet IDs (SRC_CONT, SRC_APP, TARGETS) at the top of the script — these are install-specific and need updating after a reinstall or if Plasma reassigns them.

Finding the current IDs

Find all systemtray applet headers:

awk '/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/{header=$0} /plugin=org\.kde\.plasma\.systemtray/{print header}' ~/.config/plasma-org.kde.plasma.desktop-appletsrc

This gives three lines like [Containments][N][Applets][M] — one per panel. To determine which screen each belongs to, check the lastScreen= value for each containment:

grep -A5 '^\[Containments\]\[N\]$' ~/.config/plasma-org.kde.plasma.desktop-appletsrc | head -6

lastScreen=0 is the primary (source), 1 and 2 are targets.

Updating the script

Edit the constants at the top of sync-systemtray:

SRC_CONT = <panel_id for screen 0>
SRC_APP  = <systemtray applet id for screen 0>

TARGETS = [
    (<panel_id screen 1>, <systemtray applet id screen 1>),
    (<panel_id screen 2>, <systemtray applet id screen 2>),
]

Verify with --dry-run before applying:

sync-systemtray --dry-run