create shared nixos config between physical and VM

rename nixos -> nix
This commit is contained in:
Pim Kunis 2024-01-28 12:06:30 +01:00
parent 472175c5a3
commit 32154e7163
39 changed files with 114 additions and 196 deletions

View file

@ -1,168 +0,0 @@
{ pkgs, config, lib, modulesPath, machine, microvm, disko, agenix, machines, ... }: {
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
./modules
./lab.nix
machine.nixosModule
disko.nixosModules.disko
agenix.nixosModules.default
microvm.nixosModules.host
];
config = {
boot = {
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
initrd = {
availableKernelModules = [
"ahci"
"xhci_pci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
"sdhci_pci"
];
kernelModules = [ ];
};
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
};
time.timeZone = "Europe/Amsterdam";
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_ADDRESS = "nl_NL.UTF-8";
LC_IDENTIFICATION = "nl_NL.UTF-8";
LC_MEASUREMENT = "nl_NL.UTF-8";
LC_MONETARY = "nl_NL.UTF-8";
LC_NAME = "nl_NL.UTF-8";
LC_NUMERIC = "nl_NL.UTF-8";
LC_PAPER = "nl_NL.UTF-8";
LC_TELEPHONE = "nl_NL.UTF-8";
LC_TIME = "nl_NL.UTF-8";
};
};
services = {
openssh = {
enable = true;
openFirewall = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
xserver = {
layout = "us";
xkbVariant = "";
};
};
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOodpLr+FDRyKyHjucHizNLVFHZ5AQmE9GmxMnOsSoaw pimkunis@thinkpadpim"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINUZp4BCxf7uLa1QWonx/Crf8tYZ5MKIZ+EuaBa82LrV user@user-laptop"
];
programs = {
ssh = {
knownHosts = {
dmz = {
hostNames = [ "*.dmz" ];
publicKey =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAX2IhgHNxC6JTvLu9cej+iWuG+uJFMXn4AiRro9533x";
certAuthority = true;
};
hypervisors = {
hostNames = [ "*.hyp" ];
publicKey =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFzRkH3d/KVJQouswY/DMpenWbDFVOnI3Vut0xR0e1tb";
certAuthority = true;
};
};
};
neovim = {
enable = true;
vimAlias = true;
viAlias = true;
};
};
nixpkgs = {
config.allowUnfree = true;
hostPlatform = "x86_64-linux";
};
environment.systemPackages = with pkgs; [
neofetch
wget
git
btop
htop
ripgrep
dig
tree
file
tcpdump
lsof
parted
radvd
];
hardware.cpu.intel.updateMicrocode = config.hardware.enableRedistributableFirmware;
age.identityPaths = [ "/etc/age_ed25519" ];
virtualisation.libvirtd.enable = true;
nix = {
package = pkgs.nixFlakes;
extraOptions = ''
experimental-features = nix-command flakes
'';
};
system = {
stateVersion = "23.05";
activationScripts.diff = ''
if [[ -e /run/current-system ]]; then
${pkgs.nix}/bin/nix store diff-closures /run/current-system "$systemConfig"
fi
'';
};
microvm.vms =
let
vmsForHypervisor = lib.attrValues (lib.filterAttrs (n: v: v.type == "virtual" && v.hypervisorName == machine.hostName) machines);
in
lib.attrsets.mergeAttrsList (map
(vm:
{
"${vm.hostName}" = {
# TODO Simplify?
specialArgs = { inherit agenix disko pkgs lib microvm; machine = vm; hypervisorConfig = config; };
config = {
imports = [
./vm.nix
];
};
};
}
)
vmsForHypervisor
);
};
}

View file

@ -1,11 +0,0 @@
{
lab.networking = {
publicIPv4 = "192.145.57.90";
dockerSwarmInternalIPv4 = "192.168.30.8";
dockerSwarmIPv6 = "2a0d:6e00:1a77:30:c8fe:c0ff:feff:ee08";
dmzRouterIPv4 = "192.168.30.1";
dmzServicesIPv4 = "192.168.30.7";
# TODO: configure prefix length as well
dmzServicesIPv6 = "2a0d:6e00:1a77:30::7";
};
}

View file

@ -1 +0,0 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIH4CQGHwWytKnkn7lYjT6G1NyPzINvfroZgwCLoOLO74AAAAIOMoSSEqM4VUBWUeFweJbqK9z7Ygp7fkX22hyWmgCNg8AAAAAAAAAAAAAAACAAAACWF0bGFzLmh5cAAAAA0AAAAJYXRsYXMuaHlwAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgXNGQfd38pUlCi6zBj8Myl6dZsMVU6cjdW63TFHR7W1sAAABTAAAAC3NzaC1lZDI1NTE5AAAAQAYModSEVNG06xvAcRn8XFeCp/iXFeqVcbtfT1NmmMkyIgybkXhJyHjp89BPg0zeAaoScFx8Xpsdd8CsxTeP+QU= root@atlas

View file

@ -1 +0,0 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIItpNkjaH8o51VKydwHYbbLxXMtf4euzojFKPxz+XqdwAAAAIG1vJNH1p8l8HlmYMT/vHGTjEnIul7ORQhutNnKiXlgqAAAAAAAAAAAAAAABAAAACWF0bGFzLmh5cAAAABsAAAAJYXRsYXMuaHlwAAAACmh5cGVydmlzb3IAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgdmt4SFL+swd8kHsh6cQR+TfzMKObJx75fYBbHNT83zUAAABTAAAAC3NzaC1lZDI1NTE5AAAAQIW4tC+FJA6bKFUfRVcHLWz1u3ZL/GRTWD2WCW4ApHq7no6ODeMwE10noNt/42mwYjFmjwR+cd9EuMyUErXmaw8= root@atlas

View file

