home-lab/research/gnu-stow.md
Geir Okkenhaug Jerstad 9837d82199 Refactor: Simplify module structure and reorganize services
- Removed system/ directory, merged applications into users/geir.nix
- Simplified fonts.nix to bare minimum (users can add more)
- Moved transmission.nix to sleeper-service/services/ (machine-specific)
- Organized grey-area services into services/ directory
- Updated import paths and tested all configurations
- Added research documentation for deploy-rs and GNU Stow
2025-06-07 12:11:20 +02:00

10 KiB

GNU Stow Research Summary

Overview

GNU Stow is a symlink farm manager that helps organize and deploy dotfiles and software packages. It creates symbolic links from a source directory to a target directory, making it ideal for managing dotfiles across multiple systems without copying files.

Repository: https://www.gnu.org/software/stow/ Language: Perl License: GPL-3.0+ Status: Mature, stable, widely adopted

Core Concept

Stow works by creating symbolic links from a "stow directory" (source) to a "target directory" (typically $HOME). Each subdirectory in the stow directory represents a "package" that can be independently stowed or unstowed.

dotfiles/               # Stow directory
├── zsh/               # Package: zsh configuration
│   └── .zshrc         # Will link to ~/.zshrc
├── emacs/             # Package: emacs configuration  
│   └── .emacs.d/      # Will link to ~/.emacs.d/
│       └── init.el
└── git/               # Package: git configuration
    └── .gitconfig     # Will link to ~/.gitconfig

Key Features

  • Non-destructive: Creates symlinks without overwriting existing files
  • Conflict detection: Warns about file conflicts before creating links
  • Tree folding: Optimizes symlink structure for efficiency
  • Partial deployment: Deploy only specific packages (e.g., just zsh config)

📦 Package-Based Organization

  • Modular structure: Each application gets its own package directory
  • Selective deployment: Install only needed configurations per machine
  • Easy maintenance: Add/remove configurations without affecting others
  • Version control friendly: Git can track each package independently

🛡️ Safety Features

  • Dry-run mode: Preview what would be done without making changes
  • Conflict resolution: Handles existing files and directories gracefully
  • Rollback capability: Easy to unstow (remove) configurations
  • Target verification: Ensures target directory exists and is writable

Command Examples

# Basic stow operations
cd ~/dotfiles
stow zsh              # Deploy zsh configuration
stow emacs git        # Deploy multiple packages
stow --target=/opt/local mypackage  # Custom target directory

# Management operations
stow --delete zsh     # Remove zsh symlinks (unstow)
stow --restow emacs   # Restow (unstow then stow again)
stow --simulate zsh   # Dry run - show what would happen

# Advanced usage
stow --verbose zsh    # Verbose output
stow --no-folding emacs  # Disable tree folding optimization
stow --ignore='\.DS_Store' zsh  # Ignore certain files

Directory Structure Example

~/dotfiles/                    # Stow directory
├── zsh/                      # Package: ZSH
│   ├── .zshrc               # → ~/.zshrc
│   └── .config/             # → ~/.config/
│       └── zsh/             # → ~/.config/zsh/
│           └── aliases.zsh  # → ~/.config/zsh/aliases.zsh
├── emacs/                   # Package: Emacs
│   ├── .emacs.d/           # → ~/.emacs.d/
│   │   ├── init.el         # → ~/.emacs.d/init.el
│   │   └── config.org      # → ~/.emacs.d/config.org
│   └── .config/            # → ~/.config/
│       └── emacs/          # → ~/.config/emacs/
├── git/                    # Package: Git
│   ├── .gitconfig         # → ~/.gitconfig
│   └── .gitignore_global  # → ~/.gitignore_global
└── nixos/                 # Package: NixOS-specific
    └── .config/           # → ~/.config/
        └── nixos/         # → ~/.config/nixos/
            └── user.nix   # → ~/.config/nixos/user.nix

Comparison with Current Org-Mode Approach

Feature Current Org-Mode GNU Stow
Configuration format Literate programming Traditional dotfiles
Deployment method Tangle + copy/symlink Automatic symlinking
Documentation Embedded in code Separate documentation
Version control Single org file Multiple files in packages
Learning curve Steep (Emacs/Org) Gentle (simple concept)
Flexibility Very high Moderate
Maintenance Manual tangling Automatic linking
Cross-platform Excellent Excellent
NixOS integration Native External tool

Advantages of GNU Stow

Simplicity & Reliability

  • Minimal learning curve: Understand symlinks = understand Stow
  • No dependencies: Works on any Unix-like system with Perl
  • Predictable behavior: Simple, well-defined symlink creation rules
  • Mature and stable: Decades of development and testing

Flexible Organization

  • Package-based: Logical separation of application configurations
  • Selective deployment: Deploy only needed configs per machine
  • Easy experimentation: Test new configs without affecting others
  • Conflict handling: Safe deployment with conflict detection

Version Control Benefits

  • Git-friendly: Each package can be tracked separately
  • Branching: Different branches for different machine types
  • History: Track changes to individual application configs
  • Collaboration: Easy to share specific application configurations

