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).
|
||||
- **Environment**:
|
||||
- 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.
|
||||
- **2 main users** (Xavier, Frida) + system users (`root`, `admin`, `guest`).
|
||||
- **Hardware**: ThinkCentre m710q (16 GB RAM, i3) with **KDE 6.3**.
|
||||
@@ -35,14 +35,16 @@
|
||||
| **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. |
|
||||
| **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. |
|
||||
| **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)
|
||||
│ └── 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
|
||||
│ ├── machine-types/ # Machine types
|
||||
│ │ ├── hypervisor.nix # Module for hypervisors
|
||||
│ │ ├── vm.nix # Module for VMs
|
||||
│ │ ├── lxc.nix # Module for LXC containers
|
||||
│ │ └── workstation.nix # Module for workstations
|
||||
│ │ ├── 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/
|
||||
@@ -104,7 +117,7 @@ nixos-infra/
|
||||
│ └── user-profiles/ # User profiles (roles)
|
||||
│ ├── admin.nix # Administrator profile
|
||||
│ ├── dev.nix # Developer profile
|
||||
│ ├── mao.nix # Audio production profile
|
||||
│ ├── cam.nix # Audio production profile
|
||||
│ └── standard.nix # Standard profile
|
||||
│
|
||||
├── users/ # Specific users
|
||||
@@ -138,16 +151,16 @@ nixos-infra/
|
||||
### **Machine Profiles**
|
||||
| Profile | Description | File | Usage |
|
||||
| --------------| --------------------------------------------------------------| ----------------------------------------| ---------------------------------------------|
|
||||
| `hypervisor` | Common configuration for hypervisors (KVM, libvirtd, etc.). | `modules/machine-types/hypervisor.nix` | Proxmox hypervisors. |
|
||||
| `vm` | Common configuration for virtual machines. | `modules/machine-types/vm.nix` | VMs under Proxmox. |
|
||||
| `lxc` | Common configuration for LXC containers. | `modules/machine-types/lxc.nix` | LXC containers under Proxmox. |
|
||||
| `workstation` | Common configuration for workstations. | `modules/machine-types/workstation.nix` | Development, audio production, office stations. |
|
||||
| `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` |
|
||||
| `cam` | Computer-assisted music (CAM). | `modules/user-profiles/cam.nix` |
|
||||
| `standard` | Standard user profile (basic access). | `modules/user-profiles/standard.nix` |
|
||||
|
||||
|
||||
@@ -157,20 +170,35 @@ nixos-infra/
|
||||
### **1. Machine List**
|
||||
|
||||
|
||||
| Name | Machine Type | Services | IPv4 | IPv6 Token |
|
||||
| ----------| --------------------| -------------| ------| ------------|
|
||||
| hyper01 | Hypervisor | Proxmox | | |
|
||||
| hyper02 | Hypervisor | Proxmox | | |
|
||||
| dns01 | LXC Container | DNS | | |
|
||||
| git01 | LXC Container | Git forge | | |
|
||||
| pass01 | LXC Container | Password mgr| | |
|
||||
| rp01 | LXC Container | Reverse proxy| | |
|
||||
| sting | Workstation | | | |
|
||||
| PC-FRIDA | Workstation | | | |
|
||||
| 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. 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 |
|
||||
@@ -183,7 +211,7 @@ nixos-infra/
|
||||
|
||||
---
|
||||
|
||||
### **3. User List**
|
||||
### **4. User List**
|
||||
| Name | Role | SSH Access |
|
||||
| --------| -----------------------| -----------|
|
||||
| root | Superuser | ❌ |
|
||||
@@ -194,7 +222,7 @@ nixos-infra/
|
||||
|
||||
---
|
||||
|
||||
### **4. User/Machine/Profile Mappings**
|
||||
### **5. User/Machine/Profile Mappings**
|
||||
|
||||
|
||||
| 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**
|
||||
|
||||
### **For LXC containers (Proxmox)**
|
||||
@@ -276,6 +341,7 @@ nixos-infra/
|
||||
| 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. | ⬜ | ⭐ |
|
||||
|
||||
@@ -293,6 +359,10 @@ nixos-infra/
|
||||
- **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** :
|
||||
- Update `nixpkgs` regularly (`nix-channel --update`).
|
||||
- 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
|
||||
workstations). Reproductible deployments via NixOS, agenix for secrets,
|
||||
Proxmox for hypervision. See `../README.md` for an overview.
|
||||
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,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
|
||||
2. `pct start <CT_ID>` — start the container
|
||||
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`
|
||||
6. `pct exec nixos-rebuild switch` — apply initial config (SSH, git, curl)
|
||||
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`
|
||||
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
|
||||
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
|
||||
└─ pct create
|
||||
└─ pct push initial-configuration.nix
|
||||
└─ 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
|
||||
|
||||
@@ -38,7 +38,7 @@ Options:
|
||||
--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-configuration.nix].
|
||||
[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].
|
||||
@@ -77,7 +77,7 @@ TAGS="${TAGS:-}"
|
||||
SSH_PUBLIC_KEYS="${SSH_PUBLIC_KEYS:-}"
|
||||
|
||||
# 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}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
SKIP_DEPLOY="${SKIP_DEPLOY:-false}"
|
||||
@@ -279,7 +279,7 @@ for i in $(seq 1 30); do
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# 3. Push initial-configuration.nix
|
||||
# 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
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
set -euo pipefail
|
||||
|
||||
# --- 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}"
|
||||
BRANCH="${BRANCH:-main}"
|
||||
ENVIRONMENT="${ENVIRONMENT:-production}"
|
||||
DRY_RUN="${DRY_RUN:-false}"
|
||||
|
||||
# --- Usage ---
|
||||
@@ -22,11 +23,13 @@ Options:
|
||||
[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, DRY_RUN (same as options above).
|
||||
REPO_URL, REPO_DIR, BRANCH, ENVIRONMENT, DRY_RUN (same as options above).
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
@@ -34,11 +37,12 @@ EOF
|
||||
# --- 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 ;;
|
||||
-n|--dry-run) DRY_RUN="true"; shift ;;
|
||||
-h|--help) usage ;;
|
||||
-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
|
||||
@@ -56,8 +60,9 @@ if [ "$DRY_RUN" = "true" ]; then
|
||||
echo " - Repository URL: $REPO_URL"
|
||||
echo " - Repository dir: $REPO_DIR"
|
||||
echo " - Branch: $BRANCH"
|
||||
echo " - Environment: $ENVIRONMENT"
|
||||
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 " Would execute:"
|
||||
echo " git clone --branch $BRANCH $REPO_URL $REPO_DIR"
|
||||
@@ -79,21 +84,21 @@ else
|
||||
fi
|
||||
|
||||
# --- 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
|
||||
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 "❌ 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 " - $REPO_DIR/hosts/servers/$HOSTNAME/configuration.nix" >&2
|
||||
echo " - $REPO_DIR/hosts/workstations/$HOSTNAME/configuration.nix" >&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
|
||||
|
||||
# --- 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"
|
||||
|
||||
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