From fea03b98caee0453d47e1a2018ae72f195aedfaa Mon Sep 17 00:00:00 2001 From: Julian Sutter Date: Mon, 16 Feb 2026 13:25:54 -0800 Subject: [PATCH] Update server configurations and remove outdated documentation --- docs/README-unstable and stable packages.md | 117 -- docs/agents.md | 1136 ------------------- flake.nix | 1 + servers/forgejo.nix | 48 +- servers/nginx.nix | 3 +- 5 files changed, 44 insertions(+), 1261 deletions(-) delete mode 100755 docs/README-unstable and stable packages.md delete mode 100755 docs/agents.md diff --git a/docs/README-unstable and stable packages.md b/docs/README-unstable and stable packages.md deleted file mode 100755 index 402d6f9..0000000 --- a/docs/README-unstable and stable packages.md +++ /dev/null @@ -1,117 +0,0 @@ -# Hybrid Package Management: Stable + Unstable - -This NixOS configuration uses a hybrid approach where the system runs on the stable NixOS 24.05 branch but can selectively use packages from the unstable branch when needed. - -## How It Works - -The `flake.nix` includes both stable and unstable nixpkgs inputs: - -```nix -inputs = { - nixpkgs.url = "nixpkgs/nixos-24.05"; # Stable base - nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; # Unstable packages - # ... other inputs -}; -``` - -The unstable packages are made available to all system configurations via `specialArgs`: - -```nix -nixosConfigurations = { - framework = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - specialArgs = { - pkgs-unstable = import nixpkgs-unstable { - system = "x86_64-linux"; - config.allowUnfree = true; - }; - }; - modules = [ /* ... */ ]; - }; -}; -``` - -## Using Unstable Packages - -### In System Configuration Files - -To use an unstable package in any `.nix` configuration file: - -1. **Add `pkgs-unstable` to the function parameters:** - ```nix - { config, pkgs, pkgs-unstable, ... }: - ``` - -2. **Use the unstable package:** - ```nix - environment.systemPackages = with pkgs; [ - # Stable packages - firefox - git - - # Unstable packages - pkgs-unstable.windsurf - pkgs-unstable.some-other-package - ]; - ``` - -### Example: Current Usage - -See `desktop/dev.nix` for a working example: - -```nix -{ config, pkgs, pkgs-unstable, ... }: - -{ - environment.systemPackages = with pkgs; [ - # Stable packages - nodejs - rpi-imager - - # Unstable packages - pkgs-unstable.windsurf # Use windsurf from unstable - ]; -} -``` - -## When to Use Unstable Packages - -Use unstable packages when: -- A package is not available in the stable branch -- You need a newer version with specific features or bug fixes -- You're developing with cutting-edge tools - -## Benefits of This Approach - -1. **System Stability**: Core system components use stable, well-tested packages -2. **Package Availability**: Access to the latest packages when needed -3. **Selective Updates**: Choose which packages to get from unstable -4. **Easy Maintenance**: Clear separation between stable and unstable dependencies - -## Adding New Unstable Packages - -To add a new unstable package: - -1. Find the configuration file where you want to add the package -2. Ensure the file accepts `pkgs-unstable` parameter -3. Add `pkgs-unstable.package-name` to the appropriate list -4. Test with `nixos-rebuild dry-run --flake .#framework` -5. Apply with `nixos-rebuild switch --flake .#framework` - -## Updating Packages - -- **Stable packages**: Updated when you update the flake lock -- **Unstable packages**: Updated when you run `nix flake update` - -To update only unstable packages: -```bash -nix flake lock --update-input nixpkgs-unstable -``` - -## Current Unstable Packages in Use - -- `windsurf` - Modern code editor (in `desktop/dev.nix`) - ---- - -This hybrid approach gives you the stability of NixOS stable with the flexibility to use cutting-edge packages when needed. diff --git a/docs/agents.md b/docs/agents.md deleted file mode 100755 index d599dcc..0000000 --- a/docs/agents.md +++ /dev/null @@ -1,1136 +0,0 @@ -# NixOS Configuration Repository - AI Agent Guide - -This guide provides everything you need to know to work efficiently with this NixOS configuration repository. Keep this file handy when making changes. - -## Repository Overview - -This repository manages NixOS configurations for multiple systems using flakes and Home Manager. All systems are defined declaratively in Nix expressions. - -### Managed Systems - -| Hostname | Type | Hardware | Special Notes | -|----------|------|----------|---------------| -| `framework` | Desktop/Laptop | Framework AMD AI 300 series | User: jsutter, Uses nixos-hardware module | -| `aurora` | Desktop | Custom | Users: jsutter, isutter, aksutter | -| `labrizor` | Desktop | Custom | User: jsutter | -| `skip01` | Server | Custom | Headless, Docker support | -| `warp` | Server | Custom | Minimal headless configuration | - -### Core Technologies - -- **NixOS**: 25.11 (stable channel) -- **Nixpkgs Unstable**: For packages requiring latest versions -- **Home Manager**: Release 25.11 -- **Plasma Manager**: KDE Plasma configuration management -- **Flakes**: For reproducible, declarative system definitions -- **App Flakes**: Standalone flakes for server applications (Immich, Octofriend, etc.) - -## Project Structure - -``` -nixos/ -├── appflakes/ # Standalone flake inputs for server applications -│ ├── immich/ # Self-hosted photo/video backup (Docker Compose) -│ └── octofriend/ # CLI coding assistant -├── desktop/ # Desktop environment configurations -│ ├── plasma.nix # KDE Plasma + Plasma Manager -│ ├── dev.nix # Development tools and languages -│ ├── office.nix # Office applications -│ ├── gaming.nix # Games and gaming platforms -│ ├── media.nix # Audio/video software -│ ├── virtualization.nix # VMs and containers -│ ├── tailscale.nix # VPN configuration -│ ├── 2dprinting.nix # Printer setup -│ ├── 3dprinting.nix # 3D printer tools -│ ├── dnm.nix # Framework-specific config -│ └── stp-elc-udmshare.nix # Specific mount/share config -├── docs/ # Documentation -│ └── agents.md # This file -├── servers/ # Server service modules -│ ├── common.nix # Common server settings (Docker enablement) -│ ├── forgejo.nix # Forgejo Git server module -│ └── hugo.nix # Hugo web server module (Docker compose) -├── systems/ # Hardware-specific configurations -│ ├── common.nix # Shared system settings (bootloader, nix config, etc.) -│ ├── framework.nix # Framework laptop hardware config -│ ├── aurora.nix # Aurora desktop hardware config -│ ├── labrizor.nix # Labrizor desktop hardware config -│ ├── skip01.nix # Skip01 server config -│ └── warp.nix # Warp server config -├── users/ # User configurations with Home Manager -│ ├── common-home.nix # Shared user packages and settings -│ ├── jsutter.nix # Primary user configuration -│ ├── isutter.nix # Secondary user configuration -│ └── aksutter.nix # Secondary user configuration -└── flake.nix # Top-level flake definition -``` - -### App Flakes Architecture - - -The `appflakes/` directory contains standalone flakes for server applications. These are self-contained, reusable flake definitions that can be used independently or integrated into NixOS configurations. - -**Current App Flakes:** -- `immich/`: Self-hosted photo and video backup solution (Docker Compose deployment) -- `octofriend/`: CLI coding assistant packaged for Nix/NixOS - -**App Flake Structure:** -```nix -{ - inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - flake-utils.url = "github:numtide/flake-utils"; - # Additional inputs as needed - }; - - outputs = { self, nixpkgs, flake-utils, ... }: - { - # NixOS module (if applicable) - nixosModules.app-name = nixosModule; - - # Package definition - packages = flake-utils.lib.eachDefaultSystem (system: { ... }); - - # App entry (if CLI tool) - apps.default = ...; - }; -} -``` - -**Using App Flakes:** - -1. **As a local input in main flake.nix:** - ```nix - inputs = { - immich = { url = "path:./appflakes/immich"; }; - }; - - outputs = { self, nixpkgs, immich, ... }: { - nixosConfigurations.server = nixpkgs.lib.nixosSystem { - modules = [ - immich.nixosModules.immich-docker - ./systems/server.nix - ]; - }; - }; - ``` - -2. **Directly on a system:** - ```bash - # Use app flake package on any system - nix run .#appflakes/octofriend - ``` - -### Server Service Modules - -The `servers/` directory contains NixOS modules for server-specific services. These differ from appflakes in that they are modules designed to be included in NixOS configurations rather than standalone flakes. - -**Server Module Pattern:** - -1. **Define options module-wide:** - ```nix - { config, pkgs, lib, ... }: - let - cfg = config.services.service-name; - in { - options.services.service-name = { - enable = mkEnableOption "Service description"; - - domain = mkOption { - type = types.str; - example = "service.example.com"; - description = "Domain name for the service"; - }; - - # Additional options... - }; - } - ``` - -2. **Configure service only if enabled:** - ```nix - config = mkIf cfg.enable { - # Service dependencies (PostgreSQL, Nginx, etc.) - - # Main service configuration - services.service-name = { - enable = true; - settings = { ... }; - }; - - # Reverse proxy configuration (Nginx) - services.nginx.virtualHosts.${cfg.domain} = { ... }; - - # Firewall rules - networking.firewall.allowedTCPPorts = [ ... ]; - - # Backup systemd services - systemd.services.service-name-backup = { ... }; - }; - ``` - -**Common Server Module Elements:** - -- **Database backing:** PostgreSQL (`services.postgresql`) -- **Reverse proxy:** Nginx with SSL/TLS (`services.nginx`) -- **Firewall:** Open required ports (`networking.firewall`) -- **Backups:** Systemd timers for automated backups -- **Logging:** Centralized logging configuration -- **Monitoring:** Optional Prometheus/metrics endpoints -- **Security:** Hardening options, secret management - -**Creating a New Server Module:** - -1. Create `servers/.nix` -2. Follow the standard module pattern with options -3. Use `mkIf cfg.enable` for conditional configuration -4. Include backup systemd service with timer -5. Add firewall rules if service is network-accessible -6. Document required secrets/password files -7. Test on a headless system first (`skip01` or `warp`) - -**Server Module Organization:** - -- `servers/common.nix`: Shared server infrastructure (Docker, etc.) -- `servers/forgejo.nix`: Forgejo Git server complete configuration -- `servers/hugo.nix`: Hugo static site server with Docker compose -- Additional server modules can be added as needed - -**Headless System Configuration:** - -Headless systems (`skip01`, `warp`) follow simplified patterns: - -```nix -{ - networking.hostName = "hostname"; - - # Minimal hardware configuration - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" ]; - boot.kernelModules = [ "kvm-intel" ]; - - # Enable container support - virtualisation.docker.enable = true; - - # SSH for remote administration - services.openssh = { - enable = true; - settings.PasswordAuthentication = false; - }; - - # Disable desktop services - services.xserver.enable = false; -} -``` - -**Deploying Server Service Modules:** - -1. Add server module to system configuration: - ```nix - in { - nixosConfigurations.skip01 = nixpkgs.lib.nixosSystem { - modules = [ - ./systems/common.nix - ./servers/forgejo.nix # Add server module - ./systems/skip01.nix - { services.forgejo.enable = true; } - ]; - }; - } - ``` - -2. Configure service options: - ```nix - { - services.forgejo = { - domain = "git.example.com"; - database.passwordFile = "/run/keys/forgejo-db"; - }; - } - ``` - -3. Test on server system: - ```bash - nixos-rebuild dry-run --flake .#skip01 - sudo nixos-rebuild switch --flake .#skip01 - ``` - -**Secrets Management for Servers:** - -Server services often require secrets (database passwords, API keys, OAuth secrets). Store these securely: - -- Use `/run/keys/` for runtime secrets (systemd credentials) -- Use environment files with restricted permissions -- Never commit secrets to the repository -- Example: `passwordFile` options that point to secure paths - -**Backup Strategy for Server Services:** - -Server modules include automated backup services: - -```nix -systemd.services.service-backup = { - description = "Service backup service"; - serviceConfig = { - Type = "oneshot"; - User = "service-user"; - ExecStart = "${pkgs.service}/bin/service backup"; - }; -}; - -systemd.timers.service-backup = { - wantedBy = [ "timers.target" ]; - timerConfig = { - OnCalendar = "daily"; - Persistent = true; - }; -}; -``` - -**Testing Server Modules:** - -Always test server modules on headless systems before deploying to production: - -```bash -# Check flake outputs -nix flake show - -# Dry-run for server system -sudo nixos-rebuild dry-run --flake .#server-hostname - -# Build without switching -sudo nixos-rebuild build --flake .#server-hostname - -# Switch to new configuration -sudo nixos-rebuild switch --flake .#server-hostname -``` - -**Monitoring and Maintenance:** - -- Check service status: `systemctl status service-name` -- View logs: `journalctl -u service-name` -- Monitor backup timers: `systemctl list-timers` -- Verify firewall rules: `nft list ruleset` -- Check Docker containers: `docker ps` (if using Docker-based services) - -``` - -## Core Principles - -### 1. Declarative Configuration -- All system state must be defined in Nix expressions -- Never use imperative commands for permanent changes -- Every configuration change should be reproducible - -### 2. Modular Architecture -- Maintain separation between hardware, software, and user configurations -- Use existing modules before creating new ones -- Follow the established directory structure strictly - -### 3. Security First -- Never expose sensitive data (passwords, private keys, API tokens) -- Use proper user privilege separation -- Validate all external inputs and configurations - -## Configuration Patterns - -### Function Parameters - -Always include the appropriate parameters based on what the module needs: - -```nix -# For modules using unstable packages -{ config, pkgs, pkgs-unstable, lib, ... }: - -# For stable-only modules -{ config, pkgs, lib, ... }: - -# For modules using special args from flake -{ config, pkgs, pkgs-unstable, lib, octofriend, ... }: - -# For Home Manager modules -{ pkgs, ... }: -``` - -### System Configuration Pattern - -```nix -{ config, lib, pkgs, ... }: -{ - # Always include hostname first - networking.hostName = "system-name"; - - # Hardware configuration - fileSystems."/" = { - device = "/dev/disk/by-partlabel/primary"; - fsType = "ext4"; - }; - fileSystems."/boot" = { - device = "/dev/disk/by-partlabel/ESP"; - fsType = "vfat"; - }; - - # System-specific settings - # Group related configurations together -} -``` - -### User Configuration Pattern - -```nix -{ config, pkgs, pkgs-unstable, home-manager, ... }: -{ - # System user definition - users.users.username = { - shell = pkgs.zsh; - isNormalUser = true; - description = "User Description"; - extraGroups = [ "networkmanager" "wheel" ]; # Only essential groups - }; - - # Home Manager configuration - home-manager.users.username = { - home.username = "username"; - home.homeDirectory = "/home/username"; - home.stateVersion = "25.05"; - - # User configurations - }; -} -``` - -### Desktop Module Pattern - -```nix -{ config, pkgs, pkgs-unstable, lib, ... }: -{ - # System packages for this category - environment.systemPackages = with pkgs; [ - package1 - package2 - ]; - - # Configuration options - services.service-name.enable = true; - - # Home Manager integrations (if applicable) -} -``` - -## Package Management Guidelines - -### Stable vs Unstable Packages - -```nix -# PREFERRED: Use stable packages by default -environment.systemPackages = with pkgs; [ - firefox - git - vim -]; - -# ACCEPTABLE: Use unstable when necessary -# Add comments explaining why unstable is needed -environment.systemPackages = with pkgs; [ - firefox - pkgs-unstable.windsurf # Latest features not in stable -]; -``` - -### Package Selection Criteria - -1. **Use stable unless**: Package doesn't exist OR needs newer version -2. **Document reasons**: Always comment why unstable is used -3. **Test thoroughly**: Unstable packages may have issues -4. **Review regularly**: Check if unstable packages can move to stable - -### Common Package Sets by Module - -- `dev.nix`: IDEs, languages, development tools -- `office.nix`: LibreOffice, productivity apps -- `gaming.nix`: Steam, Lutris, game launchers -- `media.nix`: Audio/video players, editors -- `virtualization.nix`: VirtualBox, Docker, other virt tools -- `plasma.nix`: KDE Plasma applications and themes - -## System-Specific Information - -### Framework (`framework.nix`) -- Uses `nixos-hardware` module: `framework-amd-ai-300-series` -- Additional modules: `dnm.nix`, `stp-elc-udmshare.nix` -- Single user: jsutter - -### Aurora (`aurora.nix`) -- Multi-user system: jsutter, isutter, aksutter -- Additional modules: `3dprinting.nix`, `2dprinting.nix` -- No specialized hardware module - -### Labrizor (`labrizor.nix`) -- Single user: jsutter -- Additional modules: `3dprinting.nix` -- No specialized hardware module - -### Common Settings (`systems/common.nix`) -Includes: -- Hardware firmware and fwupd -- NetworkManager with VPN plugins (OpenVPN, OpenConnect) -- Systemd-boot EFI bootloader -- Latest kernel -- Nix settings with experimental features (flakes, nix-command) -- Weekly garbage collection (7-day retention) -- Auto-optimized Nix store -- Trusted users: root, jsutter -- Timezone: America/Los_Angeles -- Locale: en_US.UTF-8 -- PipeWire audio stack -- SSH service enabled -- Zsh shell enabled -- Passwordless sudo for wheel group -- Flatpak enabled -- USB plugdev group rules - -### Server Common Settings (`servers/common.nix`) -Includes: -- Docker containerization enabled for server services - -## File Naming Conventions - -- Use lowercase with hyphens: `vpn-config.nix`, `development-tools.nix` -- System configurations must match hostname: `framework.nix`, `aurora.nix` -- User configurations must match username: `jsutter.nix`, `isutter.nix` -- Common configurations: `common.nix`, `common-home.nix` - -## Code Style - -- Use 2-space indentation -- Align attribute lists consistently -- Add comments for non-obvious configurations -- Group related configurations together - -Example: -```nix -{ - # Audio configuration - sound.enable = true; - hardware.pulseaudio.enable = false; - security.rtkit.enable = true; - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - }; -} -``` - -Server module example: -```nix -{ config, pkgs, lib, ... }: - -let - cfg = config.services.example-service; -in { - options.services.example-service = { - enable = mkEnableOption "Example service"; - domain = mkOption { - type = types.str; - example = "service.example.com"; - description = "Domain name for the service"; - }; - port = mkOption { - type = types.port; - default = 8080; - description = "Service port number"; - }; - }; - - config = mkIf cfg.enable { - systemd.services.example-service = { - description = "Example service"; - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - ExecStart = "${pkgs.example}/bin/example --port ${toString cfg.port}"; - Restart = "on-failure"; - }; - }; - - services.nginx.virtualHosts.${cfg.domain} = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://localhost:${toString cfg.port}"; - }; - - networking.firewall.allowedTCPPorts = [ 80 443 ]; - }; -} -``` - -## Common Workflows - -### Adding a New Package - -1. Determine appropriate module (desktop/, systems/, users/) -2. Check if package exists in stable channel: `nix search nixpkgs package-name` -3. Use unstable only if necessary with documentation -4. Add to appropriate environment.systemPackages or home.packages -5. Run dry-run before applying -6. Update relevant documentation if it affects multiple systems - -Example: -```nix -# In desktop/dev.nix -environment.systemPackages = with pkgs; [ - # Added for Python development - python312 - python312Packages.pip - pkgs-unstable.windsurf # Latest AI features not in stable -]; -``` - -### Creating a New Desktop Module - -1. Create file in `desktop/` with descriptive name -2. Include proper function parameters -3. Add packages, services, and configurations -4. Test module independently -5. Add to `commonDesktopModules` in flake.nix if for all desktops -6. Add to specific system in flake.nix if selective - -### Adding a New System - -1. Create `systems/.nix` following existing patterns -2. Set `networking.hostName = ""` -3. Configure hardware (fileSystems, hardware-specific settings) -4. Add system entry to `flake.nix`: -```nix -new-system = mkSystem { - modules = commonDesktopModules ++ [ - ./systems/new-system.nix - ./users/username.nix - ]; -}; -``` -5. Test with dry-run and build - -### Modifying User Configuration - -1. Edit appropriate file in `users/` -2. For shared changes: modify `common-home.nix` -3. For user-specific changes: modify `.nix` -4. Home Manager configuration goes in `home-manager.users.` - -### Creating a New Server Module - -1. Create `servers/.nix` following the module pattern -2. Define options using `mkOption` for all configurable parameters -3. Use `mkIf cfg.enable` to wrap all configuration -4. Include database, reverse proxy (Nginx), and firewall configuration -5. Add automated backup systemd service with timer -6. Document required secrets (passwordFile paths, API keys) -7. Test on headless system first - -### Creating a New App Flake - -1. Create `appflakes//` directory with `flake.nix` -2. Include `nixpkgs` and `flake-utils` as inputs -3. Define outputs with `packages` (and optionally `nixosModules`, `apps`) -4. Use `flake-utils.lib.eachDefaultSystem` for multi-system support -5. Add local input reference in main `flake.nix` if needed -6. Test build with `nix build .#appflakes/` - -### Adding a Server Service to a System - -1. Choose target system (typically headless: `skip01` or `warp`) -2. Add server module to system's modules list in `flake.nix`: -```nix -nixosConfigurations.server = mkSystem { - modules = [ - ./systems/common.nix - ./servers/common.nix - ./servers/service-name.nix - ./systems/server.nix - { services.service-name.enable = true; } - ]; -}; -``` -3. Configure service-specific options in host config or separate file -4. Set up secret files (e.g., `/run/keys/service-db`) -5. Run dry-run and test before switching - -## Testing and Validation - -### Pre-commit Testing - -ALWAYS run these commands before submitting changes: - -```bash -# 1. Syntax check -nix flake check - -# 2. Dry run for affected systems (run for ALL affected) -sudo nixos-rebuild dry-run --flake .#framework -sudo nixos-rebuild dry-run --flake .#aurora -sudo nixos-rebuild dry-run --flake .#labrizor - -# 3. Check flake outputs -nix flake show - -# For server configurations, also test: -sudo nixos-rebuild dry-run --flake .#skip01 -sudo nixos-rebuild dry-run --flake .#warp -``` - -### Applying Changes - -```bash -# Build and switch (active system only) -sudo nixos-rebuild switch --flake .#hostname - -# Build only (test without switching) -sudo nixos-rebuild build --flake .#hostname - -# Build and boot (adds to GRUB menu) -sudo nixos-rebuild boot --flake .#hostname -``` - -### Build Verification - -- Test on at least one system before merging -- Verify all services start correctly: `systemctl status` -- Check for package conflicts -- Validate hardware-specific configurations -- For server modules: verify Docker containers run, check systemd timers, validate firewall rules - -### Updating Packages - -```bash -# Update flake inputs -nix flake update - -# Check what changed -nix flake diff - -# Rebuild after update -sudo nixos-rebuild switch --flake .#hostname -``` - -## Security Rules - -### Sensitive Data Handling - -- **NEVER** commit plaintext passwords -- **NEVER** commit private SSH keys -- **NEVER** commit API tokens or secrets -- **ALWAYS** use hashed passwords: `hashedPassword = "$6$..."` -- **CONSIDER** using sops-nix for advanced secret management - -### User Privilege Management - -```nix -# GOOD: Minimal necessary groups -extraGroups = [ "networkmanager" "wheel" "audio" ]; - -# BAD: Over-privileged users -extraGroups = [ "networkmanager" "wheel" "audio" "video" "input" "disk" "lp" "scanner" ]; -``` - -### SSH Key Management - -```nix -# GOOD: Use authorizedKeys for SSH access -openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBNVUh+RrcOSMRV6qysnsdPs5AyK8dSm4QhhnwgpikyI user@domain" -]; - -# FORBIDDEN: Never include private keys -``` - -## Rollback Procedures - -### Configuration Rollback - -```bash -# List available generations -sudo nix-env --list-generations --profile /nix/var/nix/profiles/system - -# Rollback to previous working generation -sudo nixos-rebuild switch --profile-name generation-123 - -# Or use rollback shortcut -sudo nixos-rebuild switch --rollback - -# Rollback specific system -sudo nixos-rebuild switch --rollback --flake .#hostname -``` - -### Emergency System Recovery - -If a system fails to boot after changes: - -1. Boot from installation media -2. Mount root filesystem: `mount /dev/disk/by-partlabel/primary /mnt` -3. Roll back: `sudo nixos-rebuild switch --rollback --install-bootloader /mnt` -4. Identify and fix configuration issues -5. Test before rebooting - -### Booting into Previous Generations - -At boot time (GRUB menu): -1. Hold Shift during boot to see GRUB menu -2. Select "Advanced options for NixOS" -3. Choose previous generation - -## NixOS Installation (New System) - -```bash -# Partition disk (example for NVMe) -sudo parted /dev/nvme0n1 -- mklabel gpt -sudo parted /dev/nvme0n1 -- mkpart primary ext4 512MB 100% -sudo parted /dev/nvme0n1 -- mkpart ESP fat32 1MB 512MB -sudo parted /dev/nvme0n1 -- set 2 esp on -sudo mkfs.ext4 /dev/disk/by-partlabel/primary -sudo mkfs.vfat /dev/disk/by-partlabel/ESP - -# Mount filesystems -sudo mount -o rw /dev/disk/by-partlabel/primary /mnt/ -sudo mkdir /mnt/boot -sudo mount -o rw /dev/disk/by-partlabel/ESP /mnt/boot/ -sudo mkdir /mnt/root -sudo git clone https://git.symbiotrip.com/jsutter/nixos /mnt/root/nixos - -# Install (no root password, impure for git access) -sudo -i -cd /mnt/root/nixos -nixos-install --flake .# --no-root-password --impure - -# Set password after install -nixos-enter --root '/mnt' -passwd jsutter -``` - -## Module Dependencies - -### Known Dependencies - -- `plasma.nix` depends on: `common.nix`, `home-manager` -- `dev.nix` is included in all desktop systems -- All desktop systems include: `common.nix`, `plasma.nix`, `dev.nix`, `office.nix`, `gaming.nix`, `media.nix`, `virtualization.nix`, `tailscale.nix` -- User files include Home Manager configuration - -### Avoiding Circular Dependencies - -- Don't import system modules into user modules -- Use `common.nix` for shared system settings only -- Use `common-home.nix` for shared user settings only -- Hardware-specific modules should not depend on desktop modules - -## Emergency Tools - -### Useful Commands - -```bash -# Check what packages provide a command -nix-locate bin/commandname - -# Search for packages -nix search nixpkgs package-name -nix search nixpkgs-unstable package-name - -# Check Nix store size -du -sh /nix/store - -# Garbage collect manually -sudo nix-collect-garbage -d - -# Profile Nix operations -sudo nix-env --profile /nix/var/nix/profiles/system --list-generations - -# Check hardware info -lshw -lspci -lsusb -lsblk -hwinfo -``` - -## Troubleshooting Common Issues - -### Build Errors - -1. Read the error message carefully -2. Check for syntax errors in the modified file -3. Verify all attributes are closed properly -4. Run `nix flake check` to validate syntax - -### Service Failures - -```bash -# Check service status -systemctl status service-name - -# View service logs -journalctl -u service-name -e - -# Restart service -systemctl restart service-name -``` - -### Package Conflicts - -- If two modules try to enable the same service with different settings -- Use `lib.mkForce` to override settings if necessary -- Or consolidate the configuration in one place - -## Flakes Reference - -### Input Structure - -```nix -inputs = { - nixpkgs.url = "nixpkgs/nixos-25.11"; # Stable - nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; # Unstable - nixos-hardware.url = "github:NixOS/nixos-hardware/master"; - home-manager.url = "github:nix-community/home-manager/release-25.11"; - plasma-manager.url = "github:nix-community/plasma-manager"; - octofriend.url = "path:./appflakes/octofriend"; # Local flake -}; -``` - -### Special Args - -Available in all modules: -- `pkgs`: Stable Nix packages -- `pkgs-unstable`: Unstable Nix packages -- `octofriend`: Local octofriend flake - -### Output Structure - -```nix -outputs = { - self, # Self reference - nixpkgs, # Stable packages - nixpkgs-unstable, # Unstable packages - nixos-hardware, # Hardware modules - home-manager, # Home Manager - plasma-manager, # Plasma Manager - octofriend # Custom app flake -}: { - nixosConfigurations = { - framework = { ... }; # Define each system - aurora = { ... }; - labrizor = { ... }; - }; -}; -``` - -## Documentation Requirements - -### Code Comments - -- Explain non-obvious configurations -- Document reasons for unstable package usage -- Note hardware-specific requirements -- Reference external dependencies - -Example: -```nix -# Use unstable neovim for LuaLS integration not in stable -pkgs-unstable.neovim # Latest features needed for Lua development -``` - -### Commit Messages - -Use clear, descriptive commit messages: -- Reference affected systems/modules -- Explain reasoning for significant changes -- Include testing steps when applicable - -Example: -``` -feat(framework): Add 3D printing support for Prusa printers - -- Added 3dprinting.nix module with PrusaSlicer and Cura -- Installed USB rules for Prusa devices -- Added to framework system configuration - -Tested: Prusa MK4 recognized and can start print via USB -``` - -## Performance Considerations - -### Nix Settings - -The repository uses optimized Nix settings: -- `auto-optimise-store`: Auto-optimizes the Nix store -- `keep-outputs = true`: Keeps build outputs -- `keep-derivations = true`: Keeps derivations for evaluation -- `download-buffer-size`: 512MB for faster downloads - -### Garbage Collection - -Automatically runs weekly: -- Deletes builds older than 7 days -- Run manually: `sudo nix-collect-garbage -d` - -### Build Caching - -Consider using `nix-serve` or Cachix for: -- Faster rebuilds -- Shared cache across systems -- CI/CD integration - -## Resources - -### Official Documentation -- [NixOS Manual](https://nixos.org/manual/nixos/stable/) -- [Home Manager Manual](https://nix-community.github.io/home-manager/) -- [Nix Pills](https://nixos.org/guides/nix-pills/) -- [NixOS Wiki](https://nixos.wiki/) - -### Community Resources -- [NixOS Discourse](https://discourse.nixos.org/) -- [NixOS subreddit](https://reddit.com/r/NixOS/) -- [NixOS Matrix](https://matrix.to/#/#nixos:nixos.org) - -### Package Search -- [search.nixos.org](https://search.nixos.org/packages) -- Command line: `nix search nixpkgs package-name` - -## Quick Reference - -### Essential Commands - -| Action | Command | -|--------|---------| -| Update system | `sudo nixos-rebuild switch --flake .#hostname` | -| Dry run | `sudo nixos-rebuild dry-run --flake .#hostname` | -| Rollback | `sudo nixos-rebuild switch --rollback` | -| Update flakes | `nix flake update` | -| Check flakes | `nix flake check` | -| Search packages | `nix search nixpkgs name` | -| Garbage collect | `sudo nix-collect-garbage -d` | - -**Server-Specific Commands:** -| Action | Command | -|--------|---------| -| Check service status | `systemctl status service-name` | -| View service logs | `journalctl -u service-name` | -| List active timers | `systemctl list-timers` | -| Check Docker containers | `docker ps` | -| View Docker logs | `docker logs container-name` | -| Restart docker-compose stack | `docker-compose -f /etc/compose/service/docker-compose.yml restart` | -| Check firewall rules | `nft list ruleset` | -| Verify SSL certificates | `certbot certificates` | -| List backup directory | `ls -lh /var/backups/service-name` | -| Run manual backup | `systemctl start service-backup` | - -### File Paths Reference - -| Type | Location | -|------|----------| -| Common system settings | `systems/common.nix` | -| System hardware config | `systems/.nix` | -| Common user settings | `users/common-home.nix` | -| User config | `users/.nix` | -| Desktop apps | `desktop/.nix` | -| Server common settings | `servers/common.nix` | -| Server service modules | `servers/.nix` | -| App flakes | `appflakes//flake.nix` | -| Docker compose configs | `/etc/compose//docker-compose.yml` | -| Backup directories | `/var/backups//` | -| Runtime secrets | `/run/keys/` | -| Flake definition | `flake.nix` | - -## Maintenance & Changelog - -This section tracks changes to the repository structure and when this document was updated. Keep this in sync! - -### Current Repository State -- **Last Updated**: February 2026 -- **NixOS Version**: 25.11 -- **Managed Systems**: 5 (framework, aurora, labrizor, skip01, warp) -- **Users**: jsutter (primary), isutter, aksutter -- **App Flakes**: 2 (immich, octofriend) -- **Server Modules**: 3 (common, forgejo, hugo) - -### Repository Change Log - -| Date | Change | Updated Sections | -|------|--------|------------------| -| 2026-02 - Created | Created `agents.md` with comprehensive guide | All sections | -| 2026-02 - Removed | Removed .clinerules file, consolidated into agents.md | Maintenance section | -| 2026-02 - Cleanup | Removed unused gnome.nix module, common-headless.nix; removed allowBroken setting | System structure | -| 2026-02 - Cleanup | Removed commented packages across multiple files; fixed trailing whitespace | Code quality | -| 2026-02 - Cleanup | Removed .clinerules file; deleted gnome.nix (unused); common-headless.nix (duplicated) | File structure | -| 2026-02 - Improvement | Added result, *.swp, *~ to .gitignore | Maintenance | -| 2026-02 - Added | Added appflakes directory (immich, octofriend) and servers directory (forgejo, hugo) | Project structure, all server sections | -| 2026-02 - Documentation | Added comprehensive server module patterns, appflake architecture, server workflows, server-specific commands | Repository Overview, Workflows, Quick Reference | - -### When to Update This Document - -Update `agents.md` when any of the following occur: - -- **Structural Changes**: - - New system added to `flake.nix` - - New user configuration added - - New or renamed desktop module - - Directory restructuring - - New app flake added to `appflakes/` - - New server module added to `servers/` - -- **Configuration Changes**: - - New shared settings in `systems/common.nix` - - New shared user settings in `users/common-home.nix` - - New shared settings in `servers/common.nix` - - Changes to module pattern or function parameters - - New package categories or organizational changes - - Changes to server module standard pattern - - Updates to headless system configuration patterns - -- **Technology Updates**: - - NixOS version changes - - Channel updates (stable/unstable) - - New major inputs added to flake - - Significant Nix configuration changes - - New app flake with different architecture - - Changes to Docker/compose deployment patterns - -- **Procedure Changes**: - - New testing workflow - - Changed emergency procedures - - Updated installation steps - - New common commands - - New server deployment or backup procedures - - Changes to secrets management approach for servers - -- **Server Changes**: - - New server service added to production - - Changes to backup strategy for server services - - Updates to monitoring or logging for servers - - New headless system deployed or configured - - Security hardening changes for server modules - -### Update Template - -When making changes, add an entry using this format: - -``` -| YYYY-MM - One-line description | More detail if needed | Section(s) affected | -| --- | --- | --- | -``` - -### Version History for agents.md - -- **v1.1** (2026-02): Added comprehensive server module patterns, appflake architecture, server workflows, and server-specific commands -- **v1.0** (2025-01): Initial creation with full repository documentation - -## Getting Help - -When unsure about something: -1. Check this documentation first -2. Review existing similar configurations -3. Search NixOS manual and wiki -4. Test changes with dry-run before applying - ---- - -**Remember**: This repository values declarative, reproducible configurations. When in doubt, prefer explicit configuration over implicit behavior. Test thoroughly, document changes, and never skip the dry-run step! \ No newline at end of file diff --git a/flake.nix b/flake.nix index 280dde0..6adf9b4 100755 --- a/flake.nix +++ b/flake.nix @@ -85,6 +85,7 @@ ./systems/common.nix ./users/jsutter.nix ./systems/warp.nix + ./servers/nginx.nix ./servers/forgejo.nix ]; }; diff --git a/servers/forgejo.nix b/servers/forgejo.nix index e8bd8f5..24c485a 100755 --- a/servers/forgejo.nix +++ b/servers/forgejo.nix @@ -12,25 +12,50 @@ let adminUser = "jsutter"; adminEmail = "jsutter@symbiotrip.com"; - in { - security.acme.certs.${fqdn}.group = config.services.nginx.group; + # DNS-based ACME certificate configuration + # Uses defaults (dnsProvider, email, credentials) from nginx.nix + security.acme.certs.${fqdn} = { + # Group needs to be set so nginx can read the certificate + group = config.services.nginx.group; + + # Inherit DNS challenge configuration from security.acme.defaults (set in nginx.nix) + # This includes: dnsProvider = "cloudflare", environmentFile with Cloudflare token, email + + # Explicitly ensure DNS mode (not HTTP-01) + webroot = null; + }; + + # Nginx virtual host for Forgejo services.nginx.virtualHosts.${fqdn} = { + # CRITICAL FIX: Don't set enableACME = true + # That would create an HTTP-01 challenge handler, which conflicts with DNS challenge + # Instead, we use useACMEHost to reference the DNS-obtained certificate + enableACME = false; # Disable automatic ACME for this vhost + useACMEHost = fqdn; # Use the certificate obtained via DNS challenge + forceSSL = true; - enableACME = true; - useACMEHost = fqdn; - acmeRoot = null; + + # acmeRoot is not needed/used with DNS challenge method + # acmeRoot = null; # Removed - implicit with enableACME = false + extraConfig = '' client_max_body_size 512M; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + + # Logging for debugging + access_log /var/log/nginx/${fqdn}-access.log; + error_log /var/log/nginx/${fqdn}-error.log warn; ''; + locations."/".proxyPass = "http://localhost:${toString srv.HTTP_PORT}"; }; + # Forgejo service configuration services.forgejo = { enable = true; database.type = "postgres"; @@ -41,6 +66,8 @@ in DOMAIN = fqdn; ROOT_URL = "https://${fqdn}/"; HTTP_PORT = 3000; + # Bind to localhost only - nginx handles public HTTPS + LOCAL_ROOT_URL = "http://localhost:3000/"; }; service.DISABLE_REGISTRATION = true; @@ -60,7 +87,13 @@ in }; }; - # Create/ensure admin user + # Ensure nginx starts after ACME certificate is available + systemd.services.nginx = { + after = [ "acme-${fqdn}.service" "acme-${fqdn}-renew.service" ]; + requires = [ "acme-${fqdn}.service" ]; + }; + + # Create/ensure admin user on startup systemd.services.forgejo.preStart = let adminCmd = "${lib.getExe cfg.package} admin user"; in '' @@ -72,9 +105,10 @@ in --must-change-password=false || true ''; - # Actions runner (runs jobs in Docker containers per labels) + # Enable Docker for Forgejo Actions runner virtualisation.docker.enable = true; + # Configure Forgejo Actions runner services.gitea-actions-runner = { package = pkgs.forgejo-runner; instances.default = { diff --git a/servers/nginx.nix b/servers/nginx.nix index d76e7c9..47927cc 100644 --- a/servers/nginx.nix +++ b/servers/nginx.nix @@ -1,8 +1,9 @@ { config, lib, pkgs, ... }: let # WARNING: this ends up world-readable in the Nix store if you inline it. + # For production, use agenix or pass through systemd credentials cloudflareEnv = pkgs.writeText "cloudflare-acme.env" '' - umnyPSYOr9U3m404_IBMl4PTOzg29nz_XzNEGw2v + CLOUDFLARE_DNS_API_TOKEN=umnyPSYOr9U3m404_IBMl4PTOzg29nz_XzNEGw2v ''; in {