Nix Config

A set of configs for my machines:

  • powerhouse (desktop) - NixOS
  • capacitor (server) - NixOS
  • turbine (laptop) - macOS with nix-darwin

Features

  • Modular Architecture: 17+ organized modules across 9 categories for maximum reusability
  • Cross-platform: Supports both NixOS and macOS with shared configurations
  • Home Manager integration: User-specific configs with modular component imports
  • Unified GPG/SSH: Integrated authentication and encryption strategy
  • Homebrew support (macOS): GUI applications and Mac-specific software
  • Minimal approach: Prefer nixpkgs over Homebrew when possible
  • Cross-compilation: Build and validate nix-darwin configs from Linux

Quick Start

Prerequisites

  1. Install Nix with flakes enabled
  2. Clone this repository
  3. Enter the development environment

Development Environment

# Enter development shell
nix develop

# View available commands
just help

Building Configurations

# Build NixOS VM
just build-linux

# Cross-compile nix-darwin config from Linux
just build-darwin

# Validate nix-darwin config (faster)
just check-darwin

Repository Structure

├── docs/               # Documentation
├── hosts/              # Host-specific configurations
│   ├── powerhouse/     # NixOS desktop
│   └── turbine/        # macOS laptop
├── modules/            # Modular components (17+ modules)
│   ├── desktop/        # Desktop environments (hyprland)
│   ├── fonts/          # Font configurations
│   ├── hardware/       # Hardware-specific modules (nvidia)
│   ├── network/        # Network configurations (wireguard)
│   ├── os/             # Operating system modules (common, darwin, nixos)
│   ├── programs/       # Application configurations (git)
│   ├── security/       # Security modules (gpg, ssh, gpg-agent)
│   ├── terminal/       # Terminal tools (nvim, starship, tmux, zsh)
│   └── virtualization/ # Virtualization tools (podman, qemu)
├── users/              # User-specific configurations
├── flake.nix           # Main flake configuration
└── justfile            # Development commands

Module Architecture

The configuration is built using a modular approach where each component serves a specific purpose:

OS Modules (modules/os/)

  • common.nix - Universal settings for all systems
  • nixos.nix - NixOS-specific configurations
  • darwin.nix - macOS-specific configurations

User-specific Modules

  • modules/terminal/ - Shell, terminal emulators, and CLI tools
  • modules/security/ - GPG, SSH, and authentication
  • modules/programs/ - Application-specific configurations

System Modules

  • modules/hardware/ - Hardware-specific configurations
  • modules/network/ - Network and VPN configurations
  • modules/desktop/ - Desktop environment configurations
  • modules/virtualization/ - Container and VM configurations

Configuration Import Strategy

Host Configurations (hosts/*/config.nix):

imports = [
  ../../modules/os/common.nix    # Universal settings
  ../../modules/os/nixos.nix     # or darwin.nix for macOS
  ./hardware.nix                 # Host-specific hardware
];

User Configurations (users/*/home.nix):

imports = [
  ../../modules/terminal/zsh.nix
  ../../modules/security/gpg.nix
  ../../modules/programs/git.nix
  # Add modules as needed
];

Getting Help

  • Check the documentation in the navigation menu
  • Run just help for available commands
  • Review existing configurations in the hosts/ directory
  • Explore modules in the modules/ directory for reusable components
  • See module import examples in users/brancengregory/home.nix
  • See GitHub Copilot Agent for development environment details

Adding New Modules

To add a new module:

  1. Create the module file in the appropriate modules/ subdirectory
  2. Follow the existing module structure and naming conventions
  3. Import the module in the relevant host or user configuration
  4. Test the configuration with just check-darwin or just build-linux

Module Architecture

This configuration uses a modular architecture with 17+ modules organized across 9 categories. Each module encapsulates specific functionality and can be imported as needed by host and user configurations.

Module Categories

Desktop Modules (modules/desktop/)

  • hyprland.nix - Hyprland window manager configuration

Font Modules (modules/fonts/)

  • default.nix - System font configurations and font packages

Hardware Modules (modules/hardware/)

  • nvidia.nix - NVIDIA GPU drivers and configuration