@ -1,91 +0,0 @@
{
jefke = {
# TODO: directly set and read this from nixos config.
hostName = "jefke";
domain = "hyp";
type = "physical";
nixosModule.lab = {
terraformDatabase.enable = true;
storage = {
osDisk = "/dev/sda";
dataPartition = "/dev/nvme0n1p1";
};
ssh = {
useCertificates = true;
hostCert = builtins.readFile ./jefke_host_ed25519-cert.pub;
userCert = builtins.readFile ./jefke_user_ed25519-cert.pub;
};
};
};
atlas = {
hostName = "atlas";
domain = "hyp";
type = "physical";
nixosModule = { config, ... }:
let inherit (config.lab.networking) dmzServicesIPv4 dmzServicesIPv6; in
{
lab = {
networking = {
# TODO: Ideally, we don't have to set this here.
staticDMZIPv4Address = "${dmzServicesIPv4}/24";
staticDMZIPv6Address = "${dmzServicesIPv6}/64";
dmzServices.enable = true;
};
storage = {
osDisk = "/dev/sda";
dataPartition = "/dev/nvme0n1p1";
};
ssh = {
useCertificates = true;
hostCert = builtins.readFile ./atlas_host_ed25519-cert.pub;
userCert = builtins.readFile ./atlas_user_ed25519-cert.pub;
};
};
};
};
lewis = {
hostName = "lewis";
domain = "hyp";
type = "physical";
nixosModule = { pkgs, ... }: {
lab = {
dataHost.enable = true;
storage = {
osDisk = "/dev/sda";
dataPartition = "/dev/nvme0n1p1";
};
ssh = {
useCertificates = true;
hostCert = builtins.readFile ./lewis_host_ed25519-cert.pub;
userCert = builtins.readFile ./lewis_user_ed25519-cert.pub;
};
};
};
};
my-microvm = {
hostName = "my-microvm";
domain = "dmz";
type = "virtual";
hypervisorName = "lewis";
nixosModule = { pkgs, config, ... }: {
programs.bash.interactiveShellInit = ''
echo "Hello world from inside a virtual machine!" | ${pkgs.lolcat}/bin/lolcat
'';
lab.vmMacAddress = "BA:DB:EE:F0:00:00";
};
};
}

View file

@ -1 +0,0 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIHzQMMRr2vNtTW3joxPzQYjFFu3iI/WyIRVD18YKY61CAAAAIKTzrsjwRmKg3JbRLY/RrWnIBfCupfFdMWZ/8AQAXg9uAAAAAAAAAAAAAAACAAAACWplZmtlLmh5cAAAAA0AAAAJamVma2UuaHlwAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgXNGQfd38pUlCi6zBj8Myl6dZsMVU6cjdW63TFHR7W1sAAABTAAAAC3NzaC1lZDI1NTE5AAAAQPNDgNAOmp5Gl//mjEHF2H5Yi8GIFfyiRm8nJ2UkGXzpNr3+bQvQhPigziuXO0+8910yY9QzXTfvc4mgAT1gpgU= root@jefke

View file

@ -1 +0,0 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIKdTRygvLfapNY6umK+TdoqWDIq4ZzXLZlUJ/lVvkuqtAAAAINZ3aw6gjrOt561j1Mh7kINqlavorKeujN1Q8mn/Fy69AAAAAAAAAAAAAAABAAAACWplZmtlLmh5cAAAABsAAAAJamVma2UuaHlwAAAACmh5cGVydmlzb3IAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgdmt4SFL+swd8kHsh6cQR+TfzMKObJx75fYBbHNT83zUAAABTAAAAC3NzaC1lZDI1NTE5AAAAQI36zBw4Epr1ijXBk7T5JENgisn4SbVTLkhYBWCquHcAv3nFFJOEZ1kdC/SfYaDwmXb/rNybpr3942wF0xD3/ws= root@jefke

View file

@ -1 +0,0 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIAP9Xu3G75HcVIVhrgiCKSM+YTkaCbTqI18NBdWikIlHAAAAIKfbZauF+7q3s7VxhvxdPT7XDapch0P3tD//U4/70D6cAAAAAAAAAAAAAAACAAAACWxld2lzLmh5cAAAAA0AAAAJbGV3aXMuaHlwAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgXNGQfd38pUlCi6zBj8Myl6dZsMVU6cjdW63TFHR7W1sAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGHtz4FNkj0LuplU+12A/sx0bE4QeHLYhctXag9DSMGJz9yOpyMpK3PPKkm6leLdGYs7RUjxwXvcj+f4k16VXA0= root@atlas

View file

@ -1 +0,0 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIGqYC+tRPZ24WMroezrFgxtm8YObweMCTpz/y+dbGrzKAAAAIEuhHYB6zdSsfvLm4zXfuUbUCkUgPRu6rdt1rninA7PwAAAAAAAAAAAAAAABAAAACWxld2lzLmh5cAAAABsAAAAJbGV3aXMuaHlwAAAACmh5cGVydmlzb3IAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgdmt4SFL+swd8kHsh6cQR+TfzMKObJx75fYBbHNT83zUAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGV0nCPl4HDo1Q24NnFcPc1/FPYxwkWg864eUp5hdbttL4f8h7YLtZw6k8hHIn50wVdHEJkUwYrXgR1dwYhfEwA= root@atlas

View file

