5 Commits

Author SHA1 Message Date
ahtlon
8c488d50a8 add install script
All checks were successful
Evaluate Hydra Jobs / eval-hydra-jobs (push) Successful in 3m41s
Evaluate Hydra Jobs / eval-hydra-jobs (pull_request) Successful in 3m39s
2024-12-31 03:39:28 +01:00
ahtlon
b0a5fd91cd fix my mistakes 2024-12-31 03:18:37 +01:00
ahtlon
4fa01acae1 Create example configuration for qemu 2024-12-31 02:59:16 +01:00
ahtlon
e9b5937af9 add configurable disko modul 2024-12-31 02:46:12 +01:00
ahtlon
4d4c4fa6fa add init ssh modul 2024-12-31 02:45:37 +01:00
10 changed files with 493 additions and 161 deletions

View File

@@ -43,3 +43,10 @@ creation_rules:
age:
- *machine_vpn
- *admin_atlan
- path_regex: testvm/disk.key
key_groups:
- pgp:
- *admin_kalipso
- *admin_kalipso_dsktp
age:
- *admin_atlan

View File

@@ -118,8 +118,6 @@ in
specialArgs.inputs = inputs;
modules = defaultModules ++ [
./fanny/configuration.nix
inputs.disko.nixosModules.disko
./modules/disko/fanny.nix
];
};
@@ -150,4 +148,11 @@ in
./lucia/hardware_configuration.nix
];
};
testvm = nixosSystem {
system = "x86_64-linux";
specialArgs.inputs = inputs;
specialArgs.self = self;
modules = defaultModules ++ [ ./testvm ];
};
}

View File

