diff --git a/README.md b/README.md index 35e842f..616919e 100755 --- a/README.md +++ b/README.md @@ -35,16 +35,6 @@ All machines are named after Goetic demons: - Vaultwarden password manager - Beszel -### 🥧 Morax (Raspberry Pi 4) -**Hardware**: Raspberry Pi 4 - -**Services**: -- Pi-hole DNS filtering -- Speedtest monitoring (every 10 minutes) -- Headscale connection - -**Notes**: Direct gigabit connection from router - looking to add more services to utilize bandwidth - ### 🍎 Gabriel **Hardware**: M4 16gb Mac Mini diff --git a/common/nvidia.nix b/common/nvidia.nix index 91e03db..5f845df 100755 --- a/common/nvidia.nix +++ b/common/nvidia.nix @@ -31,7 +31,7 @@ # supported GPUs is at: # https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus # Only available from driver 515.43.04+ - open = false; + open = true; # Enable the Nvidia settings menu, # accessible via `nvidia-settings`. diff --git a/common/services.nix b/common/services.nix index 38faaa7..7f54d98 100755 --- a/common/services.nix +++ b/common/services.nix @@ -1,4 +1,4 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { # system packages + services environment.systemPackages = with pkgs; [ @@ -21,4 +21,9 @@ services.printing.enable = true; services.tailscale.enable = true; services.tailscale.useRoutingFeatures = "both"; + services.tailscale.authKeyFile = lib.mkIf (config ? age && config.age ? secrets) + config.age.secrets."headscale-authkey".path; + services.tailscale.extraUpFlags = [ + "--login-server=https://headscale.nekomimi.pet" + ]; } diff --git a/flake.lock b/flake.lock old mode 100755 new mode 100644 index bc65be0..6931fa7 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1747575206, - "narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=", + "lastModified": 1750173260, + "narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=", "owner": "ryantm", "repo": "agenix", - "rev": "4835b1dc898959d8547a871ef484930675cb47f1", + "rev": "531beac616433bac6f9e2a19feb8e99a22a66baf", "type": "github" }, "original": { @@ -26,11 +26,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1750013871, - "narHash": "sha256-UQx3rC3QDjD/sIen51+5Juk1rqN3y/sTeMY1WinmhqQ=", + "lastModified": 1751880463, + "narHash": "sha256-aSQllMKqsTYAUp4yhpspZn0Hj5yIj7Mh4UD5iyk5iMM=", "owner": "catppuccin", "repo": "nix", - "rev": "fe78fa558d6603481c03eb03a946eadb970d1801", + "rev": "9474347c69e93e392f194dda7a57c641ba4b998e", "type": "github" }, "original": { @@ -158,11 +158,11 @@ ] }, "locked": { - "lastModified": 1750127463, - "narHash": "sha256-K2xFtlD3PcKAZriOE3LaBLYmVfGQu+rIF4Jr1RFYR0Q=", + "lastModified": 1751824240, + "narHash": "sha256-aDDC0CHTlL7QDKWWhdbEgVPK6KwWt+ca0QkmHYZxMzI=", "owner": "nix-community", "repo": "home-manager", - "rev": "28eef8722d1af18ca13e687dbf485e1c653a0402", + "rev": "fd9e55f5fac45a26f6169310afca64d56b681935", "type": "github" }, "original": { @@ -220,7 +220,7 @@ "narHash": "sha256-11R4K3iAx4tLXjUs+hQ5K90JwDABD/XHhsM9nkeS5N8=", "rev": "cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc", "type": "tarball", - "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc.tar.gz?rev=cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc" + "url": "https://git.lix.systems/api/v1/repos/lix-project/nixos-module/archive/cd2a9c028df820a83ca2807dc6c6e7abc3dfa7fc.tar.gz" }, "original": { "type": "tarball", @@ -236,11 +236,11 @@ "spectrum": "spectrum" }, "locked": { - "lastModified": 1750196518, - "narHash": "sha256-HJYnJg3TvzFZjVgYHZgH3NtwqkqKiGVCJXpZlO4Y4EE=", + "lastModified": 1751732733, + "narHash": "sha256-MuaFFGHdShvGdHKrd3PUI2om+njixdG/1dGlglRdK8Q=", "owner": "astro", "repo": "microvm.nix", - "rev": "094da86a3e68f2f0d93b654e97b5d42398ead67d", + "rev": "9d3d845ccb1a3f81747d027e95b110d4637468d0", "type": "github" }, "original": { @@ -251,11 +251,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1750083401, - "narHash": "sha256-ynqbgIYrg7P1fAKYqe8I/PMiLABBcNDYG9YaAP/d/C4=", + "lastModified": 1751432711, + "narHash": "sha256-136MeWtckSHTN9Z2WRNRdZ8oRP3vyx3L8UxeBYE+J9w=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "61837d2a33ccc1582c5fabb7bf9130d39fee59ad", + "rev": "497ae1357f1ac97f1aea31a4cb74ad0d534ef41f", "type": "github" }, "original": { @@ -283,11 +283,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1744463964, - "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", + "lastModified": 1750776420, + "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", + "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf", "type": "github" }, "original": { @@ -299,16 +299,16 @@ }, "nixpkgs_3": { "locked": { - "lastModified": 1750005367, - "narHash": "sha256-h/aac1dGLhS3qpaD2aZt25NdKY7b+JT0ZIP2WuGsJMU=", + "lastModified": 1751792365, + "narHash": "sha256-J1kI6oAj25IG4EdVlg2hQz8NZTBNYvIS0l4wpr9KcUo=", "owner": "nixos", "repo": "nixpkgs", - "rev": "6c64dabd3aa85e0c02ef1cdcb6e1213de64baee3", + "rev": "1fd8bada0b6117e6c7eb54aad5813023eed37ccb", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-25.05", + "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" } @@ -343,11 +343,11 @@ "spectrum": { "flake": false, "locked": { - "lastModified": 1746869549, - "narHash": "sha256-BKZ/yZO/qeLKh9YqVkKB6wJiDQJAZNN5rk5NsMImsWs=", + "lastModified": 1751265943, + "narHash": "sha256-XoHSo6GEElzRUOYAEg/jlh5c8TDsyDESFIux3nU/NMc=", "ref": "refs/heads/main", - "rev": "d927e78530892ec8ed389e8fae5f38abee00ad87", - "revCount": 862, + "rev": "37c8663fab86fdb202fece339ef7ac7177ffc201", + "revCount": 904, "type": "git", "url": "https://spectrum-os.org/git/spectrum" }, @@ -422,11 +422,11 @@ "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1729422940, - "narHash": "sha256-DlvJv33ml5UTKgu4b0HauOfFIoDx6QXtbqUF3vWeRCY=", + "lastModified": 1750353031, + "narHash": "sha256-Bx7DOPLhkr8Z60U9Qw4l0OidzHoqLDKQH5rDV5ef59A=", "owner": "nix-community", "repo": "nixos-vscode-server", - "rev": "8b6db451de46ecf9b4ab3d01ef76e59957ff549f", + "rev": "4ec4859b12129c0436b0a471ed1ea6dd8a317993", "type": "github" }, "original": { @@ -443,11 +443,11 @@ ] }, "locked": { - "lastModified": 1750091187, - "narHash": "sha256-mjAol6qR+onnZwLUdYjmuBr/tnyozUBXz75tSePVU00=", + "lastModified": 1751858709, + "narHash": "sha256-xghd1GDPRSa6aD6tEk2JCuQDZWdHITlCA/stwSVoZJQ=", "owner": "0xc000022070", "repo": "zen-browser-flake", - "rev": "cfdf98dac59a42e1642c533a5dbfb5bb242903b3", + "rev": "216dd333fa41aa013bf8aab9322d7c1a2aee5b4a", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index ce0fda7..6f65292 100755 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,7 @@ # flake.nix { inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixos-hardware.url = "github:nixos/nixos-hardware/master"; lix-module = { @@ -45,21 +45,12 @@ system = "x86_64-linux"; }; modules = [ - ./hosts/focalor - lix-module.nixosModules.default - - /*microvm.nixosModules.host - { - microvm.autostart = [ - "windows" - ]; - }*/ - - vscode-server.nixosModules.default agenix.nixosModules.default + ./hosts/focalor + lix-module.nixosModules.default + vscode-server.nixosModules.default catppuccin.nixosModules.catppuccin - home-manager.nixosModules.home-manager { home-manager.useGlobalPkgs = true; @@ -73,6 +64,8 @@ system = "x86_64-linux"; }; } + + { imports = builtins.attrValues nixosModules; } ]; }; @@ -83,11 +76,11 @@ system = "x86_64-linux"; }; modules = [ + agenix.nixosModules.default + ./hosts/valefar lix-module.nixosModules.default - vscode-server.nixosModules.default - agenix.nixosModules.default microvm.nixosModules.host { imports = builtins.attrValues nixosModules; } @@ -104,36 +97,10 @@ ./hosts/buer agenix.nixosModules.default - ]; - }; - morax = nixpkgs.lib.nixosSystem { - system = "aarch64-linux"; - specialArgs = { - inherit inputs; - system = "aarch64-linux"; - }; - modules = [ - ./hosts/morax - nixos-hardware.nixosModules.raspberry-pi-4 - - agenix.nixosModules.default { imports = builtins.attrValues nixosModules; } ]; }; - - - # Easy to add more hosts - /* - server2 = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - ./hosts/server2 - agenix.nixosModules.default - # different services for server2 - ]; - }; - */ }; }; } \ No newline at end of file diff --git a/home/regent/home.nix b/home/regent/home.nix index a72a81f..384e7d8 100755 --- a/home/regent/home.nix +++ b/home/regent/home.nix @@ -148,7 +148,8 @@ window#waybar { height = 0; output = [ "HDMI-A-1" - "DP-1" + "DP-3" + "DP-2" ]; modules-left = [ "sway/workspaces" @@ -161,7 +162,6 @@ window#waybar { "sway/workspaces" = { disable-scroll = true; - sort-by-name = true; }; tray = { icon-size = 13; diff --git a/host-secrets.nix b/host-secrets.nix index 15925d5..9fceec3 100755 --- a/host-secrets.nix +++ b/host-secrets.nix @@ -31,5 +31,12 @@ group = "garage"; mode = "0400"; }; + + "headscale-authkey" = { + file = ./secrets/headscale-authkey.age; + owner = "regent"; + group = "users"; + mode = "0400"; + }; }; } diff --git a/hosts/buer/default.nix b/hosts/buer/default.nix index 691f4e8..a3e14f9 100755 --- a/hosts/buer/default.nix +++ b/hosts/buer/default.nix @@ -32,6 +32,21 @@ # CUSTOM MODULES # ============================================================================= modules.garage.enable = true; + modules.seaweedfs.clusters.default = { + package = pkgs.seaweedfs; + + masters.main = { + openFirewall = true; + ip = "fs.nkp.pet"; + volumePreallocate = true; + + defaultReplication = { + dataCenter = 0; + rack = 0; + server = 0; + }; + }; + }; # ============================================================================= # BOOT CONFIGURATION @@ -79,9 +94,6 @@ virtualisation.docker = { enable = true; enableOnBoot = true; - package = pkgs.docker.override { - buildGoModule = pkgs.buildGo123Module; - }; }; # ============================================================================= diff --git a/hosts/focalor/default.nix b/hosts/focalor/default.nix index 482516c..abf8d03 100755 --- a/hosts/focalor/default.nix +++ b/hosts/focalor/default.nix @@ -25,10 +25,18 @@ # Hardware-specific ../../common/nvidia.nix - # Common secrets (commented out) - # ../../host-secrets.nix + # Common secrets + ../../host-secrets.nix ]; + services.syncthing = { + enable = true; + openDefaultPorts = true; + user = "regent"; + dataDir = "/home/regent"; + configDir = "/home/regent/.config/syncthing"; + }; + # ============================================================================= # SYSTEM CONFIGURATION # ============================================================================= @@ -96,10 +104,10 @@ # ============================================================================= boot.supportedFilesystems = [ "nfs" ]; - fileSystems."/mnt/storage" = { + /*fileSystems."/mnt/storage" = { device = "valefar:/storage"; fsType = "nfs"; - }; + };*/ # ============================================================================= # SERVICES @@ -154,6 +162,9 @@ # ============================================================================= environment.systemPackages = with pkgs; [ inputs.agenix.packages.x86_64-linux.default + prismlauncher + temurin-bin + signal-desktop ]; # ============================================================================= @@ -170,6 +181,6 @@ # code-server # DHCP (disabled in favor of systemd-networkd) - # useDHCP = true; + networking.useDHCP = false; # firewall.allowedTCPPorts = [22 80 443 2456 2457 9000 9001 9002]; -} \ No newline at end of file +} diff --git a/hosts/focalor/hardware.nix b/hosts/focalor/hardware.nix index 126d39c..a865d68 100755 --- a/hosts/focalor/hardware.nix +++ b/hosts/focalor/hardware.nix @@ -9,11 +9,11 @@ ]; boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "uas" "usbhid" "sd_mod" ]; - boot.initrd.kernelModules = [ "vfio" "vfio_iommu_type1" "vfio_pci" ]; +# boot.initrd.kernelModules = [ "vfio" "vfio_iommu_type1" "vfio_pci" ]; boot.kernelModules = [ "kvm-amd" ]; boot.kernelParams = [ "amd_iommu=on" - "vfio-pci.ids=10de:2484,10de228b,1022:149c,15b7:5045,1dbe:5236,1022:149c" +# "vfio-pci.ids=10de:2484,10de228b,1022:149c,15b7:5045,1dbe:5236,1022:149c" ]; boot.extraModulePackages = [ ]; diff --git a/hosts/morax/default.nix b/hosts/morax/default.nix deleted file mode 100755 index 1e653d0..0000000 --- a/hosts/morax/default.nix +++ /dev/null @@ -1,56 +0,0 @@ -{ config, lib, pkgs, modulesPath, inputs, ... }: - -{ - imports = [ - ./hardware.nix - ./secrets.nix - - ../../common/system.nix - ../../common/users.nix - ../../common/services.nix - ../../host-secrets.nix - ]; - - # Enable modules - modules.caddy.enable = true; - modules.garage.enable = true; - - modules.caddy = { - email = "ana@nekomimi.pet"; - reverseProxies = { - "s3.nkp.pet" = ["valefar:3900" "morax:3900"]; - }; - }; - - system.stateVersion = "25.05"; - - nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; - hardware.enableRedistributableFirmware = true; - hardware.enableAllHardware = lib.mkForce false; #https://github.com/NixOS/nixpkgs/issues/154163#issuecomment-2868994145 - - networking = { - hostName = "morax"; - hostId = "2631a44a"; - firewall.enable = false; - defaultGateway = { - address = "10.0.0.1"; - interface = "eth0"; - }; - nameservers = [ "1.1.1.1" ]; - interfaces.eth0 = { - ipv4.addresses = [{ - address = "10.0.0.210"; - prefixLength = 24; - }]; - }; - }; - - environment.systemPackages = with pkgs; [ - inputs.agenix.packages.aarch64-linux.default - ]; - - virtualisation.docker = { - enable = true; - enableOnBoot = true; - }; -} \ No newline at end of file diff --git a/hosts/morax/hardware.nix b/hosts/morax/hardware.nix deleted file mode 100755 index 79a2a14..0000000 --- a/hosts/morax/hardware.nix +++ /dev/null @@ -1,39 +0,0 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - -{ - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = [ "xhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888"; - fsType = "ext4"; - }; - - fileSystems."/garage" = { - device = "/dev/sda1"; - fsType = "ext4"; - }; - - swapDevices = [ ]; - - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.docker0.useDHCP = lib.mkDefault true; - # networking.interfaces.eth0.useDHCP = lib.mkDefault true; - # networking.interfaces.tailscale0.useDHCP = lib.mkDefault true; - # networking.interfaces.wlan0.useDHCP = lib.mkDefault true; - - nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; -} \ No newline at end of file diff --git a/hosts/morax/secrets.nix b/hosts/morax/secrets.nix deleted file mode 100755 index 077404a..0000000 --- a/hosts/morax/secrets.nix +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} \ No newline at end of file diff --git a/hosts/valefar/backup.nix b/hosts/valefar/backup.nix new file mode 100755 index 0000000..b4a5d57 --- /dev/null +++ b/hosts/valefar/backup.nix @@ -0,0 +1,64 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "mpt3sas" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/17b399da-2210-4493-9ae3-c65b20b992a0"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/6340-211B"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + +/* fileSystems."/garage" = { + device = "garage"; + fsType = "zfs"; + }; + + fileSystems."/storage" = { + device = "storage"; + fsType = "zfs"; + };*/ + + swapDevices = [ ]; + + # Fan Control + hardware.fancontrol = { + enable = false; + config = '' +INTERVAL=10 +DEVPATH=hwmon1=devices/platform/nct6775.2592 hwmon2=devices/platform/coretemp.0 +DEVNAME=hwmon1=nct6795 hwmon2=coretemp +FCTEMPS=hwmon1/pwm2=hwmon2/temp1_input hwmon1/pwm3=hwmon2/temp1_input +FCFANS=hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input +MINTEMP=hwmon1/pwm2=20 hwmon1/pwm3=20 +MAXTEMP=hwmon1/pwm2=65 hwmon1/pwm3=60 +MINSTART=hwmon1/pwm2=38 hwmon1/pwm3=75 +MINSTOP=hwmon1/pwm2=28 hwmon1/pwm3=75 +MINPWM=hwmon1/pwm2=28 hwmon1/pwm3=75 +MAXPWM=hwmon1/pwm2=150 hwmon1/pwm3=105 + ''; + }; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; +} diff --git a/hosts/valefar/default.nix b/hosts/valefar/default.nix index 24928f8..df18dd3 100755 --- a/hosts/valefar/default.nix +++ b/hosts/valefar/default.nix @@ -9,6 +9,9 @@ ./hardware.nix ./secrets.nix ../../common/nvidia.nix + + # Common secrets + ../../host-secrets.nix # Common modules shared across hosts ../../common/system.nix @@ -16,9 +19,6 @@ ../../common/services.nix ../../common/efi.nix - # Common secrets - ../../host-secrets.nix - # Hardware-specific (commented out) # ../../common/nvidia.nix ]; diff --git a/hosts/valefar/hardware.nix b/hosts/valefar/hardware.nix index b4a5d57..bd58a94 100755 --- a/hosts/valefar/hardware.nix +++ b/hosts/valefar/hardware.nix @@ -8,57 +8,33 @@ [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "mpt3sas" "sd_mod" ]; + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "mpt3sas" "nvme" "usbhid" "uas" "sd_mod" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; - fileSystems."/" = { - device = "/dev/disk/by-uuid/17b399da-2210-4493-9ae3-c65b20b992a0"; - fsType = "ext4"; - }; + fileSystems."/" = + { device = "/dev/disk/by-uuid/e02d1d07-3bc8-4d1d-a301-6d589f4b4b6d"; + fsType = "ext4"; + }; fileSystems."/boot" = - { device = "/dev/disk/by-uuid/6340-211B"; + { device = "/dev/disk/by-uuid/B3DE-0187"; fsType = "vfat"; options = [ "fmask=0022" "dmask=0022" ]; }; -/* fileSystems."/garage" = { - device = "garage"; - fsType = "zfs"; - }; - - fileSystems."/storage" = { - device = "storage"; - fsType = "zfs"; - };*/ - - swapDevices = [ ]; - - # Fan Control - hardware.fancontrol = { - enable = false; - config = '' -INTERVAL=10 -DEVPATH=hwmon1=devices/platform/nct6775.2592 hwmon2=devices/platform/coretemp.0 -DEVNAME=hwmon1=nct6795 hwmon2=coretemp -FCTEMPS=hwmon1/pwm2=hwmon2/temp1_input hwmon1/pwm3=hwmon2/temp1_input -FCFANS=hwmon1/pwm2=hwmon1/fan2_input hwmon1/pwm3=hwmon1/fan3_input -MINTEMP=hwmon1/pwm2=20 hwmon1/pwm3=20 -MAXTEMP=hwmon1/pwm2=65 hwmon1/pwm3=60 -MINSTART=hwmon1/pwm2=38 hwmon1/pwm3=75 -MINSTOP=hwmon1/pwm2=28 hwmon1/pwm3=75 -MINPWM=hwmon1/pwm2=28 hwmon1/pwm3=75 -MAXPWM=hwmon1/pwm2=150 hwmon1/pwm3=105 - ''; - }; + swapDevices = + [ { device = "/dev/disk/by-uuid/c8f24f31-49e0-486c-9f63-1d31b2e36ce9"; } + ]; # Enables DHCP on each ethernet and wireless interface. In case of scripted networking # (the default) this is the recommended approach. When using systemd-networkd it's # still possible to use this option, but it's recommended to use it in conjunction # with explicit per-interface declarations with `networking.interfaces..useDHCP`. networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp6s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - # networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true; } diff --git a/modules/headscale/default.nix b/modules/headscale/default.nix new file mode 100644 index 0000000..b72d009 --- /dev/null +++ b/modules/headscale/default.nix @@ -0,0 +1,229 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.modules.headscale; +in +{ + options = { + modules = { + headscale = { + enable = mkEnableOption "Deploy headscale"; + + oidcClientSecretPath = mkOption { + type = types.str; + default = "/etc/headscale/oidc_client_secret.key"; + description = "Path to OIDC client secret file"; + example = "config.age.secrets.headscale-oidc-key.path"; + }; + + litestream = { + enable = mkEnableOption "Enable litestream for headscale database backups"; + + replicas = mkOption { + type = types.listOf (types.attrsOf types.anything); + default = []; + description = "List of litestream replica configurations"; + example = [ + { + url = "s3://your-backup-bucket/headscale/db"; + access-key-id = "$LITESTREAM_ACCESS_KEY_ID"; + secret-access-key = "$LITESTREAM_SECRET_ACCESS_KEY"; + region = "us-east-1"; + } + ]; + }; + + backupPath = mkOption { + type = types.nullOr types.str; + default = null; + description = "Local backup path (alternative to S3)"; + example = "/backup/headscale"; + }; + + syncInterval = mkOption { + type = types.str; + default = "1s"; + description = "How often to sync to replicas"; + }; + + retention = mkOption { + type = types.str; + default = "72h"; + description = "How long to retain snapshots"; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Environment file containing S3 credentials (can be agenix secret)"; + example = "config.age.secrets.litestream-env.path"; + }; + }; + }; + }; + }; + + config = mkIf cfg.enable { + services.headscale = { + enable = true; + address = "0.0.0.0"; + port = 8080; + + settings = { + server_url = "https://headscale.nekomimi.pet"; + + # Metrics and gRPC + metrics_listen_addr = "127.0.0.1:9090"; + grpc_listen_addr = "127.0.0.1:50443"; + grpc_allow_insecure = false; + + # Prefixes + prefixes = { + v4 = "100.64.0.0/10"; + v6 = "fd7a:115c:a1e0::/48"; + allocation = "sequential"; + }; + + # Database + database = { + type = "sqlite"; + sqlite = { + path = "/var/lib/headscale/db.sqlite"; + write_ahead_log = true; + }; + }; + + # Noise + noise = { + private_key_path = "/var/lib/headscale/noise_private.key"; + }; + + # DERP + derp = { + urls = [ + "https://controlplane.tailscale.com/derpmap/default" + ]; + paths = []; + auto_update_enabled = true; + update_frequency = "24h"; + server = { + enabled = false; + region_id = 999; + region_code = "headscale"; + region_name = "Headscale Embedded DERP"; + stun_listen_addr = "0.0.0.0:3478"; + private_key_path = "/var/lib/headscale/derp_server_private.key"; + automatically_add_embedded_derp_region = true; + ipv4 = "1.2.3.4"; + ipv6 = "2001:db8::1"; + }; + }; + + # DNS + dns = { + magic_dns = true; + base_domain = "dns.sharkgirl.pet"; + nameservers = { + global = [ + "100.64.0.7" + "1.1.1.1" + "1.0.0.1" + "2606:4700:4700::1111" + "2606:4700:4700::1001" + ]; + }; + search_domains = []; + }; + + # OIDC with configurable secret path + oidc = { + only_start_if_oidc_is_available = true; + issuer = "https://pocketid.nekomimi.pet"; + client_id = "f345acad-3eac-45b7-9d91-57f388987a57"; + client_secret_path = cfg.oidcClientSecretPath; + pkce = { + enabled = true; + method = "S256"; + }; + }; + + # Policy + policy = { + mode = "database"; + }; + + # TLS/ACME + acme_url = "https://acme-v02.api.letsencrypt.org/directory"; + acme_email = ""; + tls_letsencrypt_hostname = ""; + tls_letsencrypt_cache_dir = "/var/lib/headscale/cache"; + tls_letsencrypt_challenge_type = "HTTP-01"; + tls_letsencrypt_listen = ":http"; + tls_cert_path = ""; + tls_key_path = ""; + + # Logging + log = { + format = "text"; + level = "info"; + }; + + # Misc settings + disable_check_updates = false; + ephemeral_node_inactivity_timeout = "30m"; + unix_socket = "/var/run/headscale/headscale.sock"; + unix_socket_permission = "0770"; + logtail = { + enabled = false; + }; + randomize_client_port = false; + }; + }; + + # Configurable Litestream for SQLite database backups + services.litestream = mkIf cfg.litestream.enable { + enable = true; + settings = { + dbs = [ + { + path = "/var/lib/headscale/db.sqlite"; + sync-interval = cfg.litestream.syncInterval; + retention = cfg.litestream.retention; + replicas = + # Use custom replicas if provided + if cfg.litestream.replicas != [] then + cfg.litestream.replicas + # Otherwise use local backup if path is provided + else if cfg.litestream.backupPath != null then + [{ path = cfg.litestream.backupPath; }] + # Default empty (user must configure) + else + []; + } + ]; + }; + }; + + # Configure systemd service to use agenix secrets + systemd.services.headscale.serviceConfig = mkMerge [ + { + SupplementaryGroups = [ "headscale-secrets" ]; + } + # Add environment file for litestream if specified + (mkIf (cfg.litestream.enable && cfg.litestream.environmentFile != null) { + EnvironmentFile = cfg.litestream.environmentFile; + }) + ]; + + # Configure litestream service with environment file if specified + systemd.services.litestream = mkIf (cfg.litestream.enable && cfg.litestream.environmentFile != null) { + serviceConfig = { + EnvironmentFile = cfg.litestream.environmentFile; + }; + }; + + # Create a group for accessing secrets + users.groups.headscale-secrets = {}; + }; +} \ No newline at end of file diff --git a/modules/seaweedfs/default.nix b/modules/seaweedfs/default.nix new file mode 100644 index 0000000..aa6f378 --- /dev/null +++ b/modules/seaweedfs/default.nix @@ -0,0 +1,858 @@ +/*https://hg.sr.ht/~dermetfan/seaweedfs-nixos/browse/seaweedfs.nix?rev=tip*/ + +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.modules.seaweedfs; + + clusterModule = cluster: { + options = { + package = mkOption { + type = types.package; + default = pkgs.seaweedfs; + }; + + security.grpc = let + auth = mkOption { + type = with types; nullOr (submodule { + options = { + cert = mkOption { type = path; }; + key = mkOption { type = path; }; + }; + }); + default = null; + }; + in { + ca = mkOption { + type = with types; nullOr str; + default = null; + }; + + master = auth; + volume = auth; + filer = auth; + client = auth; + msgBroker = auth; + }; + + masters = mkOption { + type = with types; attrsOf (submodule (masterModule cluster.config)); + default = {}; + description = "SeaweedFS masters"; + }; + + volumes = mkOption { + type = with types; attrsOf (submodule (volumeModule cluster.config)); + default = {}; + description = "SeaweedFS volumes"; + }; + + filers = mkOption { + type = with types; attrsOf (submodule (filerModule cluster.config)); + default = {}; + description = "SeaweedFS filers"; + }; + + webdavs = mkOption { + type = with types; attrsOf (submodule (webdavModule cluster.config)); + default = {}; + description = "SeaweedFS WebDAV servers"; + }; + + instances = mkOption { + type = with types; attrsOf (submodule instanceModule); + description = "SeaweedFS instances"; + default = + mapAttrs' (name: master: nameValuePair + "master-${name}" + { + inherit (master) cluster configs; + + command = "master"; + + args = with master; + [ + "-port=${toString port}" + "-volumeSizeLimitMB=${toString volumeSizeLimitMB}" + ] ++ + optional (cpuprofile != "") "-cpuprofile=${cpuprofile}" ++ + optional (defaultReplication != null) ("-defaultReplication=${defaultReplication.code}") ++ + optional disableHttp "-disableHttp" ++ + optional (garbageThreshold != "") "-garbageThreshold=${garbageThreshold}" ++ + optional (ip != "") "-ip=${ip}" ++ + optional (master."ip.bind" != "") "-ip.bind=${master."ip.bind"}" ++ + optional (mdir != "") "-mdir=${mdir}" ++ + optional (memprofile != "") "-memprofile=${memprofile}" ++ + optional metrics.enable "-metrics.address=${metrics.address.text}" ++ + optional (metrics.intervalSeconds != null) "-metrics.intervalSeconds=${toString metrics.intervalSeconds}" ++ + optional (peers != []) ("-peers=" + (concatStringsSep "," (map (peer: peer.text) peers))) ++ + optional resumeState "-resumeState" ++ + optional volumePreallocate "-volumePreallocate" ++ + optional (whiteList != []) ("-whiteList=" + (concatStringsSep "," whiteList)); + } + ) cluster.config.masters // + mapAttrs' (name: volume: nameValuePair + "volume-${name}" + { + inherit (volume) cluster configs; + + command = "volume"; + + args = with volume; + [ + "-port=${toString port}" + "-dir=${concatStringsSep "," dir}" + "-fileSizeLimitMB=${toString fileSizeLimitMB}" + "-idleTimeout=${toString idleTimeout}" + "-index=${index}" + "-minFreeSpacePercent=${toString minFreeSpacePercent}" + "-preStopSeconds=${toString preStopSeconds}" + ] ++ + optional (compactionMBps != null) ("-compactionMBps=${compactionMBps}") ++ + optional (cpuprofile != "") "-cpuprofile=${cpuprofile}" ++ + optional (dataCenter != "") "-dataCenter=${dataCenter}" ++ + optional volume."images.fix.orientation" "-images.fix.orientation" ++ + optional (ip != "") "-ip=${ip}" ++ + optional (volume."ip.bind" != "") "-ip.bind=${volume."ip.bind"}" ++ + optional (max != []) "-max=${concatStringsSep "," (map toString max)}" ++ + optional (memprofile != "") "-memprofile=${memprofile}" ++ + optional (metricsPort != null) "-metricsPort=${toString metricsPort}" ++ + optional (mserver != []) ("-mserver=" + (concatStringsSep "," (map (mserver: mserver.text) mserver))) ++ + optional (volume."port.public" != null) "-port.public=${toString volume."port.public"}" ++ + optional pprof "-pprof" ++ + optional (publicUrl != "") "-publicUrl=${publicUrl}" ++ + optional (rack != "") "-rack=${rack}" ++ + optional (!volume."read.redirect") "-read.redirect=false" ++ + optional (whiteList != []) ("-whiteList=" + (concatStringsSep "," whiteList)); + + systemdService.preStart = "mkdir -p ${concatStringsSep " " volume.dir}"; + } + ) cluster.config.volumes // + mapAttrs' (name: filer: nameValuePair + "filer-${name}" + { + inherit (filer) cluster configs; + + command = "filer"; + + args = with filer; + [ + "-port=${toString port}" + "-dirListLimit=${toString dirListLimit}" + "-maxMB=${toString maxMB}" + ] ++ + optional (collection != "") "-collection=${collection}" ++ + optional (dataCenter != "") "-dataCenter=${dataCenter}" ++ + optional (defaultReplicaPlacement != null) ("-defaultReplicaPlacement=${defaultReplicaPlacement.code}") ++ + optional disableDirListing "-disableDirListing" ++ + optional disableHttp "-disableHttp" ++ + optional encryptVolumeData "-encryptVolumeData" ++ + optional (ip != "") "-ip=${ip}" ++ + optional (filer."ip.bind" != "") "-ip.bind=${filer."ip.bind"}" ++ + optional (master != []) ("-master=" + (concatStringsSep "," (map (master: master.text) master))) ++ + optional (metricsPort != null) "-metricsPort=${toString metricsPort}" ++ + optional (peers != []) ("-peers=" + (concatStringsSep "," (map (peer: peer.text) peers))) ++ + optional (filer."port.readonly" != null) "-port.readonly=${toString filer."port.readonly"}" ++ + optional (rack != "") "-rack=${rack}" ++ + optionals s3.enable [ + "-s3" + "-s3.port=${toString filer.s3.port}" + ] ++ + optional (s3.enable && s3."cert.file" != "") "-s3.cert.file=${s3."cert.file"}" ++ + optional (s3.enable && s3."key.file" != "") "-s3.key.file=${s3."key.file"}" ++ + optional (s3.enable && s3.config != "") "-s3.config=${s3.config}" ++ + optional (s3.enable && s3.domainName != []) "-s3.domainName=${concatStringsSep "," s3.domainName}"; + + systemdService.preStart = let + conf = filer.configs.filer.leveldb2 or {}; + in optionalString (conf ? "dir") "mkdir -p ${conf.dir}"; + } + ) cluster.config.filers // + mapAttrs' (name: webdav: nameValuePair + "webdav-${name}" + { + inherit (webdav) cluster; + + command = "webdav"; + + args = with webdav; + [ + "-port=${toString port}" + "-filer=${filer.text}" + "-cacheCapacityMB=${toString cacheCapacityMB}" + ] ++ + optional (collection != "") "-collection=${collection}" ++ + optional (cacheDir != "") "-cacheDir=${cacheDir}"; + } + ) cluster.config.webdavs; + }; + }; + }; + + commonModule = cluster: common: { + options = { + cluster = mkOption { + type = types.submodule clusterModule; + internal = true; + }; + + openFirewall = mkEnableOption "open the firewall"; + }; + + config = { inherit cluster; }; + }; + + masterModule = cluster: master: { + imports = [ (commonModule cluster) ]; + + options = { + configs = mkOption { + type = with types; attrsOf attrs; + default.master.maintenance = { + scripts = '' + ec.encode -fullPercent=95 -quietFor=1h + ec.rebuild -force + ec.balance -force + volume.balance -force + volume.fix.replication + ''; + sleep_minutes = 17; + }; + }; + + cpuprofile = mkOption { + type = types.str; + default = ""; + }; + + defaultReplication = mkOption { + type = types.submodule replicationModule; + default = {}; + }; + + disableHttp = mkEnableOption "disable HTTP requests, gRPC only"; + + garbageThreshold = mkOption { + type = types.str; + default = ""; + }; + + ip = mkOption { + type = types.str; + default = config.networking.hostName; + }; + + "ip.bind" = mkOption { + type = types.str; + default = "0.0.0.0"; + }; + + mdir = mkOption { + type = types.str; + default = "."; + }; + + memprofile = mkOption { + type = types.str; + default = ""; + }; + + metrics = { + enable = mkEnableOption "Prometheus"; + + address = mkOption { + type = types.submodule ipPortModule; + default = {}; + }; + + intervalSeconds = mkOption { + type = types.ints.unsigned; + default = 15; + }; + }; + + peers = mkOption { + type = peersType; + default = mapAttrsIpPort master.config.cluster.masters; + }; + + port = mkOption { + type = types.port; + default = 9333; + }; + + resumeState = mkEnableOption "resume previous state on master server"; + + volumePreallocate = mkEnableOption "preallocate disk space for volumes"; + + volumeSizeLimitMB = mkOption { + type = types.ints.unsigned; + default = 30000; + }; + + whiteList = mkOption { + type = with types; listOf str; + default = []; + }; + }; + }; + + volumeModule = cluster: volume: { + imports = [ (commonModule cluster) ]; + + options = { + configs = mkOption { + type = with types; attrsOf attrs; + default = {}; + }; + + compactionMBps = mkOption { + type = with types; nullOr ints.unsigned; + default = null; + }; + + cpuprofile = mkOption { + type = types.str; + default = ""; + }; + + dataCenter = mkOption { + type = types.str; + default = ""; + }; + + dir = mkOption { + type = with types; listOf str; + default = [ "/var/lib/seaweedfs/${cluster._module.args.name}/volume-${volume.config._module.args.name}" ]; + }; + + fileSizeLimitMB = mkOption { + type = types.ints.unsigned; + default = 256; + }; + + idleTimeout = mkOption{ + type = types.ints.unsigned; + default = 30; + }; + + "images.fix.orientation" = mkEnableOption "adjustment of jpg orientation when uploading"; + + index = mkOption { + type = types.enum [ + "memory" + "leveldb" + "leveldbMedium" + "leveldbLarge" + ]; + default = "memory"; + }; + + ip = mkOption { + type = types.str; + default = config.networking.hostName; + }; + + "ip.bind" = mkOption { + type = types.str; + default = "0.0.0.0"; + }; + + max = mkOption { + type = with types; listOf ints.unsigned; + default = [ 8 ]; + }; + + memprofile = mkOption { + type = types.str; + default = ""; + }; + + metricsPort = mkOption { + type = with types; nullOr port; + default = null; + }; + + minFreeSpacePercent = mkOption { + type = types.ints.unsigned; + default = 1; + }; + + mserver = mkOption { + type = peersType; + default = mapAttrsIpPort volume.config.cluster.masters; + }; + + port = mkOption { + type = types.port; + default = 8080; + }; + + "port.public" = mkOption { + type = with types; nullOr port; + default = null; + }; + + pprof = mkEnableOption "pprof http handlers. precludes -memprofile and -cpuprofile"; + + preStopSeconds = mkOption { + type = types.int; + default = 10; + }; + + publicUrl = mkOption { + type = types.str; + default = ""; + }; + + rack = mkOption { + type = types.str; + default = ""; + }; + + "read.redirect" = mkOption { + type = types.bool; + default = true; + }; + + whiteList = mkOption { + type = with types; listOf str; + default = []; + }; + }; + }; + + filerModule = cluster: filer: { + imports = [ (commonModule cluster) ]; + + options = { + configs = mkOption { + type = with types; attrsOf attrs; + default.filer.leveldb2 = { + enabled = true; + dir = "/var/lib/seaweedfs/${cluster._module.args.name}/filer-${filer.config._module.args.name}/filerldb2"; + }; + }; + + collection = mkOption { + type = types.str; + default = ""; + }; + + dataCenter = mkOption { + type = types.str; + default = ""; + }; + + defaultReplicaPlacement = mkOption { + type = with types; nullOr (submodule replicationModule); + default = null; + }; + + dirListLimit = mkOption { + type = types.ints.unsigned; + default = 100000; + }; + + disableDirListing = mkEnableOption "turn off directory listing"; + + disableHttp = mkEnableOption "disable http request, only gRpc operations are allowed"; + + encryptVolumeData = mkEnableOption "encrypt data on volume servers"; + + ip = mkOption { + type = types.str; + default = config.networking.hostName; + }; + + "ip.bind" = mkOption { + type = types.str; + default = "0.0.0.0"; + }; + + master = mkOption { + type = peersType; + default = mapAttrsIpPort filer.config.cluster.masters; + }; + + maxMB = mkOption { + type = types.ints.unsigned; + default = 32; + }; + + metricsPort = mkOption { + type = with types; nullOr port; + default = null; + }; + + peers = mkOption { + type = peersType; + default = mapAttrsIpPort filer.config.cluster.filers; + }; + + port = mkOption { + type = types.port; + default = 8888; + }; + + "port.readonly" = mkOption { + type = with types; nullOr port; + default = null; + }; + + rack = mkOption { + type = types.str; + default = ""; + }; + + s3 = { + enable = mkEnableOption "whether to start S3 gateway"; + + "cert.file" = mkOption { + type = types.path; + default = ""; + }; + + config = mkOption { + type = types.path; + default = ""; + }; + + domainName = mkOption { + type = with types; listOf str; + default = []; + }; + + "key.file" = mkOption { + type = types.path; + default = ""; + }; + + port = mkOption { + type = types.port; + default = 8333; + }; + }; + }; + }; + + webdavModule = cluster: webdav: { + imports = [ (commonModule cluster) ]; + + options = { + cacheCapacityMB = mkOption { + type = types.int; + default = 1000; + }; + + cacheDir = mkOption { + type = types.str; + default = "."; + }; + + collection = mkOption { + type = types.str; + default = ""; + }; + + filer = mkOption { + type = types.submodule ipPortModule; + default = { + ip = "127.0.0.1"; + port = 8888; + }; + }; + + port = mkOption { + type = types.port; + default = 7333; + }; + }; + }; + + instanceModule = instance: { + options = { + cluster = mkOption { + type = types.submodule clusterModule; + internal = true; + }; + + command = mkOption { + type = types.enum [ + "server" + "master" + "volume" + "mount" + "filer" + "filer.replicate" + "filer.sync" + "s3" + "msgBroker" + "watch" + "webdav" + ]; + }; + + logArgs = mkOption { + type = with types; listOf str; + default = []; + }; + + args = mkOption { + type = with types; listOf str; + default = []; + }; + + configs = mkOption { + type = with types; attrsOf attrs; + default = {}; + }; + + package = mkOption { + type = types.package; + default = instance.config.cluster.package; + }; + + systemdService = mkOption { + type = types.attrs; + default = {}; + }; + }; + + config = { + logArgs = [ "-logtostderr" ]; + + systemdService.path = optional (instance.config.command == "mount") pkgs.fuse; + }; + }; + + replicationModule = replication: { + options = { + dataCenter = mkOption { + type = types.ints.between 0 9; + default = 0; + }; + + rack = mkOption { + type = types.ints.between 0 9; + default = 0; + }; + + server = mkOption { + type = types.ints.between 0 9; + default = 0; + }; + + code = mkOption { + readOnly = true; + internal = true; + type = types.str; + default = with replication.config; "${toString dataCenter}${toString rack}${toString server}"; + }; + }; + }; + + peersType = with types; listOf (submodule ipPortModule); + + ipPortModule = ipPort: { + options = { + ip = mkOption { + type = types.str; + }; + + port = mkOption { + type = types.port; + }; + + text = mkOption { + internal = true; + readOnly = true; + type = types.str; + default = with ipPort.config; "${ip}:${toString port}"; + }; + }; + }; + + mapAttrsIpPort = attrs: mapAttrsToList (name: value: { inherit (value) ip port; }) attrs; + + toTOML = with generators; toINI { + mkKeyValue = mkKeyValueDefault { + mkValueString = v: + if isString v + then ( + if hasInfix "\n" v + then '' + """ + ${removeSuffix "\n" v} + """ + '' + else ''"${v}"'' + ) + else mkValueStringDefault {} v; + } "="; + }; + + flattenAttrs = separator: attrs: let + /* + attrs = { + a = { + m1 = {}; + m2 = {}; + }; + b = { + m1 = {}; + }; + } + */ + + /* + step1 = { + a = [ + { name = "a-m1"; value = {}; } + { name = "a-m2"; value = {}; } + ]; + b = [ + { name = "b-m1"; value = {}; } + ]; + }; + */ + step1 = mapAttrs (outerName: outerValues: + mapAttrsToList (innerName: innerValues: nameValuePair + "${outerName}${separator}${innerName}" + innerValues + ) outerValues + ) attrs; + + /* + step2 = [ + [ + { name = "a-m1"; value = {}; } + { name = "a-m2"; value = {}; } + ] + [ + { name = "b-m1"; value = {}; } + ] + ]; + */ + step2 = mapAttrsToList (name: value: value) step1; + + /* + step3 = [ + { name = "a-m1"; value = {}; } + { name = "a-m2"; value = {}; } + { name = "b-m1"; value = {}; } + ]; + */ + step3 = flatten step2; + in + /* + { + a-m1 = {}; + a-m2 = {}; + b-m1 = {}; + }; + */ + builtins.listToAttrs step3; +in { + options.modules.seaweedfs = { + clusters = mkOption { + type = with types; attrsOf (submodule clusterModule); + default = {}; + description = "SeaweedFS clusters"; + }; + }; + + config = { + systemd.services = mapAttrs' + (name: instance: nameValuePair "seaweedfs-${name}" instance) + (flattenAttrs "-" ( + mapAttrs (clusterName: cluster: + mapAttrs (instanceName: instance: with instance; recursiveUpdate systemdService rec { + description = "SeaweedFS ${clusterName} ${instanceName}"; + wants = [ "network.target" ]; + after = wants; + wantedBy = [ "multi-user.target" ]; + preStart = with serviceConfig; '' + ${ + let securityFile = config.environment.etc."seaweedfs/${clusterName}/security.toml"; + in optionalString securityFile.enable "ln -s /etc/${securityFile.target} ${WorkingDirectory}/" + } + + # TODO replace find usage with statically known condition + find -L /etc/${ConfigurationDirectory} -type f -exec ln -s '{}' ${WorkingDirectory}/ \; + + ${optionalString (systemdService ? preStart) systemdService.preStart} + ''; + serviceConfig = rec { + ExecStart = "${package}/bin/weed ${concatStringsSep " " logArgs} ${command} ${concatStringsSep " " args}"; + Restart = "on-failure"; + Type = "exec"; + ConfigurationDirectory = "seaweedfs/${clusterName}/${instanceName}"; + RuntimeDirectory = ConfigurationDirectory; + RuntimeDirectoryPreserve = "restart"; + WorkingDirectory = "/run/${RuntimeDirectory}"; + }; + }) cluster.instances + ) cfg.clusters + )); + + environment.etc = + (mapAttrs' (name: cluster: + let file = "seaweedfs/${name}/security.toml"; + in nameValuePair file { + enable = config.environment.etc.${file}.text != ""; + text = with cluster.security.grpc; toTOML ( + (if ca == null then {} else { grpc.ca = ca; }) // + (if master == null then {} else { "grpc.master" = { inherit (master) cert key; }; }) // + (if volume == null then {} else { "grpc.volume" = { inherit (volume) cert key; }; }) // + (if filer == null then {} else { "grpc.filer" = { inherit (filer) cert key; }; }) // + (if client == null then {} else { "grpc.client" = { inherit (client) cert key; }; }) // + (if msgBroker == null then {} else { "grpc.msg_broker" = { inherit (msgBroker) cert key; }; }) + ); + } + ) cfg.clusters) // + (mapAttrs' + (name: config: nameValuePair + "seaweedfs/${name}.toml" + { text = toTOML config; } + ) + (flattenAttrs "/" ( + mapAttrs (clusterName: cluster: + flattenAttrs "/" ( + mapAttrs + (instanceName: instance: instance.configs) + cluster.instances + ) + ) cfg.clusters + )) + ); + + networking.firewall.allowedTCPPorts = let + modulesToPorts = extraPorts: mapAttrsToList (name: module: + with module; + optionals openFirewall ( + [ port (port + 10000) ] ++ + (filter (p: p != null) (extraPorts module)) + ) + ); + in flatten (mapAttrsToList (clusterName: cluster: + modulesToPorts + (master: []) + cluster.masters ++ + + modulesToPorts + (volume: with volume; [ metricsPort volume."port.public" ]) + cluster.volumes ++ + + modulesToPorts + (filer: with filer; [ metricsPort filer."port.readonly" s3.port]) + cluster.filers ++ + + modulesToPorts + (webdav: []) + cluster.webdavs + ) cfg.clusters); + }; +} diff --git a/secrets/build-token.age b/secrets/build-token.age old mode 100755 new mode 100644 index b84f02a..5bc5fca --- a/secrets/build-token.age +++ b/secrets/build-token.age @@ -1,11 +1,11 @@ age-encryption.org/v1 --> ssh-ed25519 i9wBeA kUtl1vuqH5L0wsVFgvMtIQxU6uLB+nwjeXd0sLjDVwU -Gmzx5EdaD95hrzYYWha8C17Nst3FBYH+djFcBR4/x3w --> ssh-ed25519 UbxDgg +vQhzbuLsf6PZVH6JzPwwbX3LXBT2xj9IVlGASHJvmA -jCuoFdUXzOoqdX264bcoRkoa3X2tZAL/xjL4AH54uPI --> ssh-ed25519 YYzA7Q JmX3ynggh1uv1LBEyuzK8fecUdnzj2eNQoXHreCnDXk -vRKopXRKjb4Nfmbd0N5MtLfOhDxLO1Vg36AoiJ60fVE --> ssh-ed25519 NemI1w ZBRTFjCOwEKSKVKywWphVwNOpKQy2PAVAwVc7A1ssjo -5yLLF+OFK1Y8Di3X6QQ42iemQqPqkjRW9gmYz/SEowI ---- 5W1YV8wC5V1ZDPAfGFjZzhOfTBXyyuU1/5AP/TyjHlc -2MfPeutScgZ\gbw>k@>m,g181R;0Ǭ}t(0I,^L 穋;Ez6`@ *O: i~iP  \ No newline at end of file +-> ssh-ed25519 i9wBeA iGYNmiExHD0M2Efk3zqlsZsUY9xcVW4ZyK2TKVkMxTE +PVm7Qwd+o/fP8bfSSouikZTV5yHIc1pFrS3EE/oi2wg +-> ssh-ed25519 UbxDgg n7YqLyF7ZqjOzaKDZ0j89gBT/pflBA72m/0NcW+lU3I +Jj2aFFRhn8/eNRrXdfAAH6nMAvmtCZyd0/GWfBfoPg0 +-> ssh-ed25519 YYzA7Q zrSEpBaQDjjWnCCeqqjYvSoZkZIXEwEk15R+8vNtYxA +AdEkXRqk1ekR/6wqf6gmFPPlTvxsB4WgQxQXMSpPie0 +-> ssh-ed25519 3RWqPQ iIMULw0As6DUmo+iTsXdcba4Tml65WESZlDxJfEEBBw +WxsBR7YRZGnuZpMnLld3VRrPQq8OP2UfFACrt/lPOp8 +--- D2QkZuwJA43Zezo4RhE2gW7UO8shM2upHi4tcaPSLUY +@g!h0E!i< Zgr3` #G[KL CXk/,ijL Pl@Bả26%gO!S"e q3#ւnTV)/ \ No newline at end of file diff --git a/secrets/garage-admin-token.age b/secrets/garage-admin-token.age old mode 100755 new mode 100644 index b75151c..c427d56 --- a/secrets/garage-admin-token.age +++ b/secrets/garage-admin-token.age @@ -1,12 +1,11 @@ age-encryption.org/v1 --> ssh-ed25519 i9wBeA Mh96/1m0yejgo9y/qJd2yQUwwfyhyTbv7wQH0c8FvEA -53b1uTIflTleJFkV541N2sR/VEdUeV8yMhBFKCY3koQ --> ssh-ed25519 UbxDgg Rkwi22gur/Spz8PbQQiQHhZB0NHLW7huALGFZD90JmM -CjOXUJgu95w2DeZW+PQwvN1zoeg05k66VmOnZCido1E --> ssh-ed25519 YYzA7Q 4VpUGeKS05/RmgNspD0C8Wl6mGDXtqLOQRB6zukQYn4 -TbtrwDvvBygqvs3sCcYlvr0Zewm9CLaRevemF0FBA8A --> ssh-ed25519 NemI1w LZChs2MOx+tfoV7jT8bfFx/weWmCriopHqQAkXRCjVQ -uHzjw4X/mbNPyeuSJTd9IcLDiI3/SNdypphyfDBgl+U ---- J6l7qlKG/++fjUz0nyd2LvtVnPFRCl+O/N69D50qBSw --W\frJgVk -kL0[xz!(Qy/N; t>ח]i3uߥ37sAbf \ No newline at end of file +-> ssh-ed25519 i9wBeA 8PLBgO1NF5MRPY/2WsmqQ31meGxLEq1CTOqo5ngwTFo +ymt1bCGSEN1jCb5zBc7gvaShzLKwT6Y5/J1/zO8PKWs +-> ssh-ed25519 UbxDgg JPYD8E0EDn2eBL0IltQtrgfTfFM4fqtRCjIqmrBb8is +QWzV5535zfi4wde4qY1TtWKwXEoSbkCRwpLt5R6k84I +-> ssh-ed25519 YYzA7Q YEIN85tSaLGmjECEGPVWrVtX3gXGXqy7NZEtnW86fkk +wPWnLtotf0JjJ+wPbz19DVYb8iXqXV9F61v54CAqoA4 +-> ssh-ed25519 3RWqPQ P13HdiuAj6ZOqfw41dlZdim/Qz7Pu9sQkeRbAOfKo3M +9eI3OCu9corRl7Wnpa7o2d3JxtBR3ttJG021o8fDUL4 +--- keY3p62HlGCBh2Wu9a9ZO6jcmLuk7bX1cJrRg+0BAQU +UOݵPRU]fpsUW9qLoyv%M0KSI[;(W("3) \ No newline at end of file diff --git a/secrets/garage-metrics-token.age b/secrets/garage-metrics-token.age old mode 100755 new mode 100644 index 2522456..9c6bd90 Binary files a/secrets/garage-metrics-token.age and b/secrets/garage-metrics-token.age differ diff --git a/secrets/garage-rpc-secret.age b/secrets/garage-rpc-secret.age old mode 100755 new mode 100644 index 8539de9..a544d5c Binary files a/secrets/garage-rpc-secret.age and b/secrets/garage-rpc-secret.age differ diff --git a/secrets/headscale-authkey.age b/secrets/headscale-authkey.age new file mode 100644 index 0000000..f8dfd70 Binary files /dev/null and b/secrets/headscale-authkey.age differ diff --git a/secrets/headscale-oidc-key.path b/secrets/headscale-oidc-key.path new file mode 100644 index 0000000..d6cec81 --- /dev/null +++ b/secrets/headscale-oidc-key.path @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 i9wBeA DynOTJFDKsSyHKTG9XFAAcZf/T//KKyK8UG4aGgVH2c +o+ggJe/HZmPU+Ezw4u4m+l9bQ1furG7G4Oo7xS8PMAs +-> ssh-ed25519 UbxDgg b1XiosrWXL9WI1B7YnNSw16l1p4oa3zjDCCgkU/FxiU +MY8oubHMth/wDKn9kNOUkaY9ODvrKIn7DeZTuGxj4/g +-> ssh-ed25519 YYzA7Q 6ql+gutJfteQM75WL6ywEDA1+fIcYSpLPaTSKhqE1ic +tbwXx/feysvpOrxwpDi5B5PveSIbFH0qSsV6/xmo4hk +-> ssh-ed25519 3RWqPQ hNVnobsB1OB9woXtn1T1tXJL+1Dbasc9N2tjZdXa0Bw +9HlWIX7aroc8kTUW3rPlxvMSTSGJXbMcOEipdoQqnbw +--- h8toQGhp/wUgMkJ+RU0bV7E6pHRUM8mKLPcrDmbZ5NQ +!Ŵj֖n$Z$s9fωk.ro`CU>˻RF;H;}J(0 UYP \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 1854144..e65ba7a 100755 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -4,13 +4,17 @@ let valefar = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJlXq2lSfiWwRwIxsxhffW5FDGmjt0QKYN+BaikmRR71"; buer = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMVhjwDcO8eleSoR8a37ZGGPvkHEgV+c8SYcy07SayPB"; - morax = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAmou0HU1yci/fkEVdDQWeZSy0NCNPN8i1TVDILqdi25"; - systems = [ valefar buer morax]; + focalor = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA518oTmTp5VG60/dBrLu7rlV1hh8muhMattoiGfmrei"; + systems = [ valefar buer focalor]; in { #"secret1.age".publicKeys = [ user1 system1 ]; "build-token.age".publicKeys = users ++ systems; + "garage-rpc-secret.age".publicKeys = users ++ systems; "garage-admin-token.age".publicKeys = users ++ systems; "garage-metrics-token.age".publicKeys = users ++ systems; + + "headscale-authkey.age".publicKeys = users ++ systems; + "headscale-oidc-key.path".publicKeys = users ++ systems; }