Network Modules (modules/network/)

  • wireguard.nix - WireGuard VPN configuration

OS Modules (modules/os/)

  • common.nix - Universal settings for all systems (Nix features, experimental flags)
  • nixos.nix - NixOS-specific system configurations
  • darwin.nix - macOS-specific system configurations

Program Modules (modules/programs/)

  • git.nix - Git configuration and aliases

Security Modules (modules/security/)

  • gpg.nix - GPG configuration and key management
  • gpg-agent.nix - GPG agent configuration
  • ssh.nix - SSH client and server configuration

Terminal Modules (modules/terminal/)

  • nvim.nix - Neovim editor configuration
  • starship.nix - Starship prompt configuration
  • tmux.nix - Terminal multiplexer configuration
  • zsh.nix - Z shell configuration and plugins

Virtualization Modules (modules/virtualization/)

  • podman.nix - Podman container runtime
  • qemu.nix - QEMU virtualization platform

Module Usage Patterns

Host Configuration Pattern

Host configurations (hosts/*/config.nix) typically import:

  • OS-specific modules (modules/os/common.nix + modules/os/nixos.nix or modules/os/darwin.nix)
  • Hardware-specific modules as needed
  • Host-specific hardware configuration

Example:

{pkgs, ...}: {
  imports = [
    ../../modules/os/common.nix    # Universal settings
    ../../modules/os/nixos.nix     # NixOS-specific settings
    ./hardware.nix                 # Host hardware config
  ];
  
  networking.hostName = "powerhouse";
  system.stateVersion = "25.05";
}

User Configuration Pattern

User configurations (users/*/home.nix) import user-specific modules:

{pkgs, ...}: {
  imports = [
    ../../modules/fonts/default.nix
    ../../modules/terminal/zsh.nix
    ../../modules/terminal/starship.nix
    ../../modules/terminal/tmux.nix
    ../../modules/terminal/nvim.nix
    ../../modules/security/gpg.nix
    ../../modules/security/ssh.nix
    ../../modules/security/gpg-agent.nix
    ../../modules/network/wireguard.nix
    ../../modules/programs/git.nix
  ];
  
  # User-specific configuration
  home.username = "username";
  # ... rest of configuration
}

Cross-Platform Compatibility

Modules are designed to work across NixOS and macOS:

  • OS modules provide platform-specific configurations
  • User modules use conditional logic for platform differences
  • Hardware modules are imported only when relevant

Example of cross-platform user configuration:

home.homeDirectory = 
  if pkgs.stdenv.isLinux 
  then "/home/username"
  else if pkgs.stdenv.isDarwin
  then "/Users/username" 
  else throw "Unsupported OS";

Adding New Modules

1. Choose the Right Category

Place your module in the appropriate directory:

  • System-level configs → modules/os/
  • User programs → modules/programs/
  • Terminal tools → modules/terminal/
  • Security configs → modules/security/
  • etc.

2. Follow Module Structure

{pkgs, ...}: {
  # Module configuration here
  # Use conditional logic for cross-platform support if needed
}

3. Import in Configurations

Add the module import to relevant host or user configurations:

imports = [
  ../../modules/category/your-module.nix
  # ... other imports
];

4. Test the Configuration

# Validate syntax
nix flake check

# Test darwin config
just check-darwin

# Test NixOS config  
just build-linux

Module Dependencies

Modules can depend on other modules by importing them:

{pkgs, ...}: {
  imports = [
    ./base-module.nix
  ];
  
  # Additional configuration
}

Keep dependencies minimal and well-documented to maintain modularity.

Unified GPG/SSH Strategy

This document outlines the streamlined GPG/SSH configuration implemented across the nix-config ecosystem, providing secure, unified authentication and encryption for both Linux (powerhouse) and macOS (turbine) systems.

Overview

