This commit is contained in:
Raphaël Billet
2026-01-22 12:24:11 +01:00
parent 5b59fa1039
commit eb17551aec
40 changed files with 92 additions and 240 deletions
@@ -1,8 +1,8 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
let let
libedgetpu = pkgs.callPackage ./libedgetpu.nix {}; libedgetpu = config.boot.kernelPackages.callPackage /etc/nixos/packages/libedgetpu.nix {};
gasket = config.boot.kernelPackages.callPackage ./gasket.nix {}; gasket = config.boot.kernelPackages.callPackage /etc/nixos/packages/gasket.nix {};
in in
{ {
Regular → Executable
+3 -4
View File
@@ -9,8 +9,8 @@ export GUM_SPIN_TITLE_BOLD=true
NECESSARY_VARIABLES_LIST=( "TARGET_HOST" "REMOTE_PASS" "SSH_PUBLIC_KEY" "DOMAIN_NAME" \ NECESSARY_VARIABLES_LIST=( "TARGET_HOST" "REMOTE_PASS" "SSH_PUBLIC_KEY" "DOMAIN_NAME" \
"EMAIL_ADDRESS" "CF_DNS_API_TOKEN" "SENDER_EMAIL_ADDRESS" "SENDER_EMAIL_ADDRESS_PASSWORD" \ "EMAIL_ADDRESS" "CF_DNS_API_TOKEN" "SENDER_EMAIL_ADDRESS" "SENDER_EMAIL_ADDRESS_PASSWORD" \
"SENDER_EMAIL_DOMAIN" "SENDER_EMAIL_PORT" "HOME_ROUTER_SUBNET" "HOME_ROUTER_IP" \ "SENDER_EMAIL_DOMAIN" "SENDER_EMAIL_PORT" "SERVER_OWNER_NAME" "SELECTED_SERVICES" \
"HOME_SERVER_IP" "SELECTED_SERVICES" "SERVER_OWNER_NAME" ) "HOME_ROUTER_SUBNET" "HOME_ROUTER_IP" "HOME_SERVER_IP" )
### Default settings <-- ### Default settings <--
user_input() { user_input() {
@@ -386,11 +386,10 @@ services_generation() {
} }
echo -e "\n ✅ Writing configuration files for the selected homelab services..." echo -e "\n ✅ Writing configuration files for the selected homelab services..."
cp templates/nix-config/podman/traefik.nix final-nix-config/etc/nixos/podman/traefik.nix cp -avu templates/nix-config/podman/traefik.nix final-nix-config/etc/nixos/podman/traefik.nix
cp -avu templates/nix-config/configuration.nix final-nix-config/etc/nixos/configuration.nix cp -avu templates/nix-config/configuration.nix final-nix-config/etc/nixos/configuration.nix
envsubst < templates/podman-config/traefik/traefik.yaml > final-nix-config/mnt/config/traefik/traefik.yaml envsubst < templates/podman-config/traefik/traefik.yaml > final-nix-config/mnt/config/traefik/traefik.yaml
for service in "${SELECTED_SERVICES[@]}"; do for service in "${SELECTED_SERVICES[@]}"; do
if [[ "${service}" == "frigate" ]]; then if [[ "${service}" == "frigate" ]]; then
@@ -6,18 +6,10 @@
(modulesPath + "/profiles/qemu-guest.nix") (modulesPath + "/profiles/qemu-guest.nix")
inputs.sops-nix.nixosModules.sops inputs.sops-nix.nixosModules.sops
./disks/disko.nix ./disks/disko.nix
./misc/activation.nix
./misc/mail.nix
./misc/networking.nix
./misc/smart.nix
# ./disks/pcr-check.nix
# ./disks/snapraid.nix # ./disks/snapraid.nix
# ./pcie-coral/coral.nix # ./disks/pcr-check.nix
]; ];
# Enable email notifications
email.enable = true;
# Hardware settings # Hardware settings
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
hardware.cpu.intel.updateMicrocode = true; hardware.cpu.intel.updateMicrocode = true;
@@ -30,22 +22,19 @@
sops.age.generateKey = true; sops.age.generateKey = true;
sops.secrets."ssh_public_keys" = { owner = "numbus-admin"; path = "/etc/ssh/authorized_keys.d/numbus-admin"; }; sops.secrets."ssh_public_keys" = { owner = "numbus-admin"; path = "/etc/ssh/authorized_keys.d/numbus-admin"; };
sops.secrets."sender_email_address_password" = {}; sops.secrets."sender_email_address_password" = {};
sops.secrets."podman/frigate" = { owner = "numbus-admin"; path = "/etc/podman/frigate/.env"; }; sops.secrets."docker/frigate" = { owner = "numbus-admin"; path = "/etc/docker-compose/frigate/.env"; };
sops.secrets."podman/gitea" = { owner = "numbus-admin"; path = "/etc/podman/gitea/.env"; }; sops.secrets."docker/traefik" = { owner = "numbus-admin"; path = "/etc/docker-compose/traefik/.env"; };
sops.secrets."podman/home_assistant" = { owner = "numbus-admin"; path = "/etc/podman/home-assistant/.env"; }; sops.secrets."docker/nextcloud" = { owner = "numbus-admin"; path = "/etc/docker-compose/nextcloud/.env"; };
sops.secrets."podman/immich" = { owner = "numbus-admin"; path = "/etc/podman/immich/.env"; }; sops.secrets."docker/passbolt" = { owner = "numbus-admin"; path = "/etc/docker-compose/passbolt/.env"; };
sops.secrets."podman/it_tools" = { owner = "numbus-admin"; path = "/etc/podman/it-tools/.env"; }; sops.secrets."docker/hass" = { owner = "numbus-admin"; path = "/etc/docker-compose/hass/.env"; };
sops.secrets."podman/nextcloud" = { owner = "numbus-admin"; path = "/etc/podman/nextcloud/.env"; }; sops.secrets."docker/pihole" = { owner = "numbus-admin"; path = "/etc/docker-compose/pihole/.env"; };
sops.secrets."podman/passbolt" = { owner = "numbus-admin"; path = "/etc/podman/passbolt/.env"; }; sops.secrets."docker/immich" = { owner = "numbus-admin"; path = "/etc/docker-compose/immich/.env"; };
sops.secrets."podman/pi_hole" = { owner = "numbus-admin"; path = "/etc/podman/pi-hole/.env"; };
sops.secrets."podman/traefik" = { owner = "numbus-admin"; path = "/etc/podman/traefik/.env"; };
# Bootloader options # Bootloader options
boot.initrd.systemd.enable = true; boot.initrd.systemd.enable = true;
boot.initrd.systemd.tpm2.enable = true;
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
boot.swraid.mdadmConf = "MAILADDR ${config.email.userAddress},${config.email.adminAddress}";
# boot.initrd.systemd.tpm2.enable = true;
# TPM2 PCR check # TPM2 PCR check
# systemIdentity.enable = true; # systemIdentity.enable = true;
@@ -76,14 +65,15 @@
}; };
# Enable SSH # Enable SSH
services.openssh.enable = true; services.openssh = {
enable = true;
};
# Allow unfree packages # Allow unfree packages
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
# Install packages # Install packages
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git
ncdu ncdu
fastfetch fastfetch
tpm2-tss tpm2-tss
@@ -97,12 +87,6 @@
smartmontools smartmontools
cpufrequtils cpufrequtils
intel-gpu-tools intel-gpu-tools
podman
podman-compose
podman-tui
snapraid
mergerfs
mergerfs-tools
]; ];
# Power savings # Power savings
@@ -120,25 +104,19 @@
]; ];
}; };
# Enable Podman # Enable docker
virtualisation.podman.enable = true; virtualisation.docker.enable = true;
virtualisation.podman.defaultNetwork.settings.dns_enabled = true; virtualisation.docker.daemon.settings = {
data-root = "/mnt/config-storage/docker-volumes/";
# Enable libvirt };
# virtualisation.libvirtd.enable = true;
# programs.virt-manager.enable = true;
# User account # User account
users.users.numbus-admin = { users.users.numbus-admin = {
isNormalUser = true; isNormalUser = true;
description = "Numbus Admin"; description = "Numbus Admin";
extraGroups = [ "wheel" ]; extraGroups = [ "networkmanager" "wheel" "docker" ];
uid = 1000; uid = 1000;
initialPassword = "changeMe!"; initialPassword = "changeMe!";
# required for auto start before user login
linger = true;
# required for rootless container with multiple users
autoSubUidGidRange = true;
}; };
# Login message # Login message
@@ -161,16 +139,8 @@
randomizedDelaySec = "45min"; randomizedDelaySec = "45min";
}; };
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
# Enable NixOS flakes # Enable NixOS flakes
nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Enable auto nix-store optimization
nix.settings.auto-optimise-store = true;
system.stateVersion = "25.05"; system.stateVersion = "25.05";
} }
@@ -9,11 +9,11 @@
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs"; sops-nix.inputs.nixpkgs.follows = "nixpkgs";
# Power savings # Power savings
autoaspm.url = "git+https://git.notthebe.ee/notthebee/AutoASPM"; autoaspm.url = "github:notthebee/AutoASPM";
autoaspm.inputs.nixpkgs.follows = "nixpkgs"; autoaspm.inputs.nixpkgs.follows = "nixpkgs";
}; };
outputs = { self, nixpkgs, disko, sops-nix, autoaspm, ... }@inputs: let outputs = { self, nixpkgs, disko, sops-nix, ... }@inputs: let
# System definition # System definition
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = import nixpkgs { pkgs = import nixpkgs {
@@ -21,9 +21,9 @@
config.allowUnfree = true; config.allowUnfree = true;
}; };
# Helper: collect every *.nix file inside ./podman as a list # Helper: collect every *.nix file inside ./docker as a list
podmanModules = let dockerModules = let
dir = ./podman; dir = ../docker;
entries = builtins.readDir dir; entries = builtins.readDir dir;
names = builtins.attrNames entries; names = builtins.attrNames entries;
nixNames = builtins.filter (n: builtins.match ".*\\.nix" n != null) names; nixNames = builtins.filter (n: builtins.match ".*\\.nix" n != null) names;
@@ -43,8 +43,8 @@
# Core host configuration # Core host configuration
./configuration.nix ./configuration.nix
./hardware-configuration.nix ./hardware-configuration.nix
# Podman services automatically added from ./podman/*.nix # Docker services automatically added from ./docker/*.nix
] ++ podmanModules; ] ++ dockerModules;
}; };
}; };
}; };
@@ -11,32 +11,22 @@ in
fromAddress = lib.mkOption { fromAddress = lib.mkOption {
description = "The 'from' address"; description = "The 'from' address";
type = lib.types.str; type = lib.types.str;
default = "no-reply@DOMAIN_NAME"; default = "no-reply@${DOMAIN_NAME}";
}; };
userAddress = lib.mkOption { toAddress = lib.mkOption {
description = "The 'to' address"; description = "The 'to' address";
type = lib.types.str; type = lib.types.str;
default = "EMAIL_ADDRESS"; default = "${EMAIL_ADDRESS}";
};
adminAddress = lib.mkOption {
description = "The admin email address to receive alerts in copy";
type = lib.types.str;
default = "admin@numbus.eu";
}; };
smtpServer = lib.mkOption { smtpServer = lib.mkOption {
description = "The SMTP server address"; description = "The SMTP server address";
type = lib.types.str; type = lib.types.str;
default = "SENDER_MAIL_DOMAIN"; default = "${SENDER_EMAIL_DOMAIN}";
};
smtpPort = lib.mkOption {
description = "The SMTP port";
type = lib.types.port;
default = 465;
}; };
smtpUsername = lib.mkOption { smtpUsername = lib.mkOption {
description = "The SMTP username"; description = "The SMTP username";
type = lib.types.str; type = lib.types.str;
default = "SENDER_MAIL_ADDRESS"; default = "${SENDER_EMAIL_ADDRESS}";
}; };
smtpPasswordPath = lib.mkOption { smtpPasswordPath = lib.mkOption {
description = "Path to the secret containing SMTP password"; description = "Path to the secret containing SMTP password";
@@ -46,29 +36,37 @@ in
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
environment.etc."aliases".text = ''
root: ${config.email.userAddress}, ${config.email.adminAddress}
default: ${config.email.userAddress}, ${config.email.adminAddress}
'';
programs.msmtp = { programs.msmtp = {
enable = true; enable = true;
defaults = {
aliases = "/etc/aliases";
timeout = 60;
syslog = "on";
};
accounts.default = { accounts.default = {
auth = true; auth = true;
host = config.email.smtpServer; host = config.email.smtpServer;
port = config.email.smtpPort;
from = config.email.fromAddress; from = config.email.fromAddress;
user = config.email.smtpUsername; user = config.email.smtpUsername;
tls = true; tls = true;
tls_starttls = false;
passwordeval = "${pkgs.coreutils}/bin/cat ${config.email.smtpPasswordPath}"; passwordeval = "${pkgs.coreutils}/bin/cat ${config.email.smtpPasswordPath}";
}; };
}; };
}; };
### Mail notifications configuration <-- ### Mail notifications configuration <--
### --> SMART disk heath
services.smartd = {
enable = true;
defaults.autodetected = "-a -o on -S on -s (S/../.././00|L/../../6/01) -n standby,q";
notifications = {
wall = {
enable = true;
};
mail = {
enable = true;
sender = config.email.fromAddress;
recipient = config.email.toAddress;
};
};
};
### SMART disk heath <--
} }
+37
View File
@@ -0,0 +1,37 @@
{ config, pkgs, lib, ... }:
{
# Hostname
networking.hostName = "numbus-server";
# Enable networking and firewall
networking.interfaces.eth0.ipv4.addresses = [
{
address = "HOME_SERVER_IP";
prefixLength = 24;
}
];
networking.defaultGateway = "HOME_ROUTER_IP";
networking.nameservers = [ "HOME_SERVER_IP" "9.9.9.9" ];
networking.networkmanager.enable = true;
networking.nftables.enable = true;
networking.firewall.enable = true;
networking.nftables.tables.nat = {
family = "ip";
content = ''
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport 80 redirect to :8080
tcp dport 443 redirect to :8443
tcp dport 53 redirect to :5353
udp dport 53 redirect to :5353
}
'';
};
# Open ports in the firewall
networking.firewall.allowPing = true;
networking.firewall.allowedTCPPorts = [ 53 80 443 ];
networking.firewall.allowedUDPPorts = [ 53 ];
}
BIN
View File
Binary file not shown.
-57
View File
@@ -1,57 +0,0 @@
{ config, pkgs, ... }:
{
systemd.services.numbus-activation-chowned = {
description = "Numbus-Server activation : Correct permissions";
wantedBy = [ "multi-user.target" "traefik.service" ];
after = [ "network.target" "local-fs.target" ];
path = [ pkgs.coreutils ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
#!/usr/bin/env bash
if [[ -e /home/numbus-admin/.numbus-server/chowned.true ]]; then
exit 0
fi
mkdir -p /mnt/config/ /mnt/data/ /mnt/data/nextcloud/
mkdir -p /home/numbus-admin/.numbus-server/
chown -R numbus-admin:users /mnt/config/
chown -R numbus-admin:users /mnt/data/
chown -R 100032:users /mnt/data/nextcloud/
chown -R numbus-admin:users /home/numbus-admin/.numbus-server/
touch /home/numbus-admin/.numbus-server/chowned.true
'';
};
systemd.services.numbus-activation-networked = {
description = "Numbus-Server activation : Create podman networks";
wantedBy = [ "multi-user.target" "traefik.service" ];
before = [ "traefik.service" ];
after = [ "network.target" "local-fs.target" "numbus-activation-chowned.service" ];
path = [ pkgs.podman pkgs.coreutils ];
serviceConfig = {
User = "numbus-admin";
Environment = [ "XDG_RUNTIME_DIR=/run/user/1000" ];
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
#!/usr/bin/env bash
export PATH=$PATH:/run/wrappers/bin
if [[ -e /home/numbus-admin/.numbus-server/networked.true ]]; then
exit 0
fi
PODMAN_NETWORKS
mkdir -p /home/numbus-admin/.numbus-server/
touch /home/numbus-admin/.numbus-server/networked.true
'';
};
}
-33
View File
@@ -1,33 +0,0 @@
{ config, pkgs, lib, ... }:
{
# Hostname
networking.hostName = "numbus-server";
networking.networkmanager.enable = false;
networking.resolvconf.enable = false;
networking.nftables.enable = true;
networking.firewall.enable = true;
# Allow rootless containers to bind to port 53 and up
boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 53;
# Bridge configuration for VMs
networking.bridges.br0.interfaces = [ "TARGET_INTERFACE" ];
networking.interfaces.br0.useDHCP = false;
networking.nameservers = [ "127.0.0.1" "9.9.9.9" ];
networking.interfaces.br0.ipv4.addresses = [{
address = "HOME_SERVER_IP";
prefixLength = 24;
}];
networking.defaultGateway = {
address = "HOME_ROUTER_IP";
interface = "br0";
};
# Open ports in the firewall
networking.firewall.allowPing = true;
networking.firewall.allowedTCPPorts = [ 53 80 443 ];
networking.firewall.allowedUDPPorts = [ 53 443 ];
}
-62
View File
@@ -1,62 +0,0 @@
{ config, pkgs, ... }:
let
smartd_notifier = pkgs.writeScript "smartd-notify.sh" ''
#!${pkgs.bash}/bin/bash
# 1. Send Technical Email to Admin
ADMIN_EMAIL="${config.email.adminAddress}"
SUBJECT="Numbus Server Alert: $SMARTD_FAILTYPE on $SMARTD_DEVICE"
TECH_BODY="
SMARTD Alert Details:
Server owner: $OWNER_NAME
Device: $SMARTD_DEVICE
Type: $SMARTD_DEVICETYPE
Failure Type: $SMARTD_FAILTYPE
Message: $SMARTD_MESSAGE
Full Message:
$SMARTD_FULLMESSAGE
"
printf "Subject: [ADMIN] $SUBJECT\n\n$TECH_BODY" | /run/wrappers/bin/sendmail -t "$ADMIN_EMAIL"
# 2. Send Friendly Email to Owner
USER_EMAIL="${config.email.userAddress}"
OWNER_NAME=$(cat /etc/numbus-server/owner 2>/dev/null || echo "User")
FRIENDLY_BODY="Cher/Chère $OWNER_NAME,
Votre serveur a automatiquement détecté une panne matérielle de disque dur.
Ce genre de panne est tout à fait normal selon l'âge de votre matériel et n'entraîne
dans la grande majorité des cas aucune perte de données grâce au système de
stockage redondant préventif.
Votre administrateur a été notifié de cette panne. Il vous recontactera dans de très
brefs délais afin de procéder au remplacement, si nécessaire, du disque dur défaillant.
Merci de votre confiance,
L'équipe de support,
Numbus-Server."
printf "Subject: [Alerte] Défaillance matérielle sur votre serveur Numbus\n\n$FRIENDLY_BODY" | /run/wrappers/bin/sendmail -t "$USER_EMAIL"
'';
in
{
### --> SMART disk heath
services.smartd = {
enable = true;
defaults.autodetected = "-a -o on -S on -s (S/../.././00|L/../../6/01) -n standby,q -M exec ${smartd_notifier}";
notifications = {
wall = {
enable = true;
};
mail = {
enable = true;
sender = config.email.fromAddress;
recipient = "${config.email.userAddress},${config.email.adminAddress}";
};
};
};
### SMART disk heath <--
}