Multi-Machine Management

# Different configs for different machine types
stow --target=/home/geir desktop  # Desktop-specific configs
stow --target=/home/sma server    # Server-specific configs

# Machine-specific packages
dotfiles/
├── desktop-geir/     # Only for desktop user geir
├── server-sma/       # Only for server user sma
└── common/           # Shared configurations

Disadvantages & Limitations

Compared to Org-Mode Approach

  • No literate programming: Configuration and documentation separate
  • Less integration: Not as tightly integrated with Emacs workflow
  • File-based: No ability to generate configs from templates
  • Static configuration: Less dynamic than org-mode tangling

General Limitations

  • Symlink visibility: Some applications don't handle symlinks well
  • Permission issues: Target directory permissions must be correct
  • Perl dependency: Requires Perl runtime (usually not an issue)
  • No config generation: Can't generate configs based on system state

Integration with Current NixOS Setup

🎯 Hybrid Approach Options

Option 1: Stow for Traditional Dotfiles

# Keep org-mode for complex Emacs config
# Use Stow for simple dotfiles
dotfiles/
├── emacs.org          # Keep current literate approach
├── zsh/               # Simple dotfiles via Stow
│   └── .zshrc
└── git/
    └── .gitconfig

Option 2: User-Specific Deployment

# Different approaches per user
~/dotfiles-geir/       # Org-mode for desktop user
~/dotfiles-sma/        # Stow for server user (simpler configs)

Option 3: NixOS + Stow Integration

# In NixOS configuration
environment.systemPackages = [ pkgs.stow ];

# User activation script
system.userActivationScripts.stow-dotfiles = ''
  cd /home/geir/dotfiles
  ${pkgs.stow}/bin/stow --target=/home/geir common zsh git
'';

🔧 Implementation Strategies

For Server Configurations (sma user):

  • Simple, minimal dotfiles via Stow
  • Basic shell, git, and utility configurations
  • No complex literate programming needed

For Desktop Configurations (geir user):

  • Keep org-mode for Emacs (complex, well-integrated)
  • Consider Stow for simpler applications (git, zsh aliases)
  • Hybrid approach based on complexity

Practical Examples

📝 Basic Setup

# Initialize dotfiles repository
mkdir ~/dotfiles
cd ~/dotfiles

# Create package structure
mkdir -p zsh git emacs

# Add configurations
echo 'alias ll="ls -la"' > zsh/.zshrc
echo '[user]
    name = Geir Okkenhaug Jerstad
    email = geir@geokkjer.eu' > git/.gitconfig

# Deploy configurations  
stow zsh git

🏠 Home Lab Specific Usage

# Machine-specific dotfiles
dotfiles/
├── server-common/     # Shared server configs
│   ├── .zshrc
│   └── .vimrc
├── sleeper-service/   # NFS-specific configs
│   └── .config/
│       └── nfs/
└── grey-area/         # Git server specific
    └── .gitconfig
    
# Deploy on sleeper-service
stow server-common sleeper-service

# Deploy on grey-area  
stow server-common grey-area

🔄 Migration Strategy

# Phase 1: Extract simple configs from org-mode
emacs config.org
# Tangle simple configs to separate files
# Create Stow packages for extracted configs

# Phase 2: Test Stow deployment
stow --simulate zsh    # Test before applying
stow zsh               # Deploy if tests pass

# Phase 3: Maintain hybrid approach
# Keep org-mode for complex configs (Emacs)
# Use Stow for simple configs (shell, git)

Integration with Current Workflow

Keep Current Org-Mode For:

  • Emacs configuration (complex, well-integrated)
  • Complex, documented configurations
  • Configurations that benefit from literate programming

Use GNU Stow For:

  • Server user (sma) configurations
  • Simple shell configurations
  • Git configurations
  • Application-specific dotfiles that don't need documentation

Implementation Plan:

  1. Create stow repository for server configs
  2. Test on sleeper-service with sma user
  3. Gradually migrate simple configs from org-mode
  4. Maintain hybrid approach based on complexity needs

Conclusion & Recommendation

🎯 For Our Home Lab Context

GNU Stow is excellent for:

  • Server configurations (sma user)
  • Simple, stable dotfiles
  • Multi-machine deployments
  • Configurations that don't need complex documentation

Current org-mode approach excels for:

  • Complex Emacs configurations
  • Documented, literate configurations
  • Generated configurations
  • Desktop user (geir) complex setups

📋 Action Plan

  1. Immediate: Create stow-based dotfiles repository for server users
  2. Short-term: Deploy simple sma user configs via Stow on sleeper-service
  3. Medium-term: Evaluate migration of simple configs from org-mode
  4. Long-term: Maintain hybrid approach - Stow for simple, org-mode for complex

Verdict: GNU Stow is an excellent complement to our current org-mode approach. Use Stow for simple, server-side configurations while keeping org-mode for complex desktop configurations. This provides the best of both worlds - simplicity where appropriate, power where needed.