@ -1,127 +0,0 @@
{ pkgs, lib, config, ... }:
let
cfg = config.lab.backups;
beforeEverything = pkgs.writeShellScriptBin "beforeEverything" ''
if [ -d "${cfg.snapshotLocation}" ]; then
${pkgs.btrfs-progs}/bin/btrfs subvolume delete ${cfg.snapshotLocation}
fi
${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r ${cfg.subvolumeLocation} ${cfg.snapshotLocation}
'';
borgmaticConfig = pkgs.writeTextFile {
name = "borgmatic-config";
text = ''
source_directories:
- ${cfg.snapshotLocation}
repositories:
- path: ${cfg.repoLocation}
label: nfs
- path: ssh://admin@ec2-3-254-121-39.eu-west-1.compute.amazonaws.com/mnt/data/nfs.borg
label: ec2
ssh_command: "${pkgs.openssh}/bin/ssh -i ${config.age.secrets."ec2_borg_server.pem".path} -o StrictHostKeychecking=no -o ConnectTimeout=10 -o ConnectionAttempts=3"
keep_daily: 7
keep_weekly: 4
keep_monthly: 6
encryption_passcommand: "${pkgs.coreutils}/bin/cat ''${BORG_PASSPHRASE_FILE}"
before_everything:
- ${beforeEverything}/bin/beforeEverything
postgresql_databases:
- name: nextcloud
hostname: lewis.dmz
username: nextcloud
password: ''${NEXTCLOUD_DATABASE_PASSWORD}
format: tar
- name: hedgedoc
hostname: lewis.dmz
username: hedgedoc
password: ''${HEDGEDOC_DATABASE_PASSWORD}
format: tar
- name: paperless
hostname: lewis.dmz
username: paperless
password: ''${PAPERLESS_DATABASE_PASSWORD}
format: tar
'';
};
in
{
options.lab.backups = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to enable backups of persistent data on this machine.
'';
};
repoLocation = lib.mkOption {
default = "${config.lab.storage.dataMountPoint}/backups/nfs.borg";
type = lib.types.str;
description = ''
Location of the Borg repository to back up to.
'';
};
subvolumeLocation = lib.mkOption {
default = "${config.lab.storage.dataMountPoint}/nfs";
type = lib.types.str;
description = ''
Location of the btrfs subvolume holding the data.
'';
};
snapshotLocation = lib.mkOption {
default = "${config.lab.storage.dataMountPoint}/snapshot-nfs";
type = lib.types.str;
description = ''
Location to (temporary) create a snapshot of the subvolume.
'';
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [ borgbackup postgresql ];
# Converted from:
# https://github.com/borgmatic-collective/borgmatic/tree/84823dfb912db650936e3492f6ead7e0e0d32a0f/sample/systemd
systemd.services.borgmatic = {
description = "borgmatic backup";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
unitConfig.ConditionACPower = true;
preStart = "${pkgs.coreutils}/bin/sleep 10s";
path = with pkgs; [ postgresql ];
serviceConfig = {
Type = "oneshot";
Nice = 19;
CPUSchedulingPolicy = "batch";
IOSchedulingClass = "best-effort";
IOSchedulingPriority = 7;
IOWeight = 100;
Restart = "no";
LogRateLimitIntervalSec = 0;
EnvironmentFile = config.age.secrets."database_passwords.env".path;
Environment = "BORG_PASSPHRASE_FILE=${config.age.secrets."borg_passphrase".path}";
};
script = "${pkgs.systemd}/bin/systemd-inhibit --who=\"borgmatic\" --what=\"sleep:shutdown\" --why=\"Prevent interrupting scheduled backup\" ${pkgs.borgmatic}/bin/borgmatic --verbosity -2 --syslog-verbosity 1 -c ${borgmaticConfig}";
};
systemd.timers.borgmatic = {
description = "Run borgmatic backup";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "*-*-* 3:00:00";
Persistent = true;
RandomizedDelaySec = "3h";
};
};
age.secrets = {
"database_passwords.env".file = ../secrets/database_passwords.env.age;
"borg_passphrase".file = ../secrets/borg_passphrase.age;
"ec2_borg_server.pem".file = ../secrets/ec2_borg_server.pem.age;
};
};
}

View file

@ -1,83 +0,0 @@
{ pkgs, lib, config, ... }:
let
cfg = config.lab.data-sharing;
nfsShares = [
"/nextcloud/data"
"/radicale"
"/freshrss/data"
"/freshrss/extensions"
"/pihole/data"
"/pihole/dnsmasq"
"/hedgedoc/uploads"
"/traefik/acme"
"/forgejo"
"/kitchenowl/data"
"/syncthing/config"
"/paperless-ngx/data"
"/paperless-ngx/redisdata"
];
nfsExports = lib.strings.concatLines (
builtins.map
(share:
"${cfg.nfsRoot}${share} 192.168.30.0/24(rw,sync,no_subtree_check,no_root_squash)"
)
nfsShares
);
in
{
options.lab.data-sharing = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Configure this server to serve our data using NFS and PostgreSQL.
'';
};
nfsRoot = lib.mkOption {
default = "/mnt/data/nfs";
type = lib.types.str;
description = ''
Root directory of NFS data.
'';
};
postgresDir = lib.mkOption {
default = "/mnt/data/postgresql/${config.services.postgresql.package.psqlSchema}";
type = lib.types.str;
description = ''
Postgresql data directory.
'';
};
};
config = lib.mkIf cfg.enable {
networking.firewall.interfaces.${config.lab.networking.dmzBridgeName}.allowedTCPPorts = [
2049 # NFS
5432 # PostgeSQL
111 # NFS
20048 # NFS
];
services = {
nfs.server = {
enable = true;
exports = nfsExports;
};
postgresql = {
enable = true;
package = pkgs.postgresql_15;
enableTCPIP = true;
dataDir = cfg.postgresDir;
authentication = ''
host nextcloud nextcloud all md5
host hedgedoc hedgedoc all md5
host paperless paperless all md5
'';
};
};
};
}

View file

@ -1,31 +0,0 @@
{ lib, config, ... }:
let cfg = config.lab;
in
{
imports = [
./storage.nix
./terraform-database
./ssh-certificates.nix
./k3s
./backups.nix
./networking
./data-sharing.nix
];
options.lab.dataHost.enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether this machine holds application data.
This enables NFS and PostgreSQL to serve this data, and sets up backups.
Also enables networking on the DMZ to enable serving data.
'';
};
config.lab = lib.mkIf cfg.dataHost.enable {
backups.enable = true;
data-sharing.enable = true;
networking.allowDMZConnectivity = true;
};
}

View file

