> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/soriphoono/homelab/llms.txt
> Use this file to discover all available pages before exploring further.

# Development Environment

> Setting up the development environment with direnv and nix

This homelab provides a comprehensive development environment using **Nix flakes**, **direnv**, and custom shell hooks. The environment includes all necessary tools for managing NixOS configurations, secrets, and infrastructure.

## Quick Start

If you already have Nix and direnv installed:

<Steps>
  <Step title="Clone the repository">
    ```bash theme={null}
    git clone https://github.com/soriphoono/homelab.git
    cd homelab
    ```
  </Step>

  <Step title="Allow direnv">
    ```bash theme={null}
    direnv allow
    ```

    This activates the development shell automatically when you enter the directory.
  </Step>

  <Step title="Verify tools are available">
    ```bash theme={null}
    which alejandra agenix sops
    ```

    All tools should be in your PATH.
  </Step>
</Steps>

## Prerequisites

### Install Nix

If Nix isn't installed:

```bash theme={null}
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
```

This installs Nix with flakes enabled by default.

### Install direnv

For automatic shell activation:

```bash theme={null}
# On NixOS
nixpkgs.direnv

# On other systems
curl -sfL https://direnv.net/install.sh | bash
```

Add to your shell profile (`~/.bashrc` or `~/.zshrc`):

```bash theme={null}
eval "$(direnv hook bash)"  # or 'zsh', 'fish'
```

## Development Shell Configuration

The `shell.nix` file defines the development environment:

```nix theme={null}
{
  pkgs,
  lib,
  config,
  ...
}:
with pkgs;
  mkShell {
    packages =
      [
        nil
        alejandra
        vulnix

        age
        agenix
        sops
        ssh-to-age
      ]
      ++ lib.optional stdenv.isLinux [
        disko
        nixos-facter
      ];

    shellHook = '''
      ${config.pre-commit.shellHook}
      source ${config.agenix-shell.installationScript}/bin/install-agenix-shell

      # Deploy GitHub Actions from actions.nix
      mkdir -p ./.github/workflows
      ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: file: let
          safeName = lib.removeSuffix ".yml" name;
        in '''
          cp -f ${file} ./.github/workflows/${safeName}.yml
          chmod +w ./.github/workflows/${safeName}.yml
        ''')
        config.githubActions.workflowFiles)}
    ''';
  }
```

## Available Tools

### Nix Development Tools

* **nil**: Nix language server for IDE integration
* **alejandra**: Nix code formatter
* **vulnix**: Security vulnerability scanner for Nix packages

### Secrets Management

* **age**: Encryption tool
* **agenix**: Nix secrets management
* **sops**: Alternative secrets backend
* **ssh-to-age**: Convert SSH keys to age format

### System Tools (Linux only)

* **disko**: Declarative disk partitioning
* **nixos-facter**: Hardware detection and configuration generation

## Direnv Integration

The `.envrc` file automatically activates the Nix shell:

```bash theme={null}
use flake
```

This simple configuration:

* Loads the development shell when entering the directory
* Unloads when leaving the directory
* Watches flake.nix for changes and reloads automatically

### Direnv Commands

```bash theme={null}
# Reload the environment
direnv reload

# Check current status
direnv status

# Manually allow after changes
direnv allow
```

## Shell Hooks

The shell automatically runs several setup tasks:

### 1. Pre-commit Hooks

```bash theme={null}
${config.pre-commit.shellHook}
```

Installs Git pre-commit hooks for:

* Code formatting checks
* Syntax validation
* Security scans

### 2. Agenix Shell Integration

```bash theme={null}
source ${config.agenix-shell.installationScript}/bin/install-agenix-shell
```

Loads encrypted secrets as environment variables. Secrets defined in `secrets.nix` become available:

```bash theme={null}
echo $GITHUB_TOKEN  # Automatically decrypted and loaded
```

### 3. GitHub Actions Deployment

Automatically generates workflow files from `actions.nix`:

```bash theme={null}
ls .github/workflows/
# Shows auto-generated CI workflows
```

This ensures CI configuration stays in sync with your Nix code.

## IDE Integration

### VS Code / VSCodium

Install the Nix extensions:

```json theme={null}
{
  "recommendations": [
    "jnoortheen.nix-ide",
    "mkhl.direnv"
  ]
}
```

The direnv extension automatically activates the environment in the integrated terminal.

### Language Server

The `nil` language server provides:

* Code completion
* Go-to-definition
* Error checking
* Hover documentation

It's automatically available in the shell and will be detected by your IDE.

## Formatting Code

Use alejandra to format Nix files:

```bash theme={null}
# Format a single file
alejandra systems/zephyrus/default.nix

# Format entire directory
alejandra .

# Check without modifying
alejandra --check .
```

## Security Scanning

Check for vulnerable packages:

```bash theme={null}
vulnix -S /run/current-system
```

This scans your system for packages with known CVEs.

## Common Workflows

### Testing Configuration Changes

```bash theme={null}
# Test without activating
nixos-rebuild test --flake .#zephyrus

# Build and activate
nixos-rebuild switch --flake .#zephyrus
```

### Managing Secrets

```bash theme={null}
# Edit a secret
agenix -e secrets/github_token.age

# Verify secrets are loaded in shell
env | grep -i github
```

### Building Installation Media

```bash theme={null}
nix build .#nixosConfigurations.installer.config.system.build.isoImage
```

## Environment Variables

The shell provides access to:

* Decrypted secrets (uppercase names from `secrets.nix`)
* Standard Nix variables (`NIX_PATH`, etc.)
* Custom variables from your configuration

## Troubleshooting

### Direnv not activating

Check if you added the hook to your shell:

```bash theme={null}
type direnv
# Should show: direnv is a function
```

If not, add to `~/.bashrc`:

```bash theme={null}
eval "$(direnv hook bash)"
```

### Tools not in PATH

Ensure direnv is allowed:

```bash theme={null}
direnv allow
```

Check the status:

```bash theme={null}
direnv status
```

### Secrets not loading

Verify your user has access in `secrets.nix`:

```nix theme={null}
userSecrets = {
  github_token = ["yourusername"];
};
```

Ensure your private key is available:

```bash theme={null}
ls ~/.ssh/id_ed25519
ls ~/.config/age/key.txt
```

### Shell hook errors

Reload with debug output:

```bash theme={null}
PS4='+ ' direnv allow 2>&1 | less
```

This shows detailed execution of shell hooks.

## Updating the Environment

When you modify `flake.nix` or `shell.nix`:

1. Direnv automatically detects changes
2. Prompts you to reload with `direnv allow`
3. Rebuilds the environment with new dependencies

Manual update:

```bash theme={null}
nix flake update
direnv reload
```

## Best Practices

<Warning>
  * Always use the dev shell for system operations
  * Don't install tools globally that are in the shell
  * Commit `.envrc` but not `.direnv/` cache
  * Test shell changes before committing
  * Keep secrets out of shell scripts
</Warning>

## Adding New Tools

To add a tool to the development environment:

<Steps>
  <Step title="Edit shell.nix">
    Add the package to the `packages` list:

    ```nix theme={null}
    packages = [
      nil
      alejandra
      your-new-tool  # Add here
    ];
    ```
  </Step>

  <Step title="Reload the environment">
    ```bash theme={null}
    direnv reload
    ```

    The tool is now available in your PATH.
  </Step>

  <Step title="Verify availability">
    ```bash theme={null}
    which your-new-tool
    ```
  </Step>
</Steps>

## Non-NixOS Systems

The dev shell works on any system with Nix installed:

* macOS: Full support except Linux-specific tools
* WSL2: Full Linux functionality
* Other Linux: Works without NixOS-specific tools

Linux-specific tools are automatically excluded on non-Linux systems:

```nix theme={null}
++ lib.optional stdenv.isLinux [
  disko
  nixos-facter
]
```