The strategy implements a performance-optimized, secure approach where:

  • GPG agent serves as the central authentication hub for both GPG operations and SSH authentication
  • Cross-platform compatibility ensures consistent behavior on Linux and macOS
  • Streamlined configuration with essential security settings and optimized performance
  • Unified configuration managed through home-manager for consistency

Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   GPG Client    │    │   SSH Client    │    │   Git (signed)  │
└─────────┬───────┘    └─────────┬───────┘    └─────────┬───────┘
          │                      │                      │
          └──────────────────────┼──────────────────────┘
                                 │
                    ┌─────────────▼──────────────┐
                    │        GPG Agent          │
                    │  ┌─────────────────────┐   │
                    │  │ GPG Authentication  │   │
                    │  │ SSH Authentication  │   │
                    │  │ Key Management      │   │
                    │  │ Smart Card Support  │   │
                    │  └─────────────────────┘   │
                    └────────────────────────────┘

Key Features

Streamlined Security Configuration

  • Essential Algorithms: AES256, SHA512, Ed25519 (focused on widely-used, secure algorithms)
  • Balanced SSH Settings: Secure but not overly restrictive configurations
  • Optimized Cache Settings: 8-24 hour cache TTL for good balance of security and usability

Performance Optimizations

  • Lazy GPG Agent Initialization: Only starts/connects when needed
  • Efficient Tmux Integration: Uses session/client events instead of frequent pane switches
  • Streamlined Environment Setup: Reduced conditional logic and redundant checks
  • Minimal Configuration: Essential settings only, removing rarely-used options

Cross-Platform Support

  • Unified Pinentry: Terminal-based pinentry-curses for consistent operation
  • Platform-Specific Optimizations: Tailored socket handling for Linux/macOS
  • Consistent Shell Experience: Same behavior across all platforms

Integration Features

  • Git Signing: Automatic commit signing with GPG
  • SSH Authentication: GPG keys used for SSH instead of separate SSH keys
  • Smart Card Support: Hardware token integration ready
  • Agent Management: Lazy startup and optimized TTY handling

Optimized Tmux Configuration

The strategy includes performance-optimized tmux configuration with:

programs.tmux = {
  enable = true;
  extraConfig = ''
    # Streamlined environment variable passing
    set-option -g update-environment "DISPLAY SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION SSH_AUTH_SOCK WINDOWID XAUTHORITY GPG_TTY"

    # Efficient GPG_TTY updates - only when creating sessions or attaching clients
    set-hook -g session-created 'run-shell "export GPG_TTY=$(tty) && gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1 || true"'
    set-hook -g client-attached 'run-shell "export GPG_TTY=$(tty) && gpg-connect-agent updatestartuptty /bye >/dev/null 2>&1 || true"'
  '';
};

This ensures:

  • Environment variables are properly inherited in new tmux panes
  • GPG_TTY is updated only when necessary (session creation/client attachment)
  • SSH authentication works consistently across all tmux sessions
  • Performance improvement: Eliminates expensive pane-focus-in hooks

Configuration Files

The strategy is implemented across several configuration files:

  • users/brancengregory/home.nix: Main GPG/SSH configuration
  • Environment variables: Cross-platform GPG agent integration
  • Platform-specific: Pinentry and socket configuration

Initial Setup

1. Generate GPG Master Key

# Generate a new GPG key with strong settings
gpg --full-gen-key

# Choose:
# (1) RSA and RSA (default) or (9) ECC and ECC
# Key size: 4096 bits (RSA) or Curve 25519 (ECC)
# Valid for: 1-2 years (recommended)
# Real name: Brancen Gregory
# Email: brancengregory@gmail.com

2. Generate SSH Authentication Subkey

# Add SSH authentication capability to your GPG key
gpg --edit-key brancengregory@gmail.com

# In GPG prompt:
gpg> addkey
# Choose (8) RSA (set your own capabilities)
# Toggle off Sign and Encrypt, toggle on Authenticate
# Or choose (10) ECC (set your own capabilities) for Ed25519

gpg> save

3. Export SSH Public Key

# Export SSH public key from GPG
gpg --export-ssh-key brancengregory@gmail.com

# Add this to GitHub, GitLab, servers, etc.

4. Configure Git Signing

# Set your GPG signing key (if not using default)
git config --global user.signingkey YOUR_GPG_KEY_ID