@ -1,16 +0,0 @@
{ kubenix, ... }: {
imports = [ kubenix.modules.k8s ];
kubernetes.resources.clusterRoleBindings.pim-cluster-admin = {
roleRef = {
apiGroup = "rbac.authorization.k8s.io";
kind = "ClusterRole";
name = "cluster-admin";
};
subjects = [
{
kind = "User";
name = "pim";
}
];
};
}

View file

@ -1,32 +0,0 @@
{ pkgs, lib, config, kubenix, ... }:
let cfg = config.lab.k3s;
in {
options.lab.k3s.enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to start k3s with custom configuration.
'';
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ pkgs.k3s ];
networking.firewall.allowedTCPPorts = [ 6443 ];
services.k3s = {
enable = true;
role = "server";
extraFlags = "--tls-san ${config.networking.fqdn} --data-dir ${config.lab.dataDisk.mountPoint}/k3s";
};
system.activationScripts.k3s-bootstrap.text =
let
k3sBootstrapFile = (kubenix.evalModules.x86_64-linux {
module = import ./bootstrap.nix;
}).config.kubernetes.result;
in
''
ln -sf ${k3sBootstrapFile} ${config.lab.dataDisk.mountPoint}/k3s/server/manifests/k3s-bootstrap.json
'';
};
}

View file

@ -1,165 +0,0 @@
{ lib, config, machine, ... }:
let cfg = config.lab.networking;
in {
imports = [ ./dmz ];
options.lab.networking = {
allowDMZConnectivity = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to allow networking on the DMZ bridge interface.
'';
};
staticDMZIPv4Address = lib.mkOption {
default = "";
type = lib.types.str;
description = ''
Assign a static IPv4 address on the DMZ interface.
'';
};
staticDMZIPv6Address = lib.mkOption {
default = "";
type = lib.types.str;
description = ''
Assign a static IPv6 address on the DMZ interface.
'';
};
publicIPv4 = lib.mkOption {
type = lib.types.str;
description = ''
Public IPv4 address of our home.
'';
};
dockerSwarmInternalIPv4 = lib.mkOption {
type = lib.types.str;
description = ''
Internal IPv4 address of the Docker Swarm.
'';
};
dockerSwarmIPv6 = lib.mkOption {
type = lib.types.str;
description = ''
Globally routable IPv6 address of the Docker Swarm.
'';
};
dmzRouterIPv4 = lib.mkOption {
type = lib.types.str;
description = ''
The router's IPv4 address on the DMZ network.
'';
};
dmzServicesIPv4 = lib.mkOption {
type = lib.types.str;
description = ''
The IPv4 address of the interface serving DHCP and DNS on the DMZ network.
'';
};
dmzServicesIPv6 = lib.mkOption {
type = lib.types.str;
description = ''
The IPv6 address of the interface serving DHCP and DNS on the DMZ network.
'';
};
dmzBridgeName = lib.mkOption {
default = "bridgedmz";
type = lib.types.str;
description = ''
The name of the DMZ bridge.
'';
};
mainNicNamePattern = lib.mkOption {
default = "en*";
type = lib.types.str;
description = ''
Pattern to match the name of this machine's main NIC.
'';
};
};
config = {
networking = {
hostName = machine.hostName;
domain = machine.domain;
nftables.enable = true;
useDHCP = machine.type == "virtual";
firewall = {
enable = true;
checkReversePath = false;
};
};
systemd.network = lib.mkIf (machine.type == "physical") {
enable = true;
netdevs = {
"20-vlandmz" = {
vlanConfig.Id = 30;
netdevConfig = {
Kind = "vlan";
Name = "vlandmz";
};
};
"20-bridgedmz" = {
netdevConfig = {
Kind = "bridge";
Name = cfg.dmzBridgeName;
};
};
};
networks = {
"30-main-nic" = {
matchConfig.Name = cfg.mainNicNamePattern;
vlan = [ "vlandmz" ];
networkConfig = {
DHCP = "yes";
};
};
"40-vlandmz" = {
matchConfig.Name = "vlandmz";
linkConfig.RequiredForOnline = "enslaved";
networkConfig = {
IPv6AcceptRA = false;
LinkLocalAddressing = "no";
Bridge = cfg.dmzBridgeName;
};
};
"40-bridgedmz" = {
matchConfig.Name = cfg.dmzBridgeName;
linkConfig.RequiredForOnline = "carrier";
networkConfig = {
IPv6AcceptRA = cfg.allowDMZConnectivity;
LinkLocalAddressing = if cfg.allowDMZConnectivity then "ipv6" else "no";
DHCP = lib.mkIf (cfg.allowDMZConnectivity && cfg.staticDMZIPv4Address == "") "yes";
Address = lib.lists.optional (cfg.staticDMZIPv4Address != "") cfg.staticDMZIPv4Address
++ lib.lists.optional (cfg.staticDMZIPv6Address != "") cfg.staticDMZIPv6Address;
};
};
"40-vms" = {
matchConfig.Name = "vm-*";
networkConfig.Bridge = cfg.dmzBridgeName;
};
};
};
};
}

View file

@ -1,68 +0,0 @@
{ pkgs, lib, config, dns, ... }@inputs:
let
cfg = config.lab.networking.dmzServices;
kunisZoneFile = pkgs.writeTextFile {
name = "kunis-zone-file";
text = (dns.lib.toString "kun.is" (import ./zones/kun.is.nix inputs));
};
geokunis2nlZoneFile = pkgs.writeTextFile {
name = "geokunis2nl-zone-file";
text = (dns.lib.toString "geokunis2.nl" (import ./zones/geokunis2.nl.nix inputs));
};
in
{
options.lab.networking.dmzServices.enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to enable an authoritative DNS server and DNSmasq for DMZ network.
'';
};
config = lib.mkIf cfg.enable {
lab.networking.allowDMZConnectivity = true;
networking.firewall.interfaces.${config.lab.networking.dmzBridgeName} = {
allowedTCPPorts = [ 53 5353 ];
allowedUDPPorts = [ 53 67 5353 ];
};
services = {
bind = {
enable = true;
forwarders = [ ];
extraOptions = ''
allow-transfer { none; };
allow-recursion { none; };
version none;
notify no;
'';
zones = {
"kun.is" = {
master = true;
file = kunisZoneFile;
allowQuery = [ "any" ];
};
"geokunis2.nl" = {
master = true;
file = geokunis2nlZoneFile;
allowQuery = [ "any" ];
slaves = [
"87.253.155.96/27"
"157.97.168.160/27"
];
};
};
};
dnsmasq = {
enable = true;
settings = import ./dnsmasq.nix inputs;
};
};
};
}

