# NixOS Configuration Repository

This repository contains my personal NixOS configurations for multiple systems, managed using [Snowfall Lib](https://github.com/snowfallorg/lib) and the Nix Flakes system.

## Overview

This repository provides a centralized, declarative configuration for all my systems, including:

- Desktop PC (AMD)
- NAS server
- Steam Deck
- Intel NUC
- Raspberry Pi 4
- Raspberry Pi 5
- MacBook Pro (NixOS on Apple Silicon)
- MacBook Pro (Darwin/macOS)

## Repository Structure

```
.
├── checks/                # Pre-commit hooks and other checks
├── flake.nix              # Main flake configuration
├── homes/                 # Home-manager configurations for users
│   ├── aarch64-darwin/    # macOS home configurations
│   ├── aarch64-linux/     # ARM Linux home configurations
│   └── x86_64-linux/      # x86 Linux home configurations
├── modules/               # Reusable configuration modules
│   ├── home/              # Home-manager modules
│   └── nixos/             # NixOS system modules
├── overlays/              # Nixpkgs overlays
├── packages/              # Custom package definitions
├── secrets/               # Encrypted secrets (managed with sops-nix)
└── systems/               # System-specific configurations
    ├── aarch64-darwin/    # macOS system configurations
    ├── aarch64-linux/     # ARM Linux system configurations
    └── x86_64-linux/      # x86 Linux system configurations
```

## Key Features

- **Modular Design**: Reusable modules for various system components
- **Multi-System Support**: Configurations for different hardware platforms
- **Home Manager Integration**: User environment management
- **Secret Management**: Encrypted secrets with sops-nix
- **Disk Management**: Declarative disk partitioning with disko
- **State Management**: Persistent state management with impermanence
- **Desktop Environments**: Support for GNOME, Hyprland, and COSMIC
- **Hardware-Specific Optimizations**: Tailored configurations for different hardware

## Key Technologies

- [Nix](https://nixos.org/) and [NixOS](https://nixos.org/)
- [Nix Flakes](https://nixos.wiki/wiki/Flakes)
- [Snowfall Lib](https://github.com/snowfallorg/lib)
- [Home Manager](https://github.com/nix-community/home-manager)
- [sops-nix](https://github.com/Mic92/sops-nix)
- [disko](https://github.com/nix-community/disko)
- [impermanence](https://github.com/nix-community/impermanence)
- [lanzaboote](https://github.com/nix-community/lanzaboote) (Secure Boot)

## Notable System Configurations

### Desktop

A powerful AMD-based desktop with gaming capabilities, featuring:
- AMD CPU and GPU optimizations
- Multiple desktop environment options (GNOME, Hyprland, COSMIC)
- Gaming setup with Steam and related tools

### NAS

A home server with various self-hosted services:
- Media management (Jellyfin, seerr)
- Download automation (Sonarr, Radarr, etc.)
- Document management (Paperless)
- File sharing (Samba, Nextcloud)
- AI services (Ollama)

### Raspberry Pi

Configurations for both Pi 4 and Pi 5:
- Hardware-specific optimizations
- Disk partitioning suitable for ARM devices
- Bluetooth and wireless support

### Steam Deck

Custom NixOS configuration for the Steam Deck:
- Integration with Jovian for Steam Deck compatibility
- Gaming optimizations
- Steam ROM Manager

### MacBook Pro

Configurations for both:
- NixOS on Apple Silicon
- nix-darwin for macOS

## Usage

### Building a System Configuration

```bash
# Build and activate a system configuration
sudo nixos-rebuild switch --flake .#hostname
```

### Building a Home Configuration

```bash
# Build and activate a home configuration
home-manager switch --flake .#username@hostname
```

## Secrets Management

Secrets are managed with [sops-nix](https://github.com/Mic92/sops-nix). Each secret file is encrypted with [age](https://age-encryption.org/), using the SSH host key (`/etc/ssh/ssh_host_ed25519_key`) of each machine as a recipient, so that machine can decrypt its own secrets at boot without any passphrase.

### How age keys work

sops-nix derives an age key from the machine's ed25519 SSH host key automatically. The corresponding age **public key** must be added to `.sops.yaml` before you can encrypt secrets for that machine.

To get the age public key for a machine:

```bash
# On the target machine (or from its host key file):
nix-shell -p ssh-to-age --run \
  'ssh-keyscan localhost 2>/dev/null | ssh-to-age'

# Or directly from the key file:
nix-shell -p ssh-to-age --run \
  'ssh-to-age < /etc/ssh/ssh_host_ed25519_key.pub'
```

### Adding a new machine

1. **Get the age public key** for the new machine using the command above.

2. **Add it to `.sops.yaml`**:
   ```yaml
   keys:
     - &new-machine age1<public-key-here>
   creation_rules:
     - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
       key_groups:
         - age:
             - *new-machine
             # ... existing recipients
   ```

3. **Re-encrypt all secret files** so the new machine becomes a recipient:
   ```bash
   find secrets/ -name '*.yaml' -exec sops updatekeys {} \;
   ```

### Adding a new secret

To add a secret to an existing file:

```bash
# Edit the file interactively (sops decrypts, opens $EDITOR, re-encrypts on save)
sops secrets/nas-secrets.yaml
```

To create a new secrets file:

```bash
sops secrets/mymachine-secrets.yaml
```

The `.sops.yaml` `creation_rules` determine which keys encrypt the file based on its path.

### Generating Nebula VPN certificates

The Nebula module (`mjallen.services.nebula`) expects three secrets per host under a configurable prefix:
- `<prefix>/ca-cert` — the CA certificate (shared across all nodes)
- `<prefix>/host-cert` — this node's signed certificate
- `<prefix>/host-key` — this node's private key

**Step 1 — Create the CA** (once per network, on a trusted machine):

```bash
nebula-cert ca -name "jallen-nebula"
# Produces: ca.crt, ca.key
```

**Step 2 — Sign a certificate for each node**:

```bash
# Lighthouse (assign an overlay IP, e.g. 10.1.1.1)
nebula-cert sign -name "pi5" -ip "10.1.1.1/24" \
  -ca-crt ca.crt -ca-key ca.key \
  -out-crt lighthouse.crt -out-key lighthouse.key

# Regular node (assign a unique overlay IP, e.g. 10.1.1.2)
nebula-cert sign -name "nas" -ip "10.1.1.2/24" \
  -ca-crt ca.crt -ca-key ca.key \
  -out-crt nas.crt -out-key nas.key
```

**Step 3 — Add the secrets to SOPS**:

```bash
# Edit the target host's secrets file
sops secrets/pi5-secrets.yaml
```

Add the certificate contents under the configured prefix (e.g. `pi5/nebula`):

```yaml
pi5:
  nebula:
    ca-cert: |
      <contents of ca.crt>
    lighthouse-cert: |
      <contents of lighthouse.crt>
    lighthouse-key: |
      <contents of lighthouse.key>
```

The key name for the cert/key pair matches the `hostSecretName` option (e.g. `hostSecretName = "lighthouse"` → looks for `lighthouse-cert` / `lighthouse-key`).

**Step 4 — Shred the plaintext key files** once they are in SOPS:

```bash
shred -u ca.key lighthouse.key nas.key
```

> Keep `ca.crt` accessible if you need to sign more nodes later, but store `ca.key` only in SOPS.

## Documentation

Comprehensive documentation is available in the [docs](./docs) directory:

- [Getting Started](./docs/getting-started.md) - Instructions for setting up new systems
- [Architecture](./docs/architecture.md) - Overview of the repository structure
- [System Configurations](./docs/systems/README.md) - Details about each system
- [Home Assistant](./docs/home-assistant/README.md) - Home Assistant setup and automations
- [Custom Modules](./docs/modules/README.md) - Details about reusable configuration modules
- [Troubleshooting](./docs/troubleshooting.md) - Common issues and solutions

## License

This project is licensed under the MIT License - see the LICENSE file for details.
