From ebe58addaa06ce79d1c57d4e8e2fa48b9d28a054 Mon Sep 17 00:00:00 2001 From: zenware Date: Fri, 6 Jun 2025 22:28:42 -0500 Subject: [PATCH] feat: split flake into multiple hosts and add homelab config --- .gitattributes | 1 + .sops.yaml | 13 ++ flake.lock | 61 ++++---- flake.nix | 14 +- git-agecrypt.toml | 2 + hosts/lithium/README.md | 14 ++ hosts/lithium/configuration.nix | 130 ++++++++++++++++++ hosts/lithium/default.nix | 12 ++ hosts/lithium/hardware.nix | 63 +++++++++ hosts/lithium/secrets/caddy.env | 9 ++ hosts/lithium/secrets/common.yaml | 27 ++++ hosts/lithium/semi-secret-vars.nix | 8 ++ hosts/lithium/services/caddy.nix | 41 ++++++ hosts/lithium/services/jellyfin.nix | 20 +++ hosts/lithium/services/kanidm.nix | 126 +++++++++++++++++ hosts/lithium/services/uptime-kuma.nix | 18 +++ .../neon/configuration.nix | 11 +- hosts/neon/default.nix | 7 + .../neon/hardware-configuration.nix | 2 +- 19 files changed, 539 insertions(+), 40 deletions(-) create mode 100644 .gitattributes create mode 100644 .sops.yaml create mode 100644 git-agecrypt.toml create mode 100644 hosts/lithium/README.md create mode 100644 hosts/lithium/configuration.nix create mode 100644 hosts/lithium/default.nix create mode 100644 hosts/lithium/hardware.nix create mode 100644 hosts/lithium/secrets/caddy.env create mode 100644 hosts/lithium/secrets/common.yaml create mode 100644 hosts/lithium/semi-secret-vars.nix create mode 100644 hosts/lithium/services/caddy.nix create mode 100644 hosts/lithium/services/jellyfin.nix create mode 100644 hosts/lithium/services/kanidm.nix create mode 100644 hosts/lithium/services/uptime-kuma.nix rename configuration.nix => hosts/neon/configuration.nix (95%) create mode 100644 hosts/neon/default.nix rename hardware-configuration.nix => hosts/neon/hardware-configuration.nix (97%) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..072eb55 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +hosts/lithium/semi-secret-vars.nix filter=git-agecrypt diff=git-agecrypt diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..b41d732 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,13 @@ +keys: + - &admin_jay age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu + - &server_lithium age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl +creation_rules: + - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - age: + - *admin_jay + - *server_lithium + - path_regex: secrets/lithium/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - age: + - *server_lithium diff --git a/flake.lock b/flake.lock index 9b38d63..b014985 100644 --- a/flake.lock +++ b/flake.lock @@ -2,14 +2,16 @@ "nodes": { "home-manager": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { - "lastModified": 1735053786, - "narHash": "sha256-Gm+0DcbUS338vvkwyYWms5jsWlx8z8MeQBzcnIDuIkw=", + "lastModified": 1748979197, + "narHash": "sha256-mKYwYcO9RmA2AcAFIXGDBOw5iv/fbjw6adWvMbnfIuk=", "owner": "nix-community", "repo": "home-manager", - "rev": "35b98d20ca8f4ca1f6a2c30b8a2c8bb305a36d84", + "rev": "34a13086148cbb3ae65a79f753eb451ce5cac3d3", "type": "github" }, "original": { @@ -20,11 +22,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1734954597, - "narHash": "sha256-QIhd8/0x30gEv8XEE1iAnrdMlKuQ0EzthfDR7Hwl+fk=", + "lastModified": 1748942041, + "narHash": "sha256-HEu2gTct7nY0tAPRgBtqYepallryBKR1U8B4v2zEEqA=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "def1d472c832d77885f174089b0d34854b007198", + "rev": "fc7c4714125cfaa19b048e8aaf86b9c53e04d853", "type": "github" }, "original": { @@ -35,27 +37,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1734649271, - "narHash": "sha256-4EVBRhOjMDuGtMaofAIqzJbg4Ql7Ai0PSeuVZTHjyKQ=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "d70bd19e0a38ad4790d3913bf08fcbfc9eeca507", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1735291276, - "narHash": "sha256-NYVcA06+blsLG6wpAbSPTCyLvxD/92Hy4vlY9WxFI1M=", + "lastModified": 1748929857, + "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", "owner": "nixos", "repo": "nixpkgs", - "rev": "634fd46801442d760e09493a794c4f15db2d0cbb", + "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4", "type": "github" }, "original": { @@ -69,7 +55,28 @@ "inputs": { "home-manager": "home-manager", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1747603214, + "narHash": "sha256-lAblXm0VwifYCJ/ILPXJwlz0qNY07DDYdLD+9H+Wc8o=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "8d215e1c981be3aa37e47aeabd4e61bb069548fd", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index 905f7e9..517bc72 100644 --- a/flake.nix +++ b/flake.nix @@ -4,8 +4,11 @@ nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixos-hardware.url = "github:nixos/nixos-hardware"; home-manager.url = "github:nix-community/home-manager"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + sops-nix.url = "github:Mic92/sops-nix"; + sops-nix.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = inputs@{self, nixpkgs, nixos-hardware, ...}: + outputs = inputs@{self, nixpkgs, nixos-hardware, sops-nix, ...}: { nixosConfigurations = { neon = nixpkgs.lib.nixosSystem { @@ -13,11 +16,18 @@ modules = [ # https://github.com/NixOS/nixos-hardware/blob/master/README.md#using-nix-flakes-support nixos-hardware.nixosModules.gpd-pocket-3 - ./configuration.nix + ./hosts/neon # override from nixos-hardware ({config, lib, ...}: { services.xserver.videoDrivers = lib.mkForce [ "modesetting" ]; }) ]; }; + lithium = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + ./hosts/lithium + sops-nix.nixosModules.sops + ]; + }; }; }; } diff --git a/git-agecrypt.toml b/git-agecrypt.toml new file mode 100644 index 0000000..b2ff6dc --- /dev/null +++ b/git-agecrypt.toml @@ -0,0 +1,2 @@ +[config] +"hosts/lithium/semi-secret-vars.nix" = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP2SVmZ3iJF/rviKhTgkZOvu1fWr6G29K4u6yaxjZn4H jay@lithium"] diff --git a/hosts/lithium/README.md b/hosts/lithium/README.md new file mode 100644 index 0000000..7c19beb --- /dev/null +++ b/hosts/lithium/README.md @@ -0,0 +1,14 @@ +# lithium + +This is my primary homelab host/NAS, previously powered by TrueNAS Scale/k3s. + +## Semi-Secrets + +`semi-secret-vars.nix` is following a pattern I discovered here: + https://github.com/nyawox/arcanum/blob/4629dfba1bc6d4dd2f4cf45724df81289230b61a/var/README.md + +Essentially there are some details I won't want exposed in the repository, but +I do want them available to all my nix modules. The main one being the domain. + +While it's not really a secret in the way a password is, consider this effort a +mitigation against ddos attacks and automated requests and login attempts. diff --git a/hosts/lithium/configuration.nix b/hosts/lithium/configuration.nix new file mode 100644 index 0000000..91ee105 --- /dev/null +++ b/hosts/lithium/configuration.nix @@ -0,0 +1,130 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page, on +# https://search.nixos.org/options and in the NixOS manual (`nixos-help`). +{ config, pkgs, ... }: +{ + # Setup sops default secrets. + sops.defaultSopsFile = ./secrets/common.yaml; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + # TODO: Request 192.168.50.3 over DHCP + # Currently this is enforced at the router layer on a single interface. + # I'd dramatically prefer it to be a bond0 interface but w/e it is what it is. + networking.hostName = "lithium"; # Define your hostname. + networking.domain = config.vars.domain; + # Pick only one of the below networking options. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + # networking.networkmanager.enable = true; # Easiest to use and most distros use this by default. + + # Set your time zone. + time.timeZone = "America/Chicago"; + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Select internationalisation properties. + # i18n.defaultLocale = "en_US.UTF-8"; + # console = { + # font = "Lat2-Terminus16"; + # keyMap = "us"; + # useXkbConfig = true; # use xkb.options in tty. + # }; + + # Enable the X11 windowing system. + #services.xserver.enable = true; + + + # Enable the GNOME Desktop Environment. + #services.xserver.displayManager.gdm.enable = true; + #services.xserver.desktopManager.gnome.enable = true; + + + # Configure keymap in X11 + # services.xserver.xkb.layout = "us"; + # services.xserver.xkb.options = "eurosign:e,caps:escape"; + + # Enable CUPS to print documents. + # services.printing.enable = true; + + # Enable sound. + # services.pulseaudio.enable = true; + # OR + # services.pipewire = { + # enable = true; + # pulse.enable = true; + # }; + + # Enable touchpad support (enabled default in most desktopManager). + # services.libinput.enable = true; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.jay = { + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + packages = with pkgs; [ + tree + ]; + }; + nixpkgs.config.allowUnfree = true; + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + }; + + # List packages installed in system profile. + # You can use https://search.nixos.org/ to find more packages (and options). + environment.systemPackages = with pkgs; [ + vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + git + zfs + # wget + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + # system.copySystemConfiguration = true; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "25.05"; # Did you read the comment? + +} + diff --git a/hosts/lithium/default.nix b/hosts/lithium/default.nix new file mode 100644 index 0000000..7a2d30d --- /dev/null +++ b/hosts/lithium/default.nix @@ -0,0 +1,12 @@ +{ ... }: +{ + imports = [ + ./hardware.nix + ./configuration.nix + ./semi-secret-vars.nix + ./services/caddy.nix + ./services/kanidm.nix + ./services/jellyfin.nix + ./services/uptime-kuma.nix + ]; +} diff --git a/hosts/lithium/hardware.nix b/hosts/lithium/hardware.nix new file mode 100644 index 0000000..e31edbc --- /dev/null +++ b/hosts/lithium/hardware.nix @@ -0,0 +1,63 @@ +# 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, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "mpt3sas" "nvme" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/12861f9f-ca29-444d-9af1-330699a79a78"; + fsType = "btrfs"; + options = [ "subvol=root" ]; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/2B64-2D7E"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + fileSystems."/home" = + { device = "/dev/disk/by-uuid/12861f9f-ca29-444d-9af1-330699a79a78"; + fsType = "btrfs"; + options = [ "subvol=home" ]; + }; + + fileSystems."/nix" = + { device = "/dev/disk/by-uuid/12861f9f-ca29-444d-9af1-330699a79a78"; + fsType = "btrfs"; + options = [ "subvol=nix" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/df457998-5ffc-422b-a3c9-6e5734c88a41"; } + { device = "/dev/disk/by-uuid/f970449e-2eee-450b-b19f-6361f4fb3c16"; } + ]; + + # Required despite not booting from zfs, in order to make zfs.ko available to modprobe. + # https://openzfs.github.io/openzfs-docs/Getting%20Started/NixOS/index.html#installation + boot.supportedFilesystems = [ "zfs" ]; + boot.zfs.forceImportRoot = false; + networking.hostId = "97fd89d8"; + boot.zfs.extraPools = [ "tank" ]; + services.zfs.autoScrub.enable = true; + + # 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.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.enp6s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/lithium/secrets/caddy.env b/hosts/lithium/secrets/caddy.env new file mode 100644 index 0000000..ea06e03 --- /dev/null +++ b/hosts/lithium/secrets/caddy.env @@ -0,0 +1,9 @@ +CLOUDFLARE_API_TOKEN=ENC[AES256_GCM,data:fNkufR8Zzubh1+sJWfEFwfB/YckqeNdxbYKZCZ0qWGDOjanfzjUzKQ==,iv:6FEzPk4OUxqywIz3ChxCvs9RsBK7ypkrLiY2VFCwWzA=,tag:BBvcCXr0BRevU13SfDOLeg==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCSldSdUdMYk9uQzZuS0tr\nTStEZ3owSE5xdndRVjYrdUN5SVc3cmZiM1VJCjhBa1ExL3hBWEZOWjVxU1ZMcUJR\nUTJJN0lyU2xCNUFzeUdtdDZOaWFMVEEKLS0tIEI2emxCbUxVYVl4a20ySFhab0dC\nZUxkNXhpTXRhZ1pPU0sybnRPakhuOGsKJ3wUExxovoJSAOz+A6lNsCquGgTconmP\ng3XSNwxPhqtKUdVrw4CvDFH2AuU0RCKSbOzO2SNe72pyuEhtME/01g==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_0__map_recipient=age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNSFlMZmdsOUlldnF5dENn\nRVBkMThsMEg5dHQ5UFhhK0RtbVJuWU5ZMURrCjNFTWo4K0w5SUpGMVd2c3NQODhR\nQlMrc3BYY0Z6VldvNVdiQ2ZFZ3V6OGcKLS0tIC8vcWNuYXp3NmF3MmdNRVgvbUdu\nZGxwdU12M1lTa1VLMGx2bVRheVc3c1EKFGvr6wx2CyDyT3QxkpFnw8p10AQz+FwT\n+vCmueVLskc9UZavETzbif2LIWewuPtNjqGNGZwrWFMUZcy8kyVXUQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_recipient=age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl +sops_lastmodified=2025-06-07T02:03:12Z +sops_mac=ENC[AES256_GCM,data:Uw17J9ZYOhNENlfGnFUsjvVm/9IT+hrDDt8UvIIWSMhT54gXIejEDv1IWtNho6JlSN0Wrnl5hEeDFUkHFJ4Ae9EW1FwSpGH2dy6iZ6OUMQMI2hgE28J9wk8c5kSKirhXEPvmCaTBIypQnL0NcKHCuaovKnt1PRRwLrqANLoo9iw=,iv:87f5cCHjqPby2VRhLBJThgCvkGp6sajxYnS/Oyb3hdo=,tag:Gn6a20W1WHVr/Zyvyyk5TQ==,type:str] +sops_unencrypted_suffix=_unencrypted +sops_version=3.10.2 diff --git a/hosts/lithium/secrets/common.yaml b/hosts/lithium/secrets/common.yaml new file mode 100644 index 0000000..341bc36 --- /dev/null +++ b/hosts/lithium/secrets/common.yaml @@ -0,0 +1,27 @@ +kanidm: + admin-password: ENC[AES256_GCM,data:wNE9qWAjfp8tf29sn1Q6GYrbw8g=,iv:uzg971jGIVyEkEbcOm2W8dy4wVgWiL+4Ph/f/bnieI0=,tag:/yY1okvnJLYGw2OLBd2Zdg==,type:str] + idm-admin-password: ENC[AES256_GCM,data:jIWaXUgHjhp0bP/DrF1m+plzcvE=,iv:nNpIkg9FTbCncih1/pAk4o7teuk7Gf/nPXyrnpFx4no=,tag:WhhsjtEdyS3Zw4F7uF9APg==,type:str] +sops: + age: + - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5cFlReGMxV1R3QW1Vd1RU + WTgzNm5tbGhld3RMTGpMU1M2eVdoU0hmZGtNCmZLSTNOMk9IMDh6K2svRmRveGw3 + dlFUZ2lzTDBJWnBSTEhVTmVDOHVTdW8KLS0tIDhLWVZWSVJYM2x4YTlZWWZZZVNh + T2drb0p6TjZrZldpU0VUd0xmcVJUSk0KMjX3vr/74/HU7fmulefUHiNzwX8LcAes + ob3fabhMk9lmbuQk21rpoWbz3PNTfCQH63q+h7gLJTCCW2ISTvh/KQ== + -----END AGE ENCRYPTED FILE----- + - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpK3VvNUhHNmJUQVZlREJl + c1oyZWx4ekNEM0VqL3NKanNmSmZtQXNpcWdVCmpWcklLVnhWUisvcGZzV1NHN3p4 + bW4wL09wL01XaHpveGdmbU4rbEp5NmsKLS0tIElhQVRmS05xUmJIZlI0S1dyWGhV + OGtKdHVwbWY2akJTQkF4YzlnNWQzNU0K81PyJ1tOvwOohNu9iUkS8vE7UXFRnJab + 8OLHtzX7FrkIH8rO2D5vEL9gPmxUtNKc9Ad3sndQls/yfg4wJAYedA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-06-07T02:02:46Z" + mac: ENC[AES256_GCM,data:7mWOon8Hs2oU40l1dx4tVE8yXgcKoxfUAzY8zbtTzXqCOhzTzhY4OZAZiu4RiUSIOm7dMdQbH9zSx0j+5e2k9QflfJDDM3rWfunTa7L8Bm8k9b/WjS0Fnb7OV0InO6tLxQwkTamMcc7ORrKxwHB5PwuXD+efeWNXveHo5GYgF+M=,iv:seh2Pzt+AmmxyD5hwh3VkLQTDMq0Gh9mV6J3QrtxcmM=,tag:jpXn2fht8wArB2KD/ZmbyA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/hosts/lithium/semi-secret-vars.nix b/hosts/lithium/semi-secret-vars.nix new file mode 100644 index 0000000..1598e07 --- /dev/null +++ b/hosts/lithium/semi-secret-vars.nix @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 rhvgyQ 8V5ehsrqPR8s2joIfdpZRYDQpwH5BXI1GgQ/Qcb/Wg4 +ZKRZkXT0uPbXzuXLsteW31GsKzZy1deUl1GdWeQB+4U +-> "f&DjVar +Lhe9DbPHOqqKQ9HDhJB2xbIkrsxFGm39Yzr1J+ZbJnWYx5FCdGCCIexmv3GJy94t + +--- qKkjS2aEWavCLldEwi4MUTlDoQuIu9tSRr5yoeZVQhs +bZ~lU"Up v$?;:Zu҅^ŊQ/MBɉf]Ξ)4PY-߅ܻ ؟l&e2OUqXMDS7E&usU#d#؂W9^k.07hs4CRIwU aʯMwiUrikb}yV>r[8s \ No newline at end of file diff --git a/hosts/lithium/services/caddy.nix b/hosts/lithium/services/caddy.nix new file mode 100644 index 0000000..86a39cf --- /dev/null +++ b/hosts/lithium/services/caddy.nix @@ -0,0 +1,41 @@ +{ config, pkgs, ... }: +{ + sops.secrets.caddy_env = { + sopsFile = ../secrets/caddy.env; + format = "dotenv"; + mode = "0440"; + owner = config.services.caddy.user; + group = config.services.caddy.group; + restartUnits = [ "caddy.service" ]; + }; + services.caddy = { + enable = true; + package = pkgs.caddy.withPlugins { + # NOTE: Occasionally specify @latest and update the new versions, and the result hash. + plugins = [ + "github.com/mholt/caddy-dynamicdns@v0.0.0-20250430031602-b846b9e8fb83" + "github.com/caddy-dns/cloudflare@v0.2.1" + ]; + + # NOTE: Built on 6/4/2025 + hash = "sha256-swskhAr7yFJX+qy0FR54nqJarTOojwhV2Mbk7+fyS0I="; + }; + # NOTE: Use Staging CA while testing, check `systemctl status caddy` + # to see if everything is working. + # acmeCA = "https://acme-staging-v02.api.letsencrypt.org/directory"; + + # TODO: Add Metrics with Prometheus & Grafana + environmentFile = config.sops.secrets.caddy_env.path; + globalConfig = '' + # acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN} + dynamic_dns { + provider cloudflare {env.CLOUDFLARE_API_TOKEN} + domains { + ${config.networking.domain} @ + } + dynamic_domains + } + ''; + }; + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/hosts/lithium/services/jellyfin.nix b/hosts/lithium/services/jellyfin.nix new file mode 100644 index 0000000..7e6e7dc --- /dev/null +++ b/hosts/lithium/services/jellyfin.nix @@ -0,0 +1,20 @@ +{ config, pkgs, ... }: +let + svcDomain = "tv.${config.networking.domain}"; +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :8096 + ''; + services.jellyfin = { + enable = true; + # NOTE: Keeping this open for now, for internal network use. + # ports 8096 for http and 8920 for https + openFirewall = true; + }; + environment.systemPackages = [ + pkgs.jellyfin + pkgs.jellyfin-web + pkgs.jellyfin-ffmpeg + ]; +} diff --git a/hosts/lithium/services/kanidm.nix b/hosts/lithium/services/kanidm.nix new file mode 100644 index 0000000..066652f --- /dev/null +++ b/hosts/lithium/services/kanidm.nix @@ -0,0 +1,126 @@ +{ config, pkgs, lib, ... }: +let + svcDomain = "id.${config.networking.domain}"; + caddyCertsRoot = "${config.services.caddy.dataDir}/.local/share/caddy/certificates"; + caddyCertsDir = "${caddyCertsRoot}/acme-v02.api.letsencrypt.org-directory"; + certsDir = "/var/lib/kanidm/certs"; +in +{ + # Example of yoinking certs from caddy: + # https://github.com/marcusramberg/nix-config/blob/e558914dd3705150511c5ef76278fc50bb4604f3/nixos/kanidm.nix#L3 + + # TODO: If possible, consider specifying the cert location here instead of the following kludge. + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :8443 { + transport http { + tls_server_name ${svcDomain} + } + } + ''; + + # NOTE: Attempted kludge due to caddy generating (and therefore owning the certs) + systemd.tmpfiles.rules = [ + "d ${certsDir} 0750 kanidm caddy -" + "C ${certsDir}/cert.pem - kanidm - - ${caddyCertsDir}/${svcDomain}/${svcDomain}.crt" + "C ${certsDir}/key.key - kanidm - - ${caddyCertsDir}/${svcDomain}/${svcDomain}.key" + ]; + systemd.services.kanidm = { + after = [ "systemd-tmpfiles-setup.service" ]; + requires = [ "caddy.service" "systemd-tmpfiles-setup.service" ]; + }; + users.users.kanidm.extraGroups = [ + "caddy" + ]; + + sops.secrets = { + "kanidm/admin-password" = { + group = "kanidm"; + mode = "440"; + }; + "kanidm/idm-admin-password" = { + group = "kanidm"; + mode = "440"; + }; + }; + + services.kanidm = { + package = pkgs.kanidmWithSecretProvisioning; + enableServer = true; + serverSettings = { + # NOTE: Required to start the server: https://kanidm.github.io/kanidm/stable/server_configuration.html + # domain, origin, tls_chain, tls_key + domain = svcDomain; + origin = "https://${svcDomain}"; + tls_chain = "${certsDir}/cert.pem"; + tls_key = "${certsDir}/key.key"; + + # NOTE: Optional Settings + ldapbindaddress = "127.0.0.1:3636"; # For Jellyfin LDAP integration. + + # trust_x_forwarded_for = true; + }; + + enableClient = true; + clientSettings.uri = config.services.kanidm.serverSettings.origin; + + # NOTE: POSIX accounts bound to LDAP assume 'anonymous' permissions. + # https://kanidm.github.io/kanidm/stable/integrations/pam_and_nsswitch.html + enablePam = true; + unixSettings = { + pam_allowed_login_groups = [ + "unix.admins" + ]; + home_attr = "uuid"; + home_alias = "name"; + }; + + # NOTE: There are manual steps required as root to allow a user to set + # their own credentials, or to confiugre an account as posix. As-is this + # module doesn't support provisioning a complete user /w credentials. + # Adding an account to `idm_high_privilege` prevents an account from being + # tampered with by any other admin accounts. + # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#onboarding-a-new-person--resetting-credentials + provision = { + enable = true; + autoRemove = false; + adminPasswordFile = config.sops.secrets."kanidm/admin-password".path; + idmAdminPasswordFile = config.sops.secrets."kanidm/idm-admin-password".path; + + # NOTE: Basically all this can do is pair up a uuid with a collection of + # groups, and you still need to manually issue a reset token so that the + # user can create a Passekey and/or Password /w MFA. + persons = { + # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#resetting-person-account-credentials + zenware = { + displayName = "zenware"; + groups = [ + "unix.admins" + "git.users" + "git.admins" + "tv.users" + ]; + }; + }; + groups = { + "unix.admins" = {}; + "git.users" = {}; + "git.admins" = {}; + "tv.users" = {}; + "tv.admins" = {}; + }; + }; + }; + + # NOTE: Allow Kanidm auth over SSH + services.openssh.settings = { + UsePAM = true; + PubkeyAuthentication = true; + PasswordAuthentication = true; + AuthorizedKeysCommand = "${ + lib.getExe' config.services.kanidm.package + "kanidm_ssh_authorizedkeys" + } %u"; + AuthorizedKeysCommandUser = "nobody"; + }; + +} diff --git a/hosts/lithium/services/uptime-kuma.nix b/hosts/lithium/services/uptime-kuma.nix new file mode 100644 index 0000000..c9669eb --- /dev/null +++ b/hosts/lithium/services/uptime-kuma.nix @@ -0,0 +1,18 @@ +{ config, pkgs, ... }: +let + svcDomain = "status.${config.networking.domain}"; + svcPort = config.services.uptime-kuma.settings.PORT; +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + # NOTE: Currently requires some web-interface configuration + # User must set up an admin account, monitors, and status pages manually. + services.uptime-kuma = { + enable = true; + # NOTE: NixOS Attributes here resolve into these ENV vars: + # https://github.com/louislam/uptime-kuma/wiki/Environment-Variables + # settings = {}; + }; +} diff --git a/configuration.nix b/hosts/neon/configuration.nix similarity index 95% rename from configuration.nix rename to hosts/neon/configuration.nix index 3f05730..82b0a8e 100644 --- a/configuration.nix +++ b/hosts/neon/configuration.nix @@ -2,15 +2,9 @@ # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). -{ config, pkgs, nixos-hardware, ... }: +{ config, pkgs, ... }: { - imports = - [ # Include the results of the hardware scan. - #nixos-hardware.nixosModules.gpd-pocket-3 - ./hardware-configuration.nix - ]; - # Bootloader. boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; @@ -112,9 +106,6 @@ xwayland ]; - services.udev.packages = with pkgs; [ - ]; - programs.neovim.enable = true; programs.neovim.defaultEditor = true; environment.variables = { diff --git a/hosts/neon/default.nix b/hosts/neon/default.nix new file mode 100644 index 0000000..045c642 --- /dev/null +++ b/hosts/neon/default.nix @@ -0,0 +1,7 @@ +{ ... }: +{ + imports = [ + ./hardware-configuration.nix + ./configuration.nix + ]; +} diff --git a/hardware-configuration.nix b/hosts/neon/hardware-configuration.nix similarity index 97% rename from hardware-configuration.nix rename to hosts/neon/hardware-configuration.nix index 72f143e..3edb1c2 100644 --- a/hardware-configuration.nix +++ b/hosts/neon/hardware-configuration.nix @@ -1,7 +1,7 @@ # 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, ... }: +{ config, lib, modulesPath, ... }: { imports =