View file

@ -1,50 +0,0 @@
{ config, ... }:
let
inherit (config.lab.networking) publicIPv4 dockerSwarmInternalIPv4 dmzServicesIPv4 dmzServicesIPv6 dmzRouterIPv4;
in
{
no-resolv = true;
local = "/dmz/";
dhcp-fqdn = true;
no-hosts = true;
expand-hosts = true;
domain = "dmz";
dhcp-authoritative = true;
ra-param = "*,0,0";
alias = "${publicIPv4},${dockerSwarmInternalIPv4}";
log-dhcp = true;
log-queries = true;
port = "5353";
host-record = [
"hermes.dmz,${dmzServicesIPv4},${dmzServicesIPv6}"
"ipv4.hermes.dmz,${dmzServicesIPv4}"
"ipv6.hermes.dmz,${dmzServicesIPv6}"
];
server = [
dmzRouterIPv4
"/geokunis2.nl/${dmzServicesIPv4}"
"/kun.is/${dmzServicesIPv4}"
];
dhcp-range = [
"192.168.30.50,192.168.30.127,15m"
"2a0d:6e00:1a77:30::,ra-stateless,ra-names"
];
dhcp-host = [
"b8:27:eb:b9:ab:e2,esrom"
"ca:fe:c0:ff:ee:08,maestro,${dockerSwarmInternalIPv4}"
];
dhcp-option = [
"3,${dmzRouterIPv4}"
"option:dns-server,${dmzRouterIPv4}"
"option6:dns-server,[2a02:58:19a:30::1]"
];
address = [
"/ns.pizzapim.nl/ns.geokunis2.nl/${dmzServicesIPv4}"
"/ns.pizzapim.nl/ns.geokunis2.nl/${dmzServicesIPv6}"
];
}

View file

@ -1,68 +0,0 @@
{ config, dns, ... }:
with dns.lib.combinators;
let
inherit (config.lab.networking) publicIPv4 dmzServicesIPv6 dockerSwarmIPv6;
in
{
SOA = {
nameServer = "ns";
adminEmail = "hostmaster@geokunis2.nl";
serial = 2024011401;
};
NS = [
"ns.geokunis2.nl."
"ns0.transip.net."
"ns1.transip.nl."
"ns2.transip.eu."
];
MX = [ (mx.mx 10 "mail.geokunis2.nl.") ];
A = [ publicIPv4 ];
AAAA = [ dockerSwarmIPv6 ];
CAA = letsEncrypt "caa@geokunis2.nl";
subdomains = {
"*" = {
A = [ publicIPv4 ];
AAAA = [ dockerSwarmIPv6 ];
};
ns = {
A = [ publicIPv4 ];
AAAA = [ dmzServicesIPv6 ];
};
ns1 = {
A = [ publicIPv4 ];
AAAA = [ dmzServicesIPv6 ];
};
ns2 = {
A = [ publicIPv4 ];
AAAA = [ dmzServicesIPv6 ];
};
# Override because we don't support IPv6 for KMS.
kms = {
A = [ publicIPv4 ];
AAAA = [ ];
};
wg = {
A = [ publicIPv4 ];
AAAA = [ "2a0d:6e00:1a77::1" ];
};
wg4 = {
A = [ publicIPv4 ];
AAAA = [ ];
};
wg6 = {
A = [ ];
AAAA = [ "2a0d:6e00:1a77::1" ];
};
};
}

View file

@ -1,64 +0,0 @@
{ config, dns, ... }:
with dns.lib.combinators;
let
inherit (config.lab.networking) publicIPv4 dmzServicesIPv6 dockerSwarmIPv6;
in
{
CAA = letsEncrypt "caa@kun.is";
SOA = {
nameServer = "ns1";
adminEmail = "webmaster@kun.is";
serial = 2024011401;
};
NS = [
"ns1.kun.is."
"ns2.kun.is."
];
MX = [
(mx.mx 10 "mail.kun.is.")
];
subdomains = {
"*" = {
A = [ publicIPv4 ];
AAAA = [ dockerSwarmIPv6 ];
};
ns = {
A = [ publicIPv4 ];
AAAA = [ dmzServicesIPv6 ];
};
ns1 = {
A = [ publicIPv4 ];
AAAA = [ dmzServicesIPv6 ];
};
ns2 = {
A = [ publicIPv4 ];
AAAA = [ dmzServicesIPv6 ];
};
# Override because we don't support IPv6 for Git SSH.
git = {
A = [ publicIPv4 ];
AAAA = [ ];
};
# Override because we don't support IPv6 for KMS.
kms = {
A = [ publicIPv4 ];
AAAA = [ ];
};
# Override because wg is on opnsense so ipv6 differs from "dmzServicesIPv6"
wg = {
A = [ publicIPv4 ];
AAAA = [ "2a0d:6e00:1a77::1" ];
};
};
}

View file