# Verify signing works
git commit --allow-empty -m "Test GPG signing"
git log --show-signature -1

Tmux Integration

The configuration includes performance-optimized tmux support to ensure GPG and SSH work seamlessly within tmux sessions.

Optimized Tmux Features

  • Lazy GPG_TTY Updates: Updates GPG_TTY only when creating sessions or attaching clients, not on every pane switch
  • SSH agent socket management: Ensures consistent SSH authentication in tmux
  • Terminal pinentry optimization: Configured for efficient operation in tmux sessions
  • Performance improvement: Eliminates frequent hook executions that could slow down tmux

Usage in Tmux

# Start tmux session
tmux new-session -s work

# SSH from within tmux (works seamlessly)
ssh git@github.com

# Git operations work with automatic signing
git commit -m "Update from tmux session"
git push

# If you encounter issues, manually refresh GPG state
refresh_gpg

Troubleshooting Tmux Issues

If you encounter pinentry or authentication issues in tmux:

# Check GPG agent status
gpg-status

# Restart GPG agent if needed
gpg-restart

# Manually refresh GPG state in current pane
refresh_gpg

# Check SSH keys are loaded
ssh-keys

# Verify SSH socket is correct
echo $SSH_AUTH_SOCK

Daily Usage

SSH Authentication

With the unified strategy, SSH authentication works seamlessly:

# SSH uses your GPG key automatically
ssh git@github.com

# SSH to personal servers
ssh user@server.com

GPG Operations

Standard GPG operations work as expected:

# Encrypt files
gpg --encrypt --recipient brancengregory@gmail.com file.txt

# Sign files
gpg --sign file.txt

# Decrypt/verify
gpg --decrypt file.txt.gpg

Git Integration

Git automatically signs commits with your GPG key:

# Commits are automatically signed
git commit -m "Update configuration"

# Verify signatures
git log --show-signature

Key Management

Backup Strategy

# Export your master key (keep this VERY secure)
gpg --export-secret-keys --armor brancengregory@gmail.com > private-key-backup.asc

# Export public key (safe to share)
gpg --export --armor brancengregory@gmail.com > public-key.asc

# Export revocation certificate
gpg --gen-revoke brancengregory@gmail.com > revocation-cert.asc

Key Rotation

Plan to rotate keys periodically:

  1. Annual Review: Check key expiration and usage
  2. Subkey Rotation: Rotate subkeys more frequently than master key
  3. Revocation: Have revocation certificates ready for emergency use

Troubleshooting

GPG Agent Issues

# Restart GPG agent
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent

# Check agent status
gpg-connect-agent 'keyinfo --list' /bye

# Use helpful aliases
gpg-restart  # Restart agent
gpg-status   # Check status
gpg-refresh  # Refresh in tmux pane

SSH Authentication Problems

# Check SSH agent socket
echo $SSH_AUTH_SOCK

# List loaded SSH keys (should show GPG key)
ssh-add -l

# Force GPG agent refresh
gpg-connect-agent updatestartuptty /bye

# Use aliases for quick checks
ssh-keys     # List SSH keys

Tmux-Specific Issues

Problem: Pinentry appears in wrong pane or doesn't appear at all

# Solution 1: Refresh GPG state in current pane
refresh_gpg

# Solution 2: Restart GPG agent completely
gpg-restart

# Solution 3: Check GPG_TTY is set correctly
echo $GPG_TTY

Problem: SSH authentication fails in tmux but works outside

# Check SSH socket in tmux session
echo $SSH_AUTH_SOCK

# Verify the socket file exists
ls -la $SSH_AUTH_SOCK

# If socket is missing, restart the session or refresh
refresh_gpg

Problem: Git signing fails in tmux

# Check GPG agent can sign
echo "test" | gpg --clearsign

# Refresh GPG state if needed
refresh_gpg

# Test Git signing explicitly
git commit --allow-empty -m "Test commit" --gpg-sign

Platform-Specific Issues

Linux:

# Check XDG runtime directory
echo $XDG_RUNTIME_DIR

