✨ A magical Nix flake-based dotfiles repository managing multiple machines with integrated Flox environment for development tools
🍎 macOS · 🐧 Linux · 🚀 Cross-platform · ⚡ Fast
- 🌍 Multi-platform support: macOS (nix-darwin) and Linux (NixOS)
- 🔗 Unified configuration: Shared profiles with platform-specific overrides
- 📦 Flox integration: Development tools and AI assistants in reproducible environments
- ☁️ Remote builders: Hetzner cloud builders for cross-platform compilation
- 🛠️ Modern tooling: Neovim, Ghostty terminal, tmux, and extensive CLI utilities
- flake.nix 🎯 - Central orchestrator defining all inputs, outputs, and machine configurations
- Machine configs 💻 - Minimal files in
darwinConfigurations/andnixosConfigurations/ - Profile layer 📁 - Shared configurations in
profiles/:common.nix- Core settings across all systemsdarwin.nix- macOS-specific home-manager configlinux.nix- Linux-specific home-manager configcommon_neovim.nix- Neovim configurationwayland.nix- GUI/Wayland settings for Linux
Machines are named after Game of Thrones characters:
- jaime ⚔️ - macOS work machine (aarch64-darwin)
- brienne 🛡️ - macOS personal machine (aarch64-darwin)
- cercei 👑 - Linux VM (aarch64-linux)
- floki ⚓ - Linux workstation (x86_64-linux)
- pono 🏰 - Linux server (x86_64-linux)
-
Install Nix with the Determinate Systems installer (supports macOS with Flakes enabled):
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
-
Install nix-darwin:
nix run nix-darwin -- switch --flake .#<hostname>
NixOS should already have Nix installed. Ensure Flakes are enabled in
/etc/nixos/configuration.nix:
nix.settings.experimental-features = [ "nix-command" "flakes" ];Install Flox:
curl -fsSL https://downloads.flox.dev/by-env/stable/install.sh | bash-
Clone this repository:
git clone [email protected]:garbas/dotfiles.git ~/dotfiles cd ~/dotfiles
-
Install direnv (optional but recommended):
# macOS brew install direnv # NixOS - already included in configuration
-
Allow direnv to load the development environment:
direnv allow
-
Build and activate configuration:
For macOS:
darwin-rebuild switch --flake .#<hostname> # Example: darwin-rebuild switch --flake .#jaime
For Linux (NixOS):
sudo nixos-rebuild switch --flake .#<hostname> # Example: sudo nixos-rebuild switch --flake .#floki
-
Activate the Flox environment (done automatically via shell init on Darwin):
flox activate
# macOS: Rebuild and switch system configuration
darwin-rebuild switch --flake .#<hostname>
# Linux: Rebuild and switch NixOS configuration
sudo nixos-rebuild switch --flake .#<hostname>
# Home Manager: Update user environment independently
home-manager switch --flake .#<hostname>Before applying changes system-wide, test your configuration:
# Test Darwin config without switching (build only)
nix build .#darwinConfigurations.<hostname>.system
# Test NixOS config without switching
nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel
# Test home-manager config
nix build .#homeConfigurations.<hostname>.activationPackage# Update all flake inputs
nix flake update
# Update specific input
nix flake lock --update-input nixpkgs-unstable
# Check flake for errors
nix flake check
# Show flake info
nix flake show
# Enter development shell
nix develop# Activate Flox environment (done automatically via shell init)
flox activate
# Install package
flox install <package>
# Search for packages
flox search <term>
# List installed packages
flox list
# Show package details
flox show <package>
# Edit manifest directly
vim flox/env/manifest.toml-
Create machine-specific config in
darwinConfigurations/ornixosConfigurations/:# darwinConfigurations/newmachine.nix { pkgs, lib, inputs, ... }: { imports = [ ../homeConfigurations/profiles/common.nix ../homeConfigurations/profiles/darwin.nix ]; # Machine-specific settings here }
-
Add entry to
flake.nixoutputs:darwinConfigurations.newmachine = nix-darwin.lib.darwinSystem { system = "aarch64-darwin"; modules = [ ./darwinConfigurations/newmachine.nix ]; specialArgs = { inherit inputs; }; };
-
Add machine metadata to
machineSettingsinflake.nix(lines 205-231).
Edit homeConfigurations/profiles/common.nix and add to home.packages:
home.packages = with pkgs; [
ripgrep
jq
# Add your package here
];Edit flox/env/manifest.toml under the [install] section:
[install]
ripgrep.pkg-path = "ripgrep"
your-package.pkg-path = "your-package"- Create package file in
flox/pkgs/<name>.nix - Reference in
flox/env/manifest.toml - Example: See
flox/pkgs/claude-code.nix
- 🐚 Shell: Zsh with Powerlevel10k theme
- ✏️ Editor: Neovim with extensive LSP/plugin configuration
- 👻 Terminal: Ghostty with Catppuccin theme
- 🖥️ Multiplexer: tmux with Catppuccin theme
- 🪟 Window Manager: AeroSpace (macOS), Hyprland/Sway (Linux)
- 🌳 Git UI: lazygit with Catppuccin theme
- 🚀 Modern CLI: bat, eza, ripgrep, fd, fzf, zoxide
- 🧠 claude-code - Anthropic's Claude Code CLI
- 💬 codex - OpenAI Codex CLI
- 💎 gemini-cli - Google Gemini CLI
- 🛠️ amazon-q-cli - Amazon Q CLI
- 🔓 opencode - Open source code assistant
- 📦 flox-mcp-server - Flox environment management
- 🐙 github-mcp-server - GitHub integration
- 🎭 playwright-mcp - Browser automation
The repository uses conditional git includes based on repository remotes:
- Personal repos (garbas repositories): Uses personal email
- Work repos (flox repositories): Uses work email
Configuration is in homeConfigurations/profiles/common.nix
(lines with programs.git).
Neovim configuration is in profiles/common_neovim.nix. It includes:
- 🔌 LSP support for multiple languages
- 🧩 Extensive plugin system
- ⌨️ Custom keybindings
- 🎨 Catppuccin theme
To add a new vim plugin from a Git repository:
-
Add input to
flake.nix:inputs.vimPlugin-pluginname = { url = "github:author/plugin"; flake = false; };
-
Reference as
custom-pluginnamein Neovim config
Darwin machines are configured with Hetzner remote builders for Linux builds:
- 🖥️ hetzner-aarch64-indigo-03 (aarch64-linux, 20 max jobs)
- 🖥️ hetzner-x86-64-indigo-04 (x86_64-linux, 8 max jobs)
- 🖥️ hetzner-x86-64-indigo-05 (x86_64-linux, 8 max jobs)
This enables cross-compilation without native Linux machines.
Check 1Password authentication:
op signin --account my.1password.comUse the --impure flag:
darwin-rebuild switch --flake .#<hostname> --impureClear old generations:
home-manager expire-generations "-7 days"Check SSH access:
ssh hetzner-aarch64-indigo-03Verify nix-daemon is running on remote.
Run garbage collection:
nix-collect-garbage -d # User profile
sudo nix-collect-garbage -d # System-wide (NixOS)# Collect garbage
nix-collect-garbage -d
sudo nix-collect-garbage -d # NixOS only
# Clear old generations
nix-env --delete-generations old
sudo nix-env --delete-generations old # NixOS only
# Rebuild
darwin-rebuild switch --flake .#<hostname> # macOS
sudo nixos-rebuild switch --flake .#<hostname> # LinuxThe flake is configured to use multiple substituters for faster builds:
- ❄️ cache.nixos.org - Official NixOS cache
- 📦 cache.flox.dev - Flox package cache
- 🔧 devenv.cachix.org - Devenv cache
This is a personal dotfiles repository, but feel free to fork and adapt for
your own use. See .claude/CLAUDE.md for detailed architecture documentation.
MIT License - See LICENSE file for details.
This repository uses git-hooks.nix to manage pre-commit hooks that ensure code quality and consistency.
Pre-commit hooks are automatically installed when you enter the development shell:
nix developOr if using direnv (automatically loads when entering the directory):
direnv allowAll Markdown files are checked for style consistency and line length:
- Maximum line length: 80 characters (MD013)
- Code blocks and tables: Excluded from line length checks
- Configuration file:
markdownlint.json
Important: Markdownlint will report lines longer than 80 characters but will not automatically fix them. This is intentional because line breaks in Markdown affect readability and should be done manually.
All Nix files are automatically formatted using the RFC 166 style standard:
- Formatter: nixfmt-rfc-style
- Auto-fix: Yes, files are automatically formatted on commit
- Standard: RFC 166 (will become the official Nixpkgs standard)
All Terraform files are automatically formatted using OpenTofu:
- Formatter: tofu fmt (OpenTofu)
- Auto-fix: Yes, files are automatically formatted on commit
- Files: All
.tffiles
All commit messages must follow the Conventional Commits specification:
- Standard: Conventional Commits
- Format:
type(scope): subject - Configuration file:
.czrc - Hook: commitizen
Commit Types:
feat: A new featurefix: A bug fixdocs: Documentation only changesstyle: Formatting, missing semi-colons, etc.refactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementtest: Adding or correcting testsbuild: Build system or dependency changesci: CI configuration changeschore: Other changes that don't modify src or test filesrevert: Reverts a previous commit
Examples:
feat(api): add user authentication endpointfix(ui): resolve button alignment issuedocs: update installation instructionschore: bump dependencies
Run linters manually on specific files:
# Markdownlint
markdownlint --config markdownlint.json <file.md>
# nixfmt-rfc-style
nixfmt <file.nix>
# Terraform formatting
cd terraform && tofu fmt
# Or from outside the dev shell
nix develop --command markdownlint --config markdownlint.json <file.md>
nix develop --command nixfmt <file.nix>
nix develop --command bash -c "cd terraform && tofu fmt"The following rules are configured in markdownlint.json:
- MD013: Line length limited to 80 characters
- MD024: Duplicate heading names allowed if siblings only
- MD033: HTML allowed in Markdown
- MD041: First line doesn't need to be a heading
Uses default RFC 166 formatting rules with no additional configuration needed.
This repository uses Cloudflare R2 for storing Nix build artifacts as a binary cache. This speeds up builds by downloading pre-built packages instead of building from source. 🚀
The R2 bucket and API tokens are managed using OpenTofu (Terraform) in the
terraform/ directory.
Bucket: garbas-dotfiles-nix-cache 🪣
Cost: Free tier includes 10GB storage + unlimited egress ($0/month for typical personal use) 💰✨
See terraform/README.md for complete setup
instructions including:
- 🔧 Terraform/OpenTofu installation and configuration
- 🪣 Creating the R2 bucket and API tokens
- 🔐 Generating Nix signing keys
- 🤖 Configuring GitHub Actions secrets
- 💻 Adding the cache to your local machines
- 📝 Terraform naming conventions
To use the cache on your machines, add to your flake.nix or configuration:
{
nix.settings = {
substituters = [
"https://cache.nixos.org"
"s3://garbas-dotfiles-nix-cache?endpoint=<account-id>.r2.cloudflarestorage.com®ion=auto"
];
trusted-public-keys = [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
"garbas-dotfiles-nix-cache-1:<your-public-key>"
];
};
}Primary uploads come from GitHub Actions. Manual uploads can be done with:
nix copy --to 's3://garbas-dotfiles-nix-cache?endpoint=<account-id>.r2.cloudflarestorage.com®ion=auto' ./result✨ Made with ❤️ and Nix ❄️