Compare commits
10 Commits
dac1336e4c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ff9d839609 | |||
| a00c981ecd | |||
| 13c3d63785 | |||
| 236e454e22 | |||
| 5877a51436 | |||
| 6a2ca62398 | |||
| 0cfdcffc59 | |||
| 4d4ac1487c | |||
| bd41a33bae | |||
| 09d2522bfd |
@@ -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.).
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Project Rules: nixos-infra
|
|
||||||
|
|
||||||
## Directories
|
|
||||||
- `/nixos-infra/hosts/servers`: Server-specific configurations (.nix, lxc.config).
|
|
||||||
- `/nixos-infra/hosts/workstations`: Workstation-specific configurations (.nix, lxc.config).
|
|
||||||
- `/nixos-infra/modules/machine-types`: Nix modules standardizing different host types (hypervisor, VM, LXC, workstations, etc.).
|
|
||||||
- `/nixos-infra/modules/services`: Nix modules standardizing different network infrastructure services (DNS, etc.).
|
|
||||||
- `/nixos-infra/modules/user-profiles`: Nix modules standardizing different user profiles (admin, dev, office, etc.).
|
|
||||||
- `/nixos-infra/overlays`: Nix overlays (last resort).
|
|
||||||
- `/nixos-infra/pkgs`: Custom packages not present in Nixpkgs.
|
|
||||||
- `/nixos-infra/lib`: Nix utility functions.
|
|
||||||
- `/nixos-infra/scripts`: Operational and helper scripts.
|
|
||||||
|
|
||||||
The entry point for each machine is `hosts/<servers|workstations>/<hostname>/configuration.nix`.
|
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
- **Scope**: Centralized management of **NixOS** configurations for a complete infrastructure (hypervisors, workstations, LXC containers, services).
|
- **Scope**: Centralized management of **NixOS** configurations for a complete infrastructure (hypervisors, workstations, LXC containers, services).
|
||||||
- **Environment**:
|
- **Environment**:
|
||||||
- One **Proxmox** hypervisor currently, a second one coming soon.
|
- One **Proxmox** hypervisor currently, a second one coming soon.
|
||||||
- Several **workstations** (e.g., `dev-xavier`, `mao-julien`, `office`).
|
- Several **workstations** (e.g., `sting`, `gaia`, `PC-FRIDA`).
|
||||||
- **LXC Containers** (on Proxmox) VE for infrastructure services (DNS, Gitea, Bitwarden, etc.) and applications.
|
- **LXC Containers** (on Proxmox) VE for infrastructure services (DNS, Gitea, Bitwarden, etc.) and applications.
|
||||||
- **2 main users** (Xavier, Frida) + system users (`root`, `admin`, `guest`).
|
- **2 main users** (Xavier, Frida) + system users (`root`, `admin`, `guest`).
|
||||||
- **Hardware**: ThinkCentre m710q (16 GB RAM, i3) with **KDE 6.3**.
|
- **Hardware**: ThinkCentre m710q (16 GB RAM, i3) with **KDE 6.3**.
|
||||||
@@ -42,7 +42,9 @@
|
|||||||
| **Initial configuration (`initial-configuration.nix`)** | Prepare an LXC container so it can update itself via Git. | Self-sufficient containers. |
|
| **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. |
|
| **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. |
|
| **Unprivileged LXC containers (`--unprivileged 0`)** | NixOS requires privileges to function correctly in LXC. | Functional containers with NixOS. |
|
||||||
| **IPv4, IPv6, VLAN support** | Final target is IPv6-first, or even IPv6-only. | IP plan management to be designed. |
|
| **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. |
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -82,12 +84,23 @@ nixos-infra/
|
|||||||
│ └── gaia/ # Xavier's laptop (audio)
|
│ └── gaia/ # Xavier's laptop (audio)
|
||||||
│ └── configuration.nix
|
│ └── configuration.nix
|
||||||
│
|
│
|
||||||
|
├── 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
|
├── modules/ # Autonomous modules
|
||||||
│ ├── machine-types/ # Machine types
|
│ ├── machine-types/ # Machine types
|
||||||
│ │ ├── hypervisor.nix # Module for hypervisors
|
│ │ ├── hypervisor/
|
||||||
│ │ ├── vm.nix # Module for VMs
|
│ │ │ └── default.nix # Module for hypervisors
|
||||||
│ │ ├── lxc.nix # Module for LXC containers
|
│ │ ├── vm/
|
||||||
│ │ └── workstation.nix # Module for workstations
|
│ │ │ └── default.nix # Module for VMs
|
||||||
|
│ │ ├── lxc/
|
||||||
|
│ │ │ └── default.nix # Module for LXC containers
|
||||||
|
│ │ └── workstation/
|
||||||
|
│ │ └── default.nix # Module for workstations
|
||||||
│ │
|
│ │
|
||||||
│ ├── services/ # Services
|
│ ├── services/ # Services
|
||||||
│ │ ├── dns/
|
│ │ ├── dns/
|
||||||
@@ -104,7 +117,7 @@ nixos-infra/
|
|||||||
│ └── user-profiles/ # User profiles (roles)
|
│ └── user-profiles/ # User profiles (roles)
|
||||||
│ ├── admin.nix # Administrator profile
|
│ ├── admin.nix # Administrator profile
|
||||||
│ ├── dev.nix # Developer profile
|
│ ├── dev.nix # Developer profile
|
||||||
│ ├── mao.nix # Audio production profile
|
│ ├── cam.nix # Audio production profile
|
||||||
│ └── standard.nix # Standard profile
|
│ └── standard.nix # Standard profile
|
||||||
│
|
│
|
||||||
├── users/ # Specific users
|
├── users/ # Specific users
|
||||||
@@ -138,16 +151,16 @@ nixos-infra/
|
|||||||
### **Machine Profiles**
|
### **Machine Profiles**
|
||||||
| Profile | Description | File | Usage |
|
| Profile | Description | File | Usage |
|
||||||
| --------------| --------------------------------------------------------------| ----------------------------------------| ---------------------------------------------|
|
| --------------| --------------------------------------------------------------| ----------------------------------------| ---------------------------------------------|
|
||||||
| `hypervisor` | Common configuration for hypervisors (KVM, libvirtd, etc.). | `modules/machine-types/hypervisor.nix` | Proxmox hypervisors. |
|
| `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.nix` | VMs under Proxmox. |
|
| `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.nix` | LXC containers 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.nix` | Development, audio production, office stations. |
|
| `workstation` | Common configuration for workstations. | `modules/machine-types/workstation/default.nix` | Development, audio production, office stations. |
|
||||||
|
|
||||||
| Profile | Description | File |
|
| Profile | Description | File |
|
||||||
| ------------| --------------------------------------------------| --------------------------------------|
|
| ------------| --------------------------------------------------| --------------------------------------|
|
||||||
| `admin` | Administrator access (sudo, service management). | `modules/user-profiles/admin.nix` |
|
| `admin` | Administrator access (sudo, service management). | `modules/user-profiles/admin.nix` |
|
||||||
| `dev` | Development environment (tools, permissions). | `modules/user-profiles/dev.nix` |
|
| `dev` | Development environment (tools, permissions). | `modules/user-profiles/dev.nix` |
|
||||||
| `cam` | Computer assisted music (cam). | `modules/user-profiles/cam.nix` |
|
| `cam` | Computer-assisted music (CAM). | `modules/user-profiles/cam.nix` |
|
||||||
| `standard` | Standard user profile (basic access). | `modules/user-profiles/standard.nix` |
|
| `standard` | Standard user profile (basic access). | `modules/user-profiles/standard.nix` |
|
||||||
|
|
||||||
|
|
||||||
@@ -157,20 +170,35 @@ nixos-infra/
|
|||||||
### **1. Machine List**
|
### **1. Machine List**
|
||||||
|
|
||||||
|
|
||||||
| Name | Machine Type | Services | IPv4 | IPv6 Token |
|
| Name | Machine Type | VLAN | IPv4 | IPv6 Token |
|
||||||
| ----------| --------------------| -------------| ------| ------------|
|
| ----------| --------------------| ---------| ------------------| ------------|
|
||||||
| hyper01 | Hypervisor | Proxmox | | |
|
| hyper01 | Hypervisor | ADMIN | 10.10.128.10/16 | ::10 |
|
||||||
| hyper02 | Hypervisor | Proxmox | | |
|
| hyper02 | Hypervisor | ADMIN | 10.10.128.11/16 | ::11 |
|
||||||
| dns01 | LXC Container | DNS | | |
|
| dns01 | LXC Container | DMZ | 10.40.128.10/16 | ::10 |
|
||||||
| git01 | LXC Container | Git forge | | |
|
| dns02 | LXC Container | DMZ | 10.40.128.11/16 | ::11 |
|
||||||
| pass01 | LXC Container | Password mgr| | |
|
| git01 | LXC Container | DMZ | 10.40.128.20/16 | ::20 |
|
||||||
| rp01 | LXC Container | Reverse proxy| | |
|
| pass01 | LXC Container | DMZ | 10.40.128.30/16 | ::30 |
|
||||||
| sting | Workstation | | | |
|
| rp01 | LXC Container | DMZ | 10.40.128.199/16 | ::199 |
|
||||||
| PC-FRIDA | Workstation | | | |
|
| 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. List of User Profiles**
|
### **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 |
|
| Name | Role |
|
||||||
@@ -183,7 +211,7 @@ nixos-infra/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **3. User List**
|
### **4. User List**
|
||||||
| Name | Role | SSH Access |
|
| Name | Role | SSH Access |
|
||||||
| --------| -----------------------| -----------|
|
| --------| -----------------------| -----------|
|
||||||
| root | Superuser | ❌ |
|
| root | Superuser | ❌ |
|
||||||
@@ -194,7 +222,7 @@ nixos-infra/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### **4. User/Machine/Profile Mappings**
|
### **5. User/Machine/Profile Mappings**
|
||||||
|
|
||||||
|
|
||||||
| User | Machine | Applied Profiles | Role |
|
| User | Machine | Applied Profiles | Role |
|
||||||
@@ -214,6 +242,43 @@ nixos-infra/
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## **🌐 Network Architecture**
|
||||||
|
|
||||||
|
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`)
|
||||||
|
|
||||||
|
### Prefix rules
|
||||||
|
|
||||||
|
| 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` |
|
||||||
|
|
||||||
|
> **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**
|
## **🔄 Deployment Workflow**
|
||||||
|
|
||||||
### **For LXC containers (Proxmox)**
|
### **For LXC containers (Proxmox)**
|
||||||
@@ -276,6 +341,7 @@ nixos-infra/
|
|||||||
| Write the DNS module | Module for the DNS service (Bind). | ⬜ | ⭐⭐⭐ |
|
| Write the DNS module | Module for the DNS service (Bind). | ⬜ | ⭐⭐⭐ |
|
||||||
| Configure `agenix` | Encrypt the first secrets. | ⬜ | ⭐⭐ |
|
| Configure `agenix` | Encrypt the first secrets. | ⬜ | ⭐⭐ |
|
||||||
| Document the process | `README.md` to explain deployment. | ⬜ | ⭐⭐ |
|
| 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. | ⬜ | ⭐ |
|
| Automate with Ansible | Playbook to create multiple containers. | ⬜ | ⭐ |
|
||||||
| Integrate CI/CD | Test configurations before deployment. | ⬜ | ⭐ |
|
| Integrate CI/CD | Test configurations before deployment. | ⬜ | ⭐ |
|
||||||
|
|
||||||
@@ -293,6 +359,10 @@ nixos-infra/
|
|||||||
- **Security** :
|
- **Security** :
|
||||||
- Disable root SSH access once deployment is complete.
|
- Disable root SSH access once deployment is complete.
|
||||||
- Use SSH keys for authentication.
|
- 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** :
|
- **Maintenance** :
|
||||||
- Update `nixpkgs` regularly (`nix-channel --update`).
|
- Update `nixpkgs` regularly (`nix-channel --update`).
|
||||||
- Document changes in the `CHANGELOG.md`.
|
- Document changes in the `CHANGELOG.md`.
|
||||||
|
|||||||
+40
-4
@@ -1,5 +1,41 @@
|
|||||||
# nixos-infra
|
# nixos-infra — Private environments
|
||||||
|
|
||||||
Central infrastructure-as-code repository for the NixOS fleet (servers and
|
This repository contains **environment-specific declarations** (hosts, network
|
||||||
workstations). Reproductible deployments via NixOS, agenix for secrets,
|
layout, secrets, users) for the NixOS fleet. Reusable technical components
|
||||||
Proxmox for hypervision. See `../README.md` for an overview.
|
(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,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,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,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
|
|
||||||
../../../modules/machine-types/lxc.nix
|
|
||||||
# Module pour le reverse proxy
|
|
||||||
../../../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 = "git"; internalHost = "git01"; port = 3000; }
|
|
||||||
{ host = "pass"; internalHost = "pass01"; 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,4 +0,0 @@
|
|||||||
# Lib
|
|
||||||
Custom Nix utility functions and helpers.
|
|
||||||
Used across the configuration to factorize code.
|
|
||||||
Simplifies data and string manipulation.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Modules
|
|
||||||
Reusable NixOS modules for the infrastructure.
|
|
||||||
@@ -1,48 +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
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# 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,22 +0,0 @@
|
|||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
options.secrets = {
|
|
||||||
enable = lib.mkEnableOption "agenix secret management";
|
|
||||||
|
|
||||||
identity = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
default = "/etc/ssh/ssh_host_ed25519_key";
|
|
||||||
description = "Path to the SSH host private key used for age decryption.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf config.secrets.enable {
|
|
||||||
age = {
|
|
||||||
identityPaths = [ config.secrets.identity ];
|
|
||||||
secrets = { };
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ agenix ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,56 +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}";
|
|
||||||
tls = {
|
|
||||||
email = config.services.caddy.email or "xavier@lagraula.fr";
|
|
||||||
};
|
|
||||||
}) (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,4 +0,0 @@
|
|||||||
# Overlays
|
|
||||||
Custom modifications and extensions to Nixpkgs.
|
|
||||||
Applies patches or version overrides to existing packages.
|
|
||||||
Applied globally across the infrastructure.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
self: super: {
|
|
||||||
# Custom packages and overrides for nixos-infra
|
|
||||||
# agenix is already available in nixpkgs — no custom overlay needed.
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Packages
|
|
||||||
Custom software packages not found in upstream Nixpkgs.
|
|
||||||
Contains project-specific derivations (default.nix).
|
|
||||||
Can be referenced via overlays or directly by hosts.
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
let
|
|
||||||
spec = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
|
|
||||||
in
|
|
||||||
import (builtins.fetchTarball {
|
|
||||||
url = "https://github.com/NixOS/nixpkgs/archive/${spec.rev}.tar.gz";
|
|
||||||
sha256 = spec.sha256;
|
|
||||||
}) {}
|
|
||||||
# TODO: add a nixos-infra module
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"url": "https://github.com/NixOS/nixpkgs/archive/755f5aa91337890c432639c60b6064bb7fe67769.tar.gz",
|
|
||||||
"rev": "755f5aa91337890c432639c60b6064bb7fe67769",
|
|
||||||
"sha256": "1lmn8dicfwmsfdaiw18xjjys78bal6yjy3a41j02my7kw0wlb76a"
|
|
||||||
}
|
|
||||||
@@ -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'
|
|
||||||
@@ -30,7 +30,7 @@ to apply the host-specific configuration.
|
|||||||
1. `pct create` — create the container from the NixOS template
|
1. `pct create` — create the container from the NixOS template
|
||||||
2. `pct start <CT_ID>` — start the container
|
2. `pct start <CT_ID>` — start the container
|
||||||
3. Wait for the container to be ready (polling `pct exec`)
|
3. Wait for the container to be ready (polling `pct exec`)
|
||||||
4. `pct push initial-configuration.nix` → `/etc/nixos/configuration.nix`
|
4. `pct push initial-lxc-configuration.nix` → `/etc/nixos/configuration.nix`
|
||||||
5. `pct push deploy.sh` → `/usr/local/bin/deploy-nixos`
|
5. `pct push deploy.sh` → `/usr/local/bin/deploy-nixos`
|
||||||
6. `pct exec nixos-rebuild switch` — apply initial config (SSH, git, curl)
|
6. `pct exec nixos-rebuild switch` — apply initial config (SSH, git, curl)
|
||||||
7. `pct exec deploy-nixos` — clone repo and apply host-specific config
|
7. `pct exec deploy-nixos` — clone repo and apply host-specific config
|
||||||
@@ -56,7 +56,7 @@ finds the corresponding configuration file, and applies it with
|
|||||||
1. `hosts/servers/<hostname>/configuration.nix`
|
1. `hosts/servers/<hostname>/configuration.nix`
|
||||||
2. `hosts/workstations/<hostname>/configuration.nix`
|
2. `hosts/workstations/<hostname>/configuration.nix`
|
||||||
|
|
||||||
### `initial-configuration.nix` — Bootstrap NixOS configuration
|
### `initial-lxc-configuration.nix` — Bootstrap NixOS configuration (LXC)
|
||||||
|
|
||||||
Minimal NixOS configuration pushed to a new LXC container during the
|
Minimal NixOS configuration pushed to a new LXC container during the
|
||||||
bootstrap phase. Installs SSH, git, and curl so the container can
|
bootstrap phase. Installs SSH, git, and curl so the container can
|
||||||
@@ -93,7 +93,7 @@ Updates `pkgs/nixpkgs.json` with the latest commit from nixpkgs stable.
|
|||||||
```
|
```
|
||||||
create-lxc-nixos.sh # Step 1: Create + bootstrap
|
create-lxc-nixos.sh # Step 1: Create + bootstrap
|
||||||
└─ pct create
|
└─ pct create
|
||||||
└─ pct push initial-configuration.nix
|
└─ pct push initial-lxc-configuration.nix
|
||||||
└─ pct push deploy.sh
|
└─ pct push deploy.sh
|
||||||
└─ pct exec nixos-rebuild switch
|
└─ pct exec nixos-rebuild switch
|
||||||
└─ pct exec deploy.sh # Step 2: Clone repo + apply config
|
└─ pct exec deploy.sh # Step 2: Clone repo + apply config
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Options:
|
|||||||
--pve-port PORT SSH port for Proxmox (default: 22).
|
--pve-port PORT SSH port for Proxmox (default: 22).
|
||||||
--pve-ssh-key KEY SSH key file for authentication.
|
--pve-ssh-key KEY SSH key file for authentication.
|
||||||
--initial-config FILE Initial NixOS configuration file to push
|
--initial-config FILE Initial NixOS configuration file to push
|
||||||
[default: ./initial-configuration.nix].
|
[default: ./initial-lxc-configuration.nix].
|
||||||
--repo-url URL Git repository URL for deploy.sh
|
--repo-url URL Git repository URL for deploy.sh
|
||||||
[default: https://gitea.lagraula.fr/xavier/nixos-infra.git].
|
[default: https://gitea.lagraula.fr/xavier/nixos-infra.git].
|
||||||
--branch BRANCH Git branch for deploy.sh [default: main].
|
--branch BRANCH Git branch for deploy.sh [default: main].
|
||||||
@@ -77,7 +77,7 @@ TAGS="${TAGS:-}"
|
|||||||
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
|
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
|
||||||
|
|
||||||
# Bootstrap
|
# Bootstrap
|
||||||
INITIAL_CONFIG="${INITIAL_CONFIG:-./initial-configuration.nix}"
|
INITIAL_CONFIG="${INITIAL_CONFIG:-./initial-lxc-configuration.nix}"
|
||||||
REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
|
REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
|
||||||
BRANCH="${BRANCH:-main}"
|
BRANCH="${BRANCH:-main}"
|
||||||
SKIP_DEPLOY="${SKIP_DEPLOY:-false}"
|
SKIP_DEPLOY="${SKIP_DEPLOY:-false}"
|
||||||
@@ -279,7 +279,7 @@ for i in $(seq 1 30); do
|
|||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
# 3. Push initial-configuration.nix
|
# 3. Push initial-lxc-configuration.nix
|
||||||
echo "📄 Pushing initial NixOS configuration..."
|
echo "📄 Pushing initial NixOS configuration..."
|
||||||
run_proxmox "pct push $LXC_ID '$INITIAL_CONFIG' /etc/nixos/configuration.nix" || {
|
run_proxmox "pct push $LXC_ID '$INITIAL_CONFIG' /etc/nixos/configuration.nix" || {
|
||||||
echo "❌ Error: Failed to push initial configuration." >&2
|
echo "❌ Error: Failed to push initial configuration." >&2
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# --- Default values (can be overridden by environment variables) ---
|
# --- Default values (can be overridden by environment variables) ---
|
||||||
REPO_URL="${REPO_URL:-https://gitea.lagraula.fr/xavier/nixos-infra.git}"
|
REPO_URL="${REPO_URL:-ssh://git@gitea.prod.lagraula.fr:2222/xavier/nixos-infra.git}"
|
||||||
REPO_DIR="${REPO_DIR:-/etc/nixos-infra}"
|
REPO_DIR="${REPO_DIR:-/etc/nixos-infra}"
|
||||||
BRANCH="${BRANCH:-main}"
|
BRANCH="${BRANCH:-main}"
|
||||||
|
ENVIRONMENT="${ENVIRONMENT:-production}"
|
||||||
DRY_RUN="${DRY_RUN:-false}"
|
DRY_RUN="${DRY_RUN:-false}"
|
||||||
|
|
||||||
# --- Usage ---
|
# --- Usage ---
|
||||||
@@ -22,11 +23,13 @@ Options:
|
|||||||
[default: ${REPO_DIR}]
|
[default: ${REPO_DIR}]
|
||||||
-b, --branch BRANCH Git branch to deploy
|
-b, --branch BRANCH Git branch to deploy
|
||||||
[default: ${BRANCH}]
|
[default: ${BRANCH}]
|
||||||
|
-e, --environment ENV Environment name (production, dev, staging, etc.)
|
||||||
|
[default: ${ENVIRONMENT}]
|
||||||
-n, --dry-run Simulate deployment without making changes.
|
-n, --dry-run Simulate deployment without making changes.
|
||||||
-h, --help Show this help message.
|
-h, --help Show this help message.
|
||||||
|
|
||||||
Environment variables:
|
Environment variables:
|
||||||
REPO_URL, REPO_DIR, BRANCH, DRY_RUN (same as options above).
|
REPO_URL, REPO_DIR, BRANCH, ENVIRONMENT, DRY_RUN (same as options above).
|
||||||
EOF
|
EOF
|
||||||
exit 0
|
exit 0
|
||||||
}
|
}
|
||||||
@@ -37,6 +40,7 @@ while [[ $# -gt 0 ]]; do
|
|||||||
-u|--repo-url) REPO_URL="$2"; shift 2 ;;
|
-u|--repo-url) REPO_URL="$2"; shift 2 ;;
|
||||||
-d|--repo-dir) REPO_DIR="$2"; shift 2 ;;
|
-d|--repo-dir) REPO_DIR="$2"; shift 2 ;;
|
||||||
-b|--branch) BRANCH="$2"; shift 2 ;;
|
-b|--branch) BRANCH="$2"; shift 2 ;;
|
||||||
|
-e|--environment) ENVIRONMENT="$2"; shift 2 ;;
|
||||||
-n|--dry-run) DRY_RUN="true"; shift ;;
|
-n|--dry-run) DRY_RUN="true"; shift ;;
|
||||||
-h|--help) usage ;;
|
-h|--help) usage ;;
|
||||||
*) echo "❌ Unknown option: $1" >&2; usage ;;
|
*) echo "❌ Unknown option: $1" >&2; usage ;;
|
||||||
@@ -56,8 +60,9 @@ if [ "$DRY_RUN" = "true" ]; then
|
|||||||
echo " - Repository URL: $REPO_URL"
|
echo " - Repository URL: $REPO_URL"
|
||||||
echo " - Repository dir: $REPO_DIR"
|
echo " - Repository dir: $REPO_DIR"
|
||||||
echo " - Branch: $BRANCH"
|
echo " - Branch: $BRANCH"
|
||||||
|
echo " - Environment: $ENVIRONMENT"
|
||||||
echo " - Hostname: $HOSTNAME"
|
echo " - Hostname: $HOSTNAME"
|
||||||
echo " - Expected config: $REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix"
|
echo " - Expected config: $REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix"
|
||||||
echo ""
|
echo ""
|
||||||
echo " Would execute:"
|
echo " Would execute:"
|
||||||
echo " git clone --branch $BRANCH $REPO_URL $REPO_DIR"
|
echo " git clone --branch $BRANCH $REPO_URL $REPO_DIR"
|
||||||
@@ -79,21 +84,21 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Find the configuration for this machine ---
|
# --- Find the configuration for this machine ---
|
||||||
CONFIG_PATH="$REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix"
|
CONFIG_PATH="$REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix"
|
||||||
if [ ! -f "$CONFIG_PATH" ]; then
|
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
|
fi
|
||||||
|
|
||||||
if [ ! -f "$CONFIG_PATH" ]; then
|
if [ ! -f "$CONFIG_PATH" ]; then
|
||||||
echo "❌ Error : No configuration found for $HOSTNAME in $REPO_DIR" >&2
|
echo "❌ Error : No configuration found for $HOSTNAME in environment '$ENVIRONMENT'" >&2
|
||||||
echo " Checked paths :" >&2
|
echo " Checked paths :" >&2
|
||||||
echo " - $REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix" >&2
|
echo " - $REPO_DIR/environments/$ENVIRONMENT/hosts/servers/$HOSTNAME/configuration.nix" >&2
|
||||||
echo " - $REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix" >&2
|
echo " - $REPO_DIR/environments/$ENVIRONMENT/hosts/workstations/$HOSTNAME/configuration.nix" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# --- Apply the configuration ---
|
# --- Apply the configuration ---
|
||||||
echo "🚀 Deploying the configuration for $HOSTNAME..."
|
echo "🚀 Deploying the configuration for $HOSTNAME (environment: $ENVIRONMENT)..."
|
||||||
nixos-rebuild switch -I nixos-config="$CONFIG_PATH"
|
nixos-rebuild switch -I nixos-config="$CONFIG_PATH"
|
||||||
|
|
||||||
echo "✅ Deployment was successful !"
|
echo "✅ Deployment was successful !"
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user