@@ -1,4 +1,4 @@
{ config, pkgs, ... }:
{ inputs, pkgs, ... }:
{
imports =
@@ -8,6 +8,8 @@
../modules/sshd.nix
../modules/minimal_tools.nix
../modules/autoupdate.nix
inputs.self.nixosModules.malobeo.initssh
inputs.self.nixosModules.malobeo.disko
];
malobeo.autoUpdate = {
@@ -23,6 +25,18 @@
nix.settings.experimental-features = [ "nix-command" "flakes" ];
malobeo.disks = {
enable = true;
hostId = "1312acab";
root = {
disk0 = "sda";
};
storage = {
disks = ["sdb" "sdc"];
mirror = true;
};
};
services.tor = {
enable = true;
client.enable = true;
@@ -34,7 +48,6 @@
services.acpid.enable = true;
networking.hostName = "fanny";
networking.hostId = "1312acab";
networking.networkmanager.enable = true;
virtualisation.vmVariant.virtualisation.graphics = false;

View File

@@ -0,0 +1,265 @@
{config, lib, inputs, ...}:
let
cfg = config.malobeo.disks;
in
{
imports = [inputs.disko.nixosModules.disko];
options.malobeo.disks = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable disko disk creation";
};
hostId = lib.mkOption {
type = lib.types.str;
default = "";
description = "Host ID for zfs disks, generate with 'head -c4 /dev/urandom | od -A none -t x4'";
};
devNodes = lib.mkOption {
type = lib.types.str;
default = "/dev/disk/by-id/";
description = ''
where disks should be mounted from
https://openzfs.github.io/openzfs-docs/Project%20and%20Community/FAQ.html#selecting-dev-names-when-creating-a-pool-linux
use "/dev/disk/by-path/" for vm's
'';
};
root = {
disk0 = lib.mkOption {
type = lib.types.str;
default = "";
description = "name ab /dev für root dateisystem";
};
disk1 = lib.mkOption {
type = lib.types.str;
default = "";
description = "name ab /dev für eventuellen root mirror";
};
swap = lib.mkOption {
type = lib.types.str;
default = "8G";
description = "size of swap partition (only disk0)";
};
reservation = lib.mkOption {
type = lib.types.str;
default = "20GiB";
description = "zfs reservation";
};
mirror = lib.mkOption {
type = lib.types.bool;
default = false;
description = "mirror zfs root pool";
};
};
storage = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable storage pool";
};
disks = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "name ab /dev/ für storage pool";
example = "ata-ST16000NE000-2RW103_ZL2P0YSZ";
};
reservation = lib.mkOption {
type = lib.types.str;
default = "20GiB";
description = "zfs reservation";
};
mirror = lib.mkOption {
type = lib.types.bool;
default = false;
description = "mirror zfs storage pool";
};
};
};
config = lib.mkIf cfg.enable {
networking.hostId = cfg.hostId;
disko.devices = {
disk = lib.mkMerge [
{
ssd0 = lib.mkIf (cfg.root.disk0 != "") {
type = "disk";
device = "/dev/${cfg.root.disk0}";
content = {
type = "gpt";
partitions = {
ESP = {
size = "1024M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
encryptedSwap = {
size = cfg.root.swap;
content = {
type = "swap";
randomEncryption = true;
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
ssd1 = lib.mkIf (cfg.root.disk1 != "") {
type = "disk";
device = "/dev/${cfg.root.disk1}";
content = {
type = "gpt";
partitions = {
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
}
(lib.mkIf cfg.storage.enable (
lib.mkMerge (
map (diskname: {
"${diskname}" = {
type = "disk";
device = "/dev/${diskname}";
content = {
type = "gpt";
partitions = {
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "storage";
};
};
};
};
};
}) cfg.storage.disks
)
))
];
zpool = {
zroot = {
type = "zpool";
mode = lib.mkIf cfg.root.mirror "mirror";
# Workaround: cannot import 'zroot': I/O error in disko tests
options.cachefile = "none";
rootFsOptions = {
mountpoint = "none";
xattr = "sa"; # für microvm virtiofs mount
acltype = "posixacl"; # für microvm virtiofs mount
compression = "zstd";
"com.sun:auto-snapshot" = "false";
};
datasets = {
encrypted = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/root.key";
};
# use this to read the key during boot
postCreateHook = ''
zfs set keylocation="prompt" zroot/encrypted;
'';
};
"encrypted/root" = {
type = "zfs_fs";
mountpoint = "/";
};
"encrypted/var" = {
type = "zfs_fs";
mountpoint = "/var";
};
"encrypted/etc" = {
type = "zfs_fs";
mountpoint = "/etc";
};
"encrypted/home" = {
type = "zfs_fs";
mountpoint = "/home";
};
"encrypted/nix" = {
type = "zfs_fs";
mountpoint = "/nix";
};
reserved = {
# for cow delete if pool is full
options = {
canmount = "off";
mountpoint = "none";
reservation = "${cfg.root.reservation}";
};
type = "zfs_fs";
};
};
};
storage = lib.mkIf cfg.storage.enable {
type = "zpool";
mode = lib.mkIf (cfg.storage.mirror) "mirror";
rootFsOptions = {
mountpoint = "none";
xattr = "sa"; # für microvm virtiofs mount
acltype = "posixacl"; # für microvm virtiofs mount
};
datasets = {
encrypted = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/storage.key";
};
# use this to read the key during boot
postCreateHook = ''
zfs set keylocation="prompt" storage/encrypted;
'';
};
"encrypted/data" = {
type = "zfs_fs";
mountpoint = "/data";
};
reserved = {
# for cow delete if pool is full
options = {
canmount = "off";
mountpoint = "none";
reservation = "${cfg.storage.reservation}";
};
type = "zfs_fs";
};
};
};
};
};
fileSystems."/".neededForBoot = true;
fileSystems."/etc".neededForBoot = true;
fileSystems."/boot".neededForBoot = true;
fileSystems."/var".neededForBoot = true;
fileSystems."/home".neededForBoot = true;
fileSystems."/nix".neededForBoot = true;
};
}

View File

@@ -1,157 +0,0 @@
{
disko.devices = {
disk = {
ssd = {
type = "disk";
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
ESP = {
size = "1024M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
encryptedSwap = {
size = "8G"; #set to 100M for testing
content = {
type = "swap";
randomEncryption = true;
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
hdd0 = {
type = "disk";
device = "/dev/sdb";
content = {
type = "gpt";
partitions = {
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "storage";
};
};
};
};
};
hdd1 = {
type = "disk";
device = "/dev/sdc";
content = {
type = "gpt";
partitions = {
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "storage";
};
};
};
};
};
};
zpool = {
zroot = {
type = "zpool";
mode = "";
# Workaround: cannot import 'zroot': I/O error in disko tests
options.cachefile = "none";
rootFsOptions = {
mountpoint = "none";
compression = "zstd";
"com.sun:auto-snapshot" = "false";
};
datasets = {
encrypted = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/root.key";
};
# use this to read the key during boot
postCreateHook = ''
zfs set keylocation="prompt" zroot/encrypted;
'';
};
"encrypted/root" = {
type = "zfs_fs";
mountpoint = "/";
};
"encrypted/var" = {
type = "zfs_fs";
mountpoint = "/var";
};
"encrypted/etc" = {
type = "zfs_fs";
mountpoint = "/etc";
};
"encrypted/home" = {
type = "zfs_fs";
mountpoint = "/home";
};
"encrypted/nix" = {
type = "zfs_fs";
mountpoint = "/nix";
};
};
};
storage = {
type = "zpool";
mode = "mirror";
rootFsOptions = { mountpoint = "none"; };
datasets = {
encrypted = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/storage.key";
};
# use this to read the key during boot
postCreateHook = ''
zfs set keylocation="prompt" storage/encrypted;
'';
};
"encrypted/data" = {
type = "zfs_fs";
mountpoint = "/data";
};
};
};
};
};
fileSystems."/".neededForBoot = true;
fileSystems."/boot".neededForBoot = true;
fileSystems."/var".neededForBoot = true;
fileSystems."/etc".neededForBoot = true;
fileSystems."/home".neededForBoot = true;
fileSystems."/nix".neededForBoot = true;
}