# Verify socket exists
ls -la $XDG_RUNTIME_DIR/gnupg/

macOS:

# Check GPG agent socket
gpgconf --list-dirs agent-ssh-socket

# Verify agent is running
gpgconf --check-programs

Security Considerations

Best Practices

  1. Strong Passphrases: Use long, unique passphrases for GPG keys
  2. Limited Scope: Use separate subkeys for different purposes
  3. Regular Rotation: Plan key rotation schedule
  4. Secure Storage: Keep master key backup in secure location
  5. Revocation Ready: Maintain current revocation certificates

Trust Model

  • Web of Trust: Participate in key signing when appropriate
  • Key Verification: Always verify key fingerprints out-of-band
  • Certificate Authorities: Consider using keyserver certificates for verification

Hardware Tokens

The configuration supports hardware tokens (YubiKey, etc.):

  1. Smart Card Support: enableScDaemon = true in GPG agent
  2. Key Generation: Generate keys directly on hardware token
  3. Backup Strategy: Ensure backup authentication methods

Integration with Services

GitHub/GitLab

  1. Add your SSH public key to your profile
  2. Commits will be automatically signed
  3. SSH authentication works seamlessly

Personal Servers

  1. Add SSH public key to ~/.ssh/authorized_keys
  2. Configure host-specific settings in SSH config
  3. Optionally use GPG for server encryption/signing

Maintenance

Regular Tasks

  • Weekly: Check agent status and key usage
  • Monthly: Review SSH connections and Git signatures
  • Quarterly: Review key expiration dates
  • Annually: Consider key rotation and security review

Monitoring

The configuration includes logging and monitoring capabilities:

  • GPG agent logs authentication attempts
  • SSH client logs connection details
  • Git maintains signature verification history

Migration Guide

From Existing SSH Keys

  1. Backup current SSH keys
  2. Generate GPG authentication subkey
  3. Update authorized_keys on servers
  4. Test SSH authentication with GPG
  5. Remove old SSH keys once verified

From Existing GPG Setup

  1. Export current keys
  2. Apply new home-manager configuration
  3. Import keys to new agent
  4. Verify functionality
  5. Update any custom configurations

Further Reading

Security Guidelines

This document outlines security best practices and considerations for this nix-config repository.

Security Review Summary

Repository Status: Ready for public transition

Security Audit Results

✅ Clean: No hardcoded secrets, API tokens, or private keys found
✅ Clean: No sensitive credentials committed to repository
✅ Clean: Strong security configurations implemented
✅ Fixed: Removed hardcoded password from user configuration

Security Configurations

SSH Security

  • Password authentication disabled: PasswordAuthentication no
  • Strong ciphers: Modern encryption algorithms only
  • Host key verification: StrictHostKeyChecking ask
  • No agent forwarding: ForwardAgent no and ForwardX11 no
  • Key algorithms: Ed25519 and strong RSA/ECDSA only

GPG Security

  • Modern algorithms: SHA512, AES256, strong key preferences
  • Secure defaults: No weak ciphers, strong S2K settings
  • Key management: Proper keyserver configuration
  • Hardware token support: Ready for YubiKey integration

User Account Security

  • No hardcoded passwords: Users must set passwords during setup
  • Wheel group: Administrative access properly configured
  • Shell security: Zsh with proper configuration

Best Practices for Users

Initial Setup

  1. Set secure password: Run sudo passwd brancengregory after first boot
  2. Generate GPG keys: Follow GPG-SSH-STRATEGY.md
  3. Configure SSH keys: Add your public keys to services (GitHub, etc.)
  4. Review configurations: Customize settings for your environment

Ongoing Security

  • Regular updates: Keep system packages updated
  • Key rotation: Follow GPG key rotation schedule
  • Monitor access: Review SSH and GPG logs periodically
  • Backup strategy: Secure backup of GPG keys and important data

Before Contributing

  • No secrets: Never commit passwords, private keys, or API tokens
  • Personal info: Remove personal email/username if contributing upstream
  • Configuration review: Ensure changes don't introduce security vulnerabilities

Security Contact

