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, ... }:
let
libedgetpu = pkgs.callPackage ./libedgetpu.nix {};
gasket = config.boot.kernelPackages.callPackage ./gasket.nix {};
libedgetpu = config.boot.kernelPackages.callPackage /etc/nixos/packages/libedgetpu.nix {};
gasket = config.boot.kernelPackages.callPackage /etc/nixos/packages/gasket.nix {};
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" \
"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" \
"HOME_SERVER_IP" "SELECTED_SERVICES" "SERVER_OWNER_NAME" )
"SENDER_EMAIL_DOMAIN" "SENDER_EMAIL_PORT" "SERVER_OWNER_NAME" "SELECTED_SERVICES" \
"HOME_ROUTER_SUBNET" "HOME_ROUTER_IP" "HOME_SERVER_IP" )
### Default settings <--
user_input() {
@@ -386,11 +386,10 @@ services_generation() {
}
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
envsubst < templates/podman-config/traefik/traefik.yaml > final-nix-config/mnt/config/traefik/traefik.yaml
for service in "${SELECTED_SERVICES[@]}"; do
if [[ "${service}" == "frigate" ]]; then
@@ -6,18 +6,10 @@
(modulesPath + "/profiles/qemu-guest.nix")
inputs.sops-nix.nixosModules.sops
./disks/disko.nix
./misc/activation.nix
./misc/mail.nix
./misc/networking.nix
./misc/smart.nix
# ./disks/pcr-check.nix
# ./disks/snapraid.nix
# ./pcie-coral/coral.nix
# ./disks/pcr-check.nix
];
# Enable email notifications
email.enable = true;
# Hardware settings
hardware.enableRedistributableFirmware = true;
hardware.cpu.intel.updateMicrocode = true;
@@ -30,22 +22,19 @@
sops.age.generateKey = true;
sops.secrets."ssh_public_keys" = { owner = "numbus-admin"; path = "/etc/ssh/authorized_keys.d/numbus-admin"; };
sops.secrets."sender_email_address_password" = {};
sops.secrets."podman/frigate" = { owner = "numbus-admin"; path = "/etc/podman/frigate/.env"; };
sops.secrets."podman/gitea" = { owner = "numbus-admin"; path = "/etc/podman/gitea/.env"; };
sops.secrets."podman/home_assistant" = { owner = "numbus-admin"; path = "/etc/podman/home-assistant/.env"; };
sops.secrets."podman/immich" = { owner = "numbus-admin"; path = "/etc/podman/immich/.env"; };
sops.secrets."podman/it_tools" = { owner = "numbus-admin"; path = "/etc/podman/it-tools/.env"; };
sops.secrets."podman/nextcloud" = { owner = "numbus-admin"; path = "/etc/podman/nextcloud/.env"; };
sops.secrets."podman/passbolt" = { owner = "numbus-admin"; path = "/etc/podman/passbolt/.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"; };
sops.secrets."docker/frigate" = { owner = "numbus-admin"; path = "/etc/docker-compose/frigate/.env"; };
sops.secrets."docker/traefik" = { owner = "numbus-admin"; path = "/etc/docker-compose/traefik/.env"; };
sops.secrets."docker/nextcloud" = { owner = "numbus-admin"; path = "/etc/docker-compose/nextcloud/.env"; };
sops.secrets."docker/passbolt" = { owner = "numbus-admin"; path = "/etc/docker-compose/passbolt/.env"; };
sops.secrets."docker/hass" = { owner = "numbus-admin"; path = "/etc/docker-compose/hass/.env"; };
sops.secrets."docker/pihole" = { owner = "numbus-admin"; path = "/etc/docker-compose/pihole/.env"; };
sops.secrets."docker/immich" = { owner = "numbus-admin"; path = "/etc/docker-compose/immich/.env"; };
# Bootloader options
boot.initrd.systemd.enable = true;
boot.initrd.systemd.tpm2.enable = true;
boot.loader.systemd-boot.enable = 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
# systemIdentity.enable = true;
@@ -76,14 +65,15 @@
};
# Enable SSH
services.openssh.enable = true;
services.openssh = {
enable = true;
};
# Allow unfree packages
nixpkgs.config.allowUnfree = true;
# Install packages
environment.systemPackages = with pkgs; [
git
ncdu
fastfetch
tpm2-tss
@@ -97,12 +87,6 @@
smartmontools
cpufrequtils
intel-gpu-tools
podman
podman-compose
podman-tui
snapraid
mergerfs
mergerfs-tools
];
# Power savings
@@ -120,25 +104,19 @@
];
};
# Enable Podman
virtualisation.podman.enable = true;
virtualisation.podman.defaultNetwork.settings.dns_enabled = true;
# Enable libvirt
# virtualisation.libvirtd.enable = true;
# programs.virt-manager.enable = true;
# Enable docker
virtualisation.docker.enable = true;
virtualisation.docker.daemon.settings = {
data-root = "/mnt/config-storage/docker-volumes/";
};
# User account
users.users.numbus-admin = {
isNormalUser = true;
description = "Numbus Admin";
extraGroups = [ "wheel" ];
extraGroups = [ "networkmanager" "wheel" "docker" ];
uid = 1000;
initialPassword = "changeMe!";
# required for auto start before user login
linger = true;
# required for rootless container with multiple users
autoSubUidGidRange = true;
};
# Login message
@@ -161,16 +139,8 @@
randomizedDelaySec = "45min";
};
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 7d";
};
# Enable NixOS flakes
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# Enable auto nix-store optimization
nix.settings.auto-optimise-store = true;
system.stateVersion = "25.05";
}
@@ -9,11 +9,11 @@
sops-nix.url = "github:Mic92/sops-nix";
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
# Power savings
autoaspm.url = "git+https://git.notthebe.ee/notthebee/AutoASPM";
autoaspm.url = "github:notthebee/AutoASPM";
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 = "x86_64-linux";
pkgs = import nixpkgs {
@@ -21,9 +21,9 @@
config.allowUnfree = true;
};
# Helper: collect every *.nix file inside ./podman as a list
podmanModules = let
dir = ./podman;
# Helper: collect every *.nix file inside ./docker as a list
dockerModules = let
dir = ../docker;
entries = builtins.readDir dir;
names = builtins.attrNames entries;
nixNames = builtins.filter (n: builtins.match ".*\\.nix" n != null) names;
@@ -43,8 +43,8 @@
# Core host configuration
./configuration.nix
./hardware-configuration.nix
# Podman services automatically added from ./podman/*.nix
] ++ podmanModules;
# Docker services automatically added from ./docker/*.nix
] ++ dockerModules;
};
};
};
@@ -11,32 +11,22 @@ in
fromAddress = lib.mkOption {
description = "The 'from' address";
type = lib.types.str;
default = "no-reply@DOMAIN_NAME";
default = "no-reply@${DOMAIN_NAME}";
};
userAddress = lib.mkOption {
toAddress = lib.mkOption {
description = "The 'to' address";
type = lib.types.str;
default = "EMAIL_ADDRESS";
};
adminAddress = lib.mkOption {
description = "The admin email address to receive alerts in copy";
type = lib.types.str;
default = "admin@numbus.eu";
default = "${EMAIL_ADDRESS}";
};
smtpServer = lib.mkOption {
description = "The SMTP server address";
type = lib.types.str;
default = "SENDER_MAIL_DOMAIN";
};
smtpPort = lib.mkOption {
description = "The SMTP port";
type = lib.types.port;
default = 465;
default = "${SENDER_EMAIL_DOMAIN}";
};
smtpUsername = lib.mkOption {
description = "The SMTP username";
type = lib.types.str;
default = "SENDER_MAIL_ADDRESS";
default = "${SENDER_EMAIL_ADDRESS}";
};
smtpPasswordPath = lib.mkOption {
description = "Path to the secret containing SMTP password";
@@ -46,29 +36,37 @@ in
};
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 = {
enable = true;
defaults = {
aliases = "/etc/aliases";
timeout = 60;
syslog = "on";
};
accounts.default = {
auth = true;
host = config.email.smtpServer;
port = config.email.smtpPort;
from = config.email.fromAddress;
user = config.email.smtpUsername;
tls = true;
tls_starttls = false;
passwordeval = "${pkgs.coreutils}/bin/cat ${config.email.smtpPasswordPath}";
};
};
};
### 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 <--
}