Compare commits
19 Commits
6e0e86b17a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ff9d839609 | |||
| a00c981ecd | |||
| 13c3d63785 | |||
| 236e454e22 | |||
| 5877a51436 | |||
| 6a2ca62398 | |||
| 0cfdcffc59 | |||
| 4d4ac1487c | |||
| bd41a33bae | |||
| 09d2522bfd | |||
| dac1336e4c | |||
| 13dfdf01d0 | |||
| ddf3fdfb53 | |||
| a3172f477f | |||
| 834f727882 | |||
| bf96cfbee0 | |||
| 7fd43cf252 | |||
| 2adbe4751d | |||
| 23c22c4bc6 |
@@ -0,0 +1,32 @@
|
||||
## Nix
|
||||
|
||||
## General Instructions
|
||||
1. Do not use Nix flakes.
|
||||
2. Always check if an option (https://search.nixos.org/options), a package (https://search.nixos.org/packages) or a function (https://noogle.dev/) exists before inventing one.
|
||||
3. Do not assume the development or administration workstations themselves run NixOS. The development environment is more likely Debian Trixie.
|
||||
4. Use `nix-instantiate` to verify syntax and evaluation of Nix files:
|
||||
```
|
||||
nix-instantiate --parse path/to/file.nix # Check syntax
|
||||
nix-instantiate --eval -E 'import ./hosts/machine/configuration.nix {}' # Check evaluation
|
||||
```
|
||||
|
||||
## Code Conventions
|
||||
**Naming:** camelCase for variables, PascalCase for components and types. UPPER_CASE and "_" for shell environment variables.
|
||||
**Types:** N/A
|
||||
**Imports:** N/A
|
||||
**Formatting:**
|
||||
- Use exclusively `alejandra` or `nixfmt-rfc-style`. Never leave trailing whitespace.
|
||||
- Prefer `inherit` for same-name variables.
|
||||
- Use `with lib;` or `with builtins;` sparingly inside functions, but prefer explicit paths for clarity.
|
||||
- Always declare arguments at the beginning of the file: `{ config, pkgs, lib, ... }:`.
|
||||
**Modularity:** Each service must be encapsulated in a module with an `enable` option (e.g., `services.mon-service.enable = true;`).
|
||||
|
||||
## Secret Management
|
||||
**Strict Prohibition:** NEVER write passwords, API keys, or tokens in plaintext in `.nix` files.
|
||||
**Tool:** Use **agenix**.
|
||||
|
||||
## Specific Guidelines
|
||||
1. **Never** expose passwords, API keys, or any secrets in plaintext. Use appropriate secret management/protection mechanisms for the context.
|
||||
2. Prefer SSH keys for system authentication.
|
||||
3. Limit line lengths to 78 printable characters.
|
||||
4. Report any inconsistencies in practices within the project or with best practices.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Project Rules: nixos-infra
|
||||
|
||||
## Directories
|
||||
|
||||
### Private environment repo (nixos-infra)
|
||||
- `/nixos-infra/environments/production/hosts/servers`: Server-specific configurations (.nix).
|
||||
- `/nixos-infra/environments/production/hosts/workstations`: Workstation-specific configurations (.nix).
|
||||
- `/nixos-infra/environments/production/network`: Production network layout (VLANs, subnets, host IPs).
|
||||
- `/nixos-infra/environments/production/secrets`: agenix-encrypted secrets.
|
||||
- `/nixos-infra/environments/production/users`: Production user configurations.
|
||||
- `/nixos-infra/scripts`: Operational scripts (deploy.sh with --environment flag, etc.).
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Project Rules: nixos-infra
|
||||
|
||||
## Goals
|
||||
|
||||
The goal is to enable the deployment and maintenance of network infrastructure and application services
|
||||
(DNS, git repository server, password manager, file server, backup server, reverse proxy,
|
||||
workstations, etc.). The git repository contains all files needed to configure and install
|
||||
any machine in the fleet (OS images, configuration files, deployment and maintenance scripts).
|
||||
The target is to be able to rebuild the entire fleet from a Linux workstation (not necessarily NixOS)
|
||||
where this repository has been cloned.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Project Rules: nixos-infra
|
||||
|
||||
## Response Preferences
|
||||
- Language: English
|
||||
- Style: Technical, concise, Infrastructure as Code oriented.
|
||||
- Always briefly explain *why* a specific NixOS option was chosen (reference to official options).
|
||||
- Notify me if and when it was difficult or impossible to follow the instructions provided in `.ai-rules.md`.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Project Rules: nixos-infra
|
||||
|
||||
## Technical Context
|
||||
**Stack:** NixOS 25.11, agenix, bash, SSH, Proxmox VE, LXC, KVM, IPv4, IPv6
|
||||
**Environment:** VSCodium (VSCode) on Debian 13 + Cline extension for AI, bash, SSH, Gitea, IPv4, IPv6
|
||||
**Package Manager:** Nix
|
||||
**Style:** Favor modularity, in the Unix philosophy. Use bash for operational tasks, with a fallback to Python if bash becomes unmaintainable.
|
||||
**Tests:** Test Driven Development whenever possible.
|
||||
**Hardware:** X86-64 desktop computers, an old Dell T620, an old Dell T330, a Rpi 3B
|
||||
@@ -0,0 +1,35 @@
|
||||
# Role
|
||||
You are an exceptional product manager with 20 years of experience and an engineer proficient in all programming languages, skilled in assisting junior developers.
|
||||
|
||||
# Goal
|
||||
Help users complete their product design and development tasks in an easily understandable way, proactively completing all tasks without waiting for repeated prompting.
|
||||
|
||||
## Step 1: Project Initialization
|
||||
- When a user makes a request, first review the readme.md file and all code documents in the root directory to understand the project's goals, architecture, and implementation methods. If a readme file doesn't exist, create one.
|
||||
- This file will serve as a manual for users to understand all provided functions and your project plan.
|
||||
- Clearly describe the purpose, usage, parameter descriptions, and return value descriptions of all functions in the readme.md file to ensure user-friendly understanding and usage.
|
||||
|
||||
## Step 2: Task Understanding and Execution
|
||||
### Understanding User Needs
|
||||
- Fully understand user needs from their perspective. Consider: "If I were the user, what would I need?"
|
||||
- As a product manager, identify any gaps in user needs. Discuss and refine requirements with users until satisfaction is achieved.
|
||||
- Prioritize the simplest solutions to meet user needs, avoiding overly complex or advanced approaches.
|
||||
|
||||
### Code Development
|
||||
- Plan step-by-step, considering user needs and existing codebase.
|
||||
- Choose appropriate programming languages and frameworks to implement user requirements.
|
||||
- Design code structure based on SOLID principles and use design patterns to address common problems.
|
||||
- Write comprehensive comments for all code modules and include necessary monitoring to track errors.
|
||||
- Opt for simple, controllable solutions over complex ones.
|
||||
|
||||
### Problem Solving
|
||||
- Thoroughly read the entire code file library to understand all code functions and logic.
|
||||
- Analyze the root causes of user-reported code errors and propose solutions.
|
||||
- Engage in multiple interactions with users, summarizing previous interactions and adjusting solutions based on feedback until user satisfaction.
|
||||
- Initiate "System 2 Thinking Mode" for persistent bugs:
|
||||
1. Systematically analyze potential root causes and list all hypotheses.
|
||||
2. Design verification methods for each hypothesis.
|
||||
3. Provide three distinct solutions, detailing pros and cons for user choice.
|
||||
|
||||
## Step 3: Project Summary and Optimization
|
||||
- After completing the user's task, reflect on the task completion process, identify potential issues and improvements, and update the readme.md file accordingly.
|
||||
@@ -0,0 +1,32 @@
|
||||
# RTK - Rust Token Killer (Cline)
|
||||
|
||||
**Usage**: Token-optimized CLI proxy for shell commands.
|
||||
|
||||
## Rule
|
||||
|
||||
Always prefix shell commands with `rtk` to minimize token consumption.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
rtk git status
|
||||
rtk cargo test
|
||||
rtk ls src/
|
||||
rtk grep "pattern" src/
|
||||
rtk find "*.rs" .
|
||||
rtk docker ps
|
||||
rtk gh pr list
|
||||
```
|
||||
|
||||
## Meta Commands
|
||||
|
||||
```bash
|
||||
rtk gain # Show token savings
|
||||
rtk gain --history # Command history with savings
|
||||
rtk discover # Find missed RTK opportunities
|
||||
rtk proxy <cmd> # Run raw (no filtering, for debugging)
|
||||
```
|
||||
|
||||
## Why
|
||||
|
||||
RTK filters and compresses command output before it reaches the LLM context, saving 60-90% tokens on common operations. Always use `rtk <cmd>` instead of raw commands.
|
||||
@@ -1,106 +1,112 @@
|
||||
# 🏗️ **NixOS Infrastructure Project Canvas**
|
||||
|
||||
*Projet de gestion centralisée des configurations NixOS pour l'infrastructure de Xavier Lagraula*
|
||||
*Centralized NixOS configuration management project for Xavier Lagraula's infrastructure*
|
||||
---
|
||||
|
||||
## **📌 Context and Objectives**
|
||||
|
||||
- **Scope**: Centralized management of **NixOS** configurations for a complete infrastructure (hypervisors, workstations, LXC containers, services).
|
||||
- **Environment**:
|
||||
- One **Proxmox** hypervisor currently, a second one coming soon.
|
||||
- Several **workstations** (e.g., `sting`, `gaia`, `PC-FRIDA`).
|
||||
- **LXC Containers** (on Proxmox) VE for infrastructure services (DNS, Gitea, Bitwarden, etc.) and applications.
|
||||
- **2 main users** (Xavier, Frida) + system users (`root`, `admin`, `guest`).
|
||||
- **Hardware**: ThinkCentre m710q (16 GB RAM, i3) with **KDE 6.3**.
|
||||
|
||||
### **Objectives**
|
||||
|
||||
| Objective | Description | Priority |
|
||||
| ---------------------------| ------------------------------------------------------------------| ----------|
|
||||
| Centralize configurations | A single Git repository for all machines. | ⭐⭐⭐ |
|
||||
| Modularity | Reusable modules for services, machine types, and user profiles. | ⭐⭐⭐ |
|
||||
| Automation | Scripts to deploy configurations to machines and containers. | ⭐⭐⭐ |
|
||||
| Security | Secret management with `sops-nix` or `agenix`. | ⭐⭐ |
|
||||
| Portability | Autonomous modules via `callPackage`. | ⭐⭐ |
|
||||
| Maintenance | Clear documentation and simplified update processes. | ⭐ |
|
||||
|
||||
---
|
||||
|
||||
|
||||
## **📌 Contexte et Objectifs**
|
||||
|
||||
### **Contexte**
|
||||
## **🔍 Key Decisions**
|
||||
|
||||
- **Portée** : Gestion centralisée des configurations **NixOS** pour une infrastructure complète (hyperviseurs, stations de travail, conteneurs LXC, services).
|
||||
- **Environnement** :
|
||||
- Un hyperviseur **Proxmox** actuellement, un deuxième à venir.
|
||||
- Plusieurs **stations de travail** (ex: `dev-xavier`, `mao-julien`, `bureautique`).
|
||||
- **Conteneurs LXC** (sur Proxmox) pour les services d'infrastructure (DNS, Gitea, Bitwarden, etc.) et applicatifs.
|
||||
- **2 utilisateurs principaux** (Xavier, Frida) + utilisateurs système (`root`, `admin`, `guest`).
|
||||
- **Matériel** : ThinkCentre m710q (16 Go RAM, i3) avec **KDE 6.3**.
|
||||
|
||||
### **Objectifs**
|
||||
|
||||
|
||||
| Objectif | Description | Priorité |
|
||||
| ------------------------------ | ------------------------------------------------------------------------------------ | -------- |
|
||||
| Centraliser les configurations | Un dépôt Git unique pour toutes les machines. | ⭐⭐⭐ |
|
||||
| Modularité | Modules réutilisables pour les services, types de machines, et profils utilisateurs. | ⭐⭐⭐ |
|
||||
| Automatisation | Scripts pour déployer les configurations sur les machines et conteneurs. | ⭐⭐⭐ |
|
||||
| Sécurité | Gestion des secrets avec `sops-nix`. | ⭐⭐ |
|
||||
| Portabilité | Modules autonomes via `callPackage`. | ⭐⭐ |
|
||||
| Maintenance | Documentation claire et processus de mise à jour simplifiés. | ⭐ |
|
||||
| Decision | Justification | Impact |
|
||||
| ---------------------------------------------------------| -------------------------------------------------------------------------------------------------------------------------------------------| ----------------------------------------------------------------------------|
|
||||
| **No flakes** | Simplify onboarding and avoid a steep learning curve. | Configuration via `configuration.nix` + `callPackage`. |
|
||||
| **Modular structure** | Separate configurations by machine type and service. | Clear and maintainable directory tree. |
|
||||
| **Servers named by service, not by application** | Indicate what the machine does (git01 = Git forge) rather than the software (Gitea). Allows changing the underlying app without renaming. | Hosts under `hosts/servers/<service>01` (e.g. `git01`, `pass01`, `dns01`). |
|
||||
| **Modules** | Make modules autonomous, portable, and reusable. | Each module is an independent Nix package. |
|
||||
| **Separation of `user-profiles/` and `users/`** | Distinguish generic roles (e.g., `admin`) from concrete users (e.g., `xavier`). | Flexibility to apply profiles to multiple users. |
|
||||
| **`deploy.sh` script** | Automate deployment on existing machines. | Clone/update the repo + `nixos-rebuild switch`. |
|
||||
| **`create-lxc-nixos.sh` script** | Automate the creation of NixOS LXC containers on Proxmox. | Ready-to-use container with initial configuration. |
|
||||
| **Initial configuration (`initial-configuration.nix`)** | Prepare an LXC container so it can update itself via Git. | Self-sufficient containers. |
|
||||
| **Secret management with `agenix`** | Encrypt secrets (passwords, keys) for secure storage. | Enhanced security for sensitive data. |
|
||||
| **Unprivileged LXC containers (`--unprivileged 0`)** | NixOS requires privileges to function correctly in LXC. | Functional containers with NixOS. |
|
||||
| **Centralised network data** | A single declarative network data source (`network/`) consumed by NixOS configs and scripts. | VLANs, subnets, host addresses defined once in `network/hosts.nix`. |
|
||||
| **IPv6-first with dual-stack** | Both ULA (fdb2:) and GUA (2a01:) prefixes defined per VLAN. | Consistent internal addressing + global reachability for DMZ services. |
|
||||
| **DHCP-based IPv4 assignment** | LXC containers use `useDHCP = true`. Addresses are reserved in `hosts.nix` as source of truth. | Centralised address management, no static IPs in per-host configs. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **🔍 Décisions Clés**
|
||||
## **📂 File Structure**
|
||||
|
||||
|
||||
| Décision | Justification | Impact |
|
||||
| ----------------------------------------------------------| -----------------------------------------------------------------------------------------| ------------------------------------------------------------------|
|
||||
| **Pas de flakes** | Simplifier la prise en main et éviter une courbe d'apprentissage abrupte. | Configuration via `configuration.nix` + `callPackage`. |
|
||||
| **Structure modulaire** | Séparer les configurations par type de machine et service. | Arborescence claire et maintenable. |
|
||||
| `**callPackage` pour les modules** | Rendre les modules autonomes, portables et réutilisables. | Chaque module est un paquetage Nix indépendant. |
|
||||
| **Séparation `user-profiles/` et `users/**` | Distinguer les rôles génériques (ex: `admin`) des utilisateurs concrets (ex: `xavier`). | Flexibilité pour appliquer des profils à plusieurs utilisateurs. |
|
||||
| **Script `deploy.sh**` | Automatiser le déploiement sur les machines existantes. | Clone/mise à jour du dépôt + `nixos-rebuild switch`. |
|
||||
| **Script `create-lxc-nixos.sh**` | Automatiser la création de conteneurs LXC sous Proxmox. | Conteneur prêt à l'emploi avec configuration initiale. |
|
||||
| **Configuration initiale (`initial-configuration.nix`)** | Préparer un conteneur LXC pour qu'il puisse se mettre à jour via Git. | Conteneurs auto-suffisants. |
|
||||
| **Gestion des secrets avec `agenix**` | Chiffrer les secrets (mots de passe, clés) pour un stockage sécurisé. | Sécurité renforcée pour les données sensibles. |
|
||||
| **Conteneurs LXC non privilégés (`--unprivileged 0`)** | NixOS a besoin de privilèges pour fonctionner correctement. | Conteneurs fonctionnels avec NixOS. |
|
||||
| **Support IPv4, IPv6, VLANs** | La cible finale est IPv6 first, voire IPv6 only. | Gestion du plan IP à concevoir. |
|
||||
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **📂 Arborescences de Fichiers**
|
||||
|
||||
### **Structure du dépôt Git**
|
||||
### **Git Repository Structure**
|
||||
|
||||
```bash
|
||||
nixos-infra/
|
||||
├── configuration.nix # Point d'entrée principal
|
||||
├── configuration.nix # Main entry point
|
||||
├── README.md
|
||||
│
|
||||
├── hosts/ # Configurations par machine
|
||||
│ ├── servers/ # Serveurs (hyperviseurs, VMs, LXCs)
|
||||
│ │ ├── pve01/ # Hyperviseur 1
|
||||
├── hosts/ # Machine configurations
|
||||
│ ├── servers/ # Servers (hypervisors, VMs, LXCs)
|
||||
│ │ ├── hyper01/ # Hypervisor 1
|
||||
│ │ │ └── configuration.nix
|
||||
│ │ ├── pve02/ # Hyperviseur 2
|
||||
│ │ ├── hyper02/ # Hypervisor 2
|
||||
│ │ │ └── configuration.nix
|
||||
│ │ ├── dns01/ # Conteneur LXC pour DNS (master)
|
||||
│ │ ├── dns01/ # LXC container for DNS (master)
|
||||
│ │ │ └── configuration.nix
|
||||
│ │ ├── dns02/ # Conteneur LXC pour DNS (slave)
|
||||
│ │ ├── dns02/ # LXC container for DNS (slave)
|
||||
│ │ │ └── configuration.nix
|
||||
│ │ ├── gitea01/ # Conteneur LXC pour Gitea
|
||||
│ │ ├── git01/ # LXC container for Git forge (e.g. Gitea)
|
||||
│ │ │ └── configuration.nix
|
||||
│ │ └── vaultwarden/ # Conteneur LXC pour Vaultwarden
|
||||
│ │ └── configuration.nix
|
||||
│ │ └── rp01/ # Conteneur LXC reverse proxy
|
||||
│ │ ├── pass01/ # LXC container for password manager (e.g. Vaultwarden)
|
||||
│ │ │ └── configuration.nix
|
||||
│ │ └── rp01/ # LXC container for reverse proxy
|
||||
│ │ └── configuration.nix
|
||||
│ │
|
||||
│ └── workstations/ # Stations de travail
|
||||
│ ├── sting/ # Station de Xavier (admin, dev, mao)
|
||||
│ └── workstations/ # Workstations
|
||||
│ ├── sting/ # Xavier's station (admin, dev, audio)
|
||||
│ │ └── configuration.nix
|
||||
│ ├── PC-FRIDA/ # Station de Frida (bureautique)
|
||||
│ ├── PC-FRIDA/ # Frida's station (office)
|
||||
│ │ └── configuration.nix
|
||||
│ └── gaia/ # Portable de Xavier (MAO)
|
||||
│ └── gaia/ # Xavier's laptop (audio)
|
||||
│ └── configuration.nix
|
||||
│
|
||||
├── modules/ # Modules autonomes
|
||||
│ ├── machine-types/ # Types de machines
|
||||
│ │ ├── hypervisor.nix # Module pour hyperviseurs
|
||||
│ │ ├── vm.nix # Module pour VMs
|
||||
│ │ ├── lxc.nix # Module pour conteneurs LXC
|
||||
│ │ └── workstation.nix # Module pour stations de travail
|
||||
├── network/ # Centralised network data (VLANs, subnets, hosts)
|
||||
│ ├── default.nix # Aggregator — imports vlans, subnets, hosts
|
||||
│ ├── vlans.nix # VLAN definitions
|
||||
│ ├── subnets.nix # Subnet prefix allocations
|
||||
│ ├── hosts.nix # Per-machine IP/address assignments
|
||||
│ └── README.md # Network architecture documentation
|
||||
│
|
||||
├── modules/ # Autonomous modules
|
||||
│ ├── machine-types/ # Machine types
|
||||
│ │ ├── hypervisor/
|
||||
│ │ │ └── default.nix # Module for hypervisors
|
||||
│ │ ├── vm/
|
||||
│ │ │ └── default.nix # Module for VMs
|
||||
│ │ ├── lxc/
|
||||
│ │ │ └── default.nix # Module for LXC containers
|
||||
│ │ └── workstation/
|
||||
│ │ └── default.nix # Module for workstations
|
||||
│ │
|
||||
│ ├── services/ # Services
|
||||
│ │ ├── dns/
|
||||
│ │ │ ├── default.nix # Implémentation
|
||||
│ │ │ └── options.nix # Options exposées
|
||||
│ │ ├── gitea/
|
||||
│ │ │ ├── default.nix # Implementation
|
||||
│ │ │ └── options.nix # Exposed options
|
||||
│ │ ├── git-forge/
|
||||
│ │ │ └── default.nix
|
||||
│ │ ├── password-manager/
|
||||
│ │ │ └── default.nix
|
||||
@@ -108,13 +114,13 @@ nixos-infra/
|
||||
│ │ │ └── default.nix
|
||||
│ │ └── ...
|
||||
│ │
|
||||
│ └── user-profiles/ # Profils utilisateurs (rôles)
|
||||
│ ├── admin.nix # Profil administrateur
|
||||
│ ├── dev.nix # Profil développeur
|
||||
│ ├── mao.nix # Profil MAO
|
||||
│ └── standard.nix # Profil standard
|
||||
│ └── user-profiles/ # User profiles (roles)
|
||||
│ ├── admin.nix # Administrator profile
|
||||
│ ├── dev.nix # Developer profile
|
||||
│ ├── cam.nix # Audio production profile
|
||||
│ └── standard.nix # Standard profile
|
||||
│
|
||||
├── users/ # Utilisateurs concrets
|
||||
├── users/ # Specific users
|
||||
│ ├── root/
|
||||
│ │ └── configuration.nix
|
||||
│ ├── xavier/
|
||||
@@ -124,15 +130,15 @@ nixos-infra/
|
||||
│ └── guest/
|
||||
│ └── configuration.nix
|
||||
│
|
||||
├── scripts/ # Scripts utilitaires
|
||||
│ ├── deploy.sh # Déploiement pour machines existantes
|
||||
│ ├── create-lxc-nixos.sh # Création de conteneurs LXC sous Proxmox
|
||||
│ └── initial-configuration.nix # Configuration initiale pour nouveaux conteneurs
|
||||
├── scripts/ # Utility scripts
|
||||
│ ├── deploy.sh # Deployment for existing machines
|
||||
│ ├── create-lxc-nixos.sh # LXC container creation on Proxmox
|
||||
│ └── initial-configuration.nix # Initial configuration for new containers
|
||||
│
|
||||
├── secrets/ # Secrets (exclus de Git)
|
||||
├── secrets/ # Secrets (excluded from Git)
|
||||
│ └── .gitignore
|
||||
│
|
||||
└── overlays/ # Overlays pour paquets personnalisés
|
||||
└── overlays/ # Overlays for custom packages
|
||||
└── custom-pkgs.nix
|
||||
```
|
||||
|
||||
@@ -140,193 +146,240 @@ nixos-infra/
|
||||
|
||||
---
|
||||
|
||||
## **🖥️ Profils de Machines et Services**
|
||||
## **🖥️ Machine Profiles and Services**
|
||||
|
||||
### **Profils de Machines**
|
||||
### **Machine Profiles**
|
||||
| Profile | Description | File | Usage |
|
||||
| --------------| --------------------------------------------------------------| ----------------------------------------| ---------------------------------------------|
|
||||
| `hypervisor` | Common configuration for hypervisors (KVM, libvirtd, etc.). | `modules/machine-types/hypervisor/default.nix` | Proxmox hypervisors. |
|
||||
| `vm` | Common configuration for virtual machines. | `modules/machine-types/vm/default.nix` | VMs under Proxmox. |
|
||||
| `lxc` | Common configuration for LXC containers. | `modules/machine-types/lxc/default.nix` | LXC containers under Proxmox. |
|
||||
| `workstation` | Common configuration for workstations. | `modules/machine-types/workstation/default.nix` | Development, audio production, office stations. |
|
||||
|
||||
| Profile | Description | File |
|
||||
| ------------| --------------------------------------------------| --------------------------------------|
|
||||
| `admin` | Administrator access (sudo, service management). | `modules/user-profiles/admin.nix` |
|
||||
| `dev` | Development environment (tools, permissions). | `modules/user-profiles/dev.nix` |
|
||||
| `cam` | Computer-assisted music (CAM). | `modules/user-profiles/cam.nix` |
|
||||
| `standard` | Standard user profile (basic access). | `modules/user-profiles/standard.nix` |
|
||||
|
||||
|
||||
| Profil | Description | Fichier | Utilisation |
|
||||
| ---------------| ---------------------------------------------------------------| -----------------------------------------| ----------------------------------------------|
|
||||
| `hypervisor` | Configuration commune aux hyperviseurs (KVM, libvirtd, etc.). | `modules/machine-types/hypervisor.nix` | Hyperviseurs Proxmox. |
|
||||
| `vm` | Configuration commune aux machines virtuelles. | `modules/machine-types/vm.nix` | VMs sous Proxmox. |
|
||||
| `lxc` | Configuration commune aux conteneurs LXC. | `modules/machine-types/lxc.nix` | Conteneurs LXC sous Proxmox. |
|
||||
| `workstation` | Configuration commune aux stations de travail. | `modules/machine-types/workstation.nix` | Stations de développement, MAO, bureautique. |
|
||||
---
|
||||
## **📋 Reference Tables**
|
||||
|
||||
### **1. Machine List**
|
||||
|
||||
|
||||
| Name | Machine Type | VLAN | IPv4 | IPv6 Token |
|
||||
| ----------| --------------------| ---------| ------------------| ------------|
|
||||
| hyper01 | Hypervisor | ADMIN | 10.10.128.10/16 | ::10 |
|
||||
| hyper02 | Hypervisor | ADMIN | 10.10.128.11/16 | ::11 |
|
||||
| dns01 | LXC Container | DMZ | 10.40.128.10/16 | ::10 |
|
||||
| dns02 | LXC Container | DMZ | 10.40.128.11/16 | ::11 |
|
||||
| git01 | LXC Container | DMZ | 10.40.128.20/16 | ::20 |
|
||||
| pass01 | LXC Container | DMZ | 10.40.128.30/16 | ::30 |
|
||||
| rp01 | LXC Container | DMZ | 10.40.128.199/16 | ::199 |
|
||||
| sting | Workstation | INTERNAL | 10.50.128.10/16 | ::10 |
|
||||
| PC-FRIDA | Workstation | INTERNAL | 10.50.128.11/16 | ::11 |
|
||||
| gaia | Workstation | INTERNAL | 10.50.128.12/16 | ::12 |
|
||||
|
||||
---
|
||||
|
||||
### **2. VLANs**
|
||||
|
||||
| VLAN | ID | Effective ID | IPv4 Prefix | IPv6 ULA | IPv6 GUA |
|
||||
| ----------| ---| --------------| -----------------| ----------------------------------| ----------------------------------|
|
||||
| INET | 1 | 1 | Out of scope | Out of scope | Out of scope |
|
||||
| ADMIN | 90 | **100** | 10.10.0.0/16 | fdb2:ae63:d45:d941::/64 | 2a01:e0a:2ea:d941::/64 |
|
||||
| IOT | 200| 200 | 10.20.0.0/16 | fdb2:ae63:d45:d942::/64 | 2a01:e0a:2ea:d942::/64 |
|
||||
| GUEST | 300| 300 | 10.30.0.0/16 | fdb2:ae63:d45:d943::/64 | 2a01:e0a:2ea:d943::/64 |
|
||||
| DMZ | 400| 400 | 10.40.0.0/16 | fdb2:ae63:d45:d944::/64 | 2a01:e0a:2ea:d944::/64 |
|
||||
| INTERNAL | 500| 500 | 10.50.0.0/16 | fdb2:ae63:d45:d945::/64 | 2a01:e0a:2ea:d945::/64 |
|
||||
|
||||
---
|
||||
|
||||
### **3. List of User Profiles**
|
||||
|
||||
|
||||
| Name | Role |
|
||||
| ------------| -------------------|
|
||||
| `admin` | Superuser |
|
||||
| `dev` | Developer |
|
||||
| `standard` | Web & Office |
|
||||
| `guest` | Guest |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### **Profils Utilisateurs**
|
||||
|
||||
|
||||
| Profil | Description | Fichier |
|
||||
| ------------| --------------------------------------------------------| --------------------------------------|
|
||||
| `admin` | Accès administrateur (sudo, gestion des services). | `modules/user-profiles/admin.nix` |
|
||||
| `dev` | Environnement de développement (outils, permissions). | `modules/user-profiles/dev.nix` |
|
||||
| `mao` | Configuration pour la musique assistée par ordinateur. | `modules/user-profiles/mao.nix` |
|
||||
| `standard` | Profil utilisateur standard (accès basique). | `modules/user-profiles/standard.nix` |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## **📋 Tableaux de Référence**
|
||||
|
||||
### **1. Liste des Machines**
|
||||
|
||||
|
||||
| Nom | Type de Machine | Services | IPv4 | Token IPv6 |
|
||||
| ---------| --------------------| -------------| ------| ------------|
|
||||
| pve01 | Hyperviseur | Proxmox | | |
|
||||
| pve02 | Hyperviseur | Proxmox | | |
|
||||
| dns01 | Conteneur LXC | DNS | | |
|
||||
| gitea01 | Conteneur LXC | Gitea | | |
|
||||
| vault01 | Conteneur LXC | Vaultwarden | | |
|
||||
| sting | Station de travail | | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
| marley | Station de travail | | | |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### **2. Liste des profils utilisateurs**
|
||||
|
||||
|
||||
| Nom | Rôle |
|
||||
| ---------- | ----------------- |
|
||||
| `admin` | Superutilisateur |
|
||||
| `dev` | Développeur |
|
||||
| `standard` | Web & bureautique |
|
||||
| `guest` | Invité |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### **3. Liste des Utilisateurs**
|
||||
|
||||
|
||||
| Nom | Rôle | Accès SSH |
|
||||
### **4. User List**
|
||||
| Name | Role | SSH Access |
|
||||
| --------| -----------------------| -----------|
|
||||
| root | Superutilisateur | ❌ |
|
||||
| xavier | Utilisateur principal | ✅ |
|
||||
| frida | Utilisateur | ✅ |
|
||||
| guest | Invité | ❌ |
|
||||
| root | Superuser | ❌ |
|
||||
| xavier | Main user | ✅ |
|
||||
| frida | User | ✅ |
|
||||
| guest | Guest | ❌ |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### **3. Liaisons Utilisateur/Machine/Profil**
|
||||
### **5. User/Machine/Profile Mappings**
|
||||
|
||||
|
||||
| Utilisateur | Machine | Profils Appliqués | Rôle |
|
||||
| -------------| ---------| -------------------| --------------------------------|
|
||||
| root | Toutes | - | Superutilisateur |
|
||||
| xavier | Toutes | `admin` | Développement + administration |
|
||||
| xavier | sting | `admin`, `dev` | Gestion des hyperviseurs |
|
||||
| frida | marley | `standard` | Développement |
|
||||
| guest | aucune | `guest` | Utilisateur invité |
|
||||
| User | Machine | Applied Profiles | Role |
|
||||
| --------| ----------| ------------------| ------------------------------|
|
||||
| root | All | - | Superuser |
|
||||
| xavier | All | `admin` | Development + administration |
|
||||
| xavier | sting | `admin`, `dev` | Hypervisor management |
|
||||
| frida | PC-FRIDA | `standard` | Development |
|
||||
| guest | None | `guest` | Guest user |
|
||||
| xavier | sting | `admin`, `dev` | Hypervisor management |
|
||||
| frida | PC-FRIDA | `standard` | Development |
|
||||
| guest | None | `guest` | Guest user |
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **🔄 Workflow de Déploiement**
|
||||
## **🌐 Network Architecture**
|
||||
|
||||
### **Pour les conteneurs LXC (Proxmox)**
|
||||
The network topology and addressing are defined **declaratively** in `network/`, the single source of truth for:
|
||||
- VLANs (`network/vlans.nix`)
|
||||
- Subnet prefixes (`network/subnets.nix`)
|
||||
- Host address assignments (`network/hosts.nix`)
|
||||
|
||||
1. **Créer le conteneur** :
|
||||
- Utiliser `create-lxc-nixos.sh` pour créer un conteneur à partir du template NixOS.
|
||||
- Le script installe la configuration initiale (`initial-configuration.nix`).
|
||||
2. **Déployer la configuration finale** :
|
||||
- Le script `deploy.sh` est exécuté automatiquement pour appliquer la configuration spécifique au conteneur (ex: `hosts/servers/dns01/configuration.nix`).
|
||||
3. **Mettre à jour** :
|
||||
- `git pull` dans `/etc/nixos-infra` + `nixos-rebuild switch`.
|
||||
### Prefix rules
|
||||
|
||||
### **Pour les stations de travail et hyperviseurs**
|
||||
| Type | Formula | Example (DMZ, effectiveId=400) |
|
||||
|--------|-----------------------------------------------------------|--------------------------------|
|
||||
| IPv4 | `10.<effectiveId>.0.0/16` — hosts in `10.<v>.128.0/17` | `10.40.0.0/16` |
|
||||
| IPv6 ULA | `fdb2:ae63:d45:d94<N>::/64` where N = effectiveId/100 | `fdb2:ae63:d45:d944::/64` |
|
||||
| IPv6 GUA | `2a01:e0a:2ea:d94<N>::/64` where N = effectiveId/100 | `2a01:e0a:2ea:d944::/64` |
|
||||
|
||||
1. **Cloner le dépôt** :
|
||||
```bash
|
||||
git clone https://github.com/xlagraula/nixos-infra.git /etc/nixos-infra
|
||||
```
|
||||
2. **Lier la configuration** :
|
||||
```bash
|
||||
ln -s /etc/nixos-infra/hosts/workstations/dev-xavier/configuration.nix /etc/nixos/configuration.nix
|
||||
```
|
||||
3. **Appliquer la configuration** :
|
||||
```bash
|
||||
sudo nixos-rebuild switch
|
||||
```
|
||||
> **ADMIN exception:** VLAN ID is 90 but treated as effective ID 100 for
|
||||
> prefix computation. This avoids a risky production renumbering.
|
||||
|
||||
### Consumption
|
||||
|
||||
**From a NixOS configuration:**
|
||||
```nix
|
||||
let network = import ../../network { };
|
||||
in {
|
||||
networking.hostName = "dns01";
|
||||
networking.useDHCP = true;
|
||||
}
|
||||
```
|
||||
|
||||
**From a shell script:**
|
||||
```bash
|
||||
nix eval --json -f network/default.nix hosts | jq '.dns01.ipv4'
|
||||
# → "10.40.128.10"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## **🔄 Deployment Workflow**
|
||||
|
||||
### **For LXC containers (Proxmox)**
|
||||
|
||||
1. **Create the container :**
|
||||
- Use `create-lxc-nixos.sh` to create a container from the NixOS template.
|
||||
- The script installs the initial configuration (`initial-configuration.nix`).
|
||||
2. **Deploy the final configuration :**
|
||||
- The `deploy.sh` script is executed automatically to apply the specific configuration to the container (e.g., `hosts/servers/dns01/configuration.nix`).
|
||||
3. **Update :**
|
||||
- `git pull` in `/etc/nixos-infra` + `nixos-rebuild switch`.
|
||||
|
||||
### **For workstations and hypervisors**
|
||||
|
||||
1. **Clone the repository :**
|
||||
```bash
|
||||
git clone https://github.com/xlagraula/nixos-infra.git /etc/nixos-infra
|
||||
```
|
||||
2. **Link the configuration :**
|
||||
```bash
|
||||
ln -s /etc/nixos-infra/hosts/workstations/dev-xavier/configuration.nix /etc/nixos/configuration.nix
|
||||
```
|
||||
3. **Apply the configuration :**
|
||||
```bash
|
||||
sudo nixos-rebuild switch
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **🔐 Gestion des Secrets**
|
||||
## **🔐 Secret Management**
|
||||
|
||||
- **Outil** : `agenix` (recommandé) ou `sops-nix`.
|
||||
- **Processus** :
|
||||
1. Chiffrer les secrets avec `age` :
|
||||
- **Tool** : `agenix`.
|
||||
- **Process** :
|
||||
1. Encrypt secrets with `age` :
|
||||
```bash
|
||||
echo "mon-secret" | age -r age1... -o secrets/bitwarden/password.age
|
||||
echo "my-secret" | age -r age1... -o secrets/bitwarden/password.age
|
||||
```
|
||||
2. Intégrer dans la configuration :
|
||||
2. Integrate into the configuration :
|
||||
```nix
|
||||
age.secrets.bitwarden-password = {
|
||||
path = ./secrets/bitwarden/password.age;
|
||||
mode = "600";
|
||||
};
|
||||
```
|
||||
3. **Ne jamais commiter les secrets en clair** (ajouter `secrets/` à `.gitignore`).
|
||||
3. **Never commit secrets in plain text** (add `secrets/` to `.gitignore`).
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **📅 Feuille de Route**
|
||||
## **📅 Roadmap**
|
||||
|
||||
|
||||
| Étape | Description | Statut | Priorité |
|
||||
| ------------------------------- | ------------------------------------------------- | ------ | -------- |
|
||||
| Tester le template LXC NixOS | Vérifier que le template fonctionne sous Proxmox. | ⬜ | ⭐⭐⭐ |
|
||||
| Finaliser `create-lxc-nixos.sh` | Tester la création d'un conteneur LXC. | ⬜ | ⭐⭐⭐ |
|
||||
| Écrire le module DNS | Module pour le service DNS (Bind). | ⬜ | ⭐⭐⭐ |
|
||||
| Configurer `agenix` | Chiffrer les premiers secrets. | ⬜ | ⭐⭐ |
|
||||
| Documenter le processus | `README.md` pour expliquer le déploiement. | ⬜ | ⭐⭐ |
|
||||
| Automatiser avec Ansible | Playbook pour créer plusieurs conteneurs. | ⬜ | ⭐ |
|
||||
| Intégrer un CI/CD | Tester les configurations avant déploiement. | ⬜ | ⭐ |
|
||||
| Step | Description | Status | Priority |
|
||||
| --------------------------------| -----------------------------------------------| --------| ----------|
|
||||
| Test the NixOS LXC template | Verify that the template works under Proxmox. | ⬜ | ⭐⭐⭐ |
|
||||
| Finalize `create-lxc-nixos.sh` | Test the creation of an LXC container. | ⬜ | ⭐⭐⭐ |
|
||||
| Write the DNS module | Module for the DNS service (Bind). | ⬜ | ⭐⭐⭐ |
|
||||
| Configure `agenix` | Encrypt the first secrets. | ⬜ | ⭐⭐ |
|
||||
| Document the process | `README.md` to explain deployment. | ⬜ | ⭐⭐ |
|
||||
| DHCP service module | Kea or ISC DHCP consuming `network/hosts.nix` | ⬜ | ⭐⭐ |
|
||||
| Automate with Ansible | Playbook to create multiple containers. | ⬜ | ⭐ |
|
||||
| Integrate CI/CD | Test configurations before deployment. | ⬜ | ⭐ |
|
||||
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **💡 Notes et Bonnes Pratiques**
|
||||
## **💡 Notes and Best Practices**
|
||||
|
||||
- **Nommage** :
|
||||
- Utilisez des noms explicites pour les machines (ex: `dns01`, `gitea01`).
|
||||
- Pour les conteneurs LXC, préférez des noms courts et descriptifs.
|
||||
- **Sécurité** :
|
||||
- Désactivez l'accès root en SSH une fois le déploiement terminé.
|
||||
- Utilisez des clés SSH pour l'authentification.
|
||||
- **Naming** :
|
||||
- **Servers**: Name by service, not by application (e.g., `git01`, `pass01`, `dns01`).
|
||||
- **Workstations**: Use descriptive hostnames (e.g., `sting`, `gaia`).
|
||||
- **Hypervisors**: Prefix with `hyper` (e.g., `hyper01`, `hyper02`).
|
||||
- **Security** :
|
||||
- Disable root SSH access once deployment is complete.
|
||||
- Use SSH keys for authentication.
|
||||
- **Network** :
|
||||
- IPv4 addresses are allocated from the upper half of each VLAN (`10.<v>.128.0/17`).
|
||||
- Addresses are assigned via DHCP reservations — `network/hosts.nix` is the source of truth.
|
||||
- See `network/README.md` for the complete architecture documentation.
|
||||
- **Maintenance** :
|
||||
- Mettez à jour régulièrement `nixpkgs` (`nix-channel --update`).
|
||||
- Documentez les changements dans le `CHANGELOG.md`.
|
||||
- **Sauvegardes** :
|
||||
- Sauvegardez les configurations (`/etc/nixos-infra`) et les secrets (`secrets/`).
|
||||
- Pour les conteneurs LXC sous Proxmox, utilisez les sauvegardes Proxmox.
|
||||
- Update `nixpkgs` regularly (`nix-channel --update`).
|
||||
- Document changes in the `CHANGELOG.md`.
|
||||
- **Backups** :
|
||||
- Backup configurations (`/etc/nixos-infra`) and secrets (`secrets/`).
|
||||
- For LXC containers under Proxmox, use Proxmox backups.
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## **📚 Ressources Utiles**
|
||||
## **📚 Useful Resources**
|
||||
|
||||
- [NixOS Manual](https://nixos.org/manual/)
|
||||
- [Nix Flakes (pour référence future)](https://nixos.wiki/wiki/Flakes)
|
||||
- [Agenix pour les secrets](https://github.com/ryantm/agenix)
|
||||
- [Nix Flakes (for future reference)](https://nixos.wiki/wiki/Flakes)
|
||||
- [Agenix for secrets](https://github.com/ryantm/agenix)
|
||||
- [Proxmox + LXC Documentation](https://pve.proxmox.com/wiki/Linear_Container)
|
||||
- [Exemple de dépôt NixOS Infrastructure](https://github.com/NixOS/nixos-infrastructure)
|
||||
- [Example NixOS Infrastructure Repository](https://github.com/NixOS/nixos-infrastructure)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# nixos-infra — Private environments
|
||||
|
||||
This repository contains **environment-specific declarations** (hosts, network
|
||||
layout, secrets, users) for the NixOS fleet. Reusable technical components
|
||||
(modules, lib, pkgs, scripts) live in the **public framework repository**:
|
||||
|
||||
→ `nixos-infra-framework` (ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git)
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
nixos-infra/
|
||||
├── environments/
|
||||
│ └── production/ # Production infrastructure
|
||||
│ ├── configuration.nix # Environment entry point
|
||||
│ ├── hosts/
|
||||
│ │ ├── servers/ # Server configurations (LXC, hypervisors)
|
||||
│ │ └── workstations/ # Workstation configurations
|
||||
│ ├── network/ # VLANs, subnets, host IPs
|
||||
│ ├── secrets/ # agenix-encrypted secrets
|
||||
│ └── users/ # User configurations
|
||||
├── scripts/ # Environment-specific script wrappers
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Adding a New Environment
|
||||
|
||||
1. Create `environments/<name>/` with the same sub-structure as `production/`.
|
||||
2. Set up its own `network/`, `secrets/`, and `users/`.
|
||||
3. Deploy with:
|
||||
```
|
||||
deploy.sh --environment <name>
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
```
|
||||
deploy.sh --environment production
|
||||
```
|
||||
|
||||
See the framework repo for the deploy script and reusable modules.
|
||||
@@ -0,0 +1,19 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Pin to the same framework commit as production — update when testing
|
||||
# new framework features in dev before rolling to production.
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
(framework + "/lib")
|
||||
(framework + "/overlays/custom-pkgs.nix")
|
||||
];
|
||||
|
||||
# Dev environment-wide settings
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all hosts in the dev environment
|
||||
# This file is imported by all host configurations (servers and workstations)
|
||||
|
||||
# TODO: Move common settings here later
|
||||
# Examples:
|
||||
# - Common users/groups
|
||||
# - Common packages
|
||||
# - Common services
|
||||
# - Common security policies
|
||||
# - Common monitoring/alerting
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all servers in the dev environment
|
||||
# This file is imported by all server configurations
|
||||
|
||||
# TODO: Move common server settings here later
|
||||
# Examples:
|
||||
# - Server-specific users/groups
|
||||
# - Server-specific packages
|
||||
# - Server-specific services
|
||||
# - Server-specific security policies
|
||||
# - Server-specific monitoring/alerting
|
||||
# - Locale: en_US.UTF-8 (for servers)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all workstations in the dev environment
|
||||
# This file is imported by all workstation configurations
|
||||
|
||||
# TODO: Move common workstation settings here later
|
||||
# Examples:
|
||||
# - Workstation-specific users/groups
|
||||
# - Workstation-specific packages
|
||||
# - Workstation-specific services
|
||||
# - Workstation-specific security policies
|
||||
# - Workstation-specific monitoring/alerting
|
||||
# - Locale: fr_FR.UTF-8 (for workstations)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Central network data source for the dev environment.
|
||||
#
|
||||
# Usage from a configuration.nix:
|
||||
# network = import ../../network { };
|
||||
# network.dns.domain → "dev.lagraula.fr"
|
||||
# network.time.timeZone → "Europe/Paris"
|
||||
#
|
||||
# Usage from a shell script (via `nix eval`):
|
||||
# nix eval --json -f network/default.nix dns
|
||||
|
||||
{
|
||||
dns = import ./dns.nix;
|
||||
time = import ./time.nix;
|
||||
proxy = import ./proxy.nix;
|
||||
smtp = import ./smtp.nix;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Environment-specific DNS domain
|
||||
domain = "dev.lagraula.fr";
|
||||
|
||||
# Default DNS servers for this environment
|
||||
# These are the IPs of the DNS servers (e.g., dns-dev01, dns-dev02)
|
||||
# that will be deployed in this environment.
|
||||
defaultNameServers = [ "10.40.128.10" "10.40.128.11" ];
|
||||
|
||||
# Forwarders for this environment (e.g., upstream DNS)
|
||||
forwarders = [ "1.1.1.1" "8.8.8.8" ];
|
||||
|
||||
# Allow zone transfers only to secondary DNS servers in this environment
|
||||
allowZoneTransfer = [ "10.40.128.11" ];
|
||||
|
||||
# Recursion policy for this environment
|
||||
recursion = "AllowOnlyForPrivateNetworks";
|
||||
|
||||
# Email for Let's Encrypt (Caddy) — can be environment-specific
|
||||
letsEncryptEmail = "xavier@lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Proxy configuration for this environment
|
||||
# Currently no proxy is used — direct access for all hosts
|
||||
|
||||
# Workstations: no proxy
|
||||
workstations = {
|
||||
httpProxy = "";
|
||||
httpsProxy = "";
|
||||
noProxy = "";
|
||||
};
|
||||
|
||||
# Servers: no proxy
|
||||
servers = {
|
||||
httpProxy = "";
|
||||
httpsProxy = "";
|
||||
noProxy = "";
|
||||
};
|
||||
|
||||
# To enable a proxy later, uncomment and set the proxy URLs:
|
||||
# workstations = {
|
||||
# httpProxy = "http://proxy.dev.lagraula.fr:3128";
|
||||
# httpsProxy = "http://proxy.dev.lagraula.fr:3128";
|
||||
# noProxy = "localhost,127.0.0.1,::1,10.0.0.0/8";
|
||||
# };
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# SMTP relay configuration for this environment
|
||||
# Used by services that need to send email (e.g., monitoring alerts)
|
||||
|
||||
# SMTP relay host — can be an internal relay or external service
|
||||
relayHost = "smtp.lagraula.fr";
|
||||
relayPort = 587;
|
||||
|
||||
# TLS settings
|
||||
useTLS = true;
|
||||
useSTARTTLS = true;
|
||||
|
||||
# Authentication — currently none (open relay for internal use)
|
||||
# To add authentication later:
|
||||
# username = "noreply@dev.lagraula.fr";
|
||||
# passwordFile = config.age.secrets.smtp-password.path;
|
||||
|
||||
# Default "From" address for system emails
|
||||
fromAddress = "noreply@dev.lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# NTP servers for this environment
|
||||
# The gateway acts as the NTP server (IPv4 .1, IPv6 ::1)
|
||||
ntpServers = [
|
||||
"10.10.128.1" # IPv4 gateway
|
||||
"fd00::1" # IPv6 gateway
|
||||
];
|
||||
|
||||
# Time zone for this environment
|
||||
timeZone = "Europe/Paris";
|
||||
|
||||
# Hardware clock setting
|
||||
hardwareClock = "UTC";
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
# Import the framework utilities
|
||||
(framework + "/lib")
|
||||
(framework + "/overlays/custom-pkgs.nix")
|
||||
];
|
||||
|
||||
# Production environment-wide settings
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
# Host definition.
|
||||
Hosts belong to a machine type defined in `nixos-infra/modules/machine-types` and can either be `servers` running services defined in `nixos-infra/modules/services` or `workstations` used by users to access servcies and run applications depending on their profile.
|
||||
@@ -0,0 +1,14 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all hosts in the production environment
|
||||
# This file is imported by all host configurations (servers and workstations)
|
||||
|
||||
# TODO: Move common settings here later
|
||||
# Examples:
|
||||
# - Common users/groups
|
||||
# - Common packages
|
||||
# - Common services
|
||||
# - Common security policies
|
||||
# - Common monitoring/alerting
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Servers
|
||||
NixOS configurations for infrastructure servers.
|
||||
Defines service roles (DNS, Gitea, reverse-proxy, Vaultwarden)
|
||||
and hypervisor configurations (Proxmox pve01, pve02).
|
||||
@@ -0,0 +1,15 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all servers in the production environment
|
||||
# This file is imported by all server configurations
|
||||
|
||||
# TODO: Move common server settings here later
|
||||
# Examples:
|
||||
# - Server-specific users/groups
|
||||
# - Server-specific packages
|
||||
# - Server-specific services
|
||||
# - Server-specific security policies
|
||||
# - Server-specific monitoring/alerting
|
||||
# - Locale: en_US.UTF-8 (for servers)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Pin to a specific commit of the framework repo for reproducibility.
|
||||
# Update this hash when you want to pull in new framework changes.
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
# Import environment-specific network parameters
|
||||
env = import ../../../network { };
|
||||
in {
|
||||
imports = [
|
||||
# Module for LXC containers
|
||||
(framework + "/modules/machine-types/lxc")
|
||||
# Technitium DNS Server service module
|
||||
(framework + "/modules/services/dns/default.nix")
|
||||
];
|
||||
|
||||
# Explicitly enable LXC machine type
|
||||
lxc.enable = true;
|
||||
|
||||
# Host identity (IP address 10.40.128.10/16 assigned via DHCP reservation)
|
||||
networking.hostName = "dns01";
|
||||
networking.domain = env.dns.domain;
|
||||
networking.useDHCP = true;
|
||||
|
||||
# Technitium DNS Server — primary DNS server
|
||||
services.dns = {
|
||||
enable = true;
|
||||
recursion = env.dns.recursion;
|
||||
forwarders = env.dns.forwarders;
|
||||
# Uncomment and configure with agenix secret:
|
||||
# adminPasswordFile = config.age.secrets.dns-admin-password.path;
|
||||
allowZoneTransfer = env.dns.allowZoneTransfer; # Allow secondary to dns02
|
||||
listenAddresses = [ "10.40.128.10" "127.0.0.1" "::1" ];
|
||||
};
|
||||
|
||||
# Caddy-specific configuration (optional)
|
||||
services.caddy = {
|
||||
email = env.dns.letsEncryptEmail; # Email for Let's Encrypt
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
# Import environment-specific network parameters
|
||||
env = import ../../../network { };
|
||||
in {
|
||||
imports = [
|
||||
# Module for LXC containers
|
||||
(framework + "/modules/machine-types/lxc")
|
||||
# Technitium DNS Server service module
|
||||
(framework + "/modules/services/dns/default.nix")
|
||||
];
|
||||
|
||||
# Explicitly enable LXC machine type
|
||||
lxc.enable = true;
|
||||
|
||||
# Host identity (IP address 10.40.128.11/16 assigned via DHCP reservation)
|
||||
networking.hostName = "dns02";
|
||||
networking.domain = env.dns.domain;
|
||||
networking.useDHCP = true;
|
||||
|
||||
# Technitium DNS Server — secondary (replica) DNS server
|
||||
services.dns = {
|
||||
enable = true;
|
||||
recursion = env.dns.recursion;
|
||||
forwarders = env.dns.forwarders;
|
||||
# Uncomment and configure with agenix secret:
|
||||
# adminPasswordFile = config.age.secrets.dns-admin-password.path;
|
||||
listenAddresses = [ "10.40.128.11" "127.0.0.1" "::1" ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
# Module for LXC containers
|
||||
(framework + "/modules/machine-types/lxc")
|
||||
# Module for the git forge service (Forgejo)
|
||||
(framework + "/modules/services/git-forge/default.nix")
|
||||
];
|
||||
|
||||
# Explicitly enable LXC machine type
|
||||
lxc.enable = true;
|
||||
|
||||
# Host identity (IP address 10.40.128.20/16 assigned via DHCP reservation)
|
||||
networking.hostName = "git01";
|
||||
networking.domain = "prod.lagraula.fr";
|
||||
networking.useDHCP = true;
|
||||
|
||||
# Forgejo — self-hosted git forge
|
||||
services.git-forge = {
|
||||
enable = true;
|
||||
domain = "git.lagraula.fr";
|
||||
sshPort = 2222;
|
||||
httpPort = 3000;
|
||||
databaseType = "sqlite3";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# ╔══════════════════════════════════════════════════════════╗
|
||||
# ║ This machine runs Proxmox VE (not NixOS). ║
|
||||
# ║ This configuration serves as an inventory record ║
|
||||
# ║ documenting the machine's role and network settings. ║
|
||||
# ╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
networking.hostName = "hyper01";
|
||||
networking.hostId = "deadbeef01"; # Unique 8-char hex identifier
|
||||
|
||||
# Hypervisor management network
|
||||
# Proxmox management interface: 10.10.128.10/16
|
||||
# SSH: root@10.10.128.10:22
|
||||
# Proxmox web UI: https://10.10.128.10:8006
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# ╔══════════════════════════════════════════════════════════╗
|
||||
# ║ This machine runs Proxmox VE (not NixOS). ║
|
||||
# ║ This configuration serves as an inventory record ║
|
||||
# ║ documenting the machine's role and network settings. ║
|
||||
# ╚══════════════════════════════════════════════════════════╝
|
||||
|
||||
networking.hostName = "hyper02";
|
||||
networking.hostId = "deadbeef02"; # Unique 8-char hex identifier
|
||||
|
||||
# Hypervisor management network
|
||||
# Proxmox management interface: 10.10.128.11/16
|
||||
# SSH: root@10.10.128.11:22
|
||||
# Proxmox web UI: https://10.10.128.11:8006
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
# Module for LXC containers
|
||||
(framework + "/modules/machine-types/lxc")
|
||||
# Module for password manager service (Vaultwarden)
|
||||
(framework + "/modules/services/password-manager/default.nix")
|
||||
];
|
||||
|
||||
# Explicitly enable LXC machine type
|
||||
lxc.enable = true;
|
||||
|
||||
# Host identity (IP address 10.40.128.30/16 assigned via DHCP reservation)
|
||||
networking.hostName = "pass01";
|
||||
networking.domain = "prod.lagraula.fr";
|
||||
networking.useDHCP = true;
|
||||
|
||||
# Vaultwarden — Bitwarden-compatible password manager
|
||||
services.password-manager = {
|
||||
enable = true;
|
||||
domain = "pass.lagraula.fr";
|
||||
port = 8080;
|
||||
dbBackend = "sqlite";
|
||||
signupsAllowed = false; # Only admin creates accounts
|
||||
# Uncomment and configure with agenix secret:
|
||||
# adminTokenFile = config.age.secrets.vaultwarden-admin-token.path;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
# Import environment-specific network parameters
|
||||
env = import ../../../network { };
|
||||
in {
|
||||
imports = [
|
||||
# Module for LXC containers
|
||||
(framework + "/modules/machine-types/lxc")
|
||||
# Module for the reverse proxy
|
||||
(framework + "/modules/services/reverse-proxy/default.nix")
|
||||
];
|
||||
|
||||
# Host identity (IP address assigned via DHCP reservation)
|
||||
networking.hostName = "rp01";
|
||||
networking.domain = env.dns.domain;
|
||||
networking.useDHCP = true;
|
||||
|
||||
# Services to expose via the reverse proxy
|
||||
services.reverse-proxy.publicServices = [
|
||||
{ host = "git"; internalHost = "git01"; port = 3000; }
|
||||
{ host = "pass"; internalHost = "pass01"; port = 80; }
|
||||
# Add other services here (e.g. dns01, etc.)
|
||||
];
|
||||
|
||||
# Caddy-specific configuration (optional)
|
||||
services.caddy = {
|
||||
email = env.dns.letsEncryptEmail; # Email for Let's Encrypt
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Workstation configuration for PC-FRIDA
|
||||
# TODO: Fill in workstation-specific settings
|
||||
networking.hostName = "PC-FRIDA";
|
||||
networking.domain = "prod.lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all workstations in the production environment
|
||||
# This file is imported by all workstation configurations
|
||||
|
||||
# TODO: Move common workstation settings here later
|
||||
# Examples:
|
||||
# - Workstation-specific users/groups
|
||||
# - Workstation-specific packages
|
||||
# - Workstation-specific services
|
||||
# - Workstation-specific security policies
|
||||
# - Workstation-specific monitoring/alerting
|
||||
# - Locale: fr_FR.UTF-8 (for workstations)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Import environment-specific network parameters
|
||||
env = import ../../../network { };
|
||||
in {
|
||||
# Workstation configuration for gaia
|
||||
# TODO: Fill in workstation-specific settings
|
||||
networking.hostName = "gaia";
|
||||
networking.domain = env.dns.domain;
|
||||
|
||||
# Time settings
|
||||
time.timeZone = env.time.timeZone;
|
||||
time.hardwareClock = env.time.hardwareClock;
|
||||
|
||||
# NTP settings
|
||||
services.ntp.servers = env.time.ntpServers;
|
||||
|
||||
# Locale for workstations (French)
|
||||
i18n.defaultLocale = "fr_FR.UTF-8";
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Workstation configuration for sting
|
||||
# TODO: Fill in workstation-specific settings
|
||||
networking.hostName = "sting";
|
||||
networking.domain = "prod.lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
# Network Architecture
|
||||
|
||||
This directory contains the centralised, declarative network topology data for
|
||||
the infrastructure. It is the single source of truth for VLANs, subnets, and
|
||||
host addresses, consumable both by NixOS configurations (via `import`) and by
|
||||
external scripts (via `nix eval --json`).
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `vlans.nix` | VLAN definitions (ID, name, effective ID, description) |
|
||||
| `subnets.nix` | IPv4 and IPv6 prefix allocations per VLAN |
|
||||
| `hosts.nix` | Per-machine address assignments |
|
||||
| `default.nix` | Aggregator — imports all three files |
|
||||
|
||||
## Consumption
|
||||
|
||||
### From a NixOS configuration
|
||||
|
||||
```nix
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
network = import ../../network { };
|
||||
in {
|
||||
networking.hostName = "dns01";
|
||||
networking.useDHCP = true;
|
||||
}
|
||||
```
|
||||
|
||||
### From a shell script
|
||||
|
||||
```bash
|
||||
# Export all host data as JSON
|
||||
nix eval --json -f nixos-infra/network/default.nix hosts
|
||||
|
||||
# Get a specific host's IPv4 address
|
||||
nix eval -f nixos-infra/network/default.nix 'hosts.dns01.ipv4'
|
||||
|
||||
# Use with jq
|
||||
nix eval --json -f nixos-infra/network/default.nix hosts | jq '.dns01'
|
||||
```
|
||||
|
||||
## VLANs
|
||||
|
||||
| VLAN | ID | Effective ID | Description |
|
||||
|------|----|--------------|-------------|
|
||||
| INET | 1 | 1 | ISP uplink — untagged, out of project scope |
|
||||
| ADMIN | 90 | **100** | Management / hypervisors |
|
||||
| IOT | 200 | 200 | IoT devices |
|
||||
| GUEST | 300 | 300 | Guest network |
|
||||
| DMZ | 400 | 400 | Public-facing servers (LXC containers) |
|
||||
| INTERNAL | 500 | 500 | Internal workstations |
|
||||
|
||||
> **ADMIN exception:** VLAN 90 is treated as effective ID 100 for prefix
|
||||
> computation. This is a documented exception to avoid a risky production
|
||||
> change. A future renumbering may bring `id` and `effectiveId` into line.
|
||||
|
||||
## Addressing Scheme
|
||||
|
||||
### IPv4
|
||||
|
||||
The formula is `10.<effectiveId>.0.0/16` per VLAN.
|
||||
|
||||
To avoid conflicts with the lower half (DHCP pools, infrastructure
|
||||
services), **all static host addresses are allocated from the upper half**:
|
||||
`10.<effectiveId>.128.0/17`.
|
||||
|
||||
The gateway (`.1`) is distributed by DHCPv4 and is not statically assigned.
|
||||
|
||||
### IPv6
|
||||
|
||||
IPv6 prefixes are derived from `effectiveId / 100`:
|
||||
|
||||
| Type | Formula | Example (DMZ, effectiveId=400) |
|
||||
|------|---------|-------------------------------|
|
||||
| ULA | `fdb2:ae63:d45:d94<N>::/64` | `fdb2:ae63:d45:d944::/64` |
|
||||
| GUA | `2a01:e0a:2ea:d94<N>::/64` | `2a01:e0a:2ea:d944::/64` |
|
||||
|
||||
where `<N>` = `effectiveId / 100` (so 1 for ADMIN, 2 for IOT, …, 5 for
|
||||
INTERNAL).
|
||||
|
||||
IPv6 addresses are formed by appending the host's 64-bit token to the
|
||||
prefix, e.g. `fdb2:ae63:d45:d944::10` for dns01.
|
||||
|
||||
The gateway (`::1` in each subnet) is distributed via Router Advertisement.
|
||||
|
||||
### Host Address Allocation
|
||||
|
||||
IPv4 addresses are reserved via DHCP reservations. The `hosts.nix` file is
|
||||
the source of truth for these reservations and is intended to drive DHCP
|
||||
server configuration (Kea, ISC DHCP, or similar) in a future iteration.
|
||||
|
||||
IPv6 tokens are the last 64 bits of the host's address (expressed as `::XX`
|
||||
shorthand) and are expected to be distributed via SLAAC with the corresponding
|
||||
prefix.
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
1. **Why effectiveId?** The ADMIN VLAN has ID 90 but its IP prefixes are
|
||||
computed as if ID were 100. Rather than fixing the VLAN ID in production,
|
||||
the `effectiveId` field captures the exception explicitly and documents it.
|
||||
|
||||
2. **Why /16 per VLAN?** Each VLAN has a full `/16` IPv4 prefix, which is
|
||||
larger than typical container/workstation subnets. This is intentional:
|
||||
it simplifies VLAN-level routing and leaves room for future growth.
|
||||
|
||||
3. **Why DHCP and not static?** IPv4 addresses are distributed by DHCP, not
|
||||
statically configured on each host. This centralises address management
|
||||
and makes it easier to audit and change. The `hosts.nix` file is the
|
||||
source of truth for the DHCP server's configuration.
|
||||
|
||||
4. **Why NO static IP in configuration.nix?** In the current state, LXC
|
||||
containers have no static IP configuration at all — they rely entirely on
|
||||
DHCP. This is intentional: the addressing plan lives centrally in
|
||||
`network/hosts.nix` and the per-host `.nix` files only set `hostName` and
|
||||
`useDHCP = true`. A future DHCP service module (Kea, etc.) will consume
|
||||
`hosts.nix` to generate reservations.
|
||||
|
||||
5. **Why ULA + GUA for IPv6?** Both ULA (fd prefix) and GUA (2a01 prefix)
|
||||
are defined for each VLAN. ULA provides stable internal addressing
|
||||
independent of ISP changes; GUA provides global reachability for DMZ
|
||||
services and outbound connectivity for workstations.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Central network data source.
|
||||
#
|
||||
# Usage from a configuration.nix:
|
||||
# network = import ../../network { };
|
||||
# network.hosts.rp01.ipv4 → "10.40.128.199"
|
||||
#
|
||||
# Usage from a shell script (via `nix eval`):
|
||||
# nix eval --json -f network/default.nix hosts
|
||||
|
||||
{
|
||||
vlans = (import ./vlans.nix).vlans;
|
||||
subnets = (import ./subnets.nix).subnets;
|
||||
hosts = (import ./hosts.nix).hosts;
|
||||
dns = import ./dns.nix;
|
||||
time = import ./time.nix;
|
||||
proxy = import ./proxy.nix;
|
||||
smtp = import ./smtp.nix;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Environment-specific DNS domain
|
||||
domain = "prod.lagraula.fr";
|
||||
|
||||
# Default DNS servers for this environment
|
||||
defaultNameServers = [ "10.40.128.10" "10.40.128.11" ];
|
||||
|
||||
# Forwarders for this environment (e.g., upstream DNS)
|
||||
forwarders = [ "1.1.1.1" "8.8.8.8" ];
|
||||
|
||||
# Allow zone transfers only to secondary DNS servers in this environment
|
||||
allowZoneTransfer = [ "10.40.128.11" ];
|
||||
|
||||
# Recursion policy for this environment
|
||||
recursion = "AllowOnlyForPrivateNetworks";
|
||||
|
||||
# Email for Let's Encrypt (Caddy) — can be environment-specific
|
||||
letsEncryptEmail = "xavier@lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
# Host-to-network assignments.
|
||||
#
|
||||
# Each entry has:
|
||||
# vlan - Key referencing the VLAN in vlans.nix
|
||||
# type - Host role (hypervisor, lxc, workstation)
|
||||
# ipv4 - Static IPv4 address (reserved via DHCP reservation)
|
||||
# ipv6Token - Last 64-bit suffix of the IPv6 address (::XX notation)
|
||||
#
|
||||
# IPv4 addresses are allocated from the 10.<v>.128.0/17 upper-half
|
||||
# range to avoid conflicts with lower-half DHCP pools.
|
||||
#
|
||||
# IPv6 addresses are formed by appending the token to the VLAN's
|
||||
# ULA or GUA prefix, e.g. fdb2:ae63:d45:d944::10 for dns01.
|
||||
|
||||
hosts = {
|
||||
hyper01 = {
|
||||
vlan = "admin";
|
||||
type = "hypervisor";
|
||||
ipv4 = "10.10.128.10";
|
||||
ipv6Token = "::10";
|
||||
};
|
||||
|
||||
hyper02 = {
|
||||
vlan = "admin";
|
||||
type = "hypervisor";
|
||||
ipv4 = "10.10.128.11";
|
||||
ipv6Token = "::11";
|
||||
};
|
||||
|
||||
rp01 = {
|
||||
vlan = "dmz";
|
||||
type = "lxc";
|
||||
ipv4 = "10.40.128.199";
|
||||
ipv6Token = "::199";
|
||||
};
|
||||
|
||||
dns01 = {
|
||||
vlan = "dmz";
|
||||
type = "lxc";
|
||||
ipv4 = "10.40.128.10";
|
||||
ipv6Token = "::10";
|
||||
};
|
||||
|
||||
dns02 = {
|
||||
vlan = "dmz";
|
||||
type = "lxc";
|
||||
ipv4 = "10.40.128.11";
|
||||
ipv6Token = "::11";
|
||||
};
|
||||
|
||||
git01 = {
|
||||
vlan = "dmz";
|
||||
type = "lxc";
|
||||
ipv4 = "10.40.128.20";
|
||||
ipv6Token = "::20";
|
||||
};
|
||||
|
||||
pass01 = {
|
||||
vlan = "dmz";
|
||||
type = "lxc";
|
||||
ipv4 = "10.40.128.30";
|
||||
ipv6Token = "::30";
|
||||
};
|
||||
|
||||
gaia = {
|
||||
vlan = "internal";
|
||||
type = "workstation";
|
||||
ipv4 = "10.50.128.10";
|
||||
ipv6Token = "::10";
|
||||
};
|
||||
|
||||
"PC-FRIDA" = {
|
||||
vlan = "internal";
|
||||
type = "workstation";
|
||||
ipv4 = "10.50.128.11";
|
||||
ipv6Token = "::11";
|
||||
};
|
||||
|
||||
sting = {
|
||||
vlan = "internal";
|
||||
type = "workstation";
|
||||
ipv4 = "10.50.128.12";
|
||||
ipv6Token = "::12";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Proxy configuration for this environment
|
||||
# Currently no proxy is used — direct access for all hosts
|
||||
|
||||
# Workstations: no proxy
|
||||
workstations = {
|
||||
httpProxy = "";
|
||||
httpsProxy = "";
|
||||
noProxy = "";
|
||||
};
|
||||
|
||||
# Servers: no proxy
|
||||
servers = {
|
||||
httpProxy = "";
|
||||
httpsProxy = "";
|
||||
noProxy = "";
|
||||
};
|
||||
|
||||
# To enable a proxy later, uncomment and set the proxy URLs:
|
||||
# workstations = {
|
||||
# httpProxy = "http://proxy.prod.lagraula.fr:3128";
|
||||
# httpsProxy = "http://proxy.prod.lagraula.fr:3128";
|
||||
# noProxy = "localhost,127.0.0.1,::1,10.0.0.0/8";
|
||||
# };
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# SMTP relay configuration for this environment
|
||||
# Used by services that need to send email (e.g., monitoring alerts)
|
||||
|
||||
# SMTP relay host — can be an internal relay or external service
|
||||
relayHost = "smtp.lagraula.fr";
|
||||
relayPort = 587;
|
||||
|
||||
# TLS settings
|
||||
useTLS = true;
|
||||
useSTARTTLS = true;
|
||||
|
||||
# Authentication — currently none (open relay for internal use)
|
||||
# To add authentication later:
|
||||
# username = "noreply@prod.lagraula.fr";
|
||||
# passwordFile = config.age.secrets.smtp-password.path;
|
||||
|
||||
# Default "From" address for system emails
|
||||
fromAddress = "noreply@prod.lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
# Subnet definitions per VLAN.
|
||||
#
|
||||
# Prefix rules:
|
||||
# IPv4: 10.<effectiveId>.0.0/16 (hosts in the 10.<effectiveId>.128.0/17 range)
|
||||
# IPv6 ULA: fdb2:ae63:d45:d94<effectiveId/100>::/64
|
||||
# IPv6 GUA: 2a01:e0a:2ea:d94<effectiveId/100>::/64
|
||||
#
|
||||
# Gateways (.1 on each subnet) are distributed by DHCPv4 and Router
|
||||
# Advertisement (SLAAC). They are listed in comments for documentation.
|
||||
#
|
||||
# Minimum host prefix is /16 for IPv4 (the whole VLAN). Host addresses
|
||||
# are allocated from the upper half (10.<v>.128.0/17) to avoid conflicts
|
||||
# with future lower-half allocations (DHCP pools, etc.).
|
||||
#
|
||||
# INET (VLAN 1) is the untagged ISP uplink. It is out of scope of this
|
||||
# project and is listed for documentation only.
|
||||
|
||||
subnets = {
|
||||
inet = {
|
||||
vlan = "inet";
|
||||
description = "ISP uplink — out of scope";
|
||||
# No prefixes defined: inet is outside this project's addressing plan.
|
||||
};
|
||||
|
||||
admin = {
|
||||
vlan = "admin";
|
||||
description = "Management / hypervisors";
|
||||
ipv4 = {
|
||||
prefix = "10.10.0.0";
|
||||
prefixLength = 16;
|
||||
hostRange = "10.10.128.0/17";
|
||||
# gateway = "10.10.128.1";
|
||||
};
|
||||
ipv6 = {
|
||||
ula = {
|
||||
prefix = "fdb2:ae63:d45:d941::";
|
||||
prefixLength = 64;
|
||||
# gateway = "fdb2:ae63:d45:d941::1";
|
||||
};
|
||||
gua = {
|
||||
prefix = "2a01:e0a:2ea:d941::";
|
||||
prefixLength = 64;
|
||||
# gateway = "2a01:e0a:2ea:d941::1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
iot = {
|
||||
vlan = "iot";
|
||||
description = "IoT devices";
|
||||
ipv4 = {
|
||||
prefix = "10.20.0.0";
|
||||
prefixLength = 16;
|
||||
hostRange = "10.20.128.0/17";
|
||||
# gateway = "10.20.128.1";
|
||||
};
|
||||
ipv6 = {
|
||||
ula = {
|
||||
prefix = "fdb2:ae63:d45:d942::";
|
||||
prefixLength = 64;
|
||||
# gateway = "fdb2:ae63:d45:d942::1";
|
||||
};
|
||||
gua = {
|
||||
prefix = "2a01:e0a:2ea:d942::";
|
||||
prefixLength = 64;
|
||||
# gateway = "2a01:e0a:2ea:d942::1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
guest = {
|
||||
vlan = "guest";
|
||||
description = "Guest network";
|
||||
ipv4 = {
|
||||
prefix = "10.30.0.0";
|
||||
prefixLength = 16;
|
||||
hostRange = "10.30.128.0/17";
|
||||
# gateway = "10.30.128.1";
|
||||
};
|
||||
ipv6 = {
|
||||
ula = {
|
||||
prefix = "fdb2:ae63:d45:d943::";
|
||||
prefixLength = 64;
|
||||
# gateway = "fdb2:ae63:d45:d943::1";
|
||||
};
|
||||
gua = {
|
||||
prefix = "2a01:e0a:2ea:d943::";
|
||||
prefixLength = 64;
|
||||
# gateway = "2a01:e0a:2ea:d943::1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dmz = {
|
||||
vlan = "dmz";
|
||||
description = "Public-facing servers (LXC containers)";
|
||||
ipv4 = {
|
||||
prefix = "10.40.0.0";
|
||||
prefixLength = 16;
|
||||
hostRange = "10.40.128.0/17";
|
||||
# gateway = "10.40.128.1";
|
||||
};
|
||||
ipv6 = {
|
||||
ula = {
|
||||
prefix = "fdb2:ae63:d45:d944::";
|
||||
prefixLength = 64;
|
||||
# gateway = "fdb2:ae63:d45:d944::1";
|
||||
};
|
||||
gua = {
|
||||
prefix = "2a01:e0a:2ea:d944::";
|
||||
prefixLength = 64;
|
||||
# gateway = "2a01:e0a:2ea:d944::1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
internal = {
|
||||
vlan = "internal";
|
||||
description = "Internal workstations and trusted devices";
|
||||
ipv4 = {
|
||||
prefix = "10.50.0.0";
|
||||
prefixLength = 16;
|
||||
hostRange = "10.50.128.0/17";
|
||||
# gateway = "10.50.128.1";
|
||||
};
|
||||
ipv6 = {
|
||||
ula = {
|
||||
prefix = "fdb2:ae63:d45:d945::";
|
||||
prefixLength = 64;
|
||||
# gateway = "fdb2:ae63:d45:d945::1";
|
||||
};
|
||||
gua = {
|
||||
prefix = "2a01:e0a:2ea:d945::";
|
||||
prefixLength = 64;
|
||||
# gateway = "2a01:e0a:2ea:d945::1";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# NTP servers for this environment
|
||||
# The gateway acts as the NTP server (IPv4 .1, IPv6 ::1)
|
||||
ntpServers = [
|
||||
"10.10.128.1" # IPv4 gateway
|
||||
"fd00::1" # IPv6 gateway
|
||||
];
|
||||
|
||||
# Time zone for this environment
|
||||
timeZone = "Europe/Paris";
|
||||
|
||||
# Hardware clock setting
|
||||
hardwareClock = "UTC";
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{
|
||||
# VLANs used in the infrastructure.
|
||||
#
|
||||
# Each VLAN entry has:
|
||||
# id - The actual IEEE 802.1Q VLAN ID on the network equipment
|
||||
# name - Short label
|
||||
# effectiveId - The numeric value used to compute IPv4/IPv6 prefixes.
|
||||
# This matches `id` for most VLANs, but can differ when
|
||||
# the VLAN ID does not follow the mathematical scheme.
|
||||
# e.g. ADMIN is VLAN 90 but prefixes are computed as if VLAN 100.
|
||||
# description - Free-text purpose of the VLAN
|
||||
#
|
||||
# VLAN ID 1 (INET) is the untagged ISP uplink. It is listed here for
|
||||
# documentation only and is out of scope of this project.
|
||||
|
||||
vlans = {
|
||||
inet = {
|
||||
id = 1;
|
||||
name = "INET";
|
||||
effectiveId = 1;
|
||||
description = "ISP uplink — untagged, out of project scope";
|
||||
};
|
||||
|
||||
admin = {
|
||||
id = 90;
|
||||
name = "ADMIN";
|
||||
effectiveId = 100; # Exception: treated as 100 for prefix computation
|
||||
description = "Management / hypervisors";
|
||||
};
|
||||
|
||||
iot = {
|
||||
id = 200;
|
||||
name = "IOT";
|
||||
effectiveId = 200;
|
||||
description = "IoT devices";
|
||||
};
|
||||
|
||||
guest = {
|
||||
id = 300;
|
||||
name = "GUEST";
|
||||
effectiveId = 300;
|
||||
description = "Guest network";
|
||||
};
|
||||
|
||||
dmz = {
|
||||
id = 400;
|
||||
name = "DMZ";
|
||||
effectiveId = 400;
|
||||
description = "Public-facing servers (LXC containers)";
|
||||
};
|
||||
|
||||
internal = {
|
||||
id = 500;
|
||||
name = "INTERNAL";
|
||||
effectiveId = 500;
|
||||
description = "Internal workstations and trusted devices";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Ignore all age-encrypted secret files
|
||||
*.age
|
||||
|
||||
# But keep the pubkeys directory (for tracked .age pubkey files)
|
||||
!pubkeys/
|
||||
@@ -0,0 +1,4 @@
|
||||
# Users
|
||||
User account configurations and environment setup.
|
||||
Manages SSH keys, sudo permissions, and Home Manager dotfiles.
|
||||
Centralizes access control and admin profiles.
|
||||
@@ -0,0 +1,11 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# User configuration for frida
|
||||
# TODO: Fill in user-specific settings
|
||||
users.users.frida = {
|
||||
isNormalUser = true;
|
||||
description = "Frida";
|
||||
extraGroups = [ "wheel" ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# User configuration for guest
|
||||
# TODO: Fill in user-specific settings
|
||||
users.users.guest = {
|
||||
isNormalUser = true;
|
||||
description = "Guest";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# User configuration for root
|
||||
# TODO: Fill in root-specific settings
|
||||
users.root = {
|
||||
openssh.authorizedKeys.keys = [
|
||||
# Add SSH public keys for root access
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# User configuration for xavier
|
||||
# TODO: Fill in user-specific settings
|
||||
users.users.xavier = {
|
||||
isNormalUser = true;
|
||||
description = "Xavier";
|
||||
extraGroups = [ "wheel" ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Pin to the same framework commit as production — update when testing
|
||||
# new framework features in staging before rolling to production.
|
||||
frameworkRev = "c53d997d075236f6d8c2a8e9db0238e46391735a";
|
||||
framework = builtins.fetchGit {
|
||||
url = "ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra-framework.git";
|
||||
rev = frameworkRev;
|
||||
};
|
||||
in {
|
||||
imports = [
|
||||
(framework + "/lib")
|
||||
(framework + "/overlays/custom-pkgs.nix")
|
||||
];
|
||||
|
||||
# Staging environment-wide settings
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all hosts in the stage environment
|
||||
# This file is imported by all host configurations (servers and workstations)
|
||||
|
||||
# TODO: Move common settings here later
|
||||
# Examples:
|
||||
# - Common users/groups
|
||||
# - Common packages
|
||||
# - Common services
|
||||
# - Common security policies
|
||||
# - Common monitoring/alerting
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all servers in the stage environment
|
||||
# This file is imported by all server configurations
|
||||
|
||||
# TODO: Move common server settings here later
|
||||
# Examples:
|
||||
# - Server-specific users/groups
|
||||
# - Server-specific packages
|
||||
# - Server-specific services
|
||||
# - Server-specific security policies
|
||||
# - Server-specific monitoring/alerting
|
||||
# - Locale: en_US.UTF-8 (for servers)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Common settings for all workstations in the stage environment
|
||||
# This file is imported by all workstation configurations
|
||||
|
||||
# TODO: Move common workstation settings here later
|
||||
# Examples:
|
||||
# - Workstation-specific users/groups
|
||||
# - Workstation-specific packages
|
||||
# - Workstation-specific services
|
||||
# - Workstation-specific security policies
|
||||
# - Workstation-specific monitoring/alerting
|
||||
# - Locale: fr_FR.UTF-8 (for workstations)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# Central network data source for the stage environment.
|
||||
#
|
||||
# Usage from a configuration.nix:
|
||||
# network = import ../../network { };
|
||||
# network.dns.domain → "stage.lagraula.fr"
|
||||
# network.time.timeZone → "Europe/Paris"
|
||||
#
|
||||
# Usage from a shell script (via `nix eval`):
|
||||
# nix eval --json -f network/default.nix dns
|
||||
|
||||
{
|
||||
dns = import ./dns.nix;
|
||||
time = import ./time.nix;
|
||||
proxy = import ./proxy.nix;
|
||||
smtp = import ./smtp.nix;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Environment-specific DNS domain
|
||||
domain = "stage.lagraula.fr";
|
||||
|
||||
# Default DNS servers for this environment
|
||||
# These are the IPs of the DNS servers (e.g., dns-stage01, dns-stage02)
|
||||
# that will be deployed in this environment.
|
||||
defaultNameServers = [ "10.40.128.10" "10.40.128.11" ];
|
||||
|
||||
# Forwarders for this environment (e.g., upstream DNS)
|
||||
forwarders = [ "1.1.1.1" "8.8.8.8" ];
|
||||
|
||||
# Allow zone transfers only to secondary DNS servers in this environment
|
||||
allowZoneTransfer = [ "10.40.128.11" ];
|
||||
|
||||
# Recursion policy for this environment
|
||||
recursion = "AllowOnlyForPrivateNetworks";
|
||||
|
||||
# Email for Let's Encrypt (Caddy) — can be environment-specific
|
||||
letsEncryptEmail = "xavier@lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# Proxy configuration for this environment
|
||||
# Currently no proxy is used — direct access for all hosts
|
||||
|
||||
# Workstations: no proxy
|
||||
workstations = {
|
||||
httpProxy = "";
|
||||
httpsProxy = "";
|
||||
noProxy = "";
|
||||
};
|
||||
|
||||
# Servers: no proxy
|
||||
servers = {
|
||||
httpProxy = "";
|
||||
httpsProxy = "";
|
||||
noProxy = "";
|
||||
};
|
||||
|
||||
# To enable a proxy later, uncomment and set the proxy URLs:
|
||||
# workstations = {
|
||||
# httpProxy = "http://proxy.stage.lagraula.fr:3128";
|
||||
# httpsProxy = "http://proxy.stage.lagraula.fr:3128";
|
||||
# noProxy = "localhost,127.0.0.1,::1,10.0.0.0/8";
|
||||
# };
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# SMTP relay configuration for this environment
|
||||
# Used by services that need to send email (e.g., monitoring alerts)
|
||||
|
||||
# SMTP relay host — can be an internal relay or external service
|
||||
relayHost = "smtp.lagraula.fr";
|
||||
relayPort = 587;
|
||||
|
||||
# TLS settings
|
||||
useTLS = true;
|
||||
useSTARTTLS = true;
|
||||
|
||||
# Authentication — currently none (open relay for internal use)
|
||||
# To add authentication later:
|
||||
# username = "noreply@stage.lagraula.fr";
|
||||
# passwordFile = config.age.secrets.smtp-password.path;
|
||||
|
||||
# Default "From" address for system emails
|
||||
fromAddress = "noreply@stage.lagraula.fr";
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
# NTP servers for this environment
|
||||
# The gateway acts as the NTP server (IPv4 .1, IPv6 ::1)
|
||||
ntpServers = [
|
||||
"10.10.128.1" # IPv4 gateway
|
||||
"fd00::1" # IPv6 gateway
|
||||
];
|
||||
|
||||
# Time zone for this environment
|
||||
timeZone = "Europe/Paris";
|
||||
|
||||
# Hardware clock setting
|
||||
hardwareClock = "UTC";
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
# Module pour les conteneurs LXC
|
||||
(builtins.callPackage ../../../modules/machine-types/lxc.nix {})
|
||||
# Module pour le reverse proxy
|
||||
(builtins.callPackage ../../../modules/services/reverse-proxy/default.nix {})
|
||||
];
|
||||
|
||||
# Configuration réseau (IPv4 + IPv6)
|
||||
networking.hostName = "rp01";
|
||||
networking.interfaces.eth0.ipv4.addresses = [
|
||||
{ address = "10.40.0.199"; prefixLength = 24; }
|
||||
];
|
||||
# networking.interfaces.eth0.ipv6.addresses = [
|
||||
# { address = "2001:db8::1"; prefixLength = 64; }
|
||||
# ];
|
||||
|
||||
# Liste des services à exposer via le reverse proxy
|
||||
services.reverse-proxy.publicServices = [
|
||||
{ host = "gitea"; internalHost = "gitea01"; port = 3000; }
|
||||
{ host = "vaultwarden"; internalHost = "vault01"; port = 80; }
|
||||
# Ajoutez ici d'autres services (ex: dns01, etc.)
|
||||
];
|
||||
|
||||
# Configuration spécifique à Caddy (optionnelle)
|
||||
services.caddy = {
|
||||
# Vous pouvez surcharger des paramètres ici si besoin
|
||||
email = "xavier@lagraula.fr"; # Email pour Let's Encrypt
|
||||
};
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
{ config, modulesPath, pkgs, lib, ... }:
|
||||
{
|
||||
imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ];
|
||||
nix.settings = { sandbox = false; };
|
||||
proxmoxLXC = {
|
||||
manageNetwork = false;
|
||||
privileged = true;
|
||||
};
|
||||
|
||||
# Enable LXC specific options
|
||||
options.lxc = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "Enable LXC machine type";
|
||||
};
|
||||
};
|
||||
|
||||
services.fstrim.enable = false; # Let Proxmox host handle fstrim
|
||||
|
||||
# Cache DNS lookups to improve performance
|
||||
services.resolved = {
|
||||
extraConfig = ''
|
||||
Cache=true
|
||||
CacheFromLocalhost=true
|
||||
'';
|
||||
};
|
||||
|
||||
# Prise en charge IPv6
|
||||
# TODO : check whether explicitly enabling IPv6 is still encessary in 2026
|
||||
networking.ipv6.forwarding = true;
|
||||
|
||||
# Default configuration for a LXC container
|
||||
config = lib.mkIf config.lxc.enable {
|
||||
# Disabling useless services
|
||||
services.avahi.daemon.enable = false; # TODO : review the need for avahi in a container
|
||||
services.bluetooth.enable = false;
|
||||
services.printing.enable = false;
|
||||
|
||||
# Optimzing for conainters
|
||||
boot.kernelModules = [ ]; # TODO : review the disabling of all kernelModules in a container
|
||||
powerManagement.enable = false;
|
||||
|
||||
# Limiter les ressources si nécessaire
|
||||
# TODO : review the need to limit ZFS pools in the LXC container configuration, in my ZFSless context
|
||||
boot.zfs.extraPools = [ ];
|
||||
|
||||
};
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Récupère la liste des services depuis la configuration
|
||||
publicServices = config.services.reverse-proxy.publicServices or [];
|
||||
in
|
||||
{
|
||||
# Options pour le module reverse-proxy
|
||||
options.services.reverse-proxy = {
|
||||
publicServices = lib.mkOption {
|
||||
type = lib.types.listOf (lib.types.submodule {
|
||||
options = {
|
||||
host = lib.mkOption { type = lib.types.str; };
|
||||
internalHost = lib.mkOption { type = lib.types.str; };
|
||||
port = lib.mkOption { type = lib.types.int; default = 80; };
|
||||
};
|
||||
});
|
||||
default = [];
|
||||
description = "Liste des services à exposer via le reverse proxy";
|
||||
};
|
||||
};
|
||||
|
||||
# Configuration de Caddy
|
||||
config = lib.mkIf (config.services.reverse-proxy.publicServices or []) != [] {
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
virtualHosts = map (service: {
|
||||
host = "${service.host}.lagraula.fr";
|
||||
reverseProxy = "http://${service.internalHost}.lagraula.fr:${toString service.port}";
|
||||
# Challenge ACME HTTP-01 (par défaut)
|
||||
tls = {
|
||||
email = "xavier@lagraula.fr"; # À adapter
|
||||
};
|
||||
}) (config.services.reverse-proxy.publicServices or []);
|
||||
|
||||
# Configuration globale pour Caddy
|
||||
extraConfig = ''
|
||||
{
|
||||
# Rate limiting global (optionnel)
|
||||
rate_limit {
|
||||
requests 100
|
||||
burst 200
|
||||
interval 1m
|
||||
}
|
||||
# Logging
|
||||
log {
|
||||
output file /var/log/caddy/access.log
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# Ouvrir les ports firewall pour HTTP/HTTPS
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
networking.firewall.allowedUDPPorts = [];
|
||||
};
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
bridge=
|
||||
cmode=
|
||||
cores=
|
||||
domain=
|
||||
dry_run=false
|
||||
help=false
|
||||
ip=
|
||||
memory=
|
||||
password=
|
||||
pve_host=
|
||||
pve_password=
|
||||
pve_port=
|
||||
pve_ssh_key=
|
||||
pve_user=
|
||||
rootfs_size=
|
||||
ssh_public_keys=
|
||||
swap=
|
||||
tags=
|
||||
template=
|
||||
unprivileged=
|
||||
vlan=
|
||||
short_name='2'
|
||||
@@ -0,0 +1,107 @@
|
||||
# Scripts
|
||||
|
||||
Utility scripts for infrastructure management.
|
||||
Covers deployment, LXC container creation and bootstrap,
|
||||
initial configuration of new NixOS machines, and age key generation.
|
||||
|
||||
## Scripts Overview
|
||||
|
||||
### `create-lxc-nixos.sh` — Create and deploy a NixOS LXC container
|
||||
|
||||
Creates a NixOS LXC container on a remote Proxmox VE hypervisor, then
|
||||
bootstraps it with the initial NixOS configuration and runs `deploy.sh`
|
||||
to apply the host-specific configuration.
|
||||
|
||||
```bash
|
||||
# Usage
|
||||
./create-lxc-nixos.sh <short_name> [options]
|
||||
|
||||
# Example: create dns01 with static IPv4 and IPv6 token
|
||||
./create-lxc-nixos.sh dns01 \
|
||||
--ip 10.40.0.10/24 \
|
||||
--ip6 ::a:b:c:d \
|
||||
--pve-host pve01.prod.lagraula.fr
|
||||
|
||||
# Dry run to preview the commands
|
||||
./create-lxc-nixos.sh dns01 --dry-run
|
||||
```
|
||||
|
||||
**Bootstrap process:**
|
||||
1. `pct create` — create the container from the NixOS template
|
||||
2. `pct start <CT_ID>` — start the container
|
||||
3. Wait for the container to be ready (polling `pct exec`)
|
||||
4. `pct push initial-lxc-configuration.nix` → `/etc/nixos/configuration.nix`
|
||||
5. `pct push deploy.sh` → `/usr/local/bin/deploy-nixos`
|
||||
6. `pct exec nixos-rebuild switch` — apply initial config (SSH, git, curl)
|
||||
7. `pct exec deploy-nixos` — clone repo and apply host-specific config
|
||||
|
||||
### `deploy.sh` — Deploy NixOS configuration from Git repository
|
||||
|
||||
Clones or updates the nixos-infra repository, detects the hostname,
|
||||
finds the corresponding configuration file, and applies it with
|
||||
`nixos-rebuild switch`.
|
||||
|
||||
```bash
|
||||
# Usage
|
||||
./deploy.sh [options]
|
||||
|
||||
# Options
|
||||
-u, --repo-url URL Git repository URL (default: https://gitea.lagraula.fr/...)
|
||||
-d, --repo-dir DIR Local directory (default: /etc/nixos-infra)
|
||||
-b, --branch BRANCH Git branch (default: main)
|
||||
-n, --dry-run Simulate without making changes
|
||||
```
|
||||
|
||||
**Configuration lookup order:**
|
||||
1. `hosts/servers/<hostname>/configuration.nix`
|
||||
2. `hosts/workstations/<hostname>/configuration.nix`
|
||||
|
||||
### `initial-lxc-configuration.nix` — Bootstrap NixOS configuration (LXC)
|
||||
|
||||
Minimal NixOS configuration pushed to a new LXC container during the
|
||||
bootstrap phase. Installs SSH, git, and curl so the container can
|
||||
clone the repository and apply its specific configuration.
|
||||
|
||||
**Pushed to `/etc/nixos/configuration.nix` by `create-lxc-nixos.sh`.**
|
||||
|
||||
### `gen-secrets-keys.sh` — Generate age public keys for agenix
|
||||
|
||||
Connects to each host in the infrastructure, retrieves its SSH host
|
||||
key via `ssh-keyscan`, converts it to an age public key with
|
||||
`ssh-to-age`, and stores it in `secrets/pubkeys/<hostname>.age`.
|
||||
|
||||
```bash
|
||||
# Usage
|
||||
./gen-secrets-keys.sh
|
||||
|
||||
# Prerequisites
|
||||
# nix-shell -p ssh-to-age
|
||||
```
|
||||
|
||||
**After generating keys, encrypt secrets with:**
|
||||
```bash
|
||||
age -r $(cat secrets/pubkeys/<hostname>.age) -o secrets/<name>.age
|
||||
agenix -e secrets/<name>.age
|
||||
```
|
||||
|
||||
### `update-nixpkgs.sh` — Update the nixpkgs pin
|
||||
|
||||
Updates `pkgs/nixpkgs.json` with the latest commit from nixpkgs stable.
|
||||
|
||||
## Deployment workflow (LXC containers)
|
||||
|
||||
```
|
||||
create-lxc-nixos.sh # Step 1: Create + bootstrap
|
||||
└─ pct create
|
||||
└─ pct push initial-lxc-configuration.nix
|
||||
└─ pct push deploy.sh
|
||||
└─ pct exec nixos-rebuild switch
|
||||
└─ pct exec deploy.sh # Step 2: Clone repo + apply config
|
||||
└─ git clone
|
||||
└─ nixos-rebuild switch (host-specific)
|
||||
```
|
||||
|
||||
For subsequent updates on an already-deployed container:
|
||||
```bash
|
||||
ssh <hostname>
|
||||
sudo /usr/local/bin/deploy-nixos
|
||||
@@ -10,35 +10,42 @@ if ! command -v docopts &> /dev/null; then
|
||||
fi
|
||||
|
||||
# --- Usage and Documentation ---
|
||||
usage="Create and configure an LXC container on a remote Proxmox VE 9 server.
|
||||
usage="Create, bootstrap and deploy a NixOS LXC container on a remote Proxmox VE 9 server.
|
||||
|
||||
Usage:
|
||||
$0 <short_name> [options]
|
||||
$0 -h|--help
|
||||
|
||||
Options:
|
||||
-h, --help Show this message.
|
||||
-t, --template TEMPLATE LXC template (e.g. local:vztmpl/nixos-unstable).
|
||||
-r, --rootfs-size SIZE Root filesystem size (e.g. 8G).
|
||||
-c, --cores CORES Number of CPU cores.
|
||||
-m, --memory MEMORY RAM in MiB.
|
||||
-s, --swap SWAP Swap in MiB.
|
||||
-p, --password PASSWORD Root password for the container.
|
||||
-b, --bridge BRIDGE Network bridge (e.g. vmbr0).
|
||||
-v, --vlan VLAN VLAN tag (e.g. tag=10).
|
||||
-d, --domain DOMAIN DNS domain.
|
||||
-u, --unprivileged UNPRIV Unprivileged container (0 or 1).
|
||||
-i, --ip IP Static IP (e.g. 192.168.1.100/24).
|
||||
-C, --cmode CMODE Console mode (console or tty). Default: console.
|
||||
-T, --tags TAGS Tags for the container (optional).
|
||||
-k, --ssh-public-keys KEYS SSH public keys for the container.
|
||||
--pve-host HOST Proxmox host (e.g. pve).
|
||||
--pve-user USER Proxmox user (default: admin).
|
||||
--pve-port PORT SSH port for Proxmox (default: 22).
|
||||
--pve-ssh-key KEY SSH key file for authentication.
|
||||
--dry-run Simulate container creation without execution.
|
||||
-h, --help Show this message.
|
||||
-t, --template TEMPLATE LXC template (e.g. local:vztmpl/nixos-unstable).
|
||||
-r, --rootfs-size SIZE Root filesystem size (e.g. 8G).
|
||||
-c, --cores CORES Number of CPU cores.
|
||||
-m, --memory MEMORY RAM in MiB.
|
||||
-s, --swap SWAP Swap in MiB.
|
||||
-p, --password PASSWORD Root password for the container.
|
||||
-b, --bridge BRIDGE Network bridge (e.g. vmbr0).
|
||||
-v, --vlan VLAN VLAN tag (e.g. tag=10).
|
||||
-d, --domain DOMAIN DNS domain.
|
||||
-u, --unprivileged UNPRIV Unprivileged container (0 or 1).
|
||||
-i, --ip IP Static IPv4 address (e.g. 192.168.1.100/24).
|
||||
--ip6 TOKEN IPv6 token for SLAAC (e.g. ::1:2:3:4).
|
||||
-C, --cmode CMODE Console mode (console or tty). Default: console.
|
||||
-T, --tags TAGS Tags for the container (optional).
|
||||
-k, --ssh-public-keys KEYS SSH public keys for the container.
|
||||
--pve-host HOST Proxmox host (e.g. pve).
|
||||
--pve-user USER Proxmox user (default: admin).
|
||||
--pve-port PORT SSH port for Proxmox (default: 22).
|
||||
--pve-ssh-key KEY SSH key file for authentication.
|
||||
--initial-config FILE Initial NixOS configuration file to push
|
||||
[default: ./initial-lxc-configuration.nix].
|
||||
--repo-url URL Git repository URL for deploy.sh
|
||||
[default: https://gitea.lagraula.fr/xavier/nixos-infra.git].
|
||||
--branch BRANCH Git branch for deploy.sh [default: main].
|
||||
--skip-deploy Skip the post-creation bootstrap (push + nixos-rebuild).
|
||||
--dry-run Simulate container creation without execution.
|
||||
|
||||
Optional configuration files:
|
||||
Optional configuration files (loaded in order, later overrides earlier):
|
||||
/etc/nixos-infra/hosts/config
|
||||
\${XDG_CONFIG_HOME}/nixos-infra/hosts/config
|
||||
./config
|
||||
@@ -64,10 +71,17 @@ VLAN="${VLAN:-}"
|
||||
DOMAIN="${DOMAIN:-lagraula.fr}"
|
||||
UNPRIVILEGED="${UNPRIVILEGED:-0}"
|
||||
IP="${IP:-}"
|
||||
IP6="${IP6:-}"
|
||||
CMODE="${CMODE:-console}"
|
||||
TAGS="${TAGS:-}"
|
||||
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
|
||||
|
||||
# Bootstrap
|
||||
INITIAL_CONFIG="${INITIAL_CONFIG:-./initial-lxc-configuration.nix}"
|
||||
REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
SKIP_DEPLOY="${SKIP_DEPLOY:-false}"
|
||||
|
||||
# --- Parse Arguments with docopts (Highest priority) ---
|
||||
# set +e is to prevent set -e from eating the error message from docopts.
|
||||
# This code is up here to prevent useless error messages to be printed
|
||||
@@ -90,18 +104,17 @@ for conffile in ${CONFIG_FILES[*]}; do
|
||||
source "$conffile"
|
||||
set +a
|
||||
else
|
||||
echo "❌ $conffile not found."
|
||||
echo "ℹ️ $conffile not found (optional)."
|
||||
fi
|
||||
done
|
||||
|
||||
# Proxmox Server
|
||||
# Override with CLI arguments (have priority over config files)
|
||||
PVE_HOST="${pve_host:-$PVE_HOST}"
|
||||
PVE_USER="${pve_user:-$PVE_USER}"
|
||||
PVE_PORT="${pve_port:-$PVE_PORT}"
|
||||
PVE_SSH_KEY="${pve_ssh_key:-$PVE_SSH_KEY}"
|
||||
DRY_RUN="${dry_run:-$DRY_RUN}"
|
||||
|
||||
# LXC Container
|
||||
TEMPLATE="${template:-$TEMPLATE}"
|
||||
ROOTFS_SIZE="${rootfs_size:-$ROOTFS_SIZE}"
|
||||
CORES="${cores:-$CORES}"
|
||||
@@ -113,10 +126,16 @@ VLAN="${vlan:-$VLAN}"
|
||||
DOMAIN="${domain:-$DOMAIN}"
|
||||
UNPRIVILEGED="${unprivileged:-$UNPRIVILEGED}"
|
||||
IP="${ip:-$IP}"
|
||||
IP6="${ip6:-$IP6}"
|
||||
CMODE="${cmode:-$CMODE}"
|
||||
TAGS="${tags:-$TAGS}"
|
||||
SSH_PUBLIC_KEYS="${ssh_public_keys:-$SSH_PUBLIC_KEYS}"
|
||||
|
||||
INITIAL_CONFIG="${initial_config:-$INITIAL_CONFIG}"
|
||||
REPO_URL="${repo_url:-$REPO_URL}"
|
||||
BRANCH="${branch:-$BRANCH}"
|
||||
SKIP_DEPLOY="${skip_deploy:-$SKIP_DEPLOY}"
|
||||
|
||||
# --- SSH Key Default Logic ---
|
||||
if [ "$PVE_SSH_KEY" = "default" ]; then
|
||||
PVE_SSH_KEY="${HOME}/.ssh/id_${PVE_USER}"
|
||||
@@ -124,19 +143,19 @@ fi
|
||||
|
||||
# --- Critical Parameters Validation ---
|
||||
mandatory_params=(
|
||||
"TEMPLATE" \
|
||||
"ROOTFS_SIZE" \
|
||||
"CORES" \
|
||||
"MEMORY" \
|
||||
"SWAP" \
|
||||
"PASSWORD" \
|
||||
"BRIDGE" \
|
||||
"DOMAIN" \
|
||||
"UNPRIVILEGED" \
|
||||
"CMODE" \
|
||||
"SSH_PUBLIC_KEYS" \
|
||||
"PVE_HOST" \
|
||||
"PVE_USER" \
|
||||
"TEMPLATE"
|
||||
"ROOTFS_SIZE"
|
||||
"CORES"
|
||||
"MEMORY"
|
||||
"SWAP"
|
||||
"PASSWORD"
|
||||
"BRIDGE"
|
||||
"DOMAIN"
|
||||
"UNPRIVILEGED"
|
||||
"CMODE"
|
||||
"SSH_PUBLIC_KEYS"
|
||||
"PVE_HOST"
|
||||
"PVE_USER"
|
||||
"PVE_PORT"
|
||||
)
|
||||
missing_params=()
|
||||
@@ -145,7 +164,7 @@ for param in ${mandatory_params[*]}; do
|
||||
done
|
||||
if [ ${#missing_params[@]} -gt 0 ]; then
|
||||
echo "❌ Error: The following necessary parameters are missing: ${missing_params[*]}" >&2
|
||||
echo "❌ Error: Plesase provide them through one the proposed config file or the command line." >&2
|
||||
echo "❌ Error: Please provide them through a config file or the command line." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -155,6 +174,22 @@ if [ ! -f "$PVE_SSH_KEY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate initial-config.nix exists (unless --skip-deploy)
|
||||
if [ "$SKIP_DEPLOY" != "true" ] && [ ! -f "$INITIAL_CONFIG" ]; then
|
||||
echo "❌ Error: Initial NixOS configuration '$INITIAL_CONFIG' not found." >&2
|
||||
echo " Provide a valid path with --initial-config or use --skip-deploy." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate deploy.sh exists (unless --skip-deploy)
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DEPLOY_SCRIPT="${SCRIPT_DIR}/deploy.sh"
|
||||
if [ "$SKIP_DEPLOY" != "true" ] && [ ! -f "$DEPLOY_SCRIPT" ]; then
|
||||
echo "❌ Error: deploy.sh not found at '$DEPLOY_SCRIPT'." >&2
|
||||
echo " The bootstrap phase requires deploy.sh to be present." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- SSH Connection to Proxmox Server ---
|
||||
run_proxmox() {
|
||||
local ssh_cmd="ssh -p $PVE_PORT"
|
||||
@@ -174,9 +209,15 @@ fi
|
||||
if [ -n "$IP" ]; then
|
||||
NET_OPTS="$NET_OPTS,ip=$IP"
|
||||
fi
|
||||
set -x
|
||||
# IPv6: use SLAAC with a token if provided, otherwise DHCP
|
||||
if [ -n "$IP6" ]; then
|
||||
NET_OPTS="$NET_OPTS,ip6=auto,token6=${IP6}"
|
||||
else
|
||||
NET_OPTS="$NET_OPTS,ip6=dhcp"
|
||||
fi
|
||||
|
||||
# --- Container Creation ---
|
||||
echo "🚀 Creating LXC container $short_name on $PVE_HOST..."
|
||||
echo "🚀 Creating LXC container $short_name on $PVE_HOST (domain: $DOMAIN)..."
|
||||
CREATE_CMD="pct create $ROOTFS_SIZE $TEMPLATE --cores $CORES \
|
||||
--memory $MEMORY --swap $SWAP --hostname $short_name.$DOMAIN \
|
||||
--password $PASSWORD --unprivileged $UNPRIVILEGED --net0 $NET_OPTS \
|
||||
@@ -192,12 +233,89 @@ echo "🔧 Command to execute on $PVE_HOST: $DISPLAY_CMD"
|
||||
|
||||
# Execute or simulate
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "🧪 Dry run: Skipping actual execution."
|
||||
else
|
||||
LXC_ID=$(run_proxmox "$CREATE_CMD" | grep -oP '\d+')
|
||||
if [ -z "$LXC_ID" ]; then
|
||||
echo "❌ Error: Failed to create the container." >&2
|
||||
echo "🧪 Dry run mode:"
|
||||
echo " - Container creation skipped"
|
||||
echo " - Bootstrap phase skipped"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LXC_ID=$(run_proxmox "$CREATE_CMD" | grep -oP '\d+')
|
||||
if [ -z "$LXC_ID" ]; then
|
||||
echo "❌ Error: Failed to create the container." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ LXC container $short_name created successfully (ID: $LXC_ID)."
|
||||
|
||||
# --- Bootstrap Phase (unless --skip-deploy) ---
|
||||
if [ "$SKIP_DEPLOY" = "true" ]; then
|
||||
echo "⏭️ --skip-deploy set. Container created but not bootstrapped."
|
||||
echo " Start it manually with: pct start $LXC_ID"
|
||||
echo " Then apply a configuration manually."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🚀 Starting bootstrap phase for CT $LXC_ID..."
|
||||
|
||||
# 1. Start the container
|
||||
echo "▶️ Starting container $LXC_ID..."
|
||||
run_proxmox "pct start $LXC_ID" || {
|
||||
echo "❌ Error: Failed to start container $LXC_ID." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 2. Wait for the container to be ready (SSH or pct exec available)
|
||||
echo "⏳ Waiting for container to be ready..."
|
||||
for i in $(seq 1 30); do
|
||||
if run_proxmox "pct exec $LXC_ID -- true" 2>/dev/null; then
|
||||
echo "✅ Container $LXC_ID is ready."
|
||||
break
|
||||
fi
|
||||
if [ "$i" -eq 30 ]; then
|
||||
echo "❌ Error: Container $LXC_ID did not become ready in time." >&2
|
||||
echo " You can retry bootstrap manually." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "✅ LXC container $short_name created successfully (ID: $LXC_ID)."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 3. Push initial-lxc-configuration.nix
|
||||
echo "📄 Pushing initial NixOS configuration..."
|
||||
run_proxmox "pct push $LXC_ID '$INITIAL_CONFIG' /etc/nixos/configuration.nix" || {
|
||||
echo "❌ Error: Failed to push initial configuration." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 4. Push deploy.sh
|
||||
echo "📄 Pushing deploy script..."
|
||||
run_proxmox "pct push $LXC_ID '$DEPLOY_SCRIPT' /usr/local/bin/deploy-nixos" || {
|
||||
echo "❌ Error: Failed to push deploy script." >&2
|
||||
exit 1
|
||||
}
|
||||
run_proxmox "pct exec $LXC_ID -- chmod +x /usr/local/bin/deploy-nixos" || {
|
||||
echo "❌ Error: Failed to make deploy script executable." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 5. Apply initial configuration (nixos-rebuild switch)
|
||||
echo "⚙️ Applying initial NixOS configuration (this may take a while)..."
|
||||
if ! run_proxmox "pct exec $LXC_ID -- nixos-rebuild switch" 2>&1; then
|
||||
echo "⚠️ Warning: Initial nixos-rebuild may have issues." >&2
|
||||
echo " Check the container manually: pct exec $LXC_ID -- nixos-rebuild switch" >&2
|
||||
# Continue anyway — deploy.sh might still work
|
||||
fi
|
||||
echo "✅ Initial configuration applied."
|
||||
|
||||
# 6. Run deploy.sh to clone the repo and apply the specific configuration
|
||||
echo "🌐 Running deploy.sh to clone repo and apply specific configuration..."
|
||||
# Pass REPO_URL and BRANCH as environment variables to deploy.sh inside the container
|
||||
DEPLOY_CMD="REPO_URL='$REPO_URL' BRANCH='$BRANCH' /usr/local/bin/deploy-nixos"
|
||||
if ! run_proxmox "pct exec $LXC_ID -- bash -c '$DEPLOY_CMD'" 2>&1; then
|
||||
echo "⚠️ Warning: deploy.sh encountered issues." >&2
|
||||
echo " You can retry manually: pct exec $LXC_ID -- /usr/local/bin/deploy-nixos" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🎉 Container $short_name (CT $LXC_ID) successfully created and deployed!"
|
||||
echo " Connect with: ssh root@${IP%%/*} (or use pct exec $LXC_ID)"
|
||||
@@ -1,42 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_URL="https://gitea.lagraula.fr/xavier/nixos-infra.git"
|
||||
REPO_DIR="/etc/nixos-infra"
|
||||
BRANCH="main"
|
||||
# --- Default values (can be overridden by environment variables) ---
|
||||
REPO_URL="${REPO_URL:-ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra.git}"
|
||||
REPO_DIR="${REPO_DIR:-/etc/nixos-infra}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
ENVIRONMENT="${ENVIRONMENT:-production}"
|
||||
DRY_RUN="${DRY_RUN:-false}"
|
||||
|
||||
# --- Usage ---
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Deploy NixOS configuration from the nixos-infra repository.
|
||||
|
||||
Usage:
|
||||
$0 [options]
|
||||
|
||||
Options:
|
||||
-u, --repo-url URL Git repository URL
|
||||
[default: ${REPO_URL}]
|
||||
-d, --repo-dir DIR Local directory for the repository
|
||||
[default: ${REPO_DIR}]
|
||||
-b, --branch BRANCH Git branch to deploy
|
||||
[default: ${BRANCH}]
|
||||
-e, --environment ENV Environment name (production, dev, staging, etc.)
|
||||
[default: ${ENVIRONMENT}]
|
||||
-n, --dry-run Simulate deployment without making changes.
|
||||
-h, --help Show this help message.
|
||||
|
||||
Environment variables:
|
||||
REPO_URL, REPO_DIR, BRANCH, ENVIRONMENT, DRY_RUN (same as options above).
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# --- Parse arguments ---
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-u|--repo-url) REPO_URL="$2"; shift 2 ;;
|
||||
-d|--repo-dir) REPO_DIR="$2"; shift 2 ;;
|
||||
-b|--branch) BRANCH="$2"; shift 2 ;;
|
||||
-e|--environment) ENVIRONMENT="$2"; shift 2 ;;
|
||||
-n|--dry-run) DRY_RUN="true"; shift ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "❌ Unknown option: $1" >&2; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
HOSTNAME=$(hostname)
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "Ce script doit être exécuté en tant que root." >&2
|
||||
echo "❌ This script must be run as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cloner ou mettre à jour le dépôt
|
||||
# --- Dry run mode ---
|
||||
if [ "$DRY_RUN" = "true" ]; then
|
||||
echo "🧪 Dry run mode:"
|
||||
echo " - Repository URL: $REPO_URL"
|
||||
echo " - Repository dir: $REPO_DIR"
|
||||
echo " - Branch: $BRANCH"
|
||||
echo " - Environment: $ENVIRONMENT"
|
||||
echo " - Hostname: $HOSTNAME"
|
||||
echo " - Expected config: $REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix"
|
||||
echo ""
|
||||
echo " Would execute:"
|
||||
echo " git clone --branch $BRANCH $REPO_URL $REPO_DIR"
|
||||
echo " nixos-rebuild switch -I nixos-config=...$HOSTNAME/configuration.nix"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Clone or update the repository ---
|
||||
if [ -d "$REPO_DIR/.git" ]; then
|
||||
echo "Mise à jour du dépôt dans $REPO_DIR..."
|
||||
echo "🔄 Mise à jour du dépôt dans $REPO_DIR..."
|
||||
cd "$REPO_DIR"
|
||||
git fetch origin
|
||||
git checkout "$BRANCH"
|
||||
git pull origin "$BRANCH"
|
||||
else
|
||||
echo "Clonage du dépôt dans $REPO_DIR..."
|
||||
echo "📥 Clonage du dépôt dans $REPO_DIR..."
|
||||
mkdir -p "$REPO_DIR"
|
||||
git clone --branch "$BRANCH" "$REPO_URL" "$REPO_DIR"
|
||||
fi
|
||||
|
||||
# Trouver la configuration pour cette machine
|
||||
CONFIG_PATH="$REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix"
|
||||
# --- Find the configuration for this machine ---
|
||||
CONFIG_PATH="$REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix"
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
CONFIG_PATH="$REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix"
|
||||
CONFIG_PATH="$REPO_DIR/environments/$ENVIRONMENT/hosts/workstations/$HOSTNAME/configuration.nix"
|
||||
fi
|
||||
|
||||
if [ ! -f "$CONFIG_PATH" ]; then
|
||||
echo "Erreur : Aucune configuration trouvée pour $HOSTNAME dans $REPO_DIR" >&2
|
||||
echo "❌ Error : No configuration found for $HOSTNAME in environment '$ENVIRONMENT'" >&2
|
||||
echo " Checked paths :" >&2
|
||||
echo " - $REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix" >&2
|
||||
echo " - $REPO_DIR/environments/$ENVIRONMENT/hosts/workstations/$HOSTNAME/configuration.nix" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Appliquer la configuration
|
||||
echo "Déploiement de la configuration pour $HOSTNAME..."
|
||||
# --- Apply the configuration ---
|
||||
echo "🚀 Deploying the configuration for $HOSTNAME (environment: $ENVIRONMENT)..."
|
||||
nixos-rebuild switch -I nixos-config="$CONFIG_PATH"
|
||||
|
||||
echo "Déploiement terminé avec succès !"
|
||||
echo "✅ Deployment was successful !"
|
||||
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- gen-secrets-keys.sh ---
|
||||
# Generate age public keys from SSH host keys for all known hosts.
|
||||
#
|
||||
# This script retrieves each host's SSH host key, converts it to an
|
||||
# age public key using ssh-to-age, and stores it in
|
||||
# secrets/pubkeys/<hostname>.age for use with agenix.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
PUBKEYS_DIR="${PROJECT_DIR}/secrets/pubkeys"
|
||||
|
||||
# Ensure ssh-to-age is available
|
||||
if ! command -v ssh-to-age &> /dev/null; then
|
||||
echo "❌ Error: 'ssh-to-age' is required."
|
||||
echo " Install it with: nix-shell -p ssh-to-age"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$PUBKEYS_DIR"
|
||||
|
||||
echo "🔑 Generating age public keys from SSH host keys..."
|
||||
echo " Output directory: $PUBKEYS_DIR"
|
||||
echo ""
|
||||
|
||||
# Known hosts (hostname, user@host, ssh port)
|
||||
# Add entries as hosts are deployed in the infrastructure
|
||||
HOSTS=(
|
||||
# Hypervisors
|
||||
# "pve01:root@pve01.prod.lagraula.fr:22"
|
||||
# "pve02:root@pve02.prod.lagraula.fr:22"
|
||||
# LXC containers (once deployed)
|
||||
# "dns01:root@dns01.lagraula.fr:22"
|
||||
# "gitea01:root@gitea01.lagraula.fr:22"
|
||||
# "vault01:root@vault01.lagraula.fr:22"
|
||||
# "rp01:root@rp01.lagraula.fr:22"
|
||||
# Workstations
|
||||
# "sting:root@sting.lagraula.fr:22"
|
||||
)
|
||||
|
||||
if [ ${#HOSTS[@]} -eq 0 ]; then
|
||||
echo "⚠️ No hosts configured. Edit the HOSTS array in this script first."
|
||||
echo ""
|
||||
echo "For a single host, you can also run manually:"
|
||||
echo " ssh-keyscan <host> 2>/dev/null | grep ed25519 | awk '{print \$3}' | ssh-to-age > $PUBKEYS_DIR/<hostname>.age"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for entry in "${HOSTS[@]}"; do
|
||||
IFS=':' read -r hostname ssh_user_port <<< "$entry"
|
||||
IFS='@' read -r ssh_user ssh_host <<< "$ssh_user_port"
|
||||
|
||||
echo "🖥️ Processing $hostname ($ssh_user@$ssh_host)..."
|
||||
|
||||
age_key=$(ssh-keyscan -t ed25519 "$ssh_host" 2>/dev/null | \
|
||||
grep "ed25519" | \
|
||||
awk '{print $3}' | \
|
||||
ssh-to-age 2>/dev/null || true)
|
||||
|
||||
if [ -z "$age_key" ]; then
|
||||
echo " ⚠️ Could not retrieve age key for $hostname. Skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "$age_key" > "$PUBKEYS_DIR/$hostname.age"
|
||||
echo " ✅ Saved age public key: $age_key"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "🎉 Done! Generated $(ls -1 "$PUBKEYS_DIR"/*.age 2>/dev/null | wc -l) key(s)."
|
||||
echo ""
|
||||
echo "To encrypt a secret for specific hosts:"
|
||||
echo " age -r \$(cat $PUBKEYS_DIR/<hostname>.age) -o secrets/<name>.age"
|
||||
echo ""
|
||||
echo "Or with agenix:"
|
||||
echo " agenix -e secrets/<name>.age"
|
||||
@@ -1,32 +0,0 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Install Git, curl, and other required tools
|
||||
environment.systemPackages = with pkgs; [ git curl ];
|
||||
|
||||
# Enable unsecured SSH for initial deployment
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
permitRootLogin = "yes";
|
||||
passwordAuthentication = true;
|
||||
};
|
||||
|
||||
# Deployment script
|
||||
system.activationScripts.setup-deploy = ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Télécharger le script de déploiement depuis Gitea
|
||||
curl -o /usr/local/bin/deploy-nixos https://gitea.lagraula.fr/xavier/nixos-infra/raw/main/scripts/deploy.sh
|
||||
chmod +x /usr/local/bin/deploy-nixos
|
||||
|
||||
# Cloner le dépôt (si ce n'est pas déjà fait)
|
||||
mkdir -p /etc/nixos-infra
|
||||
if [ ! -d "/etc/nixos-infra/.git" ]; then
|
||||
git clone https://gitea.lagraula.fr/xavier/nixos-infra.git /etc/nixos-infra
|
||||
fi
|
||||
'';
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Install Git, curl, and other required tools
|
||||
environment.systemPackages = with pkgs; [ git curl ];
|
||||
|
||||
# Enable SSH for initial deployment
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
permitRootLogin = "yes";
|
||||
passwordAuthentication = true;
|
||||
};
|
||||
|
||||
# Clone the repository so deploy.sh can use it
|
||||
system.activationScripts.setup-deploy = ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Create the target directory
|
||||
mkdir -p /etc/nixos-infra
|
||||
|
||||
# The deploy script has already been pushed to /usr/local/bin/deploy-nixos
|
||||
# by create-lxc-nixos.sh; it will clone the repo and apply the config.
|
||||
'';
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
# Met à jour le commit de référence pour Nixpkgs
|
||||
|
||||
BRANCH="nixos-25.11"
|
||||
REPO="https://github.com/NixOS/nixpkgs"
|
||||
JSON_FILE="$(dirname "$0")/../pkgs/nixpkgs.json"
|
||||
|
||||
echo "Récupération du dernier commit sur $BRANCH..."
|
||||
REV=$(git ls-remote $REPO refs/heads/$BRANCH | cut -f1)
|
||||
|
||||
if [ -z "$REV" ]; then
|
||||
echo "Erreur : Impossible de récupérer le commit."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Calcul du hash (cela peut prendre un moment)..."
|
||||
SHA256=$(nix-prefetch-url --unpack "https://github.com/NixOS/nixpkgs/archive/$REV.tar.gz")
|
||||
|
||||
cat <<EOF > "$JSON_FILE"
|
||||
{
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/$REV.tar.gz",
|
||||
"rev": "$REV",
|
||||
"sha256": "$SHA256"
|
||||
}
|
||||
EOF
|
||||
|
||||
echo "Succès ! Nixpkgs est maintenant épinglé au commit : $REV"
|
||||
Generated
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "nixos-infra",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"help": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/help": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/help/-/help-3.0.2.tgz",
|
||||
"integrity": "sha512-jDd0MU+9xzvOQRC6CIzdjvb+agCvpzQY/Fp11quDnugDO4QQzh134EsLkRQMvFIJBleFkvnXagHFm4MTefkkpA=="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"help": "^3.0.2"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user