- Python 76.6%
- Shell 22.6%
- JavaScript 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
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> |
||
| _helper/docs | ||
| bash | ||
| bin | ||
| config | ||
| cursors | ||
| easyeffects/db | ||
| fish | ||
| git | ||
| icons/yamis-overrides | ||
| kde | ||
| packages | ||
| system | ||
| systemd | ||
| wallpapers | ||
| .gitignore | ||
| README.md | ||
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.denyonly binds the Read tool; sandboxed Bash obeyssandbox.filesystem.denyReadinstead. 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 themselveskde/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).
- Install:
kpackagetool6 --type KWin/Script -i kde/kwin-scripts/<name> - The enabled flag (
kwin4_script_<name>Enabled=trueunder[Plugins]) is already restored as part ofkwinrc, 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>thenqdbus6 org.kde.KWin /Scripting start - It auto-loads on future logins without step 2.
Proton App Icons
- Copy PNGs to
~/.local/share/icons/hicolor/256x256/apps/ - Copy
.desktopfiles to~/.local/share/applications/ - Run
gtk-update-icon-cache --force --ignore-theme-index ~/.local/share/icons/hicolor - Run
kbuildsycoca6 --noincremental - 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