@ -1,70 +0,0 @@
{ lib, config, ... }:
let
cfg = config.lab.ssh;
hostCert = builtins.toFile "host_ed25519-cert.pub" cfg.hostCert;
userCert = builtins.toFile "user_ed25519-cert.pub" cfg.userCert;
in
{
options.lab.ssh = {
useCertificates = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to use certificates at all.
'';
};
hostCert = lib.mkOption {
type = lib.types.str;
description = ''
SSH host certificate
'';
};
userCert = lib.mkOption {
type = lib.types.str;
description = ''
SSH user certificate
'';
};
hostKey = lib.mkOption {
default =
../secrets/${config.networking.hostName}_host_ed25519.age;
type = lib.types.path;
description = ''
SSH host key
'';
};
userKey = lib.mkOption {
default =
../secrets/${config.networking.hostName}_user_ed25519.age;
type = lib.types.path;
description = ''
SSH user key
'';
};
};
config = lib.mkIf cfg.useCertificates {
services.openssh = {
extraConfig = ''
HostCertificate ${hostCert}
HostKey ${config.age.secrets.host_ed25519.path}
'';
};
programs.ssh = {
extraConfig = ''
CertificateFile ${userCert}
IdentityFile ${config.age.secrets.user_ed25519.path}
'';
};
age.secrets = {
"host_ed25519".file = cfg.hostKey;
"user_ed25519".file = cfg.userKey;
};
};
}

View file

@ -1,66 +0,0 @@
{ lib, config, machine, ... }:
let cfg = config.lab.storage;
in {
options.lab.storage = {
osDisk = lib.mkOption {
type = lib.types.str;
description = ''
The disk to be used for the machine's operating system.
'';
};
dataPartition = lib.mkOption {
type = lib.types.str;
description = ''
Partition to be used for data storage on this machine.
'';
};
dataMountPoint = lib.mkOption {
default = "/mnt/data";
type = lib.types.str;
description = ''
Mount point of the machine's data partition.
'';
};
};
config = lib.mkIf (machine.type == "physical") {
fileSystems.${cfg.dataMountPoint}.device = cfg.dataPartition;
# TODO: Rename this to 'osDisk'. Unfortunately, we would need to run nixos-anywhere again then.
disko.devices.disk.vdb = {
device = cfg.osDisk;
type = "disk";
content = {
type = "gpt";
partitions = {
swap.size = "100%";
ESP = {
type = "EF00";
size = "500M";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
end = "-4G";
content = {
type = "filesystem";
format = "btrfs";
mountpoint = "/";
};
};
};
};
};
};
}

View file

@ -1,49 +0,0 @@
{ pkgs, lib, config, ... }:
let cfg = config.lab.terraformDatabase;
in {
options.lab.terraformDatabase.enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = ''
Whether to start a postgreSQL database for Terraform states
'';
};
config = lib.mkIf cfg.enable {
networking.firewall.interfaces.${config.lab.networking.mainNicNamePattern}.allowedTCPPorts = [ 5432 ];
services.postgresql = {
enable = true;
ensureDatabases = [ "terraformstates" ];
package = pkgs.postgresql_15;
enableTCPIP = true;
dataDir = "${config.lab.storage.dataMountPoint}/postgresql/${config.services.postgresql.package.psqlSchema}";
authentication = ''
hostssl terraformstates terraform all cert
'';
settings =
let
serverCert = builtins.toFile "postgresql_server.crt"
(builtins.readFile ./postgresql_server.crt);
in
{
ssl = true;
ssl_cert_file = serverCert;
ssl_key_file = config.age.secrets."postgresql_server.key".path;
ssl_ca_file = serverCert;
};
ensureUsers = [{ name = "terraform"; }];
};
age.secrets."postgresql_server.key" = {
file = ../../secrets/postgresql_server.key.age;
mode = "400";
owner = builtins.toString config.ids.uids.postgres;
group = builtins.toString config.ids.gids.postgres;
};
};
}

View file