For security-related questions or to report vulnerabilities:

  • Open an issue with the "security" label
  • Follow responsible disclosure practices

References

Homebrew Integration

This nix-darwin configuration includes Homebrew support for managing Mac applications. Here's how to use it:

Philosophy

  • Prefer nixpkgs: Use packages from nixpkgs whenever possible (managed in users/brancengregory/home.nix)
  • Use Homebrew for GUI apps: GUI applications and Mac-specific software that aren't available or don't work well in nixpkgs
  • Minimal Homebrew usage: Only use Homebrew when nixpkgs isn't sufficient

Configuration Files

  • modules/os/darwin.nix: Contains Homebrew configuration (casks, brews, taps, masApps)
  • users/brancengregory/home.nix: Contains nixpkgs packages (CLI tools, fonts, etc.)

Adding Applications

Edit modules/os/darwin.nix and add applications to the casks list:

casks = [
  "visual-studio-code"
  "docker"
  "slack"
  "1password"
];

Edit users/brancengregory/home.nix and add packages to the home.packages list:

home.packages = with pkgs; [
  git
  neovim
  bat
  # ... other packages
];

When to Use Homebrew for CLI Tools

Only use Homebrew brews for CLI tools that:

  • Aren't available in nixpkgs
  • Don't work properly when installed via nixpkgs
  • Require system integration that nixpkgs can't provide

Mac App Store Apps

For apps from the Mac App Store, add them to masApps with their app ID:

masApps = {
  "Xcode" = 497799835;
  "Pages" = 409201541;
};

Migration from Existing Homebrew

If you already have Homebrew installations:

  1. Inventory existing apps: Run brew list and brew list --cask
  2. Add to nix-darwin: Add the applications you want to keep to the appropriate lists
  3. Apply configuration: Run darwin-rebuild switch --flake .#turbine
  4. Cleanup: The cleanup = "zap" setting will remove unmanaged packages

Applying Changes

After modifying the configuration:

darwin-rebuild switch --flake .#turbine

This will:

  • Install new packages/casks
  • Remove packages not in the configuration (due to cleanup = "zap")
  • Update existing packages (due to upgrade = true)

Cross-Platform Development

This flake supports building and validating nix-darwin configurations from Linux systems.

Features

Cross-Compilation

Build nix-darwin configurations on Linux without requiring a macOS system:

# Build the full darwin configuration from Linux
nix build .#turbine-darwin

# Or use the convenience command
just build-darwin

# The result will be in ./result/

Configuration Validation

Validate nix-darwin configurations without performing a full build:

# Check if the darwin configuration is valid
nix build .#turbine-check

# Or use the convenience command
just check-darwin

# This is faster than a full build and useful for CI/testing

Note: Some darwin packages with system-specific dependencies may fail during cross-compilation. The validation target helps catch syntax and basic configuration errors without requiring full package builds.

Development Environment

Use the provided development shell for cross-platform work:

# Enter the development environment
nix develop
# Or
just dev

# This provides tools like nixos-rebuild, nix-output-monitor, alejandra, and just

Linux Builder Setup

For optimal performance when building nix-darwin configurations from Linux, you should set up nix-darwin's linux-builder feature. This enables remote building and improves cross-compilation performance.

What is nix-darwin's linux-builder?

The linux-builder is a virtual machine that runs on macOS and allows you to build Linux packages remotely. However, in our case, we're doing the reverse - building macOS packages from Linux. The linux-builder configuration in nix-darwin can be adapted for this purpose.

Setting up Remote Building

  1. Configure a macOS builder (if you have access to a macOS machine):

Add to your /etc/nix/nix.conf on the Linux system:

builders = ssh://username@macos-host x86_64-darwin /path/to/remote/nix 2 1 kvm,nixos-test,big-parallel,benchmark
builders-use-substitutes = true
  1. Alternative: Use GitHub Actions macOS runners for CI/CD:
name: Build Darwin Config
on: [push, pull_request]