View File

@@ -0,0 +1,65 @@
{ config, lib, pkgs, ... }:
let
cfg = config.malobeo.initssh;
inherit (config.networking) hostName;
in
{
options.malobeo.initssh = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable initrd-ssh";
};
authorizedKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Authorized keys for the initrd ssh";
};
ethernetDrivers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Ethernet drivers to load: run `lspci -k | grep -iA4 ethernet`";
example = "r8169";
};
};
config = lib.mkIf cfg.enable {
boot = {
loader.systemd-boot.enable = true;
loader.efi.canTouchEfiVariables = true;
supportedFilesystems = [ "vfat" "zfs" ];
zfs = {
forceImportAll = true;
requestEncryptionCredentials = true;
};
initrd = {
availableKernelModules = cfg.ethernetDrivers;
systemd = {
enable = true;
network.enable = true;
};
network.ssh = {
enable = true;
port = 222;
authorizedKeys = cfg.authorizedKeys;
hostKeys = [ "/etc/ssh/initrd" ];
};
secrets = {
"/etc/ssh/initrd" = "/etc/ssh/initrd";
};
};
kernelParams = [ "ip=::::${hostName}-initrd::dhcp" ];
systemd.services.zfs-remote-unlock = {
description = "Prepare for ZFS remote unlock";
wantedBy = ["initrd.target"];
after = ["systemd-networkd.service"];
path = with pkgs; [ zfs ];
serviceConfig.Type = "oneshot";
script = ''
echo "systemctl default" >> /var/empty/.profile
'';
};
};
};
}

View File

@@ -0,0 +1,56 @@
{ config, pkgs, inputs, ... }:
let
sshKeys = import ../ssh_keys.nix;
in
{
imports =
[ # Include the results of the hardware scan.
#./hardware-configuration.nix
../modules/malobeo_user.nix
../modules/sshd.nix
../modules/minimal_tools.nix
inputs.self.nixosModules.malobeo.initssh
inputs.self.nixosModules.malobeo.disko
];
malobeo.initssh = {
enable = true;
authorizedKeys = sshKeys.admins;
ethernetDrivers = ["virtio_net"];
};
malobeo.disks = {
enable = true;
hostId = "83abc8cb";
devNodes = "/dev/disk/by-path/";
root = {
disk0 = "disk/by-path/pci-0000:04:00.0";
swap = "1G";
reservation = "1G";
mirror = false;
};
storage = {
enable = true;
disks = ["disk/by-path/pci-0000:08:00.0" "disk/by-path/pci-0000:09:00.0"];
reservation = "1G";
mirror = true;
};
};
boot.initrd.kernelModules = ["virtio_blk" "zfs" "virtio_console" "virtio_pci" "virtio" "virtio_net"];
nix.settings.experimental-features = [ "nix-command" "flakes" ];
# needed for printing drivers
nixpkgs.config.allowUnfree = true;
services.acpid.enable = true;
networking.hostName = "fanny";
networking.networkmanager.enable = true;
time.timeZone = "Europe/Berlin";
system.stateVersion = "23.05"; # Do.. Not.. Change..
}