@ -1,67 +0,0 @@
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
ef:2f:4d:d4:26:7e:33:1b
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=jefke.hyp
Validity
Not Before: Nov 22 19:12:03 2023 GMT
Not After : Oct 29 19:12:03 2123 GMT
Subject: CN=jefke.hyp
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c7:ab:eb:9c:d0:7f:4f:f1:ba:65:0a:8b:07:7b:
2e:5b:f0:26:82:33:c9:73:e6:91:cc:11:94:05:1c:
8d:67:29:cb:5e:67:35:02:80:54:af:99:4b:aa:ce:
e8:56:62:be:63:cb:b2:4a:b0:a9:28:12:e2:77:50:
7d:d5:d2:3b:48:d8:32:59:25:26:ff:a6:5c:f6:eb:
ae:5b:3d:7a:14:10:ba:90:9c:6f:1f:b9:d8:99:0e:
b7:09:5e:62:69:c4:c0:c6:27:b0:d3:60:0d:47:4c:
a5:11:53:f2:f1:4a:f9:a6:bc:d6:a3:35:a2:e8:e5:
a9:d1:60:e8:e5:18:ce:d2:60:80:4e:dc:48:ae:7f:
b7:ea:76:51:28:39:a4:b0:95:82:95:93:98:b2:9f:
23:c9:81:69:59:a3:e4:f7:5a:1c:01:31:96:c1:4b:
59:21:f8:a2:e6:9e:21:78:0e:6b:c1:68:c7:5c:16:
9a:06:54:df:b6:77:1d:2d:89:d0:c8:9e:db:b5:d4:
8c:fb:b9:4f:b7:6e:39:5f:39:8e:48:73:76:7d:46:
6e:1f:8d:14:cb:40:b5:ff:c6:f0:c0:44:3c:ed:52:
3f:4f:7b:69:63:93:c6:41:e6:5e:ed:33:50:20:46:
db:93:bf:e8:52:51:95:f1:81:73:58:da:67:21:7b:
12:bd
Exponent: 65537 (0x10001)
Signature Algorithm: sha256WithRSAEncryption
aa:5c:89:41:a6:b7:3d:65:87:ca:50:c4:f3:58:aa:d3:b4:55:
b1:a7:8d:18:26:17:e5:8a:21:24:a1:49:53:77:31:5b:55:63:
be:01:d8:fe:b7:06:7c:da:07:1f:94:6a:de:96:ad:ca:3b:20:
2a:e1:35:90:19:83:6d:37:d1:15:12:de:3c:0e:46:be:66:a1:
6a:1d:ec:72:dc:46:79:69:e4:af:77:c8:ff:cd:d6:7d:16:88:
ab:44:fd:70:fc:40:47:ff:43:95:11:5a:9a:56:0c:d2:dd:7c:
3b:87:aa:10:26:fa:25:a3:a0:43:8a:1b:ec:54:11:7e:65:67:
d2:06:e1:3e:3b:e1:0e:b0:80:ef:4b:35:3f:fc:34:1d:95:2e:
ee:c1:67:38:da:b3:74:86:4b:95:8c:0c:1d:51:28:c1:42:e9:
77:68:d7:ec:3b:66:30:c6:e5:2a:62:ea:15:fb:24:56:cf:02:
d0:25:54:a7:58:15:b5:2a:71:93:56:c0:69:7a:36:18:6c:31:
b1:8e:3c:77:d7:77:ac:fc:e1:94:c5:08:bb:35:ac:48:5f:6b:
8b:c8:c8:78:f4:a9:ca:4f:9d:51:54:89:97:c9:af:a1:fa:71:
df:58:f6:ff:04:7c:c8:1c:95:6b:1a:e3:a7:f6:43:1c:27:94:
10:03:ce:ec
-----BEGIN CERTIFICATE-----
MIICpjCCAY4CCQDvL03UJn4zGzANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlq
ZWZrZS5oeXAwIBcNMjMxMTIyMTkxMjAzWhgPMjEyMzEwMjkxOTEyMDNaMBQxEjAQ
BgNVBAMMCWplZmtlLmh5cDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AMer65zQf0/xumUKiwd7LlvwJoIzyXPmkcwRlAUcjWcpy15nNQKAVK+ZS6rO6FZi
vmPLskqwqSgS4ndQfdXSO0jYMlklJv+mXPbrrls9ehQQupCcbx+52JkOtwleYmnE
wMYnsNNgDUdMpRFT8vFK+aa81qM1oujlqdFg6OUYztJggE7cSK5/t+p2USg5pLCV
gpWTmLKfI8mBaVmj5PdaHAExlsFLWSH4ouaeIXgOa8Fox1wWmgZU37Z3HS2J0Mie
27XUjPu5T7duOV85jkhzdn1Gbh+NFMtAtf/G8MBEPO1SP097aWOTxkHmXu0zUCBG
25O/6FJRlfGBc1jaZyF7Er0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAqlyJQaa3
PWWHylDE81iq07RVsaeNGCYX5YohJKFJU3cxW1VjvgHY/rcGfNoHH5Rq3patyjsg
KuE1kBmDbTfRFRLePA5Gvmahah3sctxGeWnkr3fI/83WfRaIq0T9cPxAR/9DlRFa
mlYM0t18O4eqECb6JaOgQ4ob7FQRfmVn0gbhPjvhDrCA70s1P/w0HZUu7sFnONqz
dIZLlYwMHVEowULpd2jX7DtmMMblKmLqFfskVs8C0CVUp1gVtSpxk1bAaXo2GGwx
sY48d9d3rPzhlMUIuzWsSF9ri8jIePSpyk+dUVSJl8mvofpx31j2/wR8yByVaxrj
p/ZDHCeUEAPO7A==
-----END CERTIFICATE-----

View file

