Configure PATH and backup strategy for non-declarative user scripts.
- Add ~/.local/bin to sessionPath in global home-manager config
- Include ~/.local/bin in onsite borgbackup (hourly to viridian)
- Include ~/.local/bin in offsite borgbackup (daily to borgbase)
Reorganize Claude configuration into dedicated subdirectory and add
reusable slash command for updating Docker services.
- Create editors/claude/ directory structure
- Move CLAUDE.md and settings.json into claude/
- Add slash commands directory with update-docker-services command
- Update default.nix to link individual files (allows Claude state files)
- Install gruvbox wallpaper to /run/current-system/sw/share/backgrounds/jade/
- Split xinitrc into "Personal Configuration" and "jade Desktop Environment"
- Move wallpaper into jade/assets/ for flake extraction readiness
This makes jade fully repo-independent - the wallpaper is now part of jade's
system packages rather than referencing the nix-config repo. When extracted
as a flake, jade will be completely self-contained.
Import DISPLAY and XAUTHORITY into systemd user environment and restart
xdg-desktop-portal-gtk service in xinitrc. This fixes the issue where
portal backends fail to start with "cannot open display" error when using
startx instead of a display manager.
Without this, Thunar waits 25 seconds for org.freedesktop.portal.Desktop
to respond before timing out and displaying.
Rename xmonad/ to jade/ and restructure as a complete desktop environment
with hybrid NixOS and home-manager modules. This establishes jade as a
self-contained, gruvbox-themed DE that can eventually be extracted as a flake.
Changes:
- Create jade/ with NixOS module (WM, system packages, GTK theme)
- Create jade/home.nix for home-manager services (wezterm, picom, dunst)
- Move dmenu with gruvbox patches into jade/dmenu/
- Convert wezterm to pure Lua config with gruvbox-material colors
- Move xinitrc into jade/ directory
- Remove feh/scrot from global env (now in jade)
- Remove dmenu overlay from global overlays
- Simplify home-manager desktop features to just user apps
This follows the pattern of real DEs (GNOME, KDE) where system and user
configs are split across NixOS and home-manager modules.
- Remove passwordless sudo for wheel group
- Update deploy command to use -S flag for sudo password prompt
- Maintain secure remote access while enabling deployments
Separated PipeWire audio configuration from bluetooth hardware settings for
better logical organization. Moved bluetooth config to hardware-configuration.nix
alongside kernel module workarounds (disable_ertm, iwlwifi power_save).
Also added documentation for permittedInsecurePackages in global config and
updated flake dependencies.
Allow devices on the WiFi network (192.168.50.x) to access the 3D printer
on the Ethernet subnet (10.1.0.x). This enables printer access from phones
and other WiFi devices when used with a static route on the router.
Changes:
- Add bidirectional forwarding rules between wlo1 and enp34s0
- Remove stateful connection restriction for simpler routing
- Improve comments to clarify traffic direction
Requires router configuration:
Route 10.1.0.0/24 via 192.168.50.237 (fuchsia's WiFi IP)
Enables internet connection sharing from WiFi (wlo1) to Ethernet (enp34s0)
to provide network access for the 3D printer. Includes DHCP server with
static IP reservation, DNS forwarding through Pi-hole, and NAT configuration.
- Add direnv module with nix-direnv integration, replacing manual hook
- Disable starship's add_newline for more compact prompt
- Clean up comments across CLI features for better readability
Create comprehensive documentation for Claude Code instances working in this
repository, including build commands, architectural patterns, and workflows.
Replace repository-level CLAUDE.md with personal global memory file that
establishes coding standards and working relationship preferences:
- Functional programming principles over OOP
- 100 character line width
- Explicit, simple, logical code with no assumptions or hacks
- FOSS principles and aesthetic appeal
- Industry standards (MISRA-C) and idiomatic code
- Senior/junior working relationship with confirmation before suggestions
- Visual clarity through whitespace and comments
The configuration is now properly integrated into home-manager to be
symlinked to ~/.claude/CLAUDE.md for persistent context across sessions.
Fixes cache initialization failures on unencrypted repositories and
standardizes environment variable configuration across all backup jobs.
Changes:
- Add BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK to unencrypted repos
(fuchsia/viridian onsite) to bypass interactive confirmation prompt
- Refactor all environment.BORG_RSH to multiline attribute set format
for consistency and future extensibility
The cache initialization error occurred after removing persistent timers
(commit d21b36a), causing borg to treat existing repos as "previously
unknown". The bypass flag allows automated jobs to proceed without
interactive confirmation for unencrypted repositories.
Removes persistentTimer from all borgbackup services and unnecessary
network-online.target dependencies. Changes fuchsia offsite to 14:00
fixed schedule when system is reliably awake.
Persistent timer catch-ups immediately after system resume caused
failures due to services starting before network/system fully stabilized:
- Onsite: DNS resolution failures (viridian.home.arpa)
- Offsite: BorgBase connection refusals during SSH/borg handshake
Fixed schedules provide reliable backups without catch-up complexity:
- fuchsia offsite: 14:00 daily (typical awake time for desktop)
- viridian offsite: midnight daily (always-on server)
- All onsite: hourly (no catch-up needed)
Offsite services retain wants/after dependencies on onsite completion
to prevent race conditions on shared /btrfs-subvolumes snapshot paths.
Network dependencies removed as fixed schedules run when system is
already stable, eliminating timing issues with network-online.target.
Add section headers and explanatory comments to clarify the purpose of each configuration block, with emphasis on the critical persistent path requirement for early boot secret decryption.
Fixes DNS resolution failures when persistent timers trigger backups
after system wake.
The NixOS borgbackup module adds network-online.target dependencies
to the timer when persistentTimer=true, but systemd timers don't pass
their dependencies to the services they trigger. This caused onsite
backups to start before the network was ready, resulting in "Could not
resolve hostname" errors.
Adding after/wants network-online.target directly to the service
ensures the backup waits for network availability regardless of how
it's triggered (timer or offsite's Wants= dependency).
Example failure (Oct 11, 07:43):
- Backup started at 07:43:43 (persistent timer caught up)
- DNS lookup failed: "Could not resolve hostname viridian.home.arpa"
- WiFi connected at 07:43:47 (4 seconds too late)
Applied to both fuchsia and viridian onsite backups.
Fixes multiple issues with borgbackup service coordination:
1. Race condition between onsite/offsite backups
- Set Type=oneshot to ensure services wait for completion
- Added Wants= dependency to trigger onsite when offsite runs
- Prevents snapshot path collision at /btrfs-subvolumes
2. Network unavailability after sleep/wake
- Added persistentTimer=true to onsite backups
- NixOS module now auto-adds network-online.target dependencies
- Fixes DNS resolution failures for SSH repos
3. Data loss risk from missed backups
- Persistent timers ensure backups run on wake if missed
- Protects work done before sleep from being unbackored
4. Duplicate onsite runs at midnight
- Removed 15-minute stagger (00:15 -> 00:00)
- Systemd deduplicates services in same transaction
- Onsite now runs once, not twice
Applied to both fuchsia and viridian for consistency.
Update backup paths to use actual persistent storage locations (/persist/*) rather than bind-mounted paths, making it clear where data truly resides and simplifying restore operations.
Changes staging directories from hidden to visible and aligns backup paths with actual BTRFS subvolume naming conventions for better clarity when browsing archives.
Adds persistentTimer=true to both fuchsia and viridian offsite backup configurations to ensure backups run on next boot if the system was asleep at the scheduled time. Without this, daily backups would be skipped entirely until the next scheduled run.
Fixes backup system authentication and hostname resolution issues.
Changes:
- Change PermitRootLogin from "no" to "prohibit-password" in global SSH config
(allows key-based root login for host-to-host backups while blocking passwords)
- Update fuchsia onsite backup to use viridian.home.arpa FQDN instead of shortname
- Update SSH knownHosts to use FQDNs (fuchsia.home.arpa, viridian.home.arpa)
(system-level config uses FQDNs, user shortcuts remain in home-manager)
This enables the complete 3-2-1 backup strategy with automated backups working
correctly between fuchsia and viridian, and fuchsia to BorgBase.
Restructures SSH trust relationships from global to host-specific configuration
for better locality of concern and principle of least privilege.
Changes:
- Collapse nixos/common/global/ssh/ back to ssh.nix (single-file module)
- Move internal host trust (fuchsia/viridian) to per-host services/ssh/
- Split BorgBase known hosts by repository (li9kg944 for fuchsia, r7ag7x1w for viridian)
- Add viridian SSH server config to accept backup connections from fuchsia
- Add fuchsia borgbackup passphrase for offsite backups
- Configure viridian to create /srv/borg-repo/fuchsia for remote backups
This enables the 3-2-1 backup strategy with fuchsia backing up to both viridian
(onsite) and BorgBase (offsite) with proper SSH authentication.
Add critical system state from persist.nix to borgbackup jobs:
- SSH host keys (required for borg authentication)
- machine-id and nixos state
- Network and bluetooth configurations
Paths mirror persist.nix configuration for maintainability.
Service-specific persist data (traefik, crowdsec) excluded -
will create dedicated subvolumes if/when needed.
Add automated snapshot and backup system with three independent tiers:
Snapper (hourly local snapshots):
- Configure snapper for all srv-* subvolumes
- Tiered retention: 24 hourly, 7 daily, 4 weekly, 12 monthly
- Snapshots stored at /.snapshots on viridian drive
- Provides fast operational rollback for user errors
Borgbackup onsite (hourly local backups):
- Independent staging snapshots at /.staging-onsite
- Repository on data drive at /srv/borg-repo
- Unencrypted (physical security assumed)
- Matches snapper retention policy
- Fast local disaster recovery
Borgbackup offsite (daily remote backups):
- Independent staging snapshots at /.staging-offsite
- Encrypted backups to borgbase repository
- Retention: 7 daily, 4 weekly, 12 monthly
- Remote disaster recovery with prune policy
Architecture decisions:
- Separate staging directories prevent job conflicts
- Staging snapshots decouple borg jobs from snapper
- Consistent zstd,9 compression across both borg jobs
- Special case handling for containers subvolume path
Migrate from path-based persistence (/persist/var/lib/*) to dedicated
BTRFS subvolumes for better data isolation and snapshot capabilities.
- Move valuable user-facing services to /srv/* with srv-* subvolumes:
- forgejo: git repositories and database
- opengist: paste data
- minecraft: game world data
- lighttpd: static web content
- containers: OCI container volumes
- Update home directory to use hm-sajenim subvolume on viridian disk
- Remove jupyterhub service (no longer in use)
- Update borgbackup paths to match new service locations
- Follow upstream service defaults where possible for maintainability
Services kept on /persist (disposable state):
- traefik, crowdsec, murmur
Restructured systemPackages list with alphabetically sorted categories to improve
maintainability and reduce vertical space. Added descriptive comments for all
environment configuration sections.
Add comprehensive inline documentation to both NixOS and Home Manager
global configuration files, explaining the purpose of each section,
overlay usage, unfree package policy, and configuration settings.
Remove PageUp/PageDown pane rotation keybinds that don't align with wezterm workflow. The static pane layout approach (fixed splits + zoom toggle) doesn't benefit from rotation like dynamic window managers do.
Also update CLAUDE.md to clarify that Home Manager is a NixOS module, so just build/switch commands handle both system and user configurations together.
Replace manual GitHub fetchFromGitHub with packaged versions of zsh plugins and consolidate plugin loading through the plugins list instead of manual sourcing.