From 2f4ebcba445cfab4713b6f0c30214bda483673c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20Schwarz=C3=A4ugl?= Date: Wed, 24 Dec 2025 14:48:27 +0100 Subject: [PATCH] feat[server]: first working microvm --- flake.lock | 117 +++++++++--- flake.nix | 1 + .../nixos/x86_64-linux/hintbooth/default.nix | 11 +- .../hintbooth/guests/adguardhome.nix | 23 +++ .../hintbooth/secrets/pii.nix.enc | 6 +- .../x86_64-linux/winters/secrets/secrets.yaml | 5 +- modules/home/default.nix | 1 + modules/nixos/client/stylix.nix | 3 +- modules/nixos/client/sway.nix | 23 +-- modules/nixos/common/globals.nix | 7 + modules/nixos/common/home-manager-secrets.nix | 60 +++--- modules/nixos/common/home-manager.nix | 4 +- modules/nixos/common/settings.nix | 7 +- modules/nixos/common/users.nix | 2 +- modules/nixos/darwin/default.nix | 22 ++- modules/nixos/default.nix | 1 + modules/nixos/optional/default.nix | 1 + modules/nixos/optional/framework.nix | 13 +- modules/nixos/optional/gaming.nix | 14 +- modules/nixos/optional/microvm-guest.nix | 31 +++- .../nixos/optional/systemd-networkd-vlan.nix | 116 ++++++++++++ modules/nixos/optional/uni.nix | 4 +- modules/nixos/optional/work.nix | 17 +- modules/nixos/server/kea.nix | 76 ++++++++ modules/nixos/server/nftables.nix | 74 ++++++++ modules/nixos/server/packages.nix | 3 +- modules/nixos/server/router.nix | 172 +++++++++++++----- modules/nixos/server/settings.nix | 24 +-- modules/nixos/server/ssh.nix | 24 +-- modules/shared/config-lib.nix | 40 +++- modules/shared/meta.nix | 5 + modules/shared/options.nix | 4 +- nix/hosts.nix | 7 +- pkgs/config/default.nix | 2 +- profiles/nixos/hotel/default.nix | 1 + profiles/nixos/localserver/default.nix | 1 + profiles/nixos/microvm/default.nix | 27 +++ profiles/nixos/minimal/default.nix | 1 + profiles/nixos/personal/default.nix | 1 + profiles/nixos/router/default.nix | 2 + 40 files changed, 759 insertions(+), 194 deletions(-) create mode 100644 hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix create mode 100644 modules/nixos/optional/systemd-networkd-vlan.nix create mode 100644 modules/nixos/server/kea.nix create mode 100644 modules/nixos/server/nftables.nix create mode 100644 profiles/nixos/microvm/default.nix diff --git a/flake.lock b/flake.lock index 3035936..e2f655d 100644 --- a/flake.lock +++ b/flake.lock @@ -156,6 +156,27 @@ "type": "github" } }, + "dependencyDagOfSubmodule": { + "inputs": { + "nixpkgs": [ + "nixos-nftables-firewall", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1656615370, + "narHash": "sha256-IZDqz1aSySoqf1qtVQg+oJMHfC4IlT55Zoa7EkjvPug=", + "owner": "thelegy", + "repo": "nix-dependencyDagOfSubmodule", + "rev": "98eb563d80b35acafbfc1abb9ccee569c1efb19c", + "type": "github" + }, + "original": { + "owner": "thelegy", + "repo": "nix-dependencyDagOfSubmodule", + "type": "github" + } + }, "devshell": { "inputs": { "nixpkgs": "nixpkgs" @@ -1508,6 +1529,25 @@ "type": "github" } }, + "nixos-nftables-firewall": { + "inputs": { + "dependencyDagOfSubmodule": "dependencyDagOfSubmodule", + "nixpkgs": "nixpkgs_17" + }, + "locked": { + "lastModified": 1715521768, + "narHash": "sha256-BQkkBqDemoPRd2a4G94I9w9fNE0IxWtVsQ9SalnNqCQ=", + "owner": "thelegy", + "repo": "nixos-nftables-firewall", + "rev": "2c5a19966b4dfc5ca92df7eb250c68f90be653c8", + "type": "github" + }, + "original": { + "owner": "thelegy", + "repo": "nixos-nftables-firewall", + "type": "github" + } + }, "nixos-stable": { "locked": { "lastModified": 1749237914, @@ -1885,15 +1925,15 @@ }, "nixpkgs_17": { "locked": { - "lastModified": 1763835633, - "narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=", + "lastModified": 1692638711, + "narHash": "sha256-J0LgSFgJVGCC1+j5R2QndadWI1oumusg6hCtYAzLID4=", "owner": "nixos", "repo": "nixpkgs", - "rev": "050e09e091117c3d7328c7b2b7b577492c43c134", + "rev": "91a22f76cd1716f9d0149e8a5c68424bb691de15", "type": "github" }, "original": { - "owner": "nixos", + "owner": "NixOS", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" @@ -1901,11 +1941,11 @@ }, "nixpkgs_18": { "locked": { - "lastModified": 1720957393, - "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", + "lastModified": 1763835633, + "narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", + "rev": "050e09e091117c3d7328c7b2b7b577492c43c134", "type": "github" }, "original": { @@ -1917,11 +1957,11 @@ }, "nixpkgs_19": { "locked": { - "lastModified": 1763835633, - "narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=", + "lastModified": 1720957393, + "narHash": "sha256-oedh2RwpjEa+TNxhg5Je9Ch6d3W1NKi7DbRO1ziHemA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "050e09e091117c3d7328c7b2b7b577492c43c134", + "rev": "693bc46d169f5af9c992095736e82c3488bf7dbb", "type": "github" }, "original": { @@ -1948,6 +1988,22 @@ } }, "nixpkgs_20": { + "locked": { + "lastModified": 1763835633, + "narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "050e09e091117c3d7328c7b2b7b577492c43c134", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_21": { "locked": { "lastModified": 1763934636, "narHash": "sha256-9glbI7f1uU+yzQCq5LwLgdZqx6svOhZWkd4JRY265fc=", @@ -1963,7 +2019,7 @@ "type": "github" } }, - "nixpkgs_21": { + "nixpkgs_22": { "locked": { "lastModified": 1763553727, "narHash": "sha256-4aRqRkYHplWk0mrtoF5i3Uo73E3niOWiUZU8kmPm9hQ=", @@ -1979,7 +2035,7 @@ "type": "github" } }, - "nixpkgs_22": { + "nixpkgs_23": { "locked": { "lastModified": 1764445028, "narHash": "sha256-ik6H/0Zl+qHYDKTXFPpzuVHSZE+uvVz2XQuQd1IVXzo=", @@ -1995,7 +2051,7 @@ "type": "github" } }, - "nixpkgs_23": { + "nixpkgs_24": { "locked": { "lastModified": 1763966396, "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", @@ -2011,7 +2067,7 @@ "type": "github" } }, - "nixpkgs_24": { + "nixpkgs_25": { "locked": { "lastModified": 1762977756, "narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=", @@ -2027,7 +2083,7 @@ "type": "github" } }, - "nixpkgs_25": { + "nixpkgs_26": { "locked": { "lastModified": 1763966396, "narHash": "sha256-6eeL1YPcY1MV3DDStIDIdy/zZCDKgHdkCmsrLJFiZf0=", @@ -2043,7 +2099,7 @@ "type": "github" } }, - "nixpkgs_26": { + "nixpkgs_27": { "locked": { "lastModified": 1761236834, "narHash": "sha256-+pthv6hrL5VLW2UqPdISGuLiUZ6SnAXdd2DdUE+fV2Q=", @@ -2059,7 +2115,7 @@ "type": "github" } }, - "nixpkgs_27": { + "nixpkgs_28": { "locked": { "lastModified": 1751274312, "narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=", @@ -2075,7 +2131,7 @@ "type": "github" } }, - "nixpkgs_28": { + "nixpkgs_29": { "locked": { "lastModified": 1754800730, "narHash": "sha256-HfVZCXic9XLBgybP0318ym3cDnGwBs/+H5MgxFVYF4I=", @@ -2298,7 +2354,7 @@ "nswitch-rcm-nix": { "inputs": { "flake-parts": "flake-parts_3", - "nixpkgs": "nixpkgs_18" + "nixpkgs": "nixpkgs_19" }, "locked": { "lastModified": 1721304043, @@ -2317,7 +2373,7 @@ "nur": { "inputs": { "flake-parts": "flake-parts_4", - "nixpkgs": "nixpkgs_19" + "nixpkgs": "nixpkgs_20" }, "locked": { "lastModified": 1763996502, @@ -2549,7 +2605,7 @@ "inputs": { "flake-compat": "flake-compat_7", "gitignore": "gitignore_4", - "nixpkgs": "nixpkgs_20" + "nixpkgs": "nixpkgs_21" }, "locked": { "lastModified": 1763988335, @@ -2589,7 +2645,8 @@ "nixos-generators": "nixos-generators", "nixos-hardware": "nixos-hardware", "nixos-images": "nixos-images", - "nixpkgs": "nixpkgs_17", + "nixos-nftables-firewall": "nixos-nftables-firewall", + "nixpkgs": "nixpkgs_18", "nixpkgs-dev": "nixpkgs-dev", "nixpkgs-kernel": "nixpkgs-kernel", "nixpkgs-stable": "nixpkgs-stable_3", @@ -2724,7 +2781,7 @@ "blobs": "blobs", "flake-compat": "flake-compat_8", "git-hooks": "git-hooks", - "nixpkgs": "nixpkgs_21" + "nixpkgs": "nixpkgs_22" }, "locked": { "lastModified": 1763564778, @@ -2760,7 +2817,7 @@ }, "sops": { "inputs": { - "nixpkgs": "nixpkgs_22" + "nixpkgs": "nixpkgs_23" }, "locked": { "lastModified": 1764483358, @@ -2794,7 +2851,7 @@ }, "spicetify-nix": { "inputs": { - "nixpkgs": "nixpkgs_23", + "nixpkgs": "nixpkgs_24", "systems": "systems_5" }, "locked": { @@ -2898,7 +2955,7 @@ "firefox-gnome-theme": "firefox-gnome-theme", "flake-parts": "flake-parts_5", "gnome-shell": "gnome-shell", - "nixpkgs": "nixpkgs_24", + "nixpkgs": "nixpkgs_25", "nur": "nur_2", "systems": "systems_6", "tinted-foot": "tinted-foot", @@ -2924,7 +2981,7 @@ "swarsel-nix": { "inputs": { "flake-parts": "flake-parts_6", - "nixpkgs": "nixpkgs_25", + "nixpkgs": "nixpkgs_26", "systems": "systems_7" }, "locked": { @@ -3175,7 +3232,7 @@ }, "treefmt-nix": { "inputs": { - "nixpkgs": "nixpkgs_26" + "nixpkgs": "nixpkgs_27" }, "locked": { "lastModified": 1762938485, @@ -3193,7 +3250,7 @@ }, "vbc-nix": { "inputs": { - "nixpkgs": "nixpkgs_27", + "nixpkgs": "nixpkgs_28", "systems": "systems_9" }, "locked": { @@ -3271,7 +3328,7 @@ "inputs": { "crane": "crane_3", "flake-utils": "flake-utils_8", - "nixpkgs": "nixpkgs_28", + "nixpkgs": "nixpkgs_29", "rust-overlay": "rust-overlay_3" }, "locked": { diff --git a/flake.nix b/flake.nix index b6fbff3..2b2ecc5 100644 --- a/flake.nix +++ b/flake.nix @@ -74,6 +74,7 @@ dns.url = "github:kirelagin/dns.nix"; nix-minecraft.url = "github:Infinidoge/nix-minecraft"; simple-nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/master"; + nixos-nftables-firewall.url = "github:thelegy/nixos-nftables-firewall"; }; outputs = diff --git a/hosts/nixos/x86_64-linux/hintbooth/default.nix b/hosts/nixos/x86_64-linux/hintbooth/default.nix index 2c957c0..b931b70 100644 --- a/hosts/nixos/x86_64-linux/hintbooth/default.nix +++ b/hosts/nixos/x86_64-linux/hintbooth/default.nix @@ -1,4 +1,4 @@ -{ self, lib, minimal, ... }: +{ self, config, lib, minimal, confLib, ... }: { imports = [ @@ -6,6 +6,7 @@ ./disk-config.nix "${self}/modules/nixos/optional/systemd-networkd-server.nix" + "${self}/modules/nixos/optional/systemd-networkd-vlan.nix" ]; topology.self = { @@ -31,6 +32,7 @@ rootDisk = "/dev/sda"; swapSize = "8G"; networkKernelModules = [ "igb" ]; + withMicroVMs = true; server = { wireguard.interfaces = { wgHome = { @@ -47,7 +49,7 @@ swarselprofiles = { server = true; - router = false; + router = true; }; swarselmodules = { @@ -56,4 +58,9 @@ }; }; + guests = lib.mkIf (!minimal && config.swarselsystems.withMicroVMs) ( + { } + // confLib.mkMicrovm "adguardhome" + ); + } diff --git a/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix b/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix new file mode 100644 index 0000000..2a0d511 --- /dev/null +++ b/hosts/nixos/x86_64-linux/hintbooth/guests/adguardhome.nix @@ -0,0 +1,23 @@ +{ self, lib, minimal, ... }: +{ + imports = [ + "${self}/profiles/nixos/microvm" + "${self}/modules/nixos" + ]; + + swarselsystems = { + isMicroVM = true; + }; + +} // lib.optionalAttrs (!minimal) { + + microvm = { + mem = 1024 * 1; + vcpu = 1; + }; + + swarselprofiles = { + microvm = true; + }; + +} diff --git a/hosts/nixos/x86_64-linux/hintbooth/secrets/pii.nix.enc b/hosts/nixos/x86_64-linux/hintbooth/secrets/pii.nix.enc index 880550a..f17c97b 100644 --- a/hosts/nixos/x86_64-linux/hintbooth/secrets/pii.nix.enc +++ b/hosts/nixos/x86_64-linux/hintbooth/secrets/pii.nix.enc @@ -1,5 +1,5 @@ { - "data": "ENC[AES256_GCM,data:mi/EbLHjvOmJyK30E719clNAN/hq6FCS1ld0pLG4ahuuDkOfgbUr0vPEmhlxoIrkmD3HNkDufTlFsWezZ9s6OiZKS1ASRSPI96Js43BwVLotub1/YJaV0JMFNVoKTo9ag/5soaAbta0GNq0wExIjBNaVExCmNOs3puXCod4nOI9qmcn/ytx+98+3iZk8p87NTauX5W3jb87QjMqucWaEWxo4DLerkLI54baEMKJUULYRO4/BJ102pFq1twOVNm7v4R8FLbjknNL0A5T2ymmAJqOSpRLApcFJjSda6JkVoMV380a7Wa9cawLF/9xHRJn2K5R5uRx7JTLxL2VuW1olYMSrImO/d08277ZHymxeV07nJCyO/Y/0aR36P5YxJrUwNwKe31oR2RSm3Ns7u/DoC3gymYzbBLlBYMfocl34lL4EkK56W2qiGAfuEf6v/kXqS9X6si+rGDEaXkuS/0UEtsP7AxsUpRYHWngk/DGOUTzKXPkMsNv6IbxHSK4wpA1Xka93r13DrKTzcaoXOqEe+K9GWiJsJl0zAM4UEmYcXF7sh7WzYeeY3D1RT7nt4I0AHaPkt7PKsdo/DR3xQPUluQ553vVUe2rAMokqRVHHzM5OuGwng5iLb3u0fZaD,iv:bmp/x16E/gRXCDqcg5sUt+DRFCRsHIO0/01nr+uFR7Y=,tag:wFw8Efid68B88gTkAbCzuw==,type:str]", + "data": "ENC[AES256_GCM,data:jaTRcoqOd3SNxwmzAcsqWyuvhYO0YipQPH2K2SM5OxhWWlUHTWQXqXmuAy0+efNnZlC8xqUWIoU//XXzUq/b7Lhi9bv9WyP7aHLOQNLFZ50Rt3b7yidFA/mxcRo2ZuGUR9mGoP8e1VtiQVVuzZQbJWqTCKtxb8s1f35aZx6NjaqeBFogfhHPwsVPL0lWdaxW2aYj/iwWb65xaxhcXa5mWpYgzfvuTXCkABFhrPxYG+NZpCyG7lt8MWpJ3yYWE0OEr/1Fe0TNfBjp7cih1wvMGIBj9uZRoJWkVwn6T+nldf52WpHCRZCdLhsjXCzM5T0g6Jj1HHatiISYZY3KLVAYKj63nSS3GkHk+BfoiAnJROcE2Aak0w7Op2csbNrNz807kU0x1A3ccbc50PKOGPFAh3JaJJUc0K+pGaIZ+FJhpIT8UyfQ7/YA7CDIvQObI9X7idsWPeuU3YN8VifgsGPznLWHyIgaUW7QmUtH1+KJdO0lo68C13FFnzEoMUroxMoUdS9Bvo1ncC9cITOr3Iuvb9nWQyg+wemyTJ5AOIx7dBh81PxMBYJ3JOTmxiO8LZapyqSbNhcbpo/3Q3s8J2DhIzgR2Ty7EI2tFxoGbzvpzBpWf/c7/rWWO67YDCfmB618w31Phes0/TTK2gxjviH917Q=,iv:M+S2woApVJAglQmvr0X1ZNvezNNl/nvxKjADWWXLiGY=,tag:CT4zP0qyJtbWCBJqqS7F5w==,type:str]", "sops": { "age": [ { @@ -7,8 +7,8 @@ "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXc3VHa0p2MVdIdHRrbEVi\ndUwxMXA3cFpDODA0Z0MyUC9aemF4U2RXeUhrCmZjSDBLZ0twRk5rZG16blorQVVZ\nRE5SNE51bGlhYTVqcThFUVIvTWxwOW8KLS0tIEVHZ3Z6VVZHK2FUQWZQNVlOTkpL\nYUpNUSsyQllQL0lUa0FaODZiSjBDSk0KSJHdYoiOuma7YFjLpssAgw8BfBo5tl+o\nRvNt9rsXUlXEwMlcmYpkgUlsSAJnus+uE9AdBSvTyFRb9Wo696YFRg==\n-----END AGE ENCRYPTED FILE-----\n" } ], - "lastmodified": "2025-12-22T09:31:39Z", - "mac": "ENC[AES256_GCM,data:rOOL5gRTILzOnIU7LveEAI3HeLkf16wTZL4toxBqDiReWwXllCeUaFJ+n5awehit44LL1HrFVgZ/uUsnJBpF6WciPjXTKeRZsazhEKEuBhvcfJzvDQvj/ls5QsEXr/xuDmVaLNM7s7QCok+iefSS4Cu9IHhrmmdo1GyIw6gvNP0=,iv:pDnLtzMbGWR0PnIshenuNNvHIglvNFD+DJuUOapWGQI=,tag:9azzi8367Nq0Z0yGW8H5sg==,type:str]", + "lastmodified": "2025-12-23T09:27:50Z", + "mac": "ENC[AES256_GCM,data:fuYSElvGFbFIdkQaTwNuXqaXxMuOmpT8moN9m/Yl+6u3e0sU9AMJLK95Azl0xffjScc79PAPXitILrK7gUwUdo4PvTpQo14IoSCzIQ4lcJFlrWXgn9dPFrc97iooMtBMk4hWmTzYL1mHkT/ab7NP3aE7j81N4HJcYwZqzVkdXaI=,iv:hpkTsdwJ+N/NVHEM5LdXC1iwZXT77OwZ+fM9mu3l3Bc=,tag:dxv4T9x9q8g8m5Imcurnag==,type:str]", "pgp": [ { "created_at": "2025-12-15T22:09:23Z", diff --git a/hosts/nixos/x86_64-linux/winters/secrets/secrets.yaml b/hosts/nixos/x86_64-linux/winters/secrets/secrets.yaml index cc3604f..fafcb97 100644 --- a/hosts/nixos/x86_64-linux/winters/secrets/secrets.yaml +++ b/hosts/nixos/x86_64-linux/winters/secrets/secrets.yaml @@ -38,6 +38,7 @@ kanidm-grafana: ENC[AES256_GCM,data:61PEA1fBcaRy8+x0dn9WrH9P0D+NOkbeZw==,iv:kbR3 kanidm-nextcloud: ENC[AES256_GCM,data:9FjsOzBos18ouHBeuzrzHIpCDowFt0Aktw==,iv:iqUQUsWsO5N+KZqHyqNxMxSija/yPrrrAqvz4b1NG1M=,tag:/WC3wg/eYXV3hLJPRVWLog==,type:str] kanidm-oauth2-proxy: ENC[AES256_GCM,data:DQ5tj7N+P1b8vFnF+MGhaUBvbVQoE4sVhQ==,iv:Xy4bdi8fSFuFHsQKgZ3PswFFYsqtiAeqeSRam1k/H0E=,tag:9W4LRPPYtDOrSpxRDK/7sg==,type:str] kanidm-freshrss: ENC[AES256_GCM,data:4y0X3sSOfs5pKNCmZGJhxlAKH7GD1UACdw==,iv:LuQQCfOpsTqglwQvohHMFpNGaOjoZ8PKDgG50qBP02k=,tag:Z5mVYP/9nToerQ1qui1eWQ==,type:str] +kanidm-firezone: ENC[AES256_GCM,data:hQWySw7EZZN2AT7rM4R2go8DAGYHph32tQ==,iv:vASPrP7qM1G5c4tC1aaAbCigglXt4keThMYOJdRYhOg=,tag:f5jevrQtiHAQTbMY07iIrQ==,type:str] #ENC[AES256_GCM,data:M9U+Mr1cAhlt7NpW,iv:LY19BZEwDdQD1Nhbmgdt9/9VNJjcTkOGP7SwEDE3Xwk=,tag:TlYrhu5dBj1D+Qd72r7Ofg==,type:comment] firefly-iii-app-key: ENC[AES256_GCM,data:hzgl8eRL0irNRP5TO7G1rNtNM7fXCkmbcaX4QoTsM0xA1rgyKwiy6a4lYDjoXZyOMy5p,iv:q5eepIELwIecyQ56A6THUOu+rebK3irKVYb7/gNHlU8=,tag:+M/KTX1JzPzXeK4TRzW42w==,type:str] #ENC[AES256_GCM,data:mBlfyJvQyrhTnpkJ,iv:hHnTCsHfzCgKuBO82JjNbjYYjWV8e7+0VRkbTGw+WRE=,tag:7Dp77Q2VjWJM5LydvpbJnQ==,type:comment] @@ -69,8 +70,8 @@ sops: c0lDa2EvQkUwM1ZIc1ppY1REZnlPKzQKJRXSl8SYQwzgPw+twNAFy3y+S2r7JwS0 xESNBdFS4Ntg9gXENRBzCaGmoOJfiFtGditBlvWUwbDYwLdn/y3kIQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-12-04T12:35:41Z" - mac: ENC[AES256_GCM,data:0Ps8slUmB7A+2vvCa44pOIVs+ehzczFyVUYh8vledsEW3odgm5LemmilspSw3xmf4V3cTl0h7mgGvLHJhpaZpI4nS4W4Cz3CrN6v3eu8ELRorVHUIDPIJNfzaCeRlat+oujGCWAuMbaEyXYj40PtXq9pSaYSluxDiPQu+QwKRaA=,iv:Rb1RcTJThoWO76vfDcyYlF3VnrDkN12frVdcQhRTLzQ=,tag:Mu5IgH541rXP3rlP1XlJrA==,type:str] + lastmodified: "2025-12-24T13:09:23Z" + mac: ENC[AES256_GCM,data:BNaX6zXAxEzarm0+X5qDIIOOfLoUFIlhhLN7QATzHIYoujZaJCGFWlM/+k9cnnIcGak22b0hwydjCF+opgH2bbau8P4NFPbWGxJHVry1Nu+EyB+Qb4QnVZZDWMcDxEMChR5eZvLAFC/K2f6oLtJeL2kGtedb079jhwpJt9nr87s=,iv:90SerUCkSoBqDYH4J6SV7cRXwGeinW44NxhSnfJ0r2k=,tag:8VnRp2oAuctwp7Nk3U7OWw==,type:str] pgp: - created_at: "2025-12-02T14:59:44Z" enc: |- diff --git a/modules/home/default.nix b/modules/home/default.nix index ed67c4d..7e60f40 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -1,3 +1,4 @@ +# @ future me: dont panic, this file is not read in by readNix { lib, ... }: let importNames = lib.swarselsystems.readNix "modules/home"; diff --git a/modules/nixos/client/stylix.nix b/modules/nixos/client/stylix.nix index 4c45cbe..8a43e2b 100644 --- a/modules/nixos/client/stylix.nix +++ b/modules/nixos/client/stylix.nix @@ -1,4 +1,4 @@ -{ self, lib, config, vars, ... }: +{ self, lib, config, vars, withHomeManager, ... }: { options.swarselmodules.stylix = lib.mkEnableOption "stylix config"; config = { @@ -12,6 +12,7 @@ image = config.swarselsystems.wallpaper; } vars.stylix); + } // lib.optionalAttrs withHomeManager { home-manager.users."${config.swarselsystems.mainUser}" = { stylix = { targets = vars.stylixHomeTargets; diff --git a/modules/nixos/client/sway.nix b/modules/nixos/client/sway.nix index 705048d..5cd6adb 100644 --- a/modules/nixos/client/sway.nix +++ b/modules/nixos/client/sway.nix @@ -1,19 +1,20 @@ -{ lib, config, pkgs, ... }: +{ lib, config, pkgs, withHomeManager, ... }: let inherit (config.swarselsystems) mainUser; in { options.swarselmodules.sway = lib.mkEnableOption "sway config"; - config = lib.mkIf config.swarselmodules.sway { - programs.sway = { - enable = true; - package = pkgs.swayfx; - wrapperFeatures = { - base = true; - gtk = true; + config = lib.mkIf config.swarselmodules.sway + { + programs.sway = { + enable = true; + package = pkgs.swayfx; + wrapperFeatures = { + base = true; + gtk = true; + }; }; - - inherit (config.home-manager.users.${mainUser}.wayland.windowManager.sway) extraSessionCommands; - }; + } // lib.optionalAttrs withHomeManager { + inherit (config.home-manager.users.${mainUser}.wayland.windowManager.sway) extraSessionCommands; }; } diff --git a/modules/nixos/common/globals.nix b/modules/nixos/common/globals.nix index 1fb53ca..aa38e6b 100644 --- a/modules/nixos/common/globals.nix +++ b/modules/nixos/common/globals.nix @@ -138,6 +138,10 @@ in type = types.nullOr types.str; default = null; }; + isHome = mkOption { + type = types.bool; + default = false; + }; }; }) ); @@ -188,6 +192,9 @@ in wanAddress6 = mkOption { type = types.nullOr types.net.ipv6; }; + isHome = mkOption { + type = types.bool; + }; }; } ); diff --git a/modules/nixos/common/home-manager-secrets.nix b/modules/nixos/common/home-manager-secrets.nix index 1dbc2c9..fd71be5 100644 --- a/modules/nixos/common/home-manager-secrets.nix +++ b/modules/nixos/common/home-manager-secrets.nix @@ -1,45 +1,47 @@ -{ self, lib, config, globals, ... }: +{ self, lib, config, globals, withHomeManager, ... }: let inherit (config.swarselsystems) mainUser homeDir; inherit (config.repo.secrets.common.emacs) radicaleUser; - modules = config.home-manager.users.${mainUser}.swarselmodules; certsSopsFile = self + /secrets/repo/certs.yaml; in { - config = lib.mkIf config.swarselsystems.withHomeManager { - sops = { - secrets = (lib.optionalAttrs modules.mail - { + config = { } // lib.optionalAttrs withHomeManager { + sops = + let + modules = config.home-manager.users.${mainUser}.swarselmodules; + in + { + secrets = (lib.optionalAttrs modules.mail { address1-token = { owner = mainUser; }; address2-token = { owner = mainUser; }; address3-token = { owner = mainUser; }; address4-token = { owner = mainUser; }; }) // (lib.optionalAttrs modules.waybar { - github-notifications-token = { owner = mainUser; }; - }) // (lib.optionalAttrs modules.emacs { - fever-pw = { path = "${homeDir}/.emacs.d/.fever"; owner = mainUser; }; - }) // (lib.optionalAttrs modules.zsh { - croc-password = { owner = mainUser; }; - github-nixpkgs-review-token = { owner = mainUser; }; - }) // (lib.optionalAttrs modules.emacs { - emacs-radicale-pw = { owner = mainUser; }; - github-forge-token = { owner = mainUser; }; - }) // (lib.optionalAttrs (modules ? optional-work) { - harica-root-ca = { sopsFile = certsSopsFile; path = "${homeDir}/.aws/certs/harica-root.pem"; owner = mainUser; }; - }) // (lib.optionalAttrs modules.anki { - anki-user = { owner = mainUser; }; - anki-pw = { owner = mainUser; }; - }); - templates = { - authinfo = lib.mkIf modules.emacs { - path = "${homeDir}/.emacs.d/.authinfo"; - content = '' - machine ${globals.services.radicale.domain} login ${radicaleUser} password ${config.sops.placeholder.emacs-radicale-pw} - ''; - owner = mainUser; + github-notifications-token = { owner = mainUser; }; + }) // (lib.optionalAttrs modules.emacs { + fever-pw = { path = "${homeDir}/.emacs.d/.fever"; owner = mainUser; }; + }) // (lib.optionalAttrs modules.zsh { + croc-password = { owner = mainUser; }; + github-nixpkgs-review-token = { owner = mainUser; }; + }) // (lib.optionalAttrs modules.emacs { + emacs-radicale-pw = { owner = mainUser; }; + github-forge-token = { owner = mainUser; }; + }) // (lib.optionalAttrs (modules ? optional-work) { + harica-root-ca = { sopsFile = certsSopsFile; path = "${homeDir}/.aws/certs/harica-root.pem"; owner = mainUser; }; + }) // (lib.optionalAttrs modules.anki { + anki-user = { owner = mainUser; }; + anki-pw = { owner = mainUser; }; + }); + templates = { + authinfo = lib.mkIf modules.emacs { + path = "${homeDir}/.emacs.d/.authinfo"; + content = '' + machine ${globals.services.radicale.domain} login ${radicaleUser} password ${config.sops.placeholder.emacs-radicale-pw} + ''; + owner = mainUser; + }; }; }; - }; }; } diff --git a/modules/nixos/common/home-manager.nix b/modules/nixos/common/home-manager.nix index edd4c88..711883a 100644 --- a/modules/nixos/common/home-manager.nix +++ b/modules/nixos/common/home-manager.nix @@ -1,8 +1,8 @@ -{ self, inputs, config, lib, homeLib, outputs, globals, nodes, minimal, configName, arch, type, ... }: +{ self, inputs, config, lib, homeLib, outputs, globals, nodes, minimal, configName, arch, type, withHomeManager, ... }: { options.swarselmodules.home-manager = lib.mkEnableOption "home-manager"; config = lib.mkIf config.swarselmodules.home-manager { - home-manager = lib.mkIf config.swarselsystems.withHomeManager { + home-manager = lib.mkIf withHomeManager { useGlobalPkgs = true; useUserPackages = true; verbose = true; diff --git a/modules/nixos/common/settings.nix b/modules/nixos/common/settings.nix index 2ab4bbe..a476389 100644 --- a/modules/nixos/common/settings.nix +++ b/modules/nixos/common/settings.nix @@ -1,4 +1,4 @@ -{ self, lib, pkgs, config, outputs, inputs, minimal, globals, ... }: +{ self, lib, pkgs, config, outputs, inputs, minimal, globals, withHomeManager, ... }: let inherit (config.swarselsystems) mainUser; inherit (config.repo.secrets.common) atticPublicKey; @@ -122,18 +122,19 @@ in nixpkgs = { overlays = [ outputs.overlays.default + ] ++ lib.optionals withHomeManager [ (final: prev: let additions = final: _: import "${self}/pkgs/config" { inherit self config lib; pkgs = final; - homeConfig = config.home-manager.users.${config.swarselsystems.mainUser}; + homeConfig = config.home-manager.users.${config.swarselsystems.mainUser} or { }; }; in additions final prev ) ]; - config = { + config = lib.mkIf (!config.swarselsystems.isMicroVM) { allowUnfree = true; }; }; diff --git a/modules/nixos/common/users.nix b/modules/nixos/common/users.nix index aada123..52e389a 100644 --- a/modules/nixos/common/users.nix +++ b/modules/nixos/common/users.nix @@ -16,7 +16,7 @@ description = "Leon S"; password = lib.mkIf (minimal || config.swarselsystems.isPublic) "setup"; hashedPasswordFile = lib.mkIf (!minimal && !config.swarselsystems.isPublic) config.sops.secrets.main-user-hashed-pw.path; - extraGroups = [ "wheel" ] ++ lib.optionals (!minimal) [ "networkmanager" "syncthing" "docker" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ]; + extraGroups = [ "wheel" ] ++ lib.optionals (!minimal && !config.swarselsystems.isMicroVM) [ "networkmanager" "syncthing" "docker" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ]; packages = with pkgs; [ ]; }; }; diff --git a/modules/nixos/darwin/default.nix b/modules/nixos/darwin/default.nix index 4e4d373..43350b5 100644 --- a/modules/nixos/darwin/default.nix +++ b/modules/nixos/darwin/default.nix @@ -1,4 +1,4 @@ -{ self, lib, config, outputs, globals, ... }: +{ self, lib, config, outputs, globals, withHomeManager, ... }: let macUser = globals.user.work; in @@ -7,20 +7,22 @@ in ]; options.swarselmodules.optional.darwin = lib.mkEnableOption "optional darwin settings"; - config = lib.mkIf config.swarselmodules.optional.darwin { - nix.settings.experimental-features = "nix-command flakes"; - nixpkgs = { - hostPlatform = "x86_64-darwin"; - overlays = [ outputs.overlays.default ]; - config = { - allowUnfree = true; + config = lib.mkIf config.swarselmodules.optional.darwin + { + nix.settings.experimental-features = "nix-command flakes"; + nixpkgs = { + hostPlatform = "x86_64-darwin"; + overlays = [ outputs.overlays.default ]; + config = { + allowUnfree = true; + }; }; - }; + system.stateVersion = 4; + } // lib.optionalAttrs withHomeManager { home-manager.users."${macUser}".imports = [ "${self}/modules/home/darwin" ]; - system.stateVersion = 4; }; } diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 6284a4a..49598e3 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -1,3 +1,4 @@ +# @ future me: dont panic, optionals and darwin are not read in by readNix { lib, ... }: let importNames = lib.swarselsystems.readNix "modules/nixos"; diff --git a/modules/nixos/optional/default.nix b/modules/nixos/optional/default.nix index 49b7058..769f54f 100644 --- a/modules/nixos/optional/default.nix +++ b/modules/nixos/optional/default.nix @@ -1,3 +1,4 @@ +# @ future me: dont panic, this file is not read in by readNix { lib, ... }: let importNames = lib.swarselsystems.readNix "modules/nixos/optional"; diff --git a/modules/nixos/optional/framework.nix b/modules/nixos/optional/framework.nix index cade27e..929441f 100644 --- a/modules/nixos/optional/framework.nix +++ b/modules/nixos/optional/framework.nix @@ -1,12 +1,7 @@ -{ self, config, ... }: +{ self, lib, config, withHomeManager, ... }: { config = { - home-manager.users."${config.swarselsystems.mainUser}" = { - imports = [ - "${self}/modules/home/optional/framework.nix" - ]; - }; services = { fwupd = { @@ -29,5 +24,11 @@ defaultStrategy = "lazy"; }; }; + } // lib.optionalAttrs withHomeManager { + home-manager.users."${config.swarselsystems.mainUser}" = { + imports = [ + "${self}/modules/home/optional/framework.nix" + ]; + }; }; } diff --git a/modules/nixos/optional/gaming.nix b/modules/nixos/optional/gaming.nix index 09dcec1..c692cd6 100644 --- a/modules/nixos/optional/gaming.nix +++ b/modules/nixos/optional/gaming.nix @@ -1,13 +1,7 @@ -{ self, pkgs, config, ... }: +{ self, lib, pkgs, config, withHomeManager, ... }: { config = { - home-manager.users."${config.swarselsystems.mainUser}" = { - imports = [ - "${self}/modules/home/optional/gaming.nix" - ]; - }; - programs.steam = { enable = true; package = pkgs.steam; @@ -41,6 +35,12 @@ # ]; # }; # }; + } // lib.optionalAttrs withHomeManager { + home-manager.users."${config.swarselsystems.mainUser}" = { + imports = [ + "${self}/modules/home/optional/gaming.nix" + ]; + }; }; } diff --git a/modules/nixos/optional/microvm-guest.nix b/modules/nixos/optional/microvm-guest.nix index a90a2cf..adf069f 100644 --- a/modules/nixos/optional/microvm-guest.nix +++ b/modules/nixos/optional/microvm-guest.nix @@ -1,9 +1,28 @@ -_: +{ self, inputs, ... }: { - # imports = [ - # inputs.microvm.nixosModules.microvm - # ]; + imports = [ + inputs.disko.nixosModules.disko + inputs.home-manager.nixosModules.home-manager + inputs.impermanence.nixosModules.impermanence + inputs.lanzaboote.nixosModules.lanzaboote + inputs.microvm.nixosModules.host + inputs.microvm.nixosModules.microvm + inputs.nix-index-database.nixosModules.nix-index + inputs.nix-minecraft.nixosModules.minecraft-servers + inputs.nix-topology.nixosModules.default + inputs.nswitch-rcm-nix.nixosModules.nswitch-rcm + inputs.simple-nixos-mailserver.nixosModules.default + inputs.sops.nixosModules.sops + inputs.stylix.nixosModules.stylix + inputs.swarsel-nix.nixosModules.default + inputs.nixos-nftables-firewall.nixosModules.default - config = - { }; + (inputs.nixos-extra-modules + "/modules/interface-naming.nix") + + "${self}/modules/shared/meta.nix" + ]; + + config = { + system.stateVersion = "23.05"; + }; } diff --git a/modules/nixos/optional/systemd-networkd-vlan.nix b/modules/nixos/optional/systemd-networkd-vlan.nix new file mode 100644 index 0000000..2a3470e --- /dev/null +++ b/modules/nixos/optional/systemd-networkd-vlan.nix @@ -0,0 +1,116 @@ +{ lib, config, globals, ... }: +{ + + systemd.network = { + wait-online.anyInterface = true; + netdevs = { + "10-veth" = { + netdevConfig = { + Kind = "veth"; + Name = "veth-br"; + }; + peerConfig = { + Name = "veth-int"; + }; + }; + "20-br" = { + netdevConfig = { + Kind = "bridge"; + Name = "br"; + }; + }; + } // lib.flip lib.concatMapAttrs globals.networks.home-lan.vlans ( + vlanName: vlanCfg: { + "30-vlan-${vlanName}" = { + netdevConfig = { + Kind = "vlan"; + Name = "vlan-${vlanName}"; + }; + vlanConfig.Id = vlanCfg.id; + }; + "40-me-${vlanName}" = { + netdevConfig = { + Name = "me-${vlanName}"; + Kind = "macvlan"; + }; + extraConfig = '' + [MACVLAN] + Mode=bridge + ''; + }; + } + ); + networks = { + "40-br" = { + matchConfig.Name = "br"; + bridgeConfig = { }; + linkConfig = { + ActivationPolicy = "always-up"; + RequiredForOnline = "no"; + }; + networkConfig = { + ConfigureWithoutCarrier = true; + LinkLocalAddressing = "no"; + }; + }; + "15-veth-br" = { + matchConfig.Name = "veth-br"; + + linkConfig = { + RequiredForOnline = "no"; + }; + + networkConfig = { + Bridge = "br"; + }; + }; + "15-veth-int" = { + matchConfig.Name = "veth-int"; + + linkConfig = { + ActivationPolicy = "always-up"; + RequiredForOnline = "no"; + }; + + networkConfig = { + ConfigureWithoutCarrier = true; + LinkLocalAddressing = "no"; + }; + + vlan = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + }; + "90-macvtap-ignore" = { + matchConfig.Kind = "macvtap"; + linkConfig.ActivationPolicy = "manual"; + linkConfig.Unmanaged = "yes"; + }; + } // lib.flip lib.concatMapAttrs globals.networks.home-lan.vlans ( + vlanName: vlanCfg: { + "30-vlan-${vlanName}" = { + matchConfig.Name = "vlan-${vlanName}"; + networkConfig.LinkLocalAddressing = "no"; + networkConfig.MACVLAN = "me-${vlanName}"; + linkConfig.RequiredForOnline = "no"; + }; + "40-me-${vlanName}" = { + address = [ + vlanCfg.hosts.${config.node.name}.cidrv4 + vlanCfg.hosts.${config.node.name}.cidrv6 + ]; + matchConfig.Name = "me-${vlanName}"; + networkConfig = { + IPv4Forwarding = "yes"; + IPv6PrivacyExtensions = "yes"; + IPv6SendRA = true; + IPv6AcceptRA = false; + }; + ipv6Prefixes = [ + { Prefix = vlanCfg.cidrv6; } + ]; + linkConfig.RequiredForOnline = "routable"; + }; + } + ); + }; + +} diff --git a/modules/nixos/optional/uni.nix b/modules/nixos/optional/uni.nix index 1edf3b4..831ea58 100644 --- a/modules/nixos/optional/uni.nix +++ b/modules/nixos/optional/uni.nix @@ -1,6 +1,6 @@ -{ self, config, ... }: +{ self, config, withHomeManager, ... }: { - config = { + config = { } // lib.optionalAttrs withHomeManager { home-manager.users."${config.swarselsystems.mainUser}" = { imports = [ diff --git a/modules/nixos/optional/work.nix b/modules/nixos/optional/work.nix index 4e2ed4d..61b224d 100644 --- a/modules/nixos/optional/work.nix +++ b/modules/nixos/optional/work.nix @@ -1,4 +1,4 @@ -{ self, lib, pkgs, config, ... }: +{ self, lib, pkgs, config, withHomeManager, ... }: let inherit (config.swarselsystems) mainUser homeDir; iwd = config.networking.networkmanager.wifi.backend == "iwd"; @@ -18,12 +18,6 @@ in }; config = { - home-manager.users."${config.swarselsystems.mainUser}" = { - imports = [ - "${self}/modules/home/optional/work.nix" - ]; - }; - sops = let secretNames = [ @@ -198,7 +192,7 @@ in openssh = { enable = true; extraConfig = '' - ''; + ''; }; syncthing = { @@ -236,6 +230,13 @@ in # ]; # }; # }; + } // lib.optionalAttrs withHomeManager { + + home-manager.users."${config.swarselsystems.mainUser}" = { + imports = [ + "${self}/modules/home/optional/work.nix" + ]; + }; }; } diff --git a/modules/nixos/server/kea.nix b/modules/nixos/server/kea.nix new file mode 100644 index 0000000..01074fa --- /dev/null +++ b/modules/nixos/server/kea.nix @@ -0,0 +1,76 @@ +{ lib, config, globals, confLib, ... }: +let + inherit (confLib.gen { name = "kea"; dir = "/var/lib/private/kea"; }) serviceName serviceDir; +in +{ + options = { + swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + }; + config = lib.mkIf config.swarselmodules.server.${serviceName} { + + environment.persistence."/persist".directories = lib.mkIf config.swarselsystems.isImpermanence [ + { directory = serviceDir; mode = "0700"; } + ]; + + services.kea.dhcp4 = { + enable = true; + settings = { + lease-database = { + name = "/var/lib/kea/dhcp4.leases"; + persist = true; + type = "memfile"; + }; + valid-lifetime = 86400; + renew-timer = 3600; + interfaces-config = { + # XXX: BUG: why does this bind other macvtaps? + interfaces = map (name: "me-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + service-sockets-max-retries = -1; + }; + subnet4 = lib.flip lib.mapAttrsToList globals.networks.home-lan.vlans ( + vlanName: vlanCfg: { + inherit (vlanCfg) id; + interface = "me-${vlanName}"; + subnet = vlanCfg.cidrv4; + pools = [ + { + pool = "${lib.net.cidr.host 20 vlanCfg.cidrv4} - ${lib.net.cidr.host (-6) vlanCfg.cidrv4}"; + } + ]; + option-data = + [ + { + name = "routers"; + data = vlanCfg.hosts.hintbooth.ipv4; # FIXME: how to advertise v6 address also? + } + ]; + # Advertise DNS server for VLANS that have internet access + # ++ + # lib.optional + # (lib.elem vlanName [ + # "services" + # "home" + # "devices" + # "guests" + # ]) + # { + # name = "domain-name-servers"; + # data = globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv4; + # }; + reservations = lib.concatLists ( + lib.forEach (builtins.attrValues vlanCfg.hosts) ( + hostCfg: + lib.optional (hostCfg.mac != null) { + hw-address = hostCfg.mac; + ip-address = hostCfg.ipv4; + } + ) + ); + } + ); + }; + }; + + + }; +} diff --git a/modules/nixos/server/nftables.nix b/modules/nixos/server/nftables.nix new file mode 100644 index 0000000..b31407f --- /dev/null +++ b/modules/nixos/server/nftables.nix @@ -0,0 +1,74 @@ +{ lib, config, confLib, ... }: +let + inherit (confLib.gen { name = "nftables"; }) serviceName; +in +{ + options = { + swarselmodules.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; + }; + config = lib.mkIf config.swarselmodules.${serviceName} { + + networking.nftables = { + stopRuleset = lib.mkDefault '' + table inet filter { + chain input { + type filter hook input priority filter; policy drop; + ct state invalid drop + ct state {established, related} accept + + iifname lo accept + meta l4proto ipv6-icmp accept + meta l4proto icmp accept + ip protocol igmp accept + tcp dport ${toString (lib.head config.services.openssh.ports)} accept + } + chain forward { + type filter hook forward priority filter; policy drop; + } + chain output { + type filter hook output priority filter; policy accept; + } + } + ''; + + firewall = { + enable = true; + localZoneName = "local"; + snippets = { + nnf-common.enable = false; + nnf-conntrack.enable = true; + nnf-drop.enable = true; + nnf-loopback.enable = true; + nnf-ssh.enable = true; + }; + + rules.untrusted-to-local = { + from = [ "untrusted" ]; + to = [ "local" ]; + + inherit (config.networking.firewall) + allowedTCPPorts + allowedTCPPortRanges + allowedUDPPorts + allowedUDPPortRanges + ; + }; + + rules.icmp-and-igmp = { + after = [ + "ct" + "ssh" + ]; + from = "all"; + to = [ "local" ]; + extraLines = [ + "meta l4proto ipv6-icmp accept" + "meta l4proto icmp accept" + "ip protocol igmp accept" + ]; + }; + }; + }; + + }; +} diff --git a/modules/nixos/server/packages.nix b/modules/nixos/server/packages.nix index b3641ce..af6702a 100644 --- a/modules/nixos/server/packages.nix +++ b/modules/nixos/server/packages.nix @@ -1,4 +1,4 @@ -{ lib, config, pkgs, ... }: +{ lib, config, pkgs, withHomeManager, ... }: { options.swarselmodules.server.packages = lib.mkEnableOption "enable packages on server"; config = lib.mkIf config.swarselmodules.server.packages { @@ -14,6 +14,7 @@ tmux busybox swarsel-deploy + ] ++ lib.optionals withHomeManager [ swarsel-gens swarsel-switch ]; diff --git a/modules/nixos/server/router.nix b/modules/nixos/server/router.nix index fb8112a..51311be 100644 --- a/modules/nixos/server/router.nix +++ b/modules/nixos/server/router.nix @@ -1,56 +1,142 @@ -{ lib, config, ... }: +{ lib, config, globals, ... }: let serviceName = "router"; in { options.swarselmodules.server.${serviceName} = lib.mkEnableOption "enable ${serviceName} on server"; - config = lib.mkIf config.swarselmodules.server.${serviceName} { + config = lib.mkIf config.swarselmodules.server.${serviceName} + { + services.avahi.reflector = true; - systemd.network = { - wait-online.anyInterface = true; - networks = { - "30-lan0" = { - matchConfig.Name = "lan0"; - linkConfig.RequiredForOnline = "enslaved"; - networkConfig = { - ConfigureWithoutCarrier = true; + networking.nftables = { + firewall = { + zones = { + untrusted.interfaces = [ "lan" ]; + wgHome.interfaces = [ "wgHome" ]; + adguardhome.ipv4Addresses = [ globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv4 ]; + adguardhome.ipv6Addresses = [ globals.networks.home-lan.vlans.services.hosts.hintbooth-adguardhome.ipv6 ]; + } + // lib.flip lib.concatMapAttrs globals.networks.home-lan.vlans ( + vlanName: _: { + "vlan-${vlanName}".interfaces = [ "me-${vlanName}" ]; + } + ); + + rules = { + masquerade-internet = { + from = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + to = [ "untrusted" ]; + # masquerade = true; NOTE: custom rule below for ip4 + ip6 + late = true; # Only accept after any rejects have been processed + verdict = "accept"; + }; + + # Allow access to the AdGuardHome DNS server from any VLAN that has internet access + access-adguardhome-dns = { + from = map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans); + to = [ "adguardhome" ]; + verdict = "accept"; + }; + + # Allow devices in the home VLAN to talk to any of the services or home devices. + access-services = { + from = [ "vlan-home" ]; + to = [ + "vlan-services" + "vlan-devices" + ]; + late = true; + verdict = "accept"; + }; + + # Allow the services VLAN to talk to our wireguard server + services-to-local = { + from = [ "vlan-services" ]; + to = [ "local" ]; + allowedUDPPorts = [ 52829 ]; + }; + + # Forward traffic between wireguard participants + forward-proxy-home-vpn-traffic = { + from = [ "wgHome" ]; + to = [ "wgHome" ]; + verdict = "accept"; + }; }; }; - "30-lan1" = { - matchConfig.Name = "lan1"; - linkConfig.RequiredForOnline = "enslaved"; - networkConfig = { - ConfigureWithoutCarrier = true; + + chains.postrouting = { + masquerade-internet = { + after = [ "hook" ]; + late = true; + rules = + lib.forEach + (map (name: "vlan-${name}") (builtins.attrNames globals.networks.home-lan.vlans)) + ( + zone: + lib.concatStringsSep " " [ + "meta protocol { ip, ip6 }" + (lib.head config.networking.nftables.firewall.zones.${zone}.ingressExpression) + (lib.head config.networking.nftables.firewall.zones.untrusted.egressExpression) + "masquerade random" + ] + ); }; }; - "30-lan2" = { - matchConfig.Name = "lan2"; - linkConfig.RequiredForOnline = "enslaved"; - networkConfig = { - ConfigureWithoutCarrier = true; - }; - }; - "30-lan3" = { - matchConfig.Name = "lan3"; - linkConfig.RequiredForOnline = "enslaved"; - networkConfig = { - ConfigureWithoutCarrier = true; - }; - }; - "10-wan" = { - matchConfig.Name = "wan"; - networkConfig = { - # start a DHCP Client for IPv4 Addressing/Routing - DHCP = "ipv4"; - DNSOverTLS = true; - DNSSEC = true; - IPv6PrivacyExtensions = false; - IPForward = true; - }; - # make routing on this interface a dependency for network-online.target - linkConfig.RequiredForOnline = "routable"; - }; }; + + boot.kernel.sysctl = { + "net.ipv4.ip_forward" = 1; + "net.ipv4.conf.all.forwarding" = true; + "net.ipv6.conf.all.forwarding" = true; + }; + + systemd.network = { + wait-online.anyInterface = true; + networks = { + "30-lan1" = { + matchConfig.MACAddress = config.repo.secrets.local.networking.networks.lan1.mac; + linkConfig.RequiredForOnline = "enslaved"; + networkConfig = { + Bridge = "br"; + ConfigureWithoutCarrier = true; + }; + }; + "30-lan2" = { + matchConfig.MACAddress = config.repo.secrets.local.networking.networks.lan2.mac; + linkConfig.RequiredForOnline = "enslaved"; + networkConfig = { + Bridge = "br"; + ConfigureWithoutCarrier = true; + }; + }; + "30-lan3" = { + matchConfig.MACAddress = config.repo.secrets.local.networking.networks.lan3.mac; + linkConfig.RequiredForOnline = "enslaved"; + networkConfig = { + Bridge = "br"; + ConfigureWithoutCarrier = true; + }; + }; + "30-lan4" = { + matchConfig.MACAddress = config.repo.secrets.local.networking.networks.lan4.mac; + linkConfig.RequiredForOnline = "enslaved"; + networkConfig = { + Bridge = "br"; + ConfigureWithoutCarrier = true; + }; + }; + "30-lan5" = { + matchConfig.MACAddress = config.repo.secrets.local.networking.networks.lan5.mac; + linkConfig.RequiredForOnline = "enslaved"; + networkConfig = { + Bridge = "br"; + ConfigureWithoutCarrier = true; + }; + }; + }; + }; + + }; - }; } diff --git a/modules/nixos/server/settings.nix b/modules/nixos/server/settings.nix index 37354db..d2b7006 100644 --- a/modules/nixos/server/settings.nix +++ b/modules/nixos/server/settings.nix @@ -22,16 +22,18 @@ in } config.swarselsystems.shellAliases; - nixpkgs.config.permittedInsecurePackages = [ - # matrix - "olm-3.2.16" - # sonarr - "aspnetcore-runtime-wrapped-6.0.36" - "aspnetcore-runtime-6.0.36" - "dotnet-sdk-wrapped-6.0.428" - "dotnet-sdk-6.0.428" - # - "SDL_ttf-2.0.11" - ]; + nixpkgs.config = lib.mkIf (!config.swarselsystems.isMicroVM) { + perittedInsecurePackages = [ + # matrix + "olm-3.2.16" + # sonarr + "aspnetcore-runtime-wrapped-6.0.36" + "aspnetcore-runtime-6.0.36" + "dotnet-sdk-wrapped-6.0.428" + "dotnet-sdk-6.0.428" + # + "SDL_ttf-2.0.11" + ]; + }; }; } diff --git a/modules/nixos/server/ssh.nix b/modules/nixos/server/ssh.nix index faf6560..877552a 100644 --- a/modules/nixos/server/ssh.nix +++ b/modules/nixos/server/ssh.nix @@ -1,4 +1,4 @@ -{ self, lib, config, ... }: +{ self, lib, config, withHomeManager, ... }: { options.swarselmodules.server.ssh = lib.mkEnableOption "enable ssh on server"; config = lib.mkIf config.swarselmodules.server.ssh { @@ -21,16 +21,18 @@ } ]; }; - users.users."${config.swarselsystems.mainUser}".openssh.authorizedKeys.keyFiles = [ - (self + /secrets/public/ssh/yubikey.pub) - (self + /secrets/public/ssh/magicant.pub) - # (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub)) - ]; - users.users.root.openssh.authorizedKeys.keyFiles = [ - (self + /secrets/public/ssh/yubikey.pub) - (self + /secrets/public/ssh/magicant.pub) - # (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub)) - ]; + users.users = { + "${config.swarselsystems.mainUser}".openssh.authorizedKeys.keyFiles = lib.mkIf withHomeManager [ + (self + /secrets/public/ssh/yubikey.pub) + (self + /secrets/public/ssh/magicant.pub) + # (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub)) + ]; + root.openssh.authorizedKeys.keyFiles = [ + (self + /secrets/public/ssh/yubikey.pub) + (self + /secrets/public/ssh/magicant.pub) + # (lib.mkIf config.swarselsystems.isBastionTarget (self + /secrets/public/ssh/jump.pub)) + ]; + }; security.sudo.extraConfig = '' Defaults env_keep+=SSH_AUTH_SOCK ''; diff --git a/modules/shared/config-lib.nix b/modules/shared/config-lib.nix index b65178f..e80d548 100644 --- a/modules/shared/config-lib.nix +++ b/modules/shared/config-lib.nix @@ -1,4 +1,4 @@ -{ config, lib, globals, nixosConfig ? null, ... }: +{ self, config, lib, globals, inputs, outputs, minimal, nixosConfig ? null, ... }: { _module.args = { confLib = rec { @@ -36,6 +36,44 @@ proxyAddress4 = globals.hosts.${proxy}.wanAddress4 or null; proxyAddress6 = globals.hosts.${proxy}.wanAddress6 or null; }; + + mkMicrovm = + if config.swarselsystems.withMicroVMs then + (guestName: { + ${guestName} = { + backend = "microvm"; + autostart = true; + modules = [ + (config.node.configDir + /guests/${guestName}.nix) + { + node.secretsDir = config.node.configDir + /secrets/${guestName}; + node.configDir = config.node.configDir + /guests/${guestName}; + networking.nftables.firewall = { + zones.untrusted.interfaces = lib.mkIf + ( + lib.length config.guests.${guestName}.networking.links == 1 + ) + config.guests.${guestName}.networking.links; + }; + } + "${self}/modules/nixos/optional/microvm-guest.nix" + ]; + microvm = { + system = config.node.arch; + baseMac = config.repo.secrets.local.networking.networks.lan.mac; + interfaces.vlan-services = { }; + }; + extraSpecialArgs = { + inherit (outputs) nodes; + inherit (inputs.self.pkgs.${config.node.arch}) lib; + inherit inputs outputs minimal; + inherit (inputs) self; + withHomeManager = false; + globals = outputs.globals.${config.node.arch}; + }; + }; + }) else (_: { _ = { }; }); + }; }; } diff --git a/modules/shared/meta.nix b/modules/shared/meta.nix index 28eb685..f37cc0f 100644 --- a/modules/shared/meta.nix +++ b/modules/shared/meta.nix @@ -7,6 +7,11 @@ type = lib.types.path; default = ./.; }; + configDir = lib.mkOption { + description = "Path to the base directory for this node."; + type = lib.types.path; + default = ./.; + }; name = lib.mkOption { type = lib.types.str; }; diff --git a/modules/shared/options.nix b/modules/shared/options.nix index 5b2fe6e..5d3f169 100644 --- a/modules/shared/options.nix +++ b/modules/shared/options.nix @@ -21,9 +21,9 @@ type = lib.types.bool; default = config.swarselsystems.isLaptop; }; - withHomeManager = lib.mkOption { + isMicroVM = lib.mkOption { type = lib.types.bool; - default = true; + default = false; }; isSwap = lib.mkOption { type = lib.types.bool; diff --git a/nix/hosts.nix b/nix/hosts.nix index 1e0d756..0bab7d5 100644 --- a/nix/hosts.nix +++ b/nix/hosts.nix @@ -14,6 +14,8 @@ inherit (config) nodes; globals = config.globals.${arch}; type = "nixos"; + withHomeManager = true; + extraModules = [ "${self}/modules/nixos/common/globals.nix" ]; }; modules = [ inputs.disko.nixosModules.disko @@ -30,6 +32,7 @@ inputs.sops.nixosModules.sops inputs.stylix.nixosModules.stylix inputs.swarsel-nix.nixosModules.default + inputs.nixos-nftables-firewall.nixosModules.default (inputs.nixos-extra-modules + "/modules/guests") (inputs.nixos-extra-modules + "/modules/interface-naming.nix") "${self}/hosts/nixos/${arch}/${configName}" @@ -47,6 +50,7 @@ arch = lib.mkForce arch; type = lib.mkForce "nixos"; secretsDir = ../hosts/nixos/${arch}/${configName}/secrets; + configDir = ../hosts/nixos/${arch}/${configName}; lockFromBootstrapping = lib.mkIf (!minimal) (lib.swarselsystems.mkStrong true); }; @@ -70,6 +74,7 @@ specialArgs = { inherit inputs lib outputs self minimal configName; inherit (config) nodes; + withHomeManager = true; globals = config.globals.${arch}; }; modules = [ @@ -181,7 +186,7 @@ guestConfigurations = lib.flip lib.concatMapAttrs config.nixosConfigurations ( _: node: - lib.flip lib.mapAttrs' (node.config.microvm.vms or { }) ( + lib.flip lib.mapAttrs' (node.config.guests or { }) ( guestName: guestDef: lib.nameValuePair guestDef.nodeName node.config.microvm.vms.${guestName}.config ) diff --git a/pkgs/config/default.nix b/pkgs/config/default.nix index 09de7fb..6ebaa5d 100644 --- a/pkgs/config/default.nix +++ b/pkgs/config/default.nix @@ -1,4 +1,4 @@ -{ self, homeConfig, lib, pkgs, config, ... }: +{ self, lib, pkgs, config, homeConfig, ... }: let mkPackages = names: pkgs: builtins.listToAttrs (map (name: { diff --git a/profiles/nixos/hotel/default.nix b/profiles/nixos/hotel/default.nix index 7ff8794..00952f4 100644 --- a/profiles/nixos/hotel/default.nix +++ b/profiles/nixos/hotel/default.nix @@ -43,6 +43,7 @@ lowBattery = lib.mkForce true; lanzaboote = lib.mkForce true; autologin = lib.mkForce true; + nftables = lib.mkDefault true; }; }; diff --git a/profiles/nixos/localserver/default.nix b/profiles/nixos/localserver/default.nix index 96c2560..0c70be5 100644 --- a/profiles/nixos/localserver/default.nix +++ b/profiles/nixos/localserver/default.nix @@ -14,6 +14,7 @@ btrfs = lib.mkDefault true; sops = lib.mkDefault true; boot = lib.mkDefault true; + nftables = lib.mkDefault true; server = { general = lib.mkDefault true; network = lib.mkDefault true; diff --git a/profiles/nixos/microvm/default.nix b/profiles/nixos/microvm/default.nix new file mode 100644 index 0000000..b00d5a1 --- /dev/null +++ b/profiles/nixos/microvm/default.nix @@ -0,0 +1,27 @@ +{ lib, config, ... }: +{ + options.swarselprofiles.microvm = lib.mkEnableOption "is this a server"; + config = lib.mkIf config.swarselprofiles.microvm { + swarselsystems = { + isLinux = true; + isNixos = true; + }; + swarselmodules = { + general = lib.mkDefault true; + pii = lib.mkDefault true; + xserver = lib.mkDefault true; + time = lib.mkDefault true; + users = lib.mkDefault true; + impermanence = lib.mkDefault true; + btrfs = lib.mkDefault true; + sops = lib.mkDefault true; + nftables = lib.mkDefault true; + server = { + general = lib.mkDefault true; + packages = lib.mkDefault true; + ssh = lib.mkDefault true; + }; + }; + }; + +} diff --git a/profiles/nixos/minimal/default.nix b/profiles/nixos/minimal/default.nix index c233faa..d0afa8a 100644 --- a/profiles/nixos/minimal/default.nix +++ b/profiles/nixos/minimal/default.nix @@ -18,6 +18,7 @@ autologin = lib.mkDefault true; boot = lib.mkDefault true; btrfs = lib.mkDefault true; + nftables = lib.mkDefault true; server = { ssh = lib.mkDefault true; diff --git a/profiles/nixos/personal/default.nix b/profiles/nixos/personal/default.nix index dc9583c..13d7d21 100644 --- a/profiles/nixos/personal/default.nix +++ b/profiles/nixos/personal/default.nix @@ -26,6 +26,7 @@ lowBattery = lib.mkDefault false; network = lib.mkDefault true; networkDevices = lib.mkDefault true; + nftables = lib.mkDefault true; nix-ld = lib.mkDefault true; nvd = lib.mkDefault true; packages = lib.mkDefault true; diff --git a/profiles/nixos/router/default.nix b/profiles/nixos/router/default.nix index 256cfa0..6e10c2e 100644 --- a/profiles/nixos/router/default.nix +++ b/profiles/nixos/router/default.nix @@ -3,8 +3,10 @@ options.swarselprofiles.router = lib.mkEnableOption "enable the router profile"; config = lib.mkIf config.swarselprofiles.router { swarselmodules = { + nftables = lib.mkDefault true; server = { router = lib.mkDefault true; + kea = lib.mkDefault true; }; }; };