@ -1,5 +0,0 @@
To create a secret:
```bash
nix run github:ryantm/agenix# -- -e secret.age
``

Binary file not shown.

Binary file not shown.

View file

@ -1,15 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 UwNSRQ Lr6HfHB1pQVAVESUkR1a1ie8o9cTtCa0LA4y20UvfRU
8X+VZUfk2oRrM+A4pZC/6yyexo2Kr8MO7isiXPsnOJk
-> ssh-ed25519 JJ7S4A fngT1OkV0pfig7UZ4vA8CWFDWc//xn2KWRsk1+EI0Ac
9J+I87tFasCug4rVaXJKNKzxr450YtZUypSTmwf/r7g
-> ssh-ed25519 aqswPA I/RtBp+6CgMOPs41nbd8CqBgpgch8ixRGbzacXSDKRE
adBD/lskyXK/QU+v/OlQ1wQK7PkhALpdxgHUc1i+jcU
-> ssh-ed25519 LAPUww JtDnT4+NqLMBc+LpQSh0eQnSyXzJOHHbaZFNQmxIdC0
/DjWq9XUAH3xZvU1PlB7Q70LQ0x9SRMmaSYQ+DyQZEM
-> ssh-ed25519 vBZj5g 4YBFh5e32ZHr8byvd4vbZ9zljHO4FTrJGhsZiH//KVw
iA+foYHtgt2PjBG9yfBWNLeygiIbW3MsbUQdVWgyrno
-> ssh-ed25519 QP0PgA urlidySF5ZG9ILjdPuJPX6V/aDIAYzwBVd+XopDF5UA
NL/RxiKPRn+uZW37jJKLOHCaktuvzm0SIwcMmBgF5CY
--- aeaUWpBxSTjrcDDQa6Zk2dcdvhsdqs22JlvkduILpqE
âå™§òQú² à¡)Š„Åçä¿7bt¡­­íu+Õ<>=¼¯M£ÁlìMúzsÕÚ8ð… aÿ

View file

@ -1,16 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 UwNSRQ XKuX/onJklTJ1ws0svIwJy1PZN1MHsf5+N3z7XGvCyY
JkyemSdV/ZcbjWLrwYLhKCE4Ln2seLR0WyYXGMepgBw
-> ssh-ed25519 JJ7S4A 9wzkTABOPcmTG7LNWvZa7dKG0Ingf+KDckZ1tL2c3QQ
IkxcStI4kwXkWj+j3PWl7FdyoVMVsiH9SZBnyffbcYQ
-> ssh-ed25519 aqswPA 3i/v1qWLseD+FrPrnAXtSoK98a6Nrb3XrHinp2QPTn0
RxuPM1oICEoF5oZAyQlCm+fOivI9sfZenZSlOGBIZK8
-> ssh-ed25519 LAPUww MkvAMN/fZiV66+ub4Q/CDTIxJ3N3cMWBT0SQajespR0
uh6SGtxR3BvsU/fTTTOnsNXD+bHNYMhTAFoc3QUtMr8
-> ssh-ed25519 vBZj5g Jiu1sEmlws4eFPriuL2oS99Q9tFCyf4Zkv/khLONvT0
cLLHcvmIb1Nb7eVmKJyYdvfulgbcZ73N0x6GWyKeJPs
-> ssh-ed25519 QP0PgA A1Raf1CiVJ5tnJXRIeS0VpCUNX/iYNzGozQxApY9KGM
998c6IZfPNW8uMttkK8xGp1hgKXBcrwuBOgOpXWPCu8
--- /Qv6sfhphlYb9WtWdmPt6RZJPHxBO4jCSgauazsHIt8
1kYiL7¸<37>Áª-Ç}—`ýŠƒÇNƒVoäCñ'ÞÛ§ýhßô[øvDŠU€pv×½¶Òõ¦~e‰Â0yœ¦ÿ—ÑÄ2`•Ý<E280A2>ºîƱŽïÑ¥ÂÔåú8/´ª ¸
÷MEÐŽh·sÈqÌâ¤|ß kتí<Ó°¡+ÊÍ9eË0óŸ¸;­)Ï?IL-ëÓJY¾gðpk+ÛíúˆHRûé5ÔÍÉÛ¥ú”§„Ø× :8·ùo©þ1¥zâs—`•_MSÒí«Q˜;Q_o]·

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,43 +0,0 @@
let
pkgs = import <nixpkgs> { };
lib = pkgs.lib;
publicKeyURLs = [
"https://github.com/pizzapim.keys"
"https://github.com/pizzaniels.keys"
];
encryptedFileNames = [
"jefke_host_ed25519.age"
"jefke_user_ed25519.age"
"postgresql_server.key.age"
"atlas_host_ed25519.age"
"atlas_user_ed25519.age"
"lewis_host_ed25519.age"
"lewis_user_ed25519.age"
"database_passwords.env.age"
"borg_passphrase.age"
"ec2_borg_server.pem.age"
];
machinePublicKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIJUSH2IQg8Y/CCcej7J6oe4co++6HlDo1MYDCR3gV3a root@jefke.hyp"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKZ1OGe8jLyc+72SFUnW4FOKbpqHs7Mym85ESBN4HWV7 root@atlas.hyp"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL5lZjsqS6C50WO8p08TY7Fg8rqQH04EkpDTxCRGtR7a root@lewis.hyp"
];
fetchPublicKeys = url:
let
publicKeysFile = builtins.fetchurl { inherit url; };
publicKeysFileContents = lib.strings.fileContents publicKeysFile;
in
lib.strings.splitString "\n" publicKeysFileContents;
adminPublicKeys = lib.flatten (builtins.map fetchPublicKeys publicKeyURLs);
allPublicKeys = lib.flatten [ machinePublicKeys adminPublicKeys ];
publicKeysForEncryptedFileName = encryptedFileName:
{ "${encryptedFileName}".publicKeys = allPublicKeys; };
in
lib.attrsets.mergeAttrsList (builtins.map publicKeysForEncryptedFileName encryptedFileNames)

View file

@ -1,119 +0,0 @@
{ pkgs, lib, config, agenix, disko, machine, hypervisorConfig, ... }: {
imports = [
./modules
./lab.nix
machine.nixosModule
disko.nixosModules.disko
agenix.nixosModules.default
];
options.lab.vmMacAddress = lib.mkOption {
type = lib.types.str;
description = ''
The MAC address of the VM's main NIC.
'';
};
# TODO: remove overlap with physical nixos module
# Perhaps a sane defaults module?
config = {
system.stateVersion = hypervisorConfig.system.stateVersion;
time.timeZone = "Europe/Amsterdam";
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_ADDRESS = "nl_NL.UTF-8";
LC_IDENTIFICATION = "nl_NL.UTF-8";
LC_MEASUREMENT = "nl_NL.UTF-8";
LC_MONETARY = "nl_NL.UTF-8";
LC_NAME = "nl_NL.UTF-8";
LC_NUMERIC = "nl_NL.UTF-8";
LC_PAPER = "nl_NL.UTF-8";
LC_TELEPHONE = "nl_NL.UTF-8";
LC_TIME = "nl_NL.UTF-8";
};
};
services = {
openssh = {
enable = true;
openFirewall = true;
settings = {
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
};
xserver = {
layout = "us";
xkbVariant = "";
};
};
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOodpLr+FDRyKyHjucHizNLVFHZ5AQmE9GmxMnOsSoaw pimkunis@thinkpadpim"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINUZp4BCxf7uLa1QWonx/Crf8tYZ5MKIZ+EuaBa82LrV user@user-laptop"
];
programs = {
ssh = {
knownHosts = {
dmz = {
hostNames = [ "*.dmz" ];
publicKey =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAX2IhgHNxC6JTvLu9cej+iWuG+uJFMXn4AiRro9533x";
certAuthority = true;
};
hypervisors = {
hostNames = [ "*.hyp" ];
publicKey =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFzRkH3d/KVJQouswY/DMpenWbDFVOnI3Vut0xR0e1tb";
certAuthority = true;
};
};
};
neovim = {
enable = true;
vimAlias = true;
viAlias = true;
};
};
environment.systemPackages = with pkgs; [
neofetch
wget
git
btop
htop
ripgrep
dig
tree
file
tcpdump
lsof
parted
radvd
];
microvm = {
shares = [{
source = "/nix/store";
mountPoint = "/nix/.ro-store";
tag = "ro-store";
proto = "virtiofs";
}];
interfaces = [{
type = "tap";
id = "vm-${machine.hostName}";
mac = config.lab.vmMacAddress;
}];
};
};
}