summaryrefslogtreecommitdiff
path: root/modules/nixos/traits
diff options
context:
space:
mode:
Diffstat (limited to 'modules/nixos/traits')
-rw-r--r--modules/nixos/traits/acme.nix46
-rw-r--r--modules/nixos/traits/cloudflared.nix50
-rw-r--r--modules/nixos/traits/containers.nix23
-rw-r--r--modules/nixos/traits/default.nix15
-rw-r--r--modules/nixos/traits/hercules.nix49
-rw-r--r--modules/nixos/traits/locale.nix25
-rw-r--r--modules/nixos/traits/nvk/default.nix43
-rw-r--r--modules/nixos/traits/nvk/mesa.nix126
-rw-r--r--modules/nixos/traits/promtail.nix49
-rw-r--r--modules/nixos/traits/secrets.nix17
-rw-r--r--modules/nixos/traits/tailscale.nix48
-rw-r--r--modules/nixos/traits/user-setup.nix45
-rw-r--r--modules/nixos/traits/users.nix44
13 files changed, 580 insertions, 0 deletions
diff --git a/modules/nixos/traits/acme.nix b/modules/nixos/traits/acme.nix
new file mode 100644
index 0000000..a377b25
--- /dev/null
+++ b/modules/nixos/traits/acme.nix
@@ -0,0 +1,46 @@
+{
+ config,
+ lib,
+ secretsDir,
+ ...
+}: let
+ cfg = config.traits.acme;
+in {
+ options.traits.acme = {
+ enable = lib.mkEnableOption "ACME support";
+
+ manageSecrets =
+ lib.mkEnableOption "automatic management of secrets"
+ // {
+ default = config.traits.secrets.enable;
+ };
+
+ useDns = lib.mkEnableOption "the usage of dns to get certs" // {default = true;};
+ };
+
+ config = lib.mkIf cfg.enable (
+ lib.mkMerge [
+ {
+ security.acme = {
+ acceptTerms = true;
+ defaults =
+ {
+ email = "[email protected]";
+ }
+ // lib.optionalAttrs cfg.useDns {
+ dnsProvider = "cloudflare";
+ }
+ // lib.optionalAttrs cfg.manageSecrets {
+ credentialsFile = config.age.secrets.cloudflareApiKey.path;
+ };
+ };
+ }
+
+ (lib.mkIf cfg.manageSecrets {
+ age.secrets = {
+ cloudflareApiKey.file = secretsDir + "/cloudflareApiKey.age";
+ };
+ })
+ ]
+ );
+}
diff --git a/modules/nixos/traits/cloudflared.nix b/modules/nixos/traits/cloudflared.nix
new file mode 100644
index 0000000..9905d33
--- /dev/null
+++ b/modules/nixos/traits/cloudflared.nix
@@ -0,0 +1,50 @@
+{
+ config,
+ lib,
+ secretsDir,
+ ...
+}: let
+ cfg = config.traits.cloudflared;
+ inherit (config.services) nginx;
+in {
+ options.traits.cloudflared = {
+ enable = lib.mkEnableOption "cloudflared";
+ manageSecrets =
+ lib.mkEnableOption "automatically managed secrets"
+ // {
+ default = config.traits.secrets.enable;
+ };
+ };
+
+ config = lib.mkIf cfg.enable (
+ lib.mkMerge [
+ {
+ services.cloudflared = {
+ enable = true;
+ tunnels = {
+ "${config.networking.hostName}-nginx" =
+ {
+ default = "http_status:404";
+
+ ingress = lib.genAttrs (builtins.attrNames nginx.virtualHosts) (
+ _: {service = "http://localhost:${toString nginx.defaultHTTPListenPort}";}
+ );
+ }
+ // lib.optionalAttrs cfg.manageSecrets {
+ credentialsFile = config.age.secrets.cloudflaredCreds.path;
+ };
+ };
+ };
+ }
+
+ (lib.mkIf cfg.manageSecrets {
+ age.secrets.cloudflaredCreds = {
+ file = secretsDir + "/cloudflaredCreds.age";
+ mode = "400";
+ owner = "cloudflared";
+ group = "cloudflared";
+ };
+ })
+ ]
+ );
+}
diff --git a/modules/nixos/traits/containers.nix b/modules/nixos/traits/containers.nix
new file mode 100644
index 0000000..43c748c
--- /dev/null
+++ b/modules/nixos/traits/containers.nix
@@ -0,0 +1,23 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ cfg = config.traits.containers;
+in {
+ options.traits.containers = {
+ enable = lib.mkEnableOption "containers support";
+ };
+
+ config.virtualisation = lib.mkIf cfg.enable {
+ podman = {
+ enable = true;
+ enableNvidia = lib.mkDefault (builtins.elem "nvidia" (config.services.xserver.videoDrivers or []));
+ extraPackages = with pkgs; [podman-compose];
+ autoPrune.enable = true;
+ };
+
+ oci-containers.backend = "podman";
+ };
+}
diff --git a/modules/nixos/traits/default.nix b/modules/nixos/traits/default.nix
new file mode 100644
index 0000000..6eda57f
--- /dev/null
+++ b/modules/nixos/traits/default.nix
@@ -0,0 +1,15 @@
+{
+ imports = [
+ ./acme.nix
+ ./cloudflared.nix
+ ./containers.nix
+ ./hercules.nix
+ ./locale.nix
+ ./nvk
+ ./promtail.nix
+ ./secrets.nix
+ ./tailscale.nix
+ ./user-setup.nix
+ ./users.nix
+ ];
+}
diff --git a/modules/nixos/traits/hercules.nix b/modules/nixos/traits/hercules.nix
new file mode 100644
index 0000000..fc3dbd0
--- /dev/null
+++ b/modules/nixos/traits/hercules.nix
@@ -0,0 +1,49 @@
+{
+ config,
+ lib,
+ unstable,
+ secretsDir,
+ ...
+}: let
+ cfg = config.traits.hercules-ci;
+in {
+ options.traits.hercules-ci = {
+ enable = lib.mkEnableOption "hercules-ci";
+ manageSecrets = lib.mkEnableOption "automatic secrets management";
+ };
+
+ config = lib.mkIf cfg.enable (
+ lib.mkMerge [
+ {
+ services = {
+ hercules-ci-agent = {
+ enable = true;
+ package = unstable.hercules-ci-agent;
+ settings = {
+ binaryCachesPath = config.age.secrets.binaryCache.path;
+ clusterJoinTokenPath = config.age.secrets.clusterToken.path;
+ secretsJsonPath = config.age.secrets.secretsJson.path;
+ };
+ };
+ };
+ }
+
+ (let
+ hercArgs = {
+ mode = "400";
+ owner = "hercules-ci-agent";
+ group = "hercules-ci-agent";
+ };
+
+ mkSecrets = lib.mapAttrs (_: file: lib.recursiveUpdate hercArgs {inherit file;});
+ in
+ lib.mkIf cfg.manageSecrets {
+ age.secrets = mkSecrets {
+ binaryCache = secretsDir + "/binaryCache.age";
+ clusterToken = secretsDir + "/clusterToken.age";
+ secretsJson = secretsDir + "/secretsJson.age";
+ };
+ })
+ ]
+ );
+}
diff --git a/modules/nixos/traits/locale.nix b/modules/nixos/traits/locale.nix
new file mode 100644
index 0000000..1de19ce
--- /dev/null
+++ b/modules/nixos/traits/locale.nix
@@ -0,0 +1,25 @@
+{
+ config,
+ lib,
+ ...
+}: let
+ cfg = config.traits.locale;
+in {
+ options.traits.locale = {
+ en_US = {
+ enable = lib.mkEnableOption "en_US locale";
+ };
+ };
+
+ config = lib.mkMerge [
+ (lib.mkIf cfg.en_US.enable {
+ i18n = {
+ supportedLocales = [
+ "en_US.UTF-8/UTF-8"
+ ];
+
+ defaultLocale = "en_US.UTF-8";
+ };
+ })
+ ];
+}
diff --git a/modules/nixos/traits/nvk/default.nix b/modules/nixos/traits/nvk/default.nix
new file mode 100644
index 0000000..8e849ce
--- /dev/null
+++ b/modules/nixos/traits/nvk/default.nix
@@ -0,0 +1,43 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ cfg = config.traits.nvk;
+ mesa = import ./mesa.nix pkgs;
+ mesa32 = import ./mesa.nix pkgs.pkgsi686Linux;
+in {
+ options.traits.nvk = {
+ enable = lib.mkEnableOption "nvk drivers";
+ };
+
+ config = lib.mkIf cfg.enable {
+ # make sure we're loading new gsp firmware
+ boot.kernelParams = [
+ "nouveau.config=NvGspRm=1"
+ "nouveau.debug=info,VBIOS=info,gsp=debug"
+ ];
+
+ environment.sessionVariables = {
+ # (fake) advertise vk 1.3
+ MESA_VK_VERSION_OVERRIDE = "1.3";
+ };
+
+ hardware.opengl = {
+ package = mesa.drivers;
+ package32 = mesa32.drivers;
+ };
+
+ system.replaceRuntimeDependencies = [
+ {
+ original = pkgs.mesa.out;
+ replacement = mesa.out;
+ }
+ {
+ original = pkgs.pkgsi686Linux.mesa.out;
+ replacement = mesa32.out;
+ }
+ ];
+ };
+}
diff --git a/modules/nixos/traits/nvk/mesa.nix b/modules/nixos/traits/nvk/mesa.nix
new file mode 100644
index 0000000..4b622c6
--- /dev/null
+++ b/modules/nixos/traits/nvk/mesa.nix
@@ -0,0 +1,126 @@
+/*
+thanks to the chaotic-cx LUG for their mesa-git expression, it inspired some of this
+https://github.com/chaotic-cx/nyx/blob/a4e9fa0795880c3330d9f86cab466a7402d6d4f5/pkgs/mesa-git/default.nix
+
+MIT License
+
+Copyright (c) 2023 Pedro Henrique Lara Campos <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+{
+ lib,
+ pkgs,
+ ...
+}: let
+ cargoDeps = {
+ proc-macro2 = {
+ version = "1.0.70";
+ hash = "sha256-OSePu/X7T2Rs5lFpCHf4nRxYEaPUrLJ3AMHLPNt4/Ts=";
+ };
+ quote = {
+ version = "1.0.33";
+ hash = "sha256-Umf8pElgKGKKlRYPxCOjPosuavilMCV54yLktSApPK4=";
+ };
+ syn = {
+ version = "2.0.39";
+ hash = "sha256-I+eLkPL89F0+hCAyzjLj8tFUW6ZjYnHcvyT6MG2Hvno=";
+ };
+ unicode-ident = {
+ version = "1.0.12";
+ hash = "sha256-M1S5rD+uH/Z1XLbbU2g622YWNPZ1V5Qt6k+s6+wP7ks=";
+ };
+ };
+ mesa =
+ (pkgs.mesa.override {
+ # we use the new flag for this
+ enablePatentEncumberedCodecs = false;
+
+ vulkanDrivers =
+ if pkgs.stdenv.isLinux
+ then
+ [
+ "amd" # AMD (aka RADV)
+ "microsoft-experimental" # WSL virtualized GPU (aka DZN/Dozen)
+ "swrast" # software renderer (aka Lavapipe)
+ "nouveau-experimental" # nvk
+ ]
+ ++ lib.optionals (pkgs.stdenv.hostPlatform.isAarch -> lib.versionAtLeast pkgs.stdenv.hostPlatform.parsed.cpu.version "6") [
+ # QEMU virtualized GPU (aka VirGL)
+ # Requires ATOMIC_INT_LOCK_FREE == 2.
+ "virtio"
+ ]
+ ++ lib.optionals pkgs.stdenv.isAarch64 [
+ "broadcom" # Broadcom VC5 (Raspberry Pi 4, aka V3D)
+ "freedreno" # Qualcomm Adreno (all Qualcomm SoCs)
+ "imagination-experimental" # PowerVR Rogue (currently N/A)
+ "panfrost" # ARM Mali Midgard and up (T/G series)
+ ]
+ ++ lib.optionals pkgs.stdenv.hostPlatform.isx86 [
+ "intel" # Intel (aka ANV), could work on non-x86 with PCIe cards, but doesn't build
+ "intel_hasvk" # Intel Haswell/Broadwell, "legacy" Vulkan driver (https://www.phoronix.com/news/Intel-HasVK-Drop-Dead-Code)
+ ]
+ else ["auto"];
+ })
+ .overrideAttrs (new: old: {
+ version = "24.0.0";
+
+ src = pkgs.fetchurl {
+ urls = [
+ "https://archive.mesa3d.org/mesa-${new.version}.tar.xz"
+ "https://mesa.freedesktop.org/archive/mesa-${new.version}.tar.xz"
+ ];
+
+ hash = "sha256-YoWlu7v0P92vtLO3JrFIpKIiRg6JK9G2mq/004DJg1U=";
+ };
+
+ nativeBuildInputs = old.nativeBuildInputs ++ [pkgs.rustc pkgs.rust-bindgen];
+
+ patches = let
+ badPatches = [
+ "0001-dri-added-build-dependencies-for-systems-using-non-s.patch"
+ "0002-util-Update-util-libdrm.h-stubs-to-allow-loader.c-to.patch"
+ "0003-glx-fix-automatic-zink-fallback-loading-between-hw-a.patch"
+ ];
+ in
+ lib.filter (patch: !(lib.elem (baseNameOf patch) badPatches)) old.patches;
+
+ postPatch = let
+ cargoFetch = crate:
+ pkgs.fetchurl {
+ url = "https://crates.io/api/v1/crates/${crate}/${cargoDeps.${crate}.version}/download";
+ inherit (cargoDeps.${crate}) hash;
+ };
+
+ cargoSubproject = crate: ''
+ ln -s ${cargoFetch crate} subprojects/packagecache/${crate}-${cargoDeps.${crate}.version}.tar.gz
+ '';
+
+ subprojects = lib.concatMapStringsSep "\n" cargoSubproject (lib.attrNames cargoDeps);
+ in
+ old.postPatch
+ + ''
+ mkdir subprojects/packagecache
+ ${subprojects}
+ '';
+
+ mesonFlags = old.mesonFlags ++ lib.optional (!pkgs.stdenv.hostPlatform.is32bit) "-D video-codecs=all";
+ });
+in
+ mesa
diff --git a/modules/nixos/traits/promtail.nix b/modules/nixos/traits/promtail.nix
new file mode 100644
index 0000000..5e08b25
--- /dev/null
+++ b/modules/nixos/traits/promtail.nix
@@ -0,0 +1,49 @@
+{
+ config,
+ lib,
+ ...
+}: let
+ cfg = config.traits.promtail;
+ inherit (lib) types;
+in {
+ options.traits.promtail = {
+ enable = lib.mkEnableOption "Promtail";
+
+ clients = lib.mkOption {
+ type = types.listOf types.attrs;
+ default = [{}];
+ description = "clients for promtail";
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.promtail = {
+ enable = true;
+ configuration = {
+ inherit (cfg) clients;
+ server.disable = true;
+
+ scrape_configs = [
+ {
+ job_name = "journal";
+
+ journal = {
+ max_age = "12h";
+ labels = {
+ job = "systemd-journal";
+ host = "${config.networking.hostName}";
+ };
+ };
+
+ relabel_configs = [
+ {
+ source_labels = ["__journal__systemd_unit"];
+ target_label = "unit";
+ }
+ ];
+ }
+ ];
+ };
+ };
+ };
+}
diff --git a/modules/nixos/traits/secrets.nix b/modules/nixos/traits/secrets.nix
new file mode 100644
index 0000000..085d8f3
--- /dev/null
+++ b/modules/nixos/traits/secrets.nix
@@ -0,0 +1,17 @@
+{
+ config,
+ lib,
+ ...
+}: let
+ cfg = config.traits.secrets;
+in {
+ options.traits.secrets = {
+ enable = lib.mkEnableOption "secrets management";
+ };
+
+ config = lib.mkIf cfg.enable {
+ age = {
+ identityPaths = ["/etc/age/key"];
+ };
+ };
+}
diff --git a/modules/nixos/traits/tailscale.nix b/modules/nixos/traits/tailscale.nix
new file mode 100644
index 0000000..93616b5
--- /dev/null
+++ b/modules/nixos/traits/tailscale.nix
@@ -0,0 +1,48 @@
+{
+ config,
+ lib,
+ secretsDir,
+ ...
+}: let
+ cfg = config.traits.tailscale;
+in {
+ options.traits.tailscale = {
+ enable = lib.mkEnableOption "Tailscale";
+ ssh.enable = lib.mkEnableOption "Tailscale SSH";
+ manageSecrets =
+ lib.mkEnableOption "the use of agenix for auth"
+ // {
+ default = config.traits.secrets.enable && cfg.ssh.enable;
+ };
+ };
+
+ config = lib.mkIf cfg.enable (lib.mkMerge [
+ {
+ networking.firewall =
+ {
+ trustedInterfaces = ["tailscale0"];
+ }
+ // lib.optionalAttrs cfg.ssh.enable {
+ allowedTCPPorts = [22];
+ };
+
+ services.tailscale =
+ {
+ enable = true;
+ openFirewall = true;
+ }
+ // lib.optionalAttrs cfg.ssh.enable {
+ extraUpFlags = ["--ssh"];
+ }
+ // lib.optionalAttrs cfg.manageSecrets {
+ authKeyFile = config.age.secrets.tailscaleAuthKey.path;
+ };
+ }
+
+ (lib.mkIf cfg.manageSecrets {
+ age.secrets = lib.mkIf cfg.manageSecrets {
+ tailscaleAuthKey.file = "${secretsDir}/tailscaleAuthKey.age";
+ };
+ })
+ ]);
+}
diff --git a/modules/nixos/traits/user-setup.nix b/modules/nixos/traits/user-setup.nix
new file mode 100644
index 0000000..a8a4cd6
--- /dev/null
+++ b/modules/nixos/traits/user-setup.nix
@@ -0,0 +1,45 @@
+{
+ config,
+ lib,
+ pkgs,
+ secretsDir,
+ ...
+}: let
+ cfg = config.traits.user-setup;
+in {
+ options.traits.user-setup = {
+ enable = lib.mkEnableOption "basic immutable user & root configurations";
+ manageSecrets =
+ lib.mkEnableOption "automatic management of secrets"
+ // {
+ default = config.traits.secrets.enable;
+ };
+ };
+
+ config = lib.mkIf cfg.enable (
+ lib.mkMerge [
+ {
+ users = {
+ defaultUserShell = pkgs.bash;
+ mutableUsers = false;
+
+ users.root =
+ {
+ home = lib.mkDefault "/root";
+ uid = lib.mkDefault config.ids.uids.root;
+ group = lib.mkDefault "root";
+ }
+ // lib.optionalAttrs cfg.manageSecrets {
+ hashedPasswordFile = config.age.secrets.rootPassword.path;
+ };
+ };
+ }
+
+ (lib.mkIf cfg.manageSecrets {
+ age.secrets = {
+ rootPassword.file = secretsDir + "/rootPassword.age";
+ };
+ })
+ ]
+ );
+}
diff --git a/modules/nixos/traits/users.nix b/modules/nixos/traits/users.nix
new file mode 100644
index 0000000..3302366
--- /dev/null
+++ b/modules/nixos/traits/users.nix
@@ -0,0 +1,44 @@
+{
+ config,
+ lib,
+ pkgs,
+ secretsDir,
+ ...
+}: let
+ cfg = config.traits.users;
+ inherit (config.networking) hostName;
+in {
+ imports = [
+ ../../../users/seth/nixos.nix
+ ];
+
+ options.traits.users = {
+ hostUser = {
+ enable = lib.mkEnableOption "${hostName} user configuration";
+ manageSecrets =
+ lib.mkEnableOption "automatically manage secrets"
+ // {
+ default = config.traits.secrets.enable;
+ };
+ };
+ };
+
+ config = lib.mkMerge [
+ (lib.mkIf cfg.hostUser.enable {
+ users.users.${hostName} = {
+ isNormalUser = true;
+ shell = pkgs.bash;
+ };
+ })
+
+ (lib.mkIf (cfg.hostUser.enable && cfg.hostUser.manageSecrets) {
+ age.secrets = {
+ userPassword.file = secretsDir + "/userPassword.age";
+ };
+
+ users.users.${hostName} = {
+ hashedPasswordFile = config.age.secrets.userPassword.path;
+ };
+ })
+ ];
+}