307 lines
9.1 KiB
Markdown
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
|
|
```
|