jobs:
  build-darwin:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cachix/install-nix-action@v27
      - name: Validate darwin config
        run: just check-darwin
      
  build-darwin-native:
    runs-on: macos-latest  
    steps:
      - uses: actions/checkout@v4
      - uses: cachix/install-nix-action@v27
      - name: Build darwin config natively
        run: just build-darwin
  1. Local cross-compilation (current setup):

For development and testing, you can use the cross-compilation support directly:

# Quick validation (recommended for most cases)
just check-darwin

# Full cross-compilation (may be slower without remote builder)
just build-darwin

Performance Tips

  • Use just check-darwin for quick validation during development
  • Set up remote builders for production deployments
  • Use binary caches to avoid rebuilding common packages:
# Add to your nix configuration
nix.settings.substituters = [
  "https://cache.nixos.org/"
  "https://nix-community.cachix.org"
];

Troubleshooting

If you encounter issues with cross-compilation:

  1. Check available builders:

    nix show-config | grep builders
    
  2. Verify cross-compilation support:

    nix-instantiate --eval -E 'builtins.currentSystem'
    
  3. Use verbose output for debugging:

    nix build .#turbine-darwin --verbose
    

Use Cases

CI/CD Validation

In continuous integration, you can validate both NixOS and nix-darwin configurations on Linux runners:

# Example GitHub Actions workflow
- name: Validate NixOS configuration
  run: just build-linux

- name: Validate nix-darwin configuration  
  run: just check-darwin

- name: Cross-compile darwin configuration
  run: just build-darwin

Development Workflow

When developing on Linux but targeting macOS:

  1. Edit configurations in your preferred Linux environment
  2. Validate syntax with just check-darwin
  3. Cross-compile with just build-darwin to catch platform-specific issues
  4. Deploy the configuration on actual macOS hardware when ready

Requirements

  • Nix with flakes enabled
  • Linux system with sufficient disk space for cross-compilation
  • Network access to download dependencies

Troubleshooting

Build Errors

If cross-compilation fails:

  • Check that all dependencies support the target platform
  • Some macOS-specific packages may not cross-compile successfully
  • Consider using remote builders for problematic packages

Performance

Cross-compilation can be resource-intensive:

  • Use nix build --max-jobs auto to utilize all CPU cores
  • Consider using a remote darwin builder for better performance
  • The validation target (turbine-check) is much faster than full builds

Remote Builders

For better performance, you can set up a remote macOS builder:

# In your nix configuration
nix.buildMachines = [{
  hostName = "mac-builder.example.com";
  system = "x86_64-darwin";
  maxJobs = 4;
  speedFactor = 2;
  supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" ];
  mandatoryFeatures = [ ];
}];

This allows Nix to automatically use the remote macOS system for darwin-specific builds.

GitHub Copilot Coding Agent Environment

This repository is configured with a GitHub Copilot coding agent environment that provides seamless access to all essential Nix development tools and commands.

Features

The Copilot agent environment automatically provides:

  • Nix with flakes support - Reliable installation using DeterminateSystems/nix-installer-action
  • Development shell - Access to all tools via nix develop
  • Command runner - just for convenient development commands
  • Code formatting - alejandra Nix formatter
  • Cross-compilation - Build and validate configs across platforms
  • Testing framework - Automated validation and testing
  • Binary caching - Fast builds with magic-nix-cache-action

Available Commands

Core Nix Commands

nix flake check          # Check flake syntax and evaluate all outputs
nix develop             # Enter development shell with all tools
nix build .#<package>   # Build specific packages or configurations

Just Command Shortcuts

just help               # Show all available development commands
just check              # Check flake syntax (alias for nix flake check)
just check-darwin       # Validate nix-darwin config (fast validation)
just build-darwin       # Cross-compile full nix-darwin config from Linux
just build-linux        # Build NixOS VM for testing
just format             # Format Nix files using alejandra
just test               # Run cross-compilation tests
just clean              # Clean build results and artifacts

Environment Setup

The environment uses GitHub Copilot's official setup workflow approach:

  1. Copilot Setup Steps - .github/workflows/copilot-setup-steps.yml follows GitHub's official documentation and uses:

    • DeterminateSystems/nix-installer-action@main for reliable, fast Nix installation
    • DeterminateSystems/magic-nix-cache-action@main for automatic binary caching
    • Proper flakes configuration and validation
  2. Development Shell - The agent enters the Nix development shell defined in flake.nix

  3. Tool Access - All development tools become available (just, alejandra, etc.)

Benefits of GitHub Copilot Setup Approach

  • Official - Follows GitHub's official documentation for Copilot setup steps
  • Simple - Single workflow file instead of multiple configuration files
  • Reliable - Uses proven, well-tested installation methods
  • Speed - Fast installation (~4s on Linux, ~20s on macOS)
  • Caching - Binary cache integration for faster builds
  • Maintenance - Minimal configuration to maintain
  • Compatibility - Works around firewall restrictions

Configuration Files

Primary Configuration

  • .github/workflows/copilot-setup-steps.yml - GitHub Copilot setup workflow following official documentation

Supporting Files

  • flake.nix - Nix flake with development shell definition
  • justfile - Development command shortcuts

The setup provides:

  • Automatic Nix installation - Uses DeterminateSystems actions for reliable setup
  • Development shell access - All tools available via nix develop
  • Flake validation - Ensures configuration syntax is correct

Validation

The copilot-setup-steps.yml workflow automatically validates the environment by:

  • ✅ Installing Nix with flakes support
  • ✅ Checking flake syntax with nix flake check
  • ✅ Entering development shell to verify tools are available

You can manually run the workflow to test the setup:

gh workflow run copilot-setup-steps.yml

Troubleshooting

Common Issues

"nix: command not found"

  • The copilot-setup-steps.yml workflow automatically installs Nix
  • Or manually install: curl -L https://nixos.org/nix/install | sh
  • Source environment: source ~/.nix-profile/etc/profile.d/nix.sh

"experimental features not enabled"

  • The copilot-setup-steps.yml workflow handles this automatically
  • Manual fix: echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf

"just: command not found"

  • Enter dev shell first: nix develop
  • Or run commands via: nix develop -c just <command>

Flake evaluation errors

  • Check syntax: nix flake check --no-build
  • Update inputs: nix flake update

GitHub Actions setup issues

  • Check workflow logs for detailed error messages
  • Ensure DeterminateSystems/nix-installer-action@main is used
  • Verify GitHub token permissions for private repositories
  • Magic Nix Cache provides automatic caching for faster builds

Build failures

  • Clean previous builds: just clean
  • Check available packages: nix flake show

Development Workflow

The typical development workflow with the Copilot agent:

  1. Validate configuration: nix flake check
  2. Make changes to Nix files
  3. Format code: just format
  4. Test changes: just test or specific validation commands
  5. Build configurations: just build-darwin or just build-linux

Cross-Platform Support

The environment supports cross-platform development:

  • Linux: Full support for NixOS configurations and cross-compilation to macOS
  • macOS: Native nix-darwin support with Linux VM building capabilities
  • Validation: Quick config validation without full builds using just check-darwin

Integration with Repository

The Copilot agent environment is fully integrated with this repository's structure:

  • Flake-based: Uses the devShells defined in flake.nix
  • Just integration: All justfile commands are available
  • Cross-compilation: Supports the existing cross-platform workflow
  • Testing: Integrates with existing test scripts

This provides the Copilot agent with full access to all development capabilities of this Nix configuration repository.

Contributing

This page outlines how to contribute to the Nix configuration and documentation.

Development Environment

  1. Install Nix with flakes enabled
  2. Clone the repository
  3. Enter the development environment:
nix develop

Making Changes

Configuration Changes

  1. Make your changes to the appropriate files in hosts/, modules/, or users/
  2. Test your changes:
    just check-darwin  # for nix-darwin configs
    just build-linux   # for NixOS configs
    
  3. Format your code:
    just format
    

Documentation Changes

  1. Edit the markdown files in the docs/ directory
  2. Build and preview the documentation:
    just docs-build
    just docs-serve
    
  3. The documentation site will be automatically deployed when changes are merged to main

Available Commands

Run just help to see all available development commands.