dotfiles/notes/docs.md
2025-09-29 04:21:01 +03:00

9.1 KiB

Dotfiles Manager Documentation

A declarative dotfiles management system that handles package installation, binary management, configuration file linking, and system setup through a simple YAML manifest.

What It Does

This dotfiles manager provides a unified approach to system configuration by:

  • Installing packages via system package managers (brew, apt, etc.)
  • Installing binaries from GitHub releases and other sources
  • Symlinking configuration files using GNU Stow-like structure
  • Setting up system configuration (hostname, SSH keys, shell)
  • Running custom commands

The system automatically detects and installs missing package managers, making it suitable for fresh system setups.

Directory Structure

~/.dotfiles/
├── dotfiles.py              # Main execution script
├── manifest.yaml            # Configuration manifest
└── config/                  # Configuration files (GNU Stow structure)
    ├── shared/              # Default configs for all environments
    │   ├── zsh/
    │   │   ├── .zshrc       # → ~/.zshrc
    │   │   └── .config/
    │   │       └── zsh/
    │   └── bin/
    │       └── scripts      # → ~/bin/scripts
    └── <environment>/       # Environment-specific overrides
        └── <config>/

Manifest Structure

Global Binaries Section

Define reusable binary installations that can be referenced by environments:

binaries:
  neovim:
    version: "0.10.4"
    source: "github:neovim/neovim"
    asset-pattern: "nvim-{{os}}-{{arch}}.tar.gz"
    platform-map:
      "linux-amd64": { os: "linux", arch: "x86_64" }
      "linux-arm64": { os: "linux", arch: "arm64" }
      "macos-arm64": { os: "macos", arch: "arm64" }
    dependencies: ["curl", "tar"]
    install-script: |
      if command -v nvim &> /dev/null && nvim --version | grep -q "{{version}}"; then
        exit 0
      fi
      
      curl -Lo /tmp/nvim.tar.gz "{{downloadUrl}}"
      rm -rf ~/.local/share/nvim
      mkdir -p ~/.local/share/nvim ~/.local/bin
      tar -xzf /tmp/nvim.tar.gz -C ~/.local/share/nvim --strip-components=1
      ln -sf "$HOME/.local/share/nvim/bin/nvim" "$HOME/.local/bin/nvim"
      rm -f /tmp/nvim.tar.gz      

Binary Properties:

  • version: Version to install
  • source: Source location (currently supports github:owner/repo format)
  • asset-pattern: Download filename pattern with {{os}}, {{arch}} placeholders
  • platform-map: Maps system platform to asset naming conventions
  • dependencies: Required system packages (installed via package manager)
  • install-script: Shell script for installation

Binary Installation Variables: The install script receives these variables:

  • {{downloadUrl}}: Computed download URL for binary assets
  • {{version}}: Binary version
  • {{os}} and {{arch}}: Platform-specific values from platform-map

Environments Section

Environment-specific configurations that define complete system setups:

environments:
  macos-host:
    os: macos
    hostname: macbook-pro
    package-manager: brew
    packages:
      formula:
        - dnsmasq
        - neovim
      cask:
        - brave-browser
        - name: rectangle
          link: false
          post-install-comment: "Needs manual configuration in System Preferences"
    configs:
      - zsh
      - bin
    ssh_keygen:
      - type: ed25519
        comment: "$USER@$TARGET_HOSTNAME"
        filename: id_ed25519_internal

Environment Properties

Basic Configuration:

  • os: Target operating system (macos or linux)
  • hostname: System hostname to set
  • package-manager: Package manager to use (brew, apt, etc.)
  • shell: Default shell to configure
  • requires: Array of required environment variables

Package Installation:

  • packages: Organized by package type
    • formula: Regular packages (brew formula, apt packages)
    • cask: GUI applications (brew cask)
    • package: Generic packages for the system package manager
    • binary: References to global binary definitions

Configuration Management:

  • configs: Array of configuration names to link from config/ directory

System Setup:

  • ssh_keygen: SSH key generation specifications
  • runcmd: Custom shell commands to execute

Package and Config Management

Package Configuration Linking

By default, all installed packages have their configurations automatically symlinked from the config/ directory. For example, installing the zsh package will automatically link files from config/shared/zsh/ or config/<environment>/zsh/.

To disable automatic config linking for a specific package:

packages:
  formula:
    - name: rectangle
      link: false

Configs Section

Use the configs section to symlink configurations without installing packages. This is useful for:

  • Custom scripts and binaries (bin)
  • Configurations for software installed outside the package manager
  • Shared configuration files
configs:
  - zsh      # Links config/shared/zsh/ or config/<env>/zsh/
  - bin      # Links custom scripts from config/shared/bin/
  - tmux     # Links tmux configs without installing tmux package

Package Specifications

Packages can be specified as simple strings or objects with additional properties:

packages:
  formula:
    - git                    # Simple package name
    - name: rectangle        # Package object with properties
      link: false
      post-install-comment: "Manual configuration required"
    - name: neovim          # Package with post-installation script
      post-install: |
        nvim --headless '+PackerSync' +qa        
      post-link: |
        echo "Neovim configuration linked"        

  binary:
    - neovim                # Reference to global binary
    - name: tree-sitter     # Binary with post-installation
      post-install: |
        tree-sitter --version        

Package Object Properties:

  • name: Package name
  • post-install: Script to run after package installation
  • post-install-comment: Human-readable message after package installation
  • link: Boolean to control config linking (default: true)
  • post-link: Script to run after config linking
  • post-link-comment: Human-readable message after config linking

Config Object Properties:

  • post-link: Script to run after config linking
  • post-link-comment: Human-readable message after config linking

SSH Key Generation

ssh_keygen:
  - type: ed25519
    comment: "$USER@$TARGET_HOSTNAME"
    filename: id_ed25519_internal

SSH Key Properties:

  • type: Key type (ed25519, rsa, etc.)
  • comment: Key comment (supports variable substitution)
  • filename: Output filename (optional, defaults to standard naming)

Custom Commands

runcmd:
  - mkdir -p ~/{tmp,projects}
  - git remote set-url origin "$DOTFILES_GIT_REMOTE"
  - systemctl --user enable podman.socket

Commands are executed in order after all other setup tasks complete.

Configuration File Management

Directory Structure

Configuration files follow GNU Stow conventions:

config/
├── shared/                 # Default configurations
│   ├── zsh/
│   │   ├── .zshrc         # Links to ~/.zshrc
│   │   └── .config/
│   │       └── zsh/
│   │           └── aliases # Links to ~/.config/zsh/aliases
│   └── bin/
│       └── my-script      # Links to ~/bin/my-script
└── macos-host/            # Environment-specific overrides
    └── zsh/
        └── .zshrc         # Overrides shared zsh config

Linking Priority

  1. Environment-specific configs (config/<environment>/) take precedence
  2. Shared configs (config/shared/) used as fallback
  3. Files are symlinked to preserve the exact directory structure

Variable Substitution

Variables can be used in scripts and strings:

  • $USER: Current username
  • $TARGET_HOSTNAME: Target hostname (from environment or --set parameter)
  • $HOME: User home directory

Custom variables can be provided at runtime:

./dotfiles.py --environment linux-vm --set TARGET_HOSTNAME=myserver --set DOTFILES_GIT_REMOTE=git@github.com:user/dotfiles.git

Usage

Basic Environment Installation

# Install complete environment
./dotfiles.py --environment macos-host

# Install with custom variables
./dotfiles.py --environment linux-vm --set TARGET_HOSTNAME=development-server

Example Environments

macOS Desktop Setup:

macos-host:
  os: macos
  hostname: macbook-pro
  package-manager: brew
  packages:
    formula: [git, tmux, zsh]
    cask: 
      - brave-browser
      - name: discord
        post-link-comment: "Import settings manually"
  configs: [bin]  # Only link bin, other configs linked automatically
  ssh_keygen:
    - type: ed25519
      comment: "$USER@$TARGET_HOSTNAME"

Linux Server Setup:

linux-server:
  requires: [TARGET_HOSTNAME]
  os: linux
  hostname: $TARGET_HOSTNAME
  shell: zsh
  packages:
    package: [zsh, tmux, git, htop]
    binary: [neovim, tree-sitter]
  configs: [bin]  # Link custom scripts
  runcmd:
    - mkdir -p ~/projects
    - systemctl --user enable podman.socket