Big update. Folder reorganization. Disk selection logic finished. Improved services selection (not done yet).
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
|
||||
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."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"; };
|
||||
@@ -109,23 +110,6 @@
|
||||
data-root = "/mnt/config-storage/docker-volumes/";
|
||||
};
|
||||
|
||||
# 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.firewall.enable = true;
|
||||
|
||||
# Open ports in the firewall
|
||||
networking.firewall.allowPing = false;
|
||||
networking.firewall.allowedTCPPorts = [ 53 80 443 ];
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
|
||||
# Hostname
|
||||
networking.hostName = "numbus-server";
|
||||
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
{ lib, utils, config, ... }:
|
||||
|
||||
let
|
||||
inherit (lib)
|
||||
head
|
||||
optional
|
||||
foldl'
|
||||
nameValuePair
|
||||
listToAttrs
|
||||
optionals
|
||||
concatStringsSep
|
||||
sortOn
|
||||
mkIf
|
||||
mkEnableOption
|
||||
mkOption
|
||||
types
|
||||
;
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
systemIdentity = {
|
||||
enable = mkEnableOption "hashing of Luks values into PCR 15 and subsequent checks";
|
||||
pcr15 = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
The expected value of PCR 15 after all luks partitions have been unlocked
|
||||
Should be a 64 character hex string as ouput by the sha256 field of
|
||||
'systemd-analyze pcrs 15 --json=short'
|
||||
If set to null (the default) it will not check the value.
|
||||
If the check fails the boot will abort and you will be dropped into an emergency shell, if enabled.
|
||||
In ermergency shell type:
|
||||
'systemctl disable check-pcrs'
|
||||
'systemctl default'
|
||||
to continue booting
|
||||
'';
|
||||
example = "6214de8c3d861c4b451acc8c4e24294c95d55bcec516bbf15c077ca3bffb6547";
|
||||
};
|
||||
};
|
||||
boot.initrd.luks.devices = lib.mkOption {
|
||||
type =
|
||||
with lib.types;
|
||||
attrsOf (submodule {
|
||||
config.crypttabExtraOpts = optionals config.systemIdentity.enable [
|
||||
"tpm2-device=auto"
|
||||
"tpm2-measure-pcr=yes"
|
||||
];
|
||||
});
|
||||
};
|
||||
};
|
||||
config = mkIf config.systemIdentity.enable {
|
||||
boot.kernelParams = [
|
||||
"rd.luks=no"
|
||||
];
|
||||
boot.initrd.systemd.services =
|
||||
{
|
||||
check-pcrs = mkIf (config.systemIdentity.pcr15 != null) {
|
||||
script = ''
|
||||
echo "Checking PCR 15 value"
|
||||
if [[ $(systemd-analyze pcrs 15 --json=short | jq -r ".[0].sha256") != "${config.systemIdentity.pcr15}" ]] ; then
|
||||
echo "PCR 15 check failed"
|
||||
exit 1
|
||||
else
|
||||
echo "PCR 15 check succeeded"
|
||||
fi
|
||||
'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
unitConfig.DefaultDependencies = "no";
|
||||
after = [ "cryptsetup.target" ];
|
||||
before = [ "sysroot.mount" ];
|
||||
requiredBy = [ "sysroot.mount" ];
|
||||
};
|
||||
}
|
||||
// (listToAttrs (
|
||||
foldl' (
|
||||
acc: attrs:
|
||||
let
|
||||
extraOpts = attrs.value.crypttabExtraOpts ++ (optional attrs.value.allowDiscards "discard");
|
||||
cfg = config.boot.initrd.systemd;
|
||||
in
|
||||
[
|
||||
(nameValuePair "cryptsetup-${attrs.name}" {
|
||||
unitConfig = {
|
||||
Description = "Cryptography setup for ${attrs.name}";
|
||||
DefaultDependencies = "no";
|
||||
IgnoreOnIsolate = true;
|
||||
Conflicts = [ "umount.target" ];
|
||||
BindsTo = "${utils.escapeSystemdPath attrs.value.device}.device";
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
TimeoutSec = "infinity";
|
||||
KeyringMode = "shared";
|
||||
OOMScoreAdjust = 500;
|
||||
ImportCredential = "cryptsetup.*";
|
||||
ExecStart = ''${cfg.package}/bin/systemd-cryptsetup attach '${attrs.name}' '${attrs.value.device}' '-' '${concatStringsSep "," extraOpts}' '';
|
||||
ExecStop = ''${cfg.package}/bin/systemd-cryptsetup detach '${attrs.name}' '';
|
||||
};
|
||||
after =
|
||||
[
|
||||
"cryptsetup-pre.target"
|
||||
"systemd-udevd-kernel.socket"
|
||||
"${utils.escapeSystemdPath attrs.value.device}.device"
|
||||
]
|
||||
++ (optional cfg.tpm2.enable "systemd-tpm2-setup-early.service")
|
||||
++ optional (acc != [ ]) "${(head acc).name}.service";
|
||||
before = [
|
||||
"blockdev@dev-mapper-${attrs.name}.target"
|
||||
"cryptsetup.target"
|
||||
"umount.target"
|
||||
];
|
||||
wants = [ "blockdev@dev-mapper-${attrs.name}.target" ];
|
||||
requiredBy = [ "sysroot.mount" ];
|
||||
})
|
||||
]
|
||||
++ acc
|
||||
) [ ] (sortOn (x: x.name) (lib.attrsets.attrsToList config.boot.initrd.luks.devices))
|
||||
));
|
||||
};
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
# --> SnapRAID disks research
|
||||
let
|
||||
contentDiskMounts = lib.attrsets.attrNames (
|
||||
lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "/mnt/content-" name) config.fileSystems
|
||||
);
|
||||
parityDiskMounts = lib.attrsets.attrNames (
|
||||
lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "/mnt/parity-" name) config.fileSystems
|
||||
);
|
||||
snapraidDataDisks = lib.lists.foldl'
|
||||
(acc: path: acc // { "d${toString (acc.i + 1)}" = path; i = acc.i + 1; })
|
||||
{ i = 0; }
|
||||
contentDiskMounts;
|
||||
in
|
||||
# SnapRAID disks research <--
|
||||
|
||||
|
||||
|
||||
# --> MergerFS setup
|
||||
{
|
||||
fileSystems."/mnt/data-storage" = {
|
||||
device = "mergerfs";
|
||||
fsType = "fuse";
|
||||
options = [
|
||||
"defaults"
|
||||
"allow_other"
|
||||
"use_ino"
|
||||
"cache.files=off"
|
||||
"moveonenospc=true"
|
||||
"category.create=mfs"
|
||||
"srcmounts=${lib.strings.concatStringsSep ":" contentDiskMounts}"
|
||||
];
|
||||
};
|
||||
# MergerFS setup <--
|
||||
|
||||
|
||||
|
||||
# --> SnapRAID setup
|
||||
services.snapraid = {
|
||||
enable = true;
|
||||
contentFiles = map (disk: "${disk}/snapraid.content") contentDiskMounts;
|
||||
parityFiles = map (disk: "${disk}/snapraid.parity") parityDiskMounts;
|
||||
dataDisks = builtins.removeAttrs snapraidDataDisks [ "i" ];
|
||||
};
|
||||
# SnapRAID setup <--
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
inputs = {
|
||||
# Core Nixpkgs
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
||||
# Disk‑partitioning helper
|
||||
disko.url = "github:nix-community/disko";
|
||||
disko.inputs.nixpkgs.follows = "nixpkgs";
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.email;
|
||||
in
|
||||
|
||||
### --> Mail notifications configuration
|
||||
{
|
||||
options.email = {
|
||||
enable = lib.mkEnableOption "Email sending functionality";
|
||||
fromAddress = lib.mkOption {
|
||||
description = "The 'from' address";
|
||||
type = lib.types.str;
|
||||
default = "no-reply@${DOMAIN_NAME}";
|
||||
};
|
||||
toAddress = lib.mkOption {
|
||||
description = "The 'to' address";
|
||||
type = lib.types.str;
|
||||
default = "${EMAIL_ADDRESS}";
|
||||
};
|
||||
smtpServer = lib.mkOption {
|
||||
description = "The SMTP server address";
|
||||
type = lib.types.str;
|
||||
default = "${SENDER_EMAIL_DOMAIN}";
|
||||
};
|
||||
smtpUsername = lib.mkOption {
|
||||
description = "The SMTP username";
|
||||
type = lib.types.str;
|
||||
default = "${SENDER_EMAIL_ADDRESS}";
|
||||
};
|
||||
smtpPasswordPath = lib.mkOption {
|
||||
description = "Path to the secret containing SMTP password";
|
||||
type = lib.types.path;
|
||||
default = config.sops.secrets.sender_email_address_password.path;
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
programs.msmtp = {
|
||||
enable = true;
|
||||
accounts.default = {
|
||||
auth = true;
|
||||
host = config.email.smtpServer;
|
||||
from = config.email.fromAddress;
|
||||
user = config.email.smtpUsername;
|
||||
tls = true;
|
||||
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/../.././02|L/../../6/03) -n standby,q";
|
||||
notifications = {
|
||||
wall = {
|
||||
enable = true;
|
||||
};
|
||||
mail = {
|
||||
enable = true;
|
||||
sender = config.email.fromAddress;
|
||||
recipient = config.email.toAddress;
|
||||
};
|
||||
};
|
||||
};
|
||||
### SMART disk heath <--
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
# 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 = false;
|
||||
networking.firewall.enable = true;
|
||||
# networking.firewall.extraCommands = "
|
||||
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
|
||||
# iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
|
||||
# ";
|
||||
|
||||
# Open ports in the firewall
|
||||
networking.firewall.allowPing = true;
|
||||
networking.firewall.allowedTCPPorts = [ 53 80 443 ];
|
||||
networking.firewall.allowedUDPPorts = [ 53 ];
|
||||
}
|
||||
Reference in New Issue
Block a user