# 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-specific overrides └── / ``` ## Manifest Structure ### Global Binaries Section Define reusable binary installations that can be referenced by environments: ```yaml 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: ```yaml 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//zsh/`. To disable automatic config linking for a specific package: ```yaml 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 ```yaml configs: - zsh # Links config/shared/zsh/ or config//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: ```yaml 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 ```yaml 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 ```yaml 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//`) 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: ```bash ./dotfiles.py --environment linux-vm --set TARGET_HOSTNAME=myserver --set DOTFILES_GIT_REMOTE=git@github.com:user/dotfiles.git ``` ## Usage ### Basic Environment Installation ```bash # 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:** ```yaml 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:** ```yaml 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 ```