13c3d637855f2f1a245eb0168eb4bfe59cb572cd
- Add dns.nix: environment-specific DNS domain, name servers, forwarders - Add time.nix: NTP servers (gateway), timezone, hardware clock - Add proxy.nix: placeholder for future proxy settings (no proxy for now) - Add smtp.nix: SMTP relay configuration for system emails - Add default.nix: unified entry point for all network parameters These files allow environment-specific settings to be managed in one place and imported by host configurations.
🏗️ NixOS Infrastructure Project Canvas
Centralized NixOS configuration management project for Xavier Lagraula's infrastructure
📌 Context and Objectives
- Scope: Centralized management of NixOS configurations for a complete infrastructure (hypervisors, workstations, LXC containers, services).
- Environment:
- One Proxmox hypervisor currently, a second one coming soon.
- Several workstations (e.g.,
sting,gaia,PC-FRIDA). - LXC Containers (on Proxmox) VE for infrastructure services (DNS, Gitea, Bitwarden, etc.) and applications.
- 2 main users (Xavier, Frida) + system users (
root,admin,guest).
- Hardware: ThinkCentre m710q (16 GB RAM, i3) with KDE 6.3.
Objectives
| Objective | Description | Priority |
|---|---|---|
| Centralize configurations | A single Git repository for all machines. | ⭐⭐⭐ |
| Modularity | Reusable modules for services, machine types, and user profiles. | ⭐⭐⭐ |
| Automation | Scripts to deploy configurations to machines and containers. | ⭐⭐⭐ |
| Security | Secret management with sops-nix or agenix. |
⭐⭐ |
| Portability | Autonomous modules via callPackage. |
⭐⭐ |
| Maintenance | Clear documentation and simplified update processes. | ⭐ |
🔍 Key Decisions
| Decision | Justification | Impact |
|---|---|---|
| No flakes | Simplify onboarding and avoid a steep learning curve. | Configuration via configuration.nix + callPackage. |
| Modular structure | Separate configurations by machine type and service. | Clear and maintainable directory tree. |
| Servers named by service, not by application | Indicate what the machine does (git01 = Git forge) rather than the software (Gitea). Allows changing the underlying app without renaming. | Hosts under hosts/servers/<service>01 (e.g. git01, pass01, dns01). |
| Modules | Make modules autonomous, portable, and reusable. | Each module is an independent Nix package. |
Separation of user-profiles/ and users/ |
Distinguish generic roles (e.g., admin) from concrete users (e.g., xavier). |
Flexibility to apply profiles to multiple users. |
deploy.sh script |
Automate deployment on existing machines. | Clone/update the repo + nixos-rebuild switch. |
create-lxc-nixos.sh script |
Automate the creation of NixOS LXC containers on Proxmox. | Ready-to-use container with initial configuration. |
Initial configuration (initial-configuration.nix) |
Prepare an LXC container so it can update itself via Git. | Self-sufficient containers. |
Secret management with agenix |
Encrypt secrets (passwords, keys) for secure storage. | Enhanced security for sensitive data. |
Unprivileged LXC containers (--unprivileged 0) |
NixOS requires privileges to function correctly in LXC. | Functional containers with NixOS. |
| Centralised network data | A single declarative network data source (network/) consumed by NixOS configs and scripts. |
VLANs, subnets, host addresses defined once in network/hosts.nix. |
| IPv6-first with dual-stack | Both ULA (fdb2:) and GUA (2a01:) prefixes defined per VLAN. | Consistent internal addressing + global reachability for DMZ services. |
| DHCP-based IPv4 assignment | LXC containers use useDHCP = true. Addresses are reserved in hosts.nix as source of truth. |
Centralised address management, no static IPs in per-host configs. |
📂 File Structure
Git Repository Structure
nixos-infra/
├── configuration.nix # Main entry point
├── README.md
│
├── hosts/ # Machine configurations
│ ├── servers/ # Servers (hypervisors, VMs, LXCs)
│ │ ├── hyper01/ # Hypervisor 1
│ │ │ └── configuration.nix
│ │ ├── hyper02/ # Hypervisor 2
│ │ │ └── configuration.nix
│ │ ├── dns01/ # LXC container for DNS (master)
│ │ │ └── configuration.nix
│ │ ├── dns02/ # LXC container for DNS (slave)
│ │ │ └── configuration.nix
│ │ ├── git01/ # LXC container for Git forge (e.g. Gitea)
│ │ │ └── configuration.nix
│ │ ├── pass01/ # LXC container for password manager (e.g. Vaultwarden)
│ │ │ └── configuration.nix
│ │ └── rp01/ # LXC container for reverse proxy
│ │ └── configuration.nix
│ │
│ └── workstations/ # Workstations
│ ├── sting/ # Xavier's station (admin, dev, audio)
│ │ └── configuration.nix
│ ├── PC-FRIDA/ # Frida's station (office)
│ │ └── configuration.nix
│ └── 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/
│ │ │ └── default.nix # Module for hypervisors
│ │ ├── vm/
│ │ │ └── default.nix # Module for VMs
│ │ ├── lxc/
│ │ │ └── default.nix # Module for LXC containers
│ │ └── workstation/
│ │ └── default.nix # Module for workstations
│ │
│ ├── services/ # Services
│ │ ├── dns/
│ │ │ ├── default.nix # Implementation
│ │ │ └── options.nix # Exposed options
│ │ ├── git-forge/
│ │ │ └── default.nix
│ │ ├── password-manager/
│ │ │ └── default.nix
│ │ ├── reverse-proxy/
│ │ │ └── default.nix
│ │ └── ...
│ │
│ └── user-profiles/ # User profiles (roles)
│ ├── admin.nix # Administrator profile
│ ├── dev.nix # Developer profile
│ ├── cam.nix # Audio production profile
│ └── standard.nix # Standard profile
│
├── users/ # Specific users
│ ├── root/
│ │ └── configuration.nix
│ ├── xavier/
│ │ └── configuration.nix
│ ├── frida/
│ │ └── configuration.nix
│ └── guest/
│ └── configuration.nix
│
├── scripts/ # Utility scripts
│ ├── deploy.sh # Deployment for existing machines
│ ├── create-lxc-nixos.sh # LXC container creation on Proxmox
│ └── initial-configuration.nix # Initial configuration for new containers
│
├── secrets/ # Secrets (excluded from Git)
│ └── .gitignore
│
└── overlays/ # Overlays for custom packages
└── custom-pkgs.nix
🖥️ Machine Profiles and Services
Machine Profiles
| Profile | Description | File | Usage |
|---|---|---|---|
hypervisor |
Common configuration for hypervisors (KVM, libvirtd, etc.). | modules/machine-types/hypervisor/default.nix |
Proxmox hypervisors. |
vm |
Common configuration for virtual machines. | modules/machine-types/vm/default.nix |
VMs under Proxmox. |
lxc |
Common configuration for LXC containers. | modules/machine-types/lxc/default.nix |
LXC containers under Proxmox. |
workstation |
Common configuration for workstations. | modules/machine-types/workstation/default.nix |
Development, audio production, office stations. |
| Profile | Description | File |
|---|---|---|
admin |
Administrator access (sudo, service management). | modules/user-profiles/admin.nix |
dev |
Development environment (tools, permissions). | modules/user-profiles/dev.nix |
cam |
Computer-assisted music (CAM). | modules/user-profiles/cam.nix |
standard |
Standard user profile (basic access). | modules/user-profiles/standard.nix |
📋 Reference Tables
1. Machine List
| Name | Machine Type | VLAN | IPv4 | IPv6 Token |
|---|---|---|---|---|
| hyper01 | Hypervisor | ADMIN | 10.10.128.10/16 | ::10 |
| hyper02 | Hypervisor | ADMIN | 10.10.128.11/16 | ::11 |
| dns01 | LXC Container | DMZ | 10.40.128.10/16 | ::10 |
| dns02 | LXC Container | DMZ | 10.40.128.11/16 | ::11 |
| git01 | LXC Container | DMZ | 10.40.128.20/16 | ::20 |
| pass01 | LXC Container | DMZ | 10.40.128.30/16 | ::30 |
| rp01 | LXC Container | DMZ | 10.40.128.199/16 | ::199 |
| sting | Workstation | INTERNAL | 10.50.128.10/16 | ::10 |
| PC-FRIDA | Workstation | INTERNAL | 10.50.128.11/16 | ::11 |
| gaia | Workstation | INTERNAL | 10.50.128.12/16 | ::12 |
2. VLANs
| VLAN | ID | Effective ID | IPv4 Prefix | IPv6 ULA | IPv6 GUA |
|---|---|---|---|---|---|
| INET | 1 | 1 | Out of scope | Out of scope | Out of scope |
| ADMIN | 90 | 100 | 10.10.0.0/16 | fdb2:ae63:d45:d941::/64 | 2a01:e0a:2ea:d941::/64 |
| IOT | 200 | 200 | 10.20.0.0/16 | fdb2:ae63:d45:d942::/64 | 2a01:e0a:2ea:d942::/64 |
| GUEST | 300 | 300 | 10.30.0.0/16 | fdb2:ae63:d45:d943::/64 | 2a01:e0a:2ea:d943::/64 |
| DMZ | 400 | 400 | 10.40.0.0/16 | fdb2:ae63:d45:d944::/64 | 2a01:e0a:2ea:d944::/64 |
| INTERNAL | 500 | 500 | 10.50.0.0/16 | fdb2:ae63:d45:d945::/64 | 2a01:e0a:2ea:d945::/64 |
3. List of User Profiles
| Name | Role |
|---|---|
admin |
Superuser |
dev |
Developer |
standard |
Web & Office |
guest |
Guest |
4. User List
| Name | Role | SSH Access |
|---|---|---|
| root | Superuser | ❌ |
| xavier | Main user | ✅ |
| frida | User | ✅ |
| guest | Guest | ❌ |
5. User/Machine/Profile Mappings
| User | Machine | Applied Profiles | Role |
|---|---|---|---|
| root | All | - | Superuser |
| xavier | All | admin |
Development + administration |
| xavier | sting | admin, dev |
Hypervisor management |
| frida | PC-FRIDA | standard |
Development |
| guest | None | guest |
Guest user |
| xavier | sting | admin, dev |
Hypervisor management |
| frida | PC-FRIDA | standard |
Development |
| guest | None | guest |
Guest user |
🌐 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:
let network = import ../../network { };
in {
networking.hostName = "dns01";
networking.useDHCP = true;
}
From a shell script:
nix eval --json -f network/default.nix hosts | jq '.dns01.ipv4'
# → "10.40.128.10"
🔄 Deployment Workflow
For LXC containers (Proxmox)
- Create the container :
- Use
create-lxc-nixos.shto create a container from the NixOS template. - The script installs the initial configuration (
initial-configuration.nix).
- Deploy the final configuration :
- The
deploy.shscript is executed automatically to apply the specific configuration to the container (e.g.,hosts/servers/dns01/configuration.nix).
- Update :
git pullin/etc/nixos-infra+nixos-rebuild switch.
For workstations and hypervisors
- Clone the repository :
git clone https://github.com/xlagraula/nixos-infra.git /etc/nixos-infra - Link the configuration :
ln -s /etc/nixos-infra/hosts/workstations/dev-xavier/configuration.nix /etc/nixos/configuration.nix - Apply the configuration :
sudo nixos-rebuild switch
🔐 Secret Management
- Tool :
agenix. - Process :
- Encrypt secrets with
age:
echo "my-secret" | age -r age1... -o secrets/bitwarden/password.age- Integrate into the configuration :
age.secrets.bitwarden-password = { path = ./secrets/bitwarden/password.age; mode = "600"; };- Never commit secrets in plain text (add
secrets/to.gitignore).
- Encrypt secrets with
📅 Roadmap
| Step | Description | Status | Priority |
|---|---|---|---|
| Test the NixOS LXC template | Verify that the template works under Proxmox. | ⬜ | ⭐⭐⭐ |
Finalize create-lxc-nixos.sh |
Test the creation of an LXC container. | ⬜ | ⭐⭐⭐ |
| Write the DNS module | Module for the DNS service (Bind). | ⬜ | ⭐⭐⭐ |
Configure agenix |
Encrypt the first secrets. | ⬜ | ⭐⭐ |
| Document the process | README.md to explain deployment. |
⬜ | ⭐⭐ |
| DHCP service module | Kea or ISC DHCP consuming network/hosts.nix |
⬜ | ⭐⭐ |
| Automate with Ansible | Playbook to create multiple containers. | ⬜ | ⭐ |
| Integrate CI/CD | Test configurations before deployment. | ⬜ | ⭐ |
💡 Notes and Best Practices
- Naming :
- Servers: Name by service, not by application (e.g.,
git01,pass01,dns01). - Workstations: Use descriptive hostnames (e.g.,
sting,gaia). - Hypervisors: Prefix with
hyper(e.g.,hyper01,hyper02).
- Servers: Name by service, not by application (e.g.,
- 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.nixis the source of truth. - See
network/README.mdfor the complete architecture documentation.
- IPv4 addresses are allocated from the upper half of each VLAN (
- Maintenance :
- Update
nixpkgsregularly (nix-channel --update). - Document changes in the
CHANGELOG.md.
- Update
- Backups :
- Backup configurations (
/etc/nixos-infra) and secrets (secrets/). - For LXC containers under Proxmox, use Proxmox backups.
- Backup configurations (
📚 Useful Resources
- NixOS Manual
- Nix Flakes (for future reference)
- Agenix for secrets
- Proxmox + LXC Documentation
- Example NixOS Infrastructure Repository
Languages
Nix
63.6%
Shell
36.4%