31
machines/testvm/disk.key Normal file
View File

@@ -0,0 +1,31 @@
{
"data": "ENC[AES256_GCM,data:GH71ek6+a++P9sDUjO0IPojdU1epX98wcTqmoEgsu0j+,iv:LysgsJdPDvKOUz7l0IyV58QHN2RHvHP14bt1p4571NM=,tag:1WrqC3S+Z6bkE2d76RYtXA==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1ljpdczmg5ctqyeezn739hv589fwhssjjnuqf7276fqun6kc62v3qmhkd0c",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHOVI3b1dBa2d5SElHcFdq\nVHZwWlpIU3NpYm8zQnY3aVhOVkxnU1pkZUJNCkJ6bzhqdU5EVy9Wa0creXJHZ1pu\nbkRPVTR1K0o0dmlYbGVIbVRiWjFyL1kKLS0tIHl0aFpUYy9hWmpsNUFoY2JpWUhL\nalluN1RRSTBNUlprZWFISlFoUExXUXMKaULQKgVLNfHX8m0Ac1YhcbM/yhioyNCu\na1AUDjBmruKL9ngqz9Dwzxx0sJJOIFKMdYMVn9uQfui/XCHewO6uRw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2024-12-31T02:35:20Z",
"mac": "ENC[AES256_GCM,data:7K8G7ZFaA7wT0lwujkuJP0HL8WW0m/IkMjgFU9ikWe/GVZMlFDWTafaRNLxdBHNhHwilM8suH2z0P36Xae6pReh47PpID5JS8NC1V38fzww5qW74eFkHq3Pu8HRWb66u7zA/LiyOcEQgtrdP1zbnfmHUgakyNluSn7W1gOtsfxw=,iv:l65AiYn7ETRySF1Wr9nOUk9Fd1I4VGqd/zZbqkCyxYA=,tag:TeVyRa8aN6hIn3iIKPPvbQ==,type:str]",
"pgp": [
{
"created_at": "2024-12-31T02:35:05Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQGMA5HdvEwzh/H7AQv/ZITVtnQl5xO2XLTTaNAZ50WhHkVV1G9H2TyxO0NbaUPj\nbo7LdbuB/+cv3wpg5oy5VpWW/JLElqizxbrE5gzQCzorwGE7lpKW0XQubofW8t9l\n+6k9UFXxyfVQJHwcIbexYfL2UhN62eSzzxPiKYVyNw4oM9ySeU+MCeCiv0omLUPg\nWSdOH4q1QYkRGJO8db7KlJSdvCoVjyEiCaLwKdWnPk5pbC+U7wp75fPdFwmzBchc\np9TXKeFF8dVGI7DKuGXA7lBm4ZzgSt4wNdZmc7mvTrTInaDVFA/ptbAfhh2/hNEx\npOijlXbc8ARKAhuLASPy6j37Nm2QdNm/8dl5x6eA7Sx7FcO8qV38Q//V4/DZZddJ\nT3NLC4tWLglpdyFX7H0zmZ+jQOLGJHorwzO+NgSOEj3N4venHYvJyI+vwVGjVCjQ\n1tZUIxGMx5iu959PinvlvBYI7oeKITPLyo8pRRx2EaA+UEBR2f3y+R0bTiBhChKM\nieUIVIK/fbvhdXhwwfRe0lgBm05hL/Vmdbal9QU8o/HIPeGTNitaqLQ59Ets7qm4\nf2FhHaOMO0YaDPtCNBGbRh/mEWH8tjhnI1sLJg/0rR9sOQ/oCzzIYILogIkm3ueE\notFqp95QQPVA\n=P16c\n-----END PGP MESSAGE-----",
"fp": "c4639370c41133a738f643a591ddbc4c3387f1fb"
},
{
"created_at": "2024-12-31T02:35:05Z",
"enc": "-----BEGIN PGP MESSAGE-----\n\nhQIMA98TrrsQEbXUAQ//fAGV0oLuiwL4TmQnrHF88ixvZ/HghKI9k/5zlORIdoaR\na1w6U32coX8HpEfcqON45ZQWSCFtlizlmL55jb1ugXFY/bS+KECO8XaMDhHXNkB/\ndfeCmASvqIlFkl/X3YeD2FhHa3ZlcS93x0duJ+oo18WIErkNuECOL7hwkh+m5YfS\nWtW9Z3J51qfS5S6ctdm9vKcYSrgTkADsyVQp9GqxO3xZGpWudGWDaK0gVBX5wk5t\n1uKhDpnIZdFZ42N5Oy/UqXF5pfEQ0OwxlOS8VMleq1wEPc/DPVku23HRSReS0k7x\nuVeFZpaOfe22ncgI4TVQln8JT0+ZPeAwqBn6LWp0XnPnQdkyE79ARMPqBTPN/6Pn\nFkVpInBVukVJ1AiGpHHxESPtiKoMUZpE+k3WG2dRFWmaON+n0kR4VFpOju3apxTH\n8RGN+Uyn6MswNOZDKoDjlVtkcwgJgar/KwxXNlF7BU3/KMDEBf1UHuQE58Y2eBsC\nI85AEpbskEeOu+MF1SNJkdx/BR+lUaR6ax+dVzOIwxLyyDoCGg4SEoL1Hh1nNRth\nxRZnYfN3FBGv3FnvpaCbfbBDLLkWxzst5HRjp+v2lyPM4eVtyvYPGdfYM5FK1den\nXVawulE3cjM786/Z7X2IK5IDzrvo8nIs/Keg2YqnZe0UgM3XFCoYnwxi2Rev1J3S\nWAHTBs22q/cEk3SLlfzLyqWochY33gI6fC2amOvC5HNhcs7vr6CF1W44d3Yx6WCO\npqxY9jmc4gVWeBLZV/d9T95qLwOQK7L1/tokdbggQcEXFOqpvPzm5pc=\n=qp/h\n-----END PGP MESSAGE-----",
"fp": "aef8d6c7e4761fc297cda833df13aebb1011b5d4"
}
],
"unencrypted_suffix": "_unencrypted",
"version": "3.9.2"
}
}

View File

@@ -40,6 +40,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems
};
packages = {
remote-install = pkgs.writeShellScriptBin "remote-install" (builtins.readFile ./scripts/remote-install-encrypt.sh);
docs = pkgs.stdenv.mkDerivation {
name = "malobeo-docs";
phases = [ "buildPhase" ];
@@ -116,6 +117,8 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems
host.imports = [ ./machines/durruti/host_config.nix ];
microvm.imports = [ ./machines/modules/malobeo/microvm_host.nix ];
vpn.imports = [ ./machines/modules/malobeo/wireguard.nix ];
initssh.imports = [ ./machines/modules/malobeo/initssh.nix ];
disko.imports = [ ./machines/modules/disko ];
};
hydraJobs = nixpkgs.lib.mapAttrs (_: nixpkgs.lib.hydraJob) (

View File

@@ -0,0 +1,44 @@
set -o errexit
set -o nounset
set -o pipefail
if [ $# -lt 2 ]; then
echo
echo "Install NixOS to the host system with secrets and encryption"
echo "Usage: $0 <hostname> <ip> (user)"
exit 1
fi
hostname=$1
ipaddress=$2
# Create a temporary directory
temp=$(mktemp -d)
# Function to cleanup temporary directory on exit
cleanup() {
rm -rf "$temp"
}
trap cleanup EXIT
# Create the directory where sshd expects to find the host keys
install -d -m755 "$temp/etc/ssh/"
ssh-keygen -f $temp/etc/ssh/"$hostname" -t ed25519 -N ""
ssh-keygen -f $temp/etc/ssh/initrd -t ed25519 -N ""
# # Set the correct permissions so sshd will accept the key
chmod 600 "$temp/etc/ssh/$hostname"
chmod 600 "$temp/etc/ssh/initrd"
# Install NixOS to the host system with our secrets and encription
# optional --build-on-remote
if [ $# = 3 ]
then
nix run github:numtide/nixos-anywhere -- --extra-files "$temp" \
--disk-encryption-keys /tmp/secret.key <(sops -d machines/$hostname/disk.key) --flake .#$hostname $3@$ipaddress
else
nix run github:numtide/nixos-anywhere -- --extra-files "$temp" \
--disk-encryption-keys /tmp/secret.key <(sops -d machines/$hostname/disk.key) --flake .#$hostname root@$ipaddress
fi