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

307 lines
9.1 KiB
Markdown

# 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:
```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/<environment>/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/<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:
```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/<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:
```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
```