Stow & Dotfiles Patterns
GNU Stow and dotfiles management patterns I’ve actually used. Every entry has a date and context.
2026-04-02: Stow Selective Deployment (37 of 44 Packages)
Problem: Not all stow packages apply to every machine — some are machine-specific (GPU config, hardware-specific settings). Blindly stowing all 44 packages causes conflicts.
Context: P16g deployment. dots-quantum has 44 packages, some Razer-specific. Private packages (gpg, secrets, hosts) are not in git and must be rsync’d first.
The Fix:
# Remove default shell configs that conflict with stow
rm -f ~/.bashrc ~/.bash_profile ~/.zshrc
# Stow Tier 1 (essential — shell, desktop, editor, tools)
cd ~/atelier/_projects/personal/dots-quantum
stow -t ~ \
zsh bash shell git \
hyprland waybar wofi mako \
kitty oh-my-posh \
bin share \
btop fastfetch fzf fd ripgrep \
claude
# Stow Tier 2 (applications)
stow -t ~ \
tmux vim lazygit \
vscodium zathura thunar \
libvirt ghostty \
gpg aider opencode
# Private packages — rsync from existing machine first (not in git)
rsync -avz razer:~/dots-quantum/gpg/ ~/dots-quantum/gpg/
rsync -avz razer:~/dots-quantum/secrets/ ~/dots-quantum/secrets/
stow -t ~ gpg secrets
Rule: Not all stow packages are git-tracked. Private packages (gpg, hosts, secrets) must be rsync’d from an existing machine before stowing. Stow in tiers: essentials first (shell, desktop), applications second. Remove default dotfiles (~/.bashrc, ~/.zshrc) before stowing — stow can’t overwrite real files with symlinks.
Worklog: WRKLOG-2026-04-02
2026-04-02: Per-Host GPU Config Symlink
Problem: NVIDIA environment variables differ between machines (RTX 4090 on Razer vs RTX 5090 on P16g). A single stowed config breaks one machine.
Context: P16g and Razer both run Hyprland but need different GPU configurations for env-gpu.conf.
The Fix:
# Directory structure in dots-quantum
# hyprland/.config/hypr/hosts/razer/env-gpu.conf (RTX 4090 settings)
# hyprland/.config/hypr/hosts/p16g/env-gpu.conf (RTX 5090 settings)
# Per-host symlink (not managed by stow — gitignored)
ln -sf hosts/p16g/env-gpu.conf ~/.config/hypr/env-gpu.conf
# Verify
ls -la ~/.config/hypr/env-gpu.conf
Rule: Per-host config files go in hosts/{hostname}/ within the stow package. Create a gitignored symlink on each machine pointing to the host-specific file. Stow doesn’t manage this symlink — it’s a manual, machine-specific step.
Worklog: WRKLOG-2026-04-02
2026-04-02: NVIM_APPNAME for Multiple Neovim Configs
Problem: Need both domus-nvim and instrumentum-nvim configurations on the same machine without conflicts. Default Neovim only supports one config at ~/.config/nvim/.
Context: P16g deployment, multiple Neovim configs for different purposes (personal editing vs infrastructure tooling).
The Fix:
# Clone config repo
git clone git@github.com:EvanusModestus/domus-nvim.git ~/atelier/_projects/personal/domus-nvim
# Symlink to match NVIM_APPNAME (NOT to ~/.config/nvim)
ln -sf ~/atelier/_projects/personal/domus-nvim ~/.config/nvim-domus
# dots-quantum .zshrc exports globally:
# export NVIM_APPNAME="nvim-domus"
# So `nvim` always uses ~/.config/nvim-domus/
# Per-invocation aliases for other configs:
alias dvim='NVIM_APPNAME=nvim-domus nvim'
alias ivim='NVIM_APPNAME=nvim-instrumentum nvim'
# Verify
echo "NVIM_APPNAME: $NVIM_APPNAME"
ls -la ~/.config/nvim-domus
Rule: NVIM_APPNAME selects the config directory under ~/.config/. Symlink your repo to ~/.config/{appname}. Data directory follows: ~/.local/share/{appname}/. Do NOT symlink to ~/.config/nvim if NVIM_APPNAME is set — Neovim won’t look there.
Worklog: WRKLOG-2026-04-02
2026-04-02: SSH Config Decrypt + Stow Sequence
Problem: SSH config is age-encrypted in dots-quantum. Must decrypt before stowing, otherwise stow creates a symlink to the encrypted .age file.
Context: P16g deployment, age keys available after Phase 7 rsync. SSH config contains sensitive internal hostnames and IPs.
The Fix:
# Decrypt SSH config (age keys must be available from rsync)
cd ~/atelier/_projects/personal/dots-quantum
age -d -i ~/.age/identities/personal.key ssh/.ssh/config.age >| ssh/.ssh/config
# Stow SSH package (creates symlink to plaintext config)
stow -t ~ ssh
# Verify config is symlinked
ls -la ~/.ssh/config
Rule: Decrypt before stow, not after. The stow target must be the plaintext file. The >| operator forces overwrite without prompting (useful when re-decrypting). The plaintext ssh/.ssh/config is gitignored — only the .age file is tracked.
Worklog: WRKLOG-2026-04-02
2026-04-02: Git SSH over Port 443 (VLAN Port Restriction)
Problem: git clone via SSH fails — port 22 is blocked on the iPSK VLAN (DOMUS-IoT). GitHub supports SSH over port 443 via ssh.github.com.
Context: P16g deployment, on iPSK VLAN before EAP-TLS migration. Need to clone repos before SSH config is stowed.
The Fix:
# Test GitHub — port 443, explicit user=git, bypass local SSH config
ssh -F /dev/null -i ~/.ssh/id_ed25519_github -T -p 443 -l git ssh.github.com
# Clone using SSH over port 443 (ssh:// URL format required for non-standard ports)
GIT_SSH_COMMAND="ssh -F /dev/null -i ~/.ssh/id_ed25519_github -p 443 -l git" \
git clone ssh://ssh.github.com:443/EvanusModestus/dots-quantum.git \
~/atelier/_projects/personal/dots-quantum
Rule: When port 22 is blocked, use ssh.github.com on port 443. The ssh:// URL format with :443 is required (the git@github.com:user/repo.git syntax doesn’t support port specification). -F /dev/null bypasses SSH config. -l git is mandatory — GitHub rejects your local username.
Worklog: WRKLOG-2026-04-02