refactor: separate framework from production environment

- Create nixos-infra-framework repo with reusable modules, lib, pkgs,
  overlays, scripts, and a sample environment
- Restructure private repo: move hosts/, network/, secrets/, users/
  into environments/production/
- Update all host configs to import from framework repo via fetchGit
- Update deploy.sh with --environment flag (default: production)
- Create hypervisor inventory records (Proxmox, non-NixOS)
- Add environment entry point: environments/production/configuration.nix
- Remove duplicated technical components (now in framework repo)
This commit is contained in:
2026-05-10 20:02:16 +02:00
parent 0cfdcffc59
commit 6a2ca62398
60 changed files with 238 additions and 609 deletions
+40 -4
View File
@@ -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.
View File
@@ -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";
}
@@ -1,11 +1,19 @@
{ 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;
};
in {
imports = [
# Module for LXC containers
../../../modules/machine-types/lxc
(framework + "/modules/machine-types/lxc")
# Technitium DNS Server service module
../../../modules/services/dns/default.nix
(framework + "/modules/services/dns/default.nix")
];
# Explicitly enable LXC machine type
@@ -13,6 +21,7 @@
# Host identity (IP address 10.40.128.10/16 assigned via DHCP reservation)
networking.hostName = "dns01";
networking.domain = "prod.lagraula.fr";
networking.useDHCP = true;
# Technitium DNS Server — primary DNS server
@@ -1,11 +1,17 @@
{ 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
../../../modules/machine-types/lxc
(framework + "/modules/machine-types/lxc")
# Technitium DNS Server service module
../../../modules/services/dns/default.nix
(framework + "/modules/services/dns/default.nix")
];
# Explicitly enable LXC machine type
@@ -13,6 +19,7 @@
# Host identity (IP address 10.40.128.11/16 assigned via DHCP reservation)
networking.hostName = "dns02";
networking.domain = "prod.lagraula.fr";
networking.useDHCP = true;
# Technitium DNS Server — secondary (replica) DNS server
@@ -1,11 +1,17 @@
{ 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
../../../modules/machine-types/lxc
(framework + "/modules/machine-types/lxc")
# Module for the git forge service (Forgejo)
../../../modules/services/git-forge/default.nix
(framework + "/modules/services/git-forge/default.nix")
];
# Explicitly enable LXC machine type
@@ -13,6 +19,7 @@
# 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
@@ -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";
}
@@ -1,11 +1,17 @@
{ 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
../../../modules/machine-types/lxc
(framework + "/modules/machine-types/lxc")
# Module for password manager service (Vaultwarden)
../../../modules/services/password-manager/default.nix
(framework + "/modules/services/password-manager/default.nix")
];
# Explicitly enable LXC machine type
@@ -13,6 +19,7 @@
# 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
@@ -1,15 +1,22 @@
{ 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
../../../modules/machine-types/lxc
(framework + "/modules/machine-types/lxc")
# Module for the reverse proxy
../../../modules/services/reverse-proxy/default.nix
(framework + "/modules/services/reverse-proxy/default.nix")
];
# Host identity (IP address assigned via DHCP reservation)
networking.hostName = "rp01";
networking.domain = "prod.lagraula.fr";
networking.useDHCP = true;
# Services to expose via the reverse proxy
@@ -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,8 @@
{ config, pkgs, lib, ... }:
{
# Workstation configuration for gaia
# TODO: Fill in workstation-specific settings
networking.hostName = "gaia";
networking.domain = "prod.lagraula.fr";
}
@@ -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,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" ];
};
}
@@ -1,3 +0,0 @@
# Do not modify!!
# Proxmox hypervisor on NixOS is not mature enough.
# Hypervisor are here for future reference only.
@@ -1,3 +0,0 @@
# Do not modify!!
# Proxmox hypervisor on NixOS is not mature enough.
# Hypervisor are here for future reference only.
-4
View File
@@ -1,4 +0,0 @@
# Lib
Custom Nix utility functions and helpers.
Used across the configuration to factorize code.
Simplifies data and string manipulation.
-2
View File
@@ -1,2 +0,0 @@
# Modules
Reusable NixOS modules for the infrastructure.
@@ -1,4 +0,0 @@
{ config, pkgs, lib, ... }:
{
# TODO: Add hypervisor-specific configuration
}
@@ -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,4 +0,0 @@
{ config, pkgs, lib, ... }:
{
# TODO: Add VM-specific configuration
}
@@ -1,4 +0,0 @@
{ config, pkgs, lib, ... }:
{
# TODO: Add workstation-specific configuration
}
-22
View File
@@ -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,116 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.dns;
dnsPkg = if cfg.package != null then cfg.package else pkgs.technitium-dns-server;
# Build the config.json for Technitium DNS Server.
# The server reads this file on startup from its config directory.
configJson = {
WebServicePort = cfg.webPort;
DNSListenerPort = cfg.dnsPort;
Recursion = cfg.recursion;
Forwarders = cfg.forwarders;
Log = false;
CachePrefetch = false;
AllowTtlOverride = true;
} // lib.optionalAttrs (cfg.adminPasswordFile != null) {
# Password hash will be set by the activation script on first run
# using the value from adminPasswordFile.
} // lib.optionalAttrs (cfg.listenAddresses != [ ]) {
ListenAddresses = cfg.listenAddresses;
} // lib.optionalAttrs (cfg.allowZoneTransfer != [ ]) {
AllowZoneTransfer = cfg.allowZoneTransfer;
} // cfg.extraConfig;
configFile = pkgs.writeText "technitium-dns-config.json"
(builtins.toJSON configJson);
in
{
imports = [
./options.nix
];
config = lib.mkIf cfg.enable {
environment.systemPackages = [ dnsPkg ];
# Create the config directory and deploy initial config.json
systemd.tmpfiles.rules = [
"d ${cfg.configDir} 0750 dns dns - -"
];
systemd.services.technitium-dns-server = {
description = "Technitium DNS Server";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
wants = [ "network-online.target" ];
# Generate a password hash if adminPasswordFile is provided.
# The server is stopped on first run if no password hash exists,
# so we pre-seed the config with the hashed password.
preStart = ''
if [ -f "${cfg.configDir}/config.json" ]; then
# Config already exists, do not overwrite
true
else
install -m 0640 ${configFile} ${cfg.configDir}/config.json
${lib.optionalString (cfg.adminPasswordFile != null) ''
if [ -f "${cfg.adminPasswordFile}" ]; then
# .NET-compatible SHA256 hash of the password
PASSWORD=$(cat "${cfg.adminPasswordFile}" | tr -d '\n')
HASH=$(echo -n "$PASSWORD" | ${pkgs.openssl}/bin/openssl dgst -sha256 -hex | cut -d' ' -f2)
${pkgs.jq}/bin/jq \
".AdminPassword = \"$HASH\" | .Pbkdf2Iterations = 600000" \
${cfg.configDir}/config.json > ${cfg.configDir}/config.json.tmp
mv ${cfg.configDir}/config.json.tmp ${cfg.configDir}/config.json
fi
''}
fi
'';
serviceConfig = {
Type = "simple";
ExecStart = "${dnsPkg}/bin/technitium-dns-server ${cfg.configDir}";
User = "dns";
Group = "dns";
Restart = "on-failure";
RestartSec = "5s";
LimitNOFILE = 1048576;
# Protect the system
ProtectSystem = "full";
ProtectHome = true;
PrivateTmp = true;
NoNewPrivileges = true;
ReadWritePaths = [ cfg.configDir ];
};
};
# Create the dns system user and group
users.users.dns = {
description = "Technitium DNS Server daemon user";
group = "dns";
isSystemUser = true;
home = cfg.configDir;
createHome = true;
};
users.groups.dns = { };
# Open firewall ports for DNS (UDP/TCP 53) and optionally the web interface
networking.firewall = lib.mkMerge [
{
allowedTCPPorts = [ cfg.dnsPort ];
allowedUDPPorts = [ cfg.dnsPort ];
}
# Allow web admin access only if listenAddresses restricts it to localhost
(lib.mkIf (cfg.listenAddresses == [ ] || builtins.elem "127.0.0.1" cfg.listenAddresses) {
allowedTCPPorts = [ cfg.webPort ];
})
];
# Ensure DNS resolution is available locally before starting
networking.nameservers = lib.mkAfter [ "127.0.0.1" ];
};
}
@@ -1,79 +0,0 @@
{ config, lib, ... }:
let
inherit (lib) types mkOption;
in
{
options.services.dns = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the Technitium DNS Server";
};
package = mkOption {
type = types.package;
default = null;
description = "Technitium DNS Server package to use. Defaults to pkgs.technitium-dns-server.";
};
webPort = mkOption {
type = types.port;
default = 5380;
description = "HTTP port for the Technitium web administration interface";
};
dnsPort = mkOption {
type = types.port;
default = 53;
description = "DNS server port (both TCP and UDP)";
};
recursion = mkOption {
type = types.enum [ "AllowOnlyForPrivateNetworks" "AllowAll" "DenyAll" ];
default = "AllowOnlyForPrivateNetworks";
description = "Recursion policy for DNS queries";
};
forwarders = mkOption {
type = types.listOf types.str;
default = [ ];
description = "Upstream DNS forwarders (e.g. [ \"1.1.1.1\" \"8.8.8.8\" ]). Empty means use root hints";
};
configDir = mkOption {
type = types.str;
default = "/etc/dns";
description = "Directory for persistent Technitium DNS configuration and zone data";
};
adminPasswordFile = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Path to a file containing the admin password for the web interface.
If not set, the default credentials (admin/admin) are used.
Use agenix or sops-nix to provide this file securely.
'';
};
listenAddresses = mkOption {
type = types.listOf types.str;
default = [ ];
description = "IP addresses to listen on. Empty means listen on all interfaces";
};
allowZoneTransfer = mkOption {
type = types.listOf types.str;
default = [ ];
description = "IP addresses or subnets allowed to request zone transfers (AXFR/IXFR)";
};
extraConfig = mkOption {
type = types.attrsOf types.anything;
default = { };
description = "Additional Technitium DNS configuration options as an attribute set";
};
};
}
@@ -1,90 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.git-forge;
inherit (lib) mkIf mkOption types;
in
{
options.services.git-forge = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the git forge service (Forgejo)";
};
domain = mkOption {
type = types.str;
default = "git.lagraula.fr";
description = "Domain name for the Forgejo instance";
};
sshPort = mkOption {
type = types.port;
default = 2222;
description = "SSH port for Git operations (avoid conflict with host SSH on 22)";
};
httpPort = mkOption {
type = types.port;
default = 3000;
description = "HTTP port for the Forgejo web interface";
};
dataDir = mkOption {
type = types.str;
default = "/var/lib/forgejo";
description = "Data directory for Forgejo repositories and database";
};
databaseType = mkOption {
type = types.enum [ "sqlite3" "postgres" "mysql" ];
default = "sqlite3";
description = "Database backend type";
};
settings = mkOption {
type = types.attrsOf types.anything;
default = { };
description = "Additional Forgejo settings (merged into services.forgejo.settings)";
};
};
config = mkIf cfg.enable {
# Use the built-in NixOS forgejo module
services.forgejo = {
enable = true;
package = pkgs.forgejo;
settings = lib.recursiveUpdate {
server = {
DOMAIN = cfg.domain;
HTTP_PORT = cfg.httpPort;
HTTP_ADDR = "0.0.0.0";
ROOT_URL = "https://${cfg.domain}";
SSH_PORT = cfg.sshPort;
SSH_LISTEN_PORT = cfg.sshPort;
};
service = {
DISABLE_REGISTRATION = false;
};
"repository".ROOT = "${cfg.dataDir}/repos";
} (lib.mapAttrs (section: values: lib.mapAttrs (key: value: lib.mkDefault value) values) cfg.settings);
database = {
type = cfg.databaseType;
};
dump = {
type = "tar.zst";
};
# LXC container specifics - use the existing forgejo user
stateDir = cfg.dataDir;
};
# Open firewall ports for HTTP and SSH (git protocol)
networking.firewall = lib.mkIf config.services.forgejo.enable {
allowedTCPPorts = [ cfg.httpPort cfg.sshPort ];
};
};
}
@@ -1,90 +0,0 @@
{ config, pkgs, lib, ... }:
let
cfg = config.services.password-manager;
inherit (lib) mkIf mkOption types;
in
{
options.services.password-manager = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the password manager service (Vaultwarden)";
};
domain = mkOption {
type = types.str;
default = "pass.lagraula.fr";
description = "Domain name for the Vaultwarden instance";
};
port = mkOption {
type = types.port;
default = 8080;
description = "HTTP port for the Vaultwarden web interface";
};
dataDir = mkOption {
type = types.str;
default = "/var/lib/vaultwarden";
description = "Data directory for Vaultwarden persistent state";
};
dbBackend = mkOption {
type = types.enum [ "sqlite" "mysql" "postgresql" ];
default = "sqlite";
description = "Database backend type";
};
adminTokenFile = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Path to a file containing the admin token for the /admin panel.
Use agenix or sops-nix to provide this file securely.
'';
};
signupsAllowed = mkOption {
type = types.bool;
default = true;
description = "Allow new user registration";
};
extraConfig = mkOption {
type = types.attrsOf (types.nullOr (types.oneOf [ types.bool types.str types.int types.port ]));
default = { };
description = "Additional Vaultwarden config options as attribute set (mapped to env vars)";
};
};
config = mkIf cfg.enable {
# Use the built-in NixOS vaultwarden module
services.vaultwarden = {
enable = true;
package = pkgs.vaultwarden;
webVaultPackage = pkgs.vaultwarden-webvault;
inherit (cfg) dbBackend;
config = {
DOMAIN = "https://${cfg.domain}";
PORT = cfg.port;
SIGNUPS_ALLOWED = cfg.signupsAllowed;
} // (lib.mapAttrs (name: value:
if value == true then "true"
else if value == false then "false"
else toString value
) cfg.extraConfig);
} // lib.optionalAttrs (cfg.adminTokenFile != null) {
environmentFile = cfg.adminTokenFile;
config = {
ADMIN_TOKEN = null; # Will be read from environmentFile
};
};
# Open firewall port
networking.firewall = mkIf config.services.vaultwarden.enable {
allowedTCPPorts = [ cfg.port ];
};
};
}
@@ -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 = [];
};
}
-4
View File
@@ -1,4 +0,0 @@
# Overlays
Custom modifications and extensions to Nixpkgs.
Applies patches or version overrides to existing packages.
Applied globally across the infrastructure.
-4
View File
@@ -1,4 +0,0 @@
self: super: {
# Custom packages and overrides for nixos-infra
# agenix is already available in nixpkgs — no custom overlay needed.
}
-4
View File
@@ -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.
-8
View File
@@ -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
-5
View File
@@ -1,5 +0,0 @@
{
"url": "https://github.com/NixOS/nixpkgs/archive/755f5aa91337890c432639c60b6064bb7fe67769.tar.gz",
"rev": "755f5aa91337890c432639c60b6064bb7fe67769",
"sha256": "1lmn8dicfwmsfdaiw18xjjys78bal6yjy3a41j02my7kw0wlb76a"
}
-22
View File
@@ -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'
+19 -14
View File
@@ -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 !"