From d7202a1af149982326448b19e3b6a51dbde0f232 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Wed, 8 Oct 2025 11:14:36 -0500 Subject: [PATCH 01/30] feat: add calibre and game virtualization --- hosts/titanium/game-emulation.nix | 57 +++++++++++++++++++ modules/nixos/desktop/calibre.nix | 27 +++++++++ .../{desktop.nix => desktop/default.nix} | 0 3 files changed, 84 insertions(+) create mode 100644 hosts/titanium/game-emulation.nix create mode 100644 modules/nixos/desktop/calibre.nix rename modules/nixos/{desktop.nix => desktop/default.nix} (100%) diff --git a/hosts/titanium/game-emulation.nix b/hosts/titanium/game-emulation.nix new file mode 100644 index 0000000..28b6c99 --- /dev/null +++ b/hosts/titanium/game-emulation.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, ... }: +let + retroarchWithCores = ( + pkgs.retroarch.withCores ( + cores: with cores; [ + # Multi-Emulators + mame # Atari / Nintendo / Sega / etc. + + # Sega + genesis-plus-gx # Sega Genesis + + # Nintendo + mesen # NES + bsnes # Super Nintendo + mupen64plus # Nintendo 64 - Maybe simple64 some day. + dolphin # GameCube + mgba # GameBoy / Color / Advance + melonds # Nintendo DS + citra # Nintendo 3DS + + + # Sony + swanstation #duckstation # PlayStation + beetle-psx-hw + pcsx2 # PlayStation 2 -- Is actually "LRPS2" + #rpcs3 # PlayStation 3 + ppsspp # PlayStation Portable + + # Commodore + vice-x64 # C64 + ] + ) + ); +in +{ + environment.systemPackages = [ + retroarchWithCores + #pkgs.emulationstation-de + pkgs.gnome-bluetooth + ]; + + hardware.xone.enable = true; # Xbox Controller Driver + hardware.enableAllFirmware = true; + hardware.bluetooth = { + enable = true; + powerOnBoot = true; + settings = { + General = { + Experimental = true; + FastConnectable = true; + }; + Policy = { + AutoEnable = true; + }; + }; + }; +} diff --git a/modules/nixos/desktop/calibre.nix b/modules/nixos/desktop/calibre.nix new file mode 100644 index 0000000..e4c1c6c --- /dev/null +++ b/modules/nixos/desktop/calibre.nix @@ -0,0 +1,27 @@ +{ config, lib, pkgs, ... }: +{ + imports = []; + + options = { + zw-calibre = { + enable = lib.mkEnableOption "Enable Calibre"; + }; + }; + + config = { + config.allowUnfreePredigate = pkg: builtins.elem (lib.getName pkg) [ + "calibre" + "unrar" + ]; + + environment.systemPackages = with pkgs; [ + (calibre.override { + unrarSupport = true; + }) + unrar + ]; + + services.udisks2.enable = true; + }; + # NOTE: Consider adding https://github.com/nydragon/calibre-plugins +} diff --git a/modules/nixos/desktop.nix b/modules/nixos/desktop/default.nix similarity index 100% rename from modules/nixos/desktop.nix rename to modules/nixos/desktop/default.nix From b8d125d4489a553253b4b0254b972e4f8053298e Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 28 Oct 2025 16:10:19 -0500 Subject: [PATCH 02/30] backing up the working dir --- README.md | 3 + flake.lock | 72 +++++++++ flake.nix | 5 +- hosts/lithium/configuration.nix | 4 +- hosts/lithium/default.nix | 26 +++- .../secrets/miniflux_admin_credentials.env | 10 ++ hosts/lithium/services/calibre-web.nix | 44 ++++++ hosts/lithium/services/forgejo.nix | 141 ++++++++++++++++++ hosts/lithium/services/grafana.nix | 24 +++ hosts/lithium/services/immich.nix | 84 +++++++++++ hosts/lithium/services/miniflux/default.nix | 53 +++++++ hosts/lithium/services/monitoring/default.nix | 6 + hosts/lithium/services/monitoring/grafana.nix | 24 +++ .../services/monitoring/prometheus.nix | 29 ++++ .../services/palworld/PalWorldSettings.ini | 2 + hosts/lithium/services/palworld/default.nix | 51 +++++++ hosts/lithium/services/smartd.nix | 32 ++++ hosts/lithium/sops.nix | 13 ++ hosts/titanium/configuration.nix | 3 + 19 files changed, 622 insertions(+), 4 deletions(-) create mode 100644 hosts/lithium/secrets/miniflux_admin_credentials.env create mode 100644 hosts/lithium/services/calibre-web.nix create mode 100644 hosts/lithium/services/forgejo.nix create mode 100644 hosts/lithium/services/grafana.nix create mode 100644 hosts/lithium/services/immich.nix create mode 100644 hosts/lithium/services/miniflux/default.nix create mode 100644 hosts/lithium/services/monitoring/default.nix create mode 100644 hosts/lithium/services/monitoring/grafana.nix create mode 100644 hosts/lithium/services/monitoring/prometheus.nix create mode 100755 hosts/lithium/services/palworld/PalWorldSettings.ini create mode 100644 hosts/lithium/services/palworld/default.nix create mode 100644 hosts/lithium/services/smartd.nix create mode 100644 hosts/lithium/sops.nix diff --git a/README.md b/README.md index 2ec089f..3544565 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,9 @@ nix build .#nixosConfigurations.installIso.config.system.build.images.iso sudo mount -o loop result/iso/nixos-*.iso mnt ls mnt umount mnt + +# Manipulate sops-nix secrets +nix-shell -p sops --run "sops secrets/example.yaml" ``` ## Design Goals diff --git a/flake.lock b/flake.lock index a50ca1f..9064650 100644 --- a/flake.lock +++ b/flake.lock @@ -72,6 +72,24 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -140,6 +158,28 @@ "type": "github" } }, + "microvm": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ], + "spectrum": "spectrum" + }, + "locked": { + "lastModified": 1750358184, + "narHash": "sha256-17EYMeY5v8KRk9HW6Z4dExY8Wg4y/zM2eM2wbbx+vMs=", + "owner": "astro", + "repo": "microvm.nix", + "rev": "fd9f5dba1ffee5ad6f29394b2a9e4c66c1ce77dc", + "type": "github" + }, + "original": { + "owner": "astro", + "repo": "microvm.nix", + "type": "github" + } + }, "nixos-hardware": { "locked": { "lastModified": 1749195551, @@ -219,6 +259,7 @@ "disko": "disko", "home-manager": "home-manager", "lanzaboote": "lanzaboote", + "microvm": "microvm", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", "sops-nix": "sops-nix" @@ -264,6 +305,37 @@ "repo": "sops-nix", "type": "github" } + }, + "spectrum": { + "flake": false, + "locked": { + "lastModified": 1746869549, + "narHash": "sha256-BKZ/yZO/qeLKh9YqVkKB6wJiDQJAZNN5rk5NsMImsWs=", + "ref": "refs/heads/main", + "rev": "d927e78530892ec8ed389e8fae5f38abee00ad87", + "revCount": 862, + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + }, + "original": { + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b4a67f8..d6b35f8 100644 --- a/flake.nix +++ b/flake.nix @@ -11,9 +11,11 @@ sops-nix.inputs.nixpkgs.follows = "nixpkgs"; disko.url = "github:nix-community/disko"; disko.inputs.nixpkgs.follows = "nixpkgs"; + microvm.url = "github:astro/microvm.nix"; + microvm.inputs.nixpkgs.follows = "nixpkgs"; }; # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument - outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, ...}: + outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, microvm, ...}: let mkSystem = (import ./lib { inherit nixpkgs home-manager inputs; @@ -30,6 +32,7 @@ lithium = mkSystem { hostname = "lithium"; # extraModules = [ inputs.sops-nix.nixosModules.sops ]; + extraModules = [ microvm.nixosModules.host ]; users = [ "jml" "breakglass" diff --git a/hosts/lithium/configuration.nix b/hosts/lithium/configuration.nix index 5023ef1..80cd057 100644 --- a/hosts/lithium/configuration.nix +++ b/hosts/lithium/configuration.nix @@ -1,8 +1,8 @@ -{ config, pkgs, ... }: +{ config, pkgs, lib, ... }: { sops.defaultSopsFile = ./secrets/common.yaml; networking.hostName = "lithium"; - networking.domain = config.vars.domain; + networking.domain = lib.mkForce config.vars.domain; environment.systemPackages = with pkgs; [ zfs ]; diff --git a/hosts/lithium/default.nix b/hosts/lithium/default.nix index 4a02b76..8834b37 100644 --- a/hosts/lithium/default.nix +++ b/hosts/lithium/default.nix @@ -1,8 +1,18 @@ { inputs, ... }: +#let + #secretsPath = builtins.toString inputs.nixos-secrets; +#in { + #sops = { + #defaultSopsFile = "${secretsPath}/${config.hostname}/secrets.yaml"; + #defaultSopsFile = "${secretsPath}/global/secrets.yaml"; + #}; + imports = [ ../../modules/nixos/base.nix - inputs.sops-nix.nixosModules.sops + #inputs.sops-nix.nixosModules.sops + #import ./sops.nix ( {inherit inputs;} ) + ./sops.nix ./hardware.nix ./configuration.nix ./semi-secret-vars.nix @@ -12,5 +22,19 @@ ./services/jellyfin.nix ./services/uptime-kuma.nix ./services/file-shares.nix + ./services/miniflux + ./services/forgejo.nix + + # Monitoring + ./services/monitoring + + # Game Servers + ./services/palworld + + + # Services running in virtual machines + #./microvms + #./microvms/palworld ]; + } diff --git a/hosts/lithium/secrets/miniflux_admin_credentials.env b/hosts/lithium/secrets/miniflux_admin_credentials.env new file mode 100644 index 0000000..669e8fc --- /dev/null +++ b/hosts/lithium/secrets/miniflux_admin_credentials.env @@ -0,0 +1,10 @@ +ADMIN_USERNAME=ENC[AES256_GCM,data:1b9RG0hCr3mV+Q==,iv:+P9LxMk7gLvCvVgrzRgHhk7s3kMnMNkWyT8cyBe0msI=,tag:2TVfhdVToEsz4mF/UrrP9w==,type:str] +ADMIN_PASSWORD=ENC[AES256_GCM,data:3HUEKnmGJ9vRSA==,iv:UpY8iFBIT01QUFINo3Cn7dT6q0uDbbDNuU2K7hjfaRY=,tag:LizvS3rkk7PHQVTLRtmbqw==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0TWxwa21pNmxJczd1Y3l2\nZjIzYWJ2TEk0VlZGTXN2a3lvaGR3Q2cwNXlBClN5dXJyMmxFWnA5UytVUjErZ1Ju\nZHY5emdBd2plM1dvRWNwaE5ydW9IbGcKLS0tIEFtUFZnUkllajhDVTU4ejlTN09n\nN0VTWi9lb1UxQm1OTGwzU2dkc25XR1EKlsqqZCJ6YTseRoxaoQRcnnqg0Q6zDezP\ni8lVt4WCK/mIXiqASNf0EaunujxftSg4g5s1PoUzdh2RWRXjjUk6Rw==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_0__map_recipient=age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu +sops_age__list_1__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCY1pnNWdpUGNmTXQ5VHY4\nazJaSUVnMEd4cTVIa3p1NWJBWHAyMEhuMXprCjk3MENuUDJ3OE13bUhJKzNxV1Yr\nZmMwMUtyZldodDRBRkRIUnN5cCswVHcKLS0tIE43RmFHQU0zMitrcmtKaGRMTXZZ\nZWdCOHNVaXp2WjNWUUtTNmVjQTdQMkUK7dbXoDOAxppQi3nmp0S7q130BBvxtdo/\nuaC5FuUXijp0U+Xrdkq3Qukv/u4b7E17mw3zMgHIaxf8w0W/XmTcXQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_1__map_recipient=age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl +sops_lastmodified=2025-07-22T01:07:11Z +sops_mac=ENC[AES256_GCM,data:I17CIK+OqttRpVc9U3Xdefnb95PFcFpCykLSxoVvO74NCvYcHYaB09Wnbt5X46u3TtX1ZmDr85WNzWocu+rM1kdJFXnGI/N9UiCgnam66QCwIlIckCldDGsnPbHpkeB7SFgCJ+1GOz19poPu2RJ41b28NRxNdV4+9HB15Xz6OcM=,iv:7u28+i8HA6wv9SuTSjCGr5o0Wak6zmUvSj3z3CzxT6U=,tag:GXEbSyBGkPSveD0zREBEyQ==,type:str] +sops_unencrypted_suffix=_unencrypted +sops_version=3.10.2 diff --git a/hosts/lithium/services/calibre-web.nix b/hosts/lithium/services/calibre-web.nix new file mode 100644 index 0000000..44f8baf --- /dev/null +++ b/hosts/lithium/services/calibre-web.nix @@ -0,0 +1,44 @@ +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + certDir = config.security.acme.certs."${homelabDomain}".directory; + svcDomain = "books.${homelabDomain}"; + svcHttpPort = config.services.calibre-web.listen.port; + web_data_dir = "calibre-web"; + library_path = "/tank/media/library/books"; +in +{ + # TODO: This isn't the right place for this, but we need to guarantee that a + # media group exists. + users.users.calibre-web.extraGroups = [ "media" ]; + users.groups.media = {}; + + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${toString svcHttpPort} + encode { + zstd + gzip + minimum_length 1024 + } + ''; + + services.calibre-web = { + enable = true; + listen.port = 8083; + # NOTE: Don't need to open calibre-web port, it's served by reverse_proxy + openFirewall = false; + + user = "calibre-web"; + group = "calibre-web"; + + # Either absolute path or directory name under "/var/lib" + # /tank/media/library/books + dataDir = web_data_dir; + + options = { + enableBookUploading = true; + enableBookConversion = true; + calibreLibrary = library_path; + }; + }; +} diff --git a/hosts/lithium/services/forgejo.nix b/hosts/lithium/services/forgejo.nix new file mode 100644 index 0000000..3cec1fa --- /dev/null +++ b/hosts/lithium/services/forgejo.nix @@ -0,0 +1,141 @@ +{ config, pkgs, lib, ... }: +let + homelabDomain = config.networking.domain; + svcDomain = "git.${homelabDomain}"; + theme = pkgs.fetchzip { + url = "https://github.com/catppuccin/gitea/releases/download/v1.0.2/catppuccin-gitea.tar.gz"; + hash = "sha256-rZHLORwLUfIFcB6K9yhrzr+UwdPNQVSadsw6rg8Q7gs="; + stripRoot = false; + }; + svcHttpPort = config.services.forgejo.settings.server.HTTP_PORT; + assetsDir = "${config.services.forgejo.stateDir}/custom/public/assets"; +in +{ + # NOTE: Periodically come update the catpuccin theme. + # `-auto` will automatically switch between latte and mocha modes. + services.forgejo.settings.ui = { + DEFAULT_THEME = "catpuccin-teal-auto"; + THEMES = builtins.concatStringsSep "," ( + [ "auto" ] + ++ (map (name: lib.removePrefix "theme-" (lib.removeSuffix ".css" name)) ( + builtins.attrNames (builtins.readDir theme) + )) + ); + }; + + # TODO: Setup a PostgreSQL Server. + # Inspiration here: https://github.com/nyawox/arcanum/blob/4629dfba1bc6d4dd2f4cf45724df81289230b61a/nixos/servers/forgejo.nix#L64 + #sops-secrets.postgres-forgejo = { + #sopsFile = ../secrets/forgejo.yaml; + #}; + + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${toString svcHttpPort} + ''; + + services.forgejo = { + enable = true; + # database.type = "postgres"; + settings = { + default.APP_NAME = "GitGarage"; + server = { + DOMAIN = svcDomain; + ROOT_URL = "https://${svcDomain}"; + }; + # NOTE: Actions support is based on: https://github.com/nektos/act + #actions = { + #ENABLED = true; + #DEFAULT_ACTIONS_URL = "github"; + #}; + actions.ENABLED = false; + # NOTE: Registration is handled with kanidm. + service = { + REGISTER_EMAIL_CONFIRM = false; + DISABLE_REGISTRATION = false; + ALLOW_ONLY_EXTERNAL_REGISTRATION = true; + SHOW_REGISTRATION_BUTTON = false; + REQUIRE_SIGNIN_VIEW = false; + # TODO: Consider setting up emails. + ENABLE_NOTIFY_MAIL = false; + }; + openid = { + ENABLE_OPENID_SIGNIN = true; + ENABLE_OPENID_SIGNUP = true; + WHITELISTED_URIS = "id.${homelabDomain}"; + }; + # TODO: Literally review all server settings, and link the forgejo documentation. + # Also perhaps include every setting here explicitly. + oauth2_client = { + REGISTER_EMAIL_CONFIRM = false; + ENABLE_AUTO_REGISTRATION = true; + ACCOUNT_LINKING = "login"; + USERNAME = "nickname"; + UPDATE_AVATAR = true; + OPENID_CONNECT_SCOPES = "openid email profile"; + }; + repository = { + DEFAULT_PRIVATE = "private"; + DEFAULT_BRANCH = "main"; + ENABLE_PUSH_CREATE_USER = true; + ENABLE_PUSH_CREATE_ORG = true; + }; + mailer.ENABLED = false; + }; + }; + + # TODO: Finish Configuring the kandim oauth for forgejo.... + services.kanidm.provision.systems.oauth2.forgejo = { + displayName = "forgejo"; + # TODO: Get this from Forgejo + originUrl = "https://git.${homelabDomain}/user/oauth2/${homelabDomain}/callback"; + originLanding = "https://git.${homelabDomain}/"; + #basicSecretFile = "TODO!SETME"; + scopeMaps."git.users" = [ + "openid" + "email" + "profile" + ]; + # WARNING: PKCE is currently not supported by gitea/forgejo, + # see https://github.com/go-gitea/gitea/issues/21376 + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + claimMaps.groups = { + joinType = "array"; + valuesByGroup."git.admins" = [ "admin" ]; + }; + }; + + systemd.services.forgejo = { + preStart = + lib.mkAfter # bash + '' + echo "Installing Catppuccin Assets" + rm -rf ${assetsDir} + mkdir -p ${assetsDir} + ln -sf ${theme} ${assetsDir}/css + ''; + }; + + + #sops.secrets.forgejo-runner-token = {}; + #services.gitea-actions-runner = { + #package = pkgs.forgejo-runner; + #instances.default = { + #enable = true; + #name = "monolith"; + #url = "https://${serviceDomain}"; + #tokenFile = config.sops.secrets.forgejo-runner-token.path; + # NOTE: I don't want huge images if it can be avoided. + # https://nektosact.com/usage/runners.html + #labels = [ + #"ubuntu-latest:docker://node:16-bullseye-slim" + #"ubuntu-22.04:docker://node:16-bullseye-slim" + #]; + #}; + #}; + + # TODO: Consider automatically creating admin account and password... + # https://wiki.nixos.org/wiki/Forgejo#Ensure_users + # Might be necessary to generate a token for kanidm + #sops.secrets.forgejo-admin-password.owner = "forgejo"; +} diff --git a/hosts/lithium/services/grafana.nix b/hosts/lithium/services/grafana.nix new file mode 100644 index 0000000..0dddf2b --- /dev/null +++ b/hosts/lithium/services/grafana.nix @@ -0,0 +1,24 @@ +{ config, pkgs, ... }: +let + svcDomain = "grafana.${config.networking.domain}"; + svcPort = config.services.grafana.settings.server.http_port; +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + + services.grafana = { + enable = true; + settings = { + server = { + http_addr = "127.0.0.1"; + http_port = 3000; + enforce_domain = true; + enable_gzip = true; + domain = svcDomain; + }; + analytics.reporting_enabled = false; # NOTE: Disable Telemetry + }; + }; +} diff --git a/hosts/lithium/services/immich.nix b/hosts/lithium/services/immich.nix new file mode 100644 index 0000000..1c71665 --- /dev/null +++ b/hosts/lithium/services/immich.nix @@ -0,0 +1,84 @@ +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + svcDomain = "photos.${homelabDomain}"; + photoStorageDir = "/tank/shares/photos"; + svcPort = config.services.immich.port; +in +{ + + # NOTE: The following repo contains a highly mature immich setup on nixos. + # https://github.com/xinyangli/nixos-config/blob/a8b5bea68caea573801ccfdb8ceacb7a8f2b0190/machines/agate/services/immich.nix + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + + # NOTE: Primarily to contain DB_PASSWORD to make it possible to backup and restore the DB. + sops.secrets.immich_env = { + sopsFile = ../../secrets/immich.env; + format = "dotenv"; + mode = "0440"; + owner = "immich"; + group = "immich"; + restartUnits = [ "immich.service" ]; + }; + sops.secrets."immich/oauth2_client_secret" = { + owner = "immich"; + group = "kanidm"; + mode = "0440"; + restartUnits = [ "immich.service" "kanidm.service" ]; + }; + + users.users.immich = { + isSystemUser = true; + }; + users.groups.immich = {}; + systemd.tmpfiles.rules = [ + "d ${photoStorageDir} 0770 immich immich -" + ]; + + # TODO: Setup mTLS for external / non-tailscale VPN immich access. + # https://github.com/alangrainger/immich-public-proxy/blob/main/docs/securing-immich-with-mtls.md + # TODO: Consider immich-public-proxy for generating "share" links + # https://github.com/alangrainger/immich-public-proxy + services.immich = { + enable = true; + openFirewall = true; + port = 2283; # default + secretsFile = config.sops.secrets."immich_secrets.env".path; + + # TODO: Build this directory with permissions for the immich user. + mediaLocation = "/tank/shares/photos"; + + # https://docs.immich.app/install/config-file/ + settings = { + # TODO: Setup OAuth with Kanidm + oauth = { + enabled = true; + issuerUrl = "https://"; # TODO: the kanidm url? + clientId = "immich"; + clientSecret = config.sops.placeholder."immich/oauth2_client_secret"; + scope = "openid email profile"; + signingAlgorithm = "ES256"; + storageLabelClaim = "email"; + buttonText = "Login with Kanidm"; + autoLaunch = true; + mobileOverrideEnabled = true; + mobileRedirectUri = "https://${svcDomain}/api/oauth/mobile-redirect/"; + }; + }; + }; + + services.kanidm.provision.systems.oauth2.immich = { + displayName = "immich"; + originUrl = "https://${svcDomain}/oauth2/oidc/callback"; + originLanding = "https://${svcDomain}/"; + basicSecretFile = config.sops.secrets."immich/oauth2_client_secret".path; + scopeMaps."immich.users" = [ + "openid" + "email" + "profile" + ]; + preferShortUsername = true; + }; +} diff --git a/hosts/lithium/services/miniflux/default.nix b/hosts/lithium/services/miniflux/default.nix new file mode 100644 index 0000000..a109874 --- /dev/null +++ b/hosts/lithium/services/miniflux/default.nix @@ -0,0 +1,53 @@ +{ config, pkgs, ... }: +let + svcDomain = "feeds.${config.networking.domain}"; + svcPort = "8080"; +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + # NOTE: Ensure the user exists ahead of trying to give secret permissions to that user. + users.users.miniflux = { + isSystemUser = true; + group = "miniflux"; + createHome = false; + }; + users.groups.miniflux = {}; + sops.secrets.miniflux_env = { + sopsFile = ../../secrets/miniflux_admin_credentials.env; + format = "dotenv"; + mode = "0440"; + owner = "miniflux"; + group = "miniflux"; + restartUnits = [ "miniflux.service" ]; + }; + services.kanidm.provision = { + groups = {}; + systems.oauth2.miniflux = { + displayName = "Miniflux Feed Reader"; + originUrl = "https://${fqdn}/callback"; + public = true; # enforces PKCE + preferShortUsername = true; + scopeMaps.pages_users = ["openid" "email" "profile"]; + claimMaps."${permissionsMap}".valuesByGroup.pages_admin = ["admin"]; + }; + }; + # NOTE: Currently requires some web-interface configuration + services.miniflux = { + enable = true; + adminCredentialsFile = config.sops.secrets.miniflux_env.path; + config = { + BASE_URL = "https://${svcDomain}"; + CREATE_ADMIN = 0; + DISABLE_LOCAL_AUTH = 1; + OAUTH2_PROVIDER = "oidc"; + OAUTH2_OIDC_PROVIDER_NAME = "Kanidm"; + OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://id.${config.networking.domain}"; + OAUTH2_REDIRECT_URL = "https://${svcDomain}/oauth2/oidc/callback"; + OAUTH2_USER_CREATION = 1; + CLEANUP_FREQUENCY = 48; + LISTEN_ADDR = "localhost:${svcPort}"; + }; + }; +} diff --git a/hosts/lithium/services/monitoring/default.nix b/hosts/lithium/services/monitoring/default.nix new file mode 100644 index 0000000..1e37aea --- /dev/null +++ b/hosts/lithium/services/monitoring/default.nix @@ -0,0 +1,6 @@ +{ ... }: { + imports = [ + ./grafana.nix + ./prometheus.nix + ]; +} diff --git a/hosts/lithium/services/monitoring/grafana.nix b/hosts/lithium/services/monitoring/grafana.nix new file mode 100644 index 0000000..7ba0206 --- /dev/null +++ b/hosts/lithium/services/monitoring/grafana.nix @@ -0,0 +1,24 @@ +{ config, pkgs, ... }: +let + svcDomain = "grafana.${config.networking.domain}"; + svcPort = config.services.grafana.settings.server.http_port; +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${toString svcPort} + ''; + + services.grafana = { + enable = true; + settings = { + server = { + http_addr = "127.0.0.1"; + http_port = 3001; + enforce_domain = true; + enable_gzip = true; + domain = svcDomain; + }; + analytics.reporting_enabled = false; # NOTE: Disable Telemetry + }; + }; +} diff --git a/hosts/lithium/services/monitoring/prometheus.nix b/hosts/lithium/services/monitoring/prometheus.nix new file mode 100644 index 0000000..51be2ea --- /dev/null +++ b/hosts/lithium/services/monitoring/prometheus.nix @@ -0,0 +1,29 @@ +{ config, pkgs, ... }: +#let + #svcDomain = "status.${config.networking.domain}"; + #svcPort = config.services.prometheus.exporters.node.port; +#in +{ + #services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + #reverse_proxy :${svcPort} + #''; + + services.prometheus = { + enable = true; + #globalConfig.scrape_interval = "10s"; # "1m" + #scrapeConfigs = [ + #{ + #job_name = "node"; + #static_configs = [{ + # targets = [ "localhost:${toString svcPort}" ]; + #}]; + #} + #]; + }; + + #services.prometheus.exporters.node = { + #enable = true; + #port = 9000; + #enabledCollectors = [ "systemd" ]; + #}; +} diff --git a/hosts/lithium/services/palworld/PalWorldSettings.ini b/hosts/lithium/services/palworld/PalWorldSettings.ini new file mode 100755 index 0000000..d589452 --- /dev/null +++ b/hosts/lithium/services/palworld/PalWorldSettings.ini @@ -0,0 +1,2 @@ +[/Script/Pal.PalGameWorldSettings] +OptionSettings=(Difficulty=None,RandomizerType=None,RandomizerSeed="",bIsRandomizerPalLevelRandom=False,DayTimeSpeedRate=1.000000,NightTimeSpeedRate=1.000000,ExpRate=1.000000,PalCaptureRate=1.100000,PalSpawnNumRate=1.100000,PalDamageRateAttack=1.000000,PalDamageRateDefense=1.000000,PlayerDamageRateAttack=1.000000,PlayerDamageRateDefense=1.000000,PlayerStomachDecreaceRate=0.800000,PlayerStaminaDecreaceRate=0.900000,PlayerAutoHPRegeneRate=1.100000,PlayerAutoHpRegeneRateInSleep=1.200000,PalStomachDecreaceRate=0.900000,PalStaminaDecreaceRate=1.000000,PalAutoHPRegeneRate=1.000000,PalAutoHpRegeneRateInSleep=1.000000,BuildObjectHpRate=1.000000,BuildObjectDamageRate=1.000000,BuildObjectDeteriorationDamageRate=1.000000,CollectionDropRate=1.000000,CollectionObjectHpRate=1.000000,CollectionObjectRespawnSpeedRate=1.000000,EnemyDropItemRate=1.000000,DeathPenalty=1,bEnablePlayerToPlayerDamage=False,bEnableFriendlyFire=False,bEnableInvaderEnemy=True,bActiveUNKO=False,bEnableAimAssistPad=True,bEnableAimAssistKeyboard=True,DropItemMaxNum=3000,DropItemMaxNum_UNKO=100,BaseCampMaxNum=128,BaseCampWorkerMaxNum=15,DropItemAliveMaxHours=1.000000,bAutoResetGuildNoOnlinePlayers=False,AutoResetGuildTimeNoOnlinePlayers=72.000000,GuildPlayerMaxNum=20,BaseCampMaxNumInGuild=4,PalEggDefaultHatchingTime=4.500000,WorkSpeedRate=1.100000,AutoSaveSpan=30.000000,bIsMultiplay=False,bIsPvP=False,bHardcore=False,bPalLost=False,bCharacterRecreateInHardcore=False,bCanPickupOtherGuildDeathPenaltyDrop=False,bEnableNonLoginPenalty=True,bEnableFastTravel=True,bIsStartLocationSelectByMap=True,bExistPlayerAfterLogout=False,bEnableDefenseOtherGuildPlayer=False,bInvisibleOtherGuildBaseCampAreaFX=False,bBuildAreaLimit=False,ItemWeightRate=1.000000,CoopPlayerMaxNum=4,ServerPlayerMaxNum=32,ServerName="GameNight Pals",ServerDescription="",AdminPassword="PenQueen",ServerPassword="penking",PublicPort=8211,PublicIP="",RCONEnabled=False,RCONPort=25575,Region="",bUseAuth=True,BanListURL="https://api.palworldgame.com/api/banlist.txt",RESTAPIEnabled=False,RESTAPIPort=8212,bShowPlayerList=False,ChatPostLimitPerMinute=30,CrossplayPlatforms=(Steam,Xbox,PS5,Mac),bIsUseBackupSaveData=True,LogFormatType=Text,SupplyDropSpan=90,EnablePredatorBossPal=True,MaxBuildingLimitNum=0,ServerReplicatePawnCullDistance=15000.000000,bAllowGlobalPalboxExport=True,bAllowGlobalPalboxImport=False,EquipmentDurabilityDamageRate=1.000000,ItemContainerForceMarkDirtyInterval=1.000000) diff --git a/hosts/lithium/services/palworld/default.nix b/hosts/lithium/services/palworld/default.nix new file mode 100644 index 0000000..e36823d --- /dev/null +++ b/hosts/lithium/services/palworld/default.nix @@ -0,0 +1,51 @@ +{ config, pkgs, lib, ... }: +let + palworldSettings = builtins.readFile ./PalWorldSettings.ini; +in +{ + # NOTE: Partly inspired by: https://github.com/pocketpairjp/palworld-dedicated-server-docker + networking.firewall.allowedUDPPorts = [ 8211 ]; + + users.users.palworld = { + isSystemUser = true; + createHome = true; + home = "/home/palworld"; + homeMode = "750"; + group = "palworld"; + extraGroups = [ "steamcmd" ]; + }; + users.groups.palworld = {}; + + systemd.services.palworld = { + enable = true; + description = "PalWorld Dedicated Server"; + #after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStartPre = '' + ${pkgs.steamcmd}/bin/steamcmd +login anonymous \ + +app_update 2394010 validate +quit + ''; + ExecStart = '' + ${pkgs.steam-run}/bin/steam-run \ + .steam/steam/Steamapps/common/PalServer/PalServer.sh -publiclobby \ + -useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS + ''; + WorkingDirectory = "/home/palworld"; + Restart = "always"; + RuntimeMaxSec = "1d"; + User = "palworld"; + }; + }; + + # NOTE: Config is stashed at the following directory. + # /home/palworld/.steam/steam/Steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini + environment.etc."palworld/PalWorldSettings.ini" = { + target = "/home/palworld/.steam/steam/Steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini"; + text = palworldSettings; + mode = "0644"; + user = "palworld"; + group = "palworld"; + }; +} diff --git a/hosts/lithium/services/smartd.nix b/hosts/lithium/services/smartd.nix new file mode 100644 index 0000000..40bb159 --- /dev/null +++ b/hosts/lithium/services/smartd.nix @@ -0,0 +1,32 @@ +{ }: +{ + services.smartd = { + enable = true; + devices = [ + { + device = "ata-CT500MX500SSD1_2206E607D6AA"; + } + { + device = "ata-CT500MX500SSD1_2206E607D728"; + } + { + device = "ata-ST16000NM001G-2KK103_ZL2B73HT"; + } + { + device = "ata-ST16000NM001G-2KK103_ZL2PSELL"; + } + { + device = "ata-ST16000NM001G-2KK103_ZL2B4RSM"; + } + { + device = "ata-ST16000NM001G-2KK103_ZL23XYMM"; + } + { + device = "nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244331X"; + } + { + device = "nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244303V"; + } + ]; + }; +} diff --git a/hosts/lithium/sops.nix b/hosts/lithium/sops.nix new file mode 100644 index 0000000..23bee33 --- /dev/null +++ b/hosts/lithium/sops.nix @@ -0,0 +1,13 @@ +{ inputs, config, ... }: +let + secretsPath = builtins.toString inputs.nixos-secrets; +in +{ + imports = [ + inputs.sops-nix.nixosModules.sops + ]; + + sops = { + defaultSopsFile = "${secretsPath}/${config.hostname}/secrets.yaml"; + }; +} diff --git a/hosts/titanium/configuration.nix b/hosts/titanium/configuration.nix index ea4519f..c791efd 100644 --- a/hosts/titanium/configuration.nix +++ b/hosts/titanium/configuration.nix @@ -10,6 +10,9 @@ signal-desktop obs-studio ]; + services.udev.extraRules = '' + SUBSYSTEM=="usb", ATTRS{idVendor}=="14ed", ATTRS{idProduct}=="1012", MODE="0666", GROUP="audio" + ''; # Hardware Specific programs... #programs.ryzen-monitor-ng.enable = true; #programs.rog-control-center.enable = true; From 630f9b0074173c011dc79e2b2fa0a8157924cc99 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 28 Oct 2025 16:11:45 -0500 Subject: [PATCH 03/30] even more backups of things --- README.md | 4 + flake.bak | 70 ++++++++++++ flake.lock | 88 +++++++++----- flake.nix | 13 ++- hosts/lithium/configuration.nix | 2 +- hosts/lithium/default.nix | 7 ++ hosts/lithium/microvms/default.nix | 18 +++ hosts/lithium/microvms/palworld/default.nix | 107 ++++++++++++++++++ hosts/lithium/microvms/valheim.nix | 50 ++++++++ hosts/lithium/private-config.nix | 8 ++ hosts/lithium/secrets/common.yaml | 31 ++--- hosts/lithium/services/README.md | 11 ++ hosts/lithium/services/acme-dns.nix | 65 +++++++++++ hosts/lithium/services/audiobookshelf.nix | 20 ++++ hosts/lithium/services/caddy.nix | 46 +++++--- hosts/lithium/services/calibre-web.nix | 27 +++-- hosts/lithium/services/forgejo.nix | 8 +- .../services/forgejo/actions-runner.nix | 0 hosts/lithium/services/forgejo/default.nix | 0 hosts/lithium/services/forgejo/forgejo.nix | 0 hosts/lithium/services/game_servers.nix | 42 +++++++ hosts/lithium/services/grafana.nix | 24 ---- hosts/lithium/services/home-assistant.nix | 7 ++ hosts/lithium/services/immich.nix | 65 ++++++----- hosts/lithium/services/kanidm.nix | 103 ++++++++++++++--- hosts/lithium/services/miniflux/default.nix | 60 +++++++--- hosts/lithium/services/monitoring/README.md | 14 +++ hosts/lithium/services/monitoring/grafana.nix | 6 +- .../monitoring/loki-local-config.yaml | 4 + hosts/lithium/services/monitoring/loki.nix | 15 +++ .../services/monitoring/prometheus.nix | 39 ++++--- hosts/lithium/services/old-kanidm.nix | 79 +++++++++++++ hosts/lithium/services/palworld/default.nix | 4 +- hosts/lithium/services/smartd.nix | 25 ++-- hosts/lithium/services/uptime-kuma.nix | 4 +- hosts/lithium/sops.nix | 12 +- hosts/titanium/default.nix | 6 +- lib/default.nix | 1 + localnotes.md | 37 ++++++ localsecrets.yaml | 24 ++++ modules/nixos/desktop.nix | 3 +- pkgs/mv7-udev-rules/package.nix | 38 +++++++ secrets/global.yaml | 36 ++++++ secrets/temp.yaml | 56 +++++++++ users/jay/default.nix | 16 +++ users/jay/home.nix | 68 +++++++++++ 46 files changed, 1166 insertions(+), 197 deletions(-) create mode 100644 flake.bak create mode 100644 hosts/lithium/microvms/default.nix create mode 100644 hosts/lithium/microvms/palworld/default.nix create mode 100644 hosts/lithium/microvms/valheim.nix create mode 100644 hosts/lithium/private-config.nix create mode 100644 hosts/lithium/services/README.md create mode 100644 hosts/lithium/services/acme-dns.nix create mode 100644 hosts/lithium/services/audiobookshelf.nix create mode 100644 hosts/lithium/services/forgejo/actions-runner.nix create mode 100644 hosts/lithium/services/forgejo/default.nix create mode 100644 hosts/lithium/services/forgejo/forgejo.nix create mode 100644 hosts/lithium/services/game_servers.nix delete mode 100644 hosts/lithium/services/grafana.nix create mode 100644 hosts/lithium/services/home-assistant.nix create mode 100644 hosts/lithium/services/monitoring/README.md create mode 100644 hosts/lithium/services/monitoring/loki-local-config.yaml create mode 100644 hosts/lithium/services/monitoring/loki.nix create mode 100644 hosts/lithium/services/old-kanidm.nix create mode 100644 localnotes.md create mode 100644 localsecrets.yaml create mode 100644 pkgs/mv7-udev-rules/package.nix create mode 100644 secrets/global.yaml create mode 100644 secrets/temp.yaml create mode 100644 users/jay/default.nix create mode 100644 users/jay/home.nix diff --git a/README.md b/README.md index 3544565..89d5ab2 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,10 @@ nix-shell -p sops --run "sops secrets/example.yaml" ``` +## Configuring and Accessing Secrets + +I need to rip out agecrypt and go pure SOPS. + ## References - [@shazow](https://github.com/shazow/) and https://github.com/shazow/nixfiles/ diff --git a/flake.bak b/flake.bak new file mode 100644 index 0000000..6f3318a --- /dev/null +++ b/flake.bak @@ -0,0 +1,70 @@ +{ + description = "Configuration for NixOS"; + inputs = { + 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"; + + # flake-parts.url = "github:hercules-ci/flake-parts"; + }; + # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument + outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, ...}: + let + lib = import ./lib { inherit (nixpkgs) lib; }; + in + { + # NOTE: Run `nix flake show` to see what this flake has to offer. + # TODO: Enable automated formatting with numtide/treefmt-nix + # `nixos-rebuild switch --flake .#` + nixosConfigurations = { + neon = nixpkgs.lib.nixosSystem { + specialArgs = { inherit inputs; }; + system = "x86_64-linux"; + modules = [ + ./hosts/neon + ]; + }; + #lithium = nixpkgs.lib.nixosSystem { + #specialArgs = { inherit inputs; }; + #system = "x86_64-linux"; + #modules = [ + #./hosts/lithium + #]; + #}; + lithium = lib.mkSystem { + users = [ + { name = "jml"; } + ]; + }; + }; + homeConfigurations = { + "jml" = home-manager.lib.homeManagerConfiguration { + modules = [ + ./users/jml/home.nix + ]; + }; + }; + # TODO: Implement a dev shell for working on this repository. + # Personally I'm using hx, nil, and git-agecrypt + # The only thing totally necessary which isn't captured by the flake inputs + # is git-agecrypt so that should be included here or somehow in the flake. + devShells.x86_64-linux.default = pkgs.mkShell { + buildInputs = with pkgs; [ + nixpkgs-fmt + sops + age + git-agecrypt + ]; + shellHook = '' + echo "ready to rock" + ''; + }; + # `nix run .#name` and `nix build .#name` + # packages = {}; + # `home-manager switch` + # homeConfigurations = {}; + }; +} diff --git a/flake.lock b/flake.lock index 9064650..d40ebb3 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1757508292, - "narHash": "sha256-7lVWL5bC6xBIMWWDal41LlGAG+9u2zUorqo3QCUL4p4=", + "lastModified": 1758287904, + "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", "owner": "nix-community", "repo": "disko", - "rev": "146f45bee02b8bd88812cfce6ffc0f933788875a", + "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", "type": "github" }, "original": { @@ -119,11 +119,11 @@ ] }, "locked": { - "lastModified": 1749499854, - "narHash": "sha256-V1BgwiX8NjbRreU6LC2EzmuqFSQAHhoSeNlYJyZ40NE=", + "lastModified": 1759337100, + "narHash": "sha256-CcT3QvZ74NGfM+lSOILcCEeU+SnqXRvl1XCRHenZ0Us=", "owner": "nix-community", "repo": "home-manager", - "rev": "1df816c407d3a5090c8496c9b00170af7891f021", + "rev": "004753ae6b04c4b18aa07192c1106800aaacf6c3", "type": "github" }, "original": { @@ -167,11 +167,11 @@ "spectrum": "spectrum" }, "locked": { - "lastModified": 1750358184, - "narHash": "sha256-17EYMeY5v8KRk9HW6Z4dExY8Wg4y/zM2eM2wbbx+vMs=", + "lastModified": 1758113222, + "narHash": "sha256-Q5i/qaj6v6F4N1Q5gI/4aL0IEEUE/LjQuwcA8L5IOMc=", "owner": "astro", "repo": "microvm.nix", - "rev": "fd9f5dba1ffee5ad6f29394b2a9e4c66c1ce77dc", + "rev": "b9206e245c07c0782beff58e1e94bb48b2531d15", "type": "github" }, "original": { @@ -182,11 +182,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1749195551, - "narHash": "sha256-W5GKQHgunda/OP9sbKENBZhMBDNu2QahoIPwnsF6CeM=", + "lastModified": 1759261527, + "narHash": "sha256-wPd5oGvBBpUEzMF0kWnXge0WITNsITx/aGI9qLHgJ4g=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "4602f7e1d3f197b3cb540d5accf5669121629628", + "rev": "e087756cf4abbe1a34f3544c480fc1034d68742f", "type": "github" }, "original": { @@ -195,18 +195,37 @@ "type": "github" } }, + "nixos-secrets": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1759474546, + "narHash": "sha256-ZOlrxrAb5x5yM13P16sZowXb8AbEH02cZxets6SmkkA=", + "ref": "refs/heads/main", + "rev": "b28dde5afb05bf107905eff5c38908463fde5c59", + "shallow": true, + "type": "git", + "url": "ssh://forgejo@git.garage.systems/jml/nixos-secrets.git" + }, + "original": { + "shallow": true, + "type": "git", + "url": "ssh://forgejo@git.garage.systems/jml/nixos-secrets.git" + } + }, "nixpkgs": { "locked": { - "lastModified": 1749285348, - "narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=", - "owner": "nixos", + "lastModified": 1757967192, + "narHash": "sha256-/aA9A/OBmnuOMgwfzdsXRusqzUpd8rQnQY8jtrHK+To=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "3e3afe5174c561dee0df6f2c2b2236990146329f", + "rev": "0d7c15863b251a7a50265e57c1dca1a7add2e291", "type": "github" }, "original": { - "owner": "nixos", - "ref": "nixos-unstable", + "owner": "NixOS", + "ref": "nixpkgs-unstable", "repo": "nixpkgs", "type": "github" } @@ -227,6 +246,22 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1759381078, + "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "pre-commit-hooks-nix": { "inputs": { "flake-compat": [ @@ -261,7 +296,8 @@ "lanzaboote": "lanzaboote", "microvm": "microvm", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs", + "nixos-secrets": "nixos-secrets", + "nixpkgs": "nixpkgs_2", "sops-nix": "sops-nix" } }, @@ -293,11 +329,11 @@ ] }, "locked": { - "lastModified": 1747603214, - "narHash": "sha256-lAblXm0VwifYCJ/ILPXJwlz0qNY07DDYdLD+9H+Wc8o=", + "lastModified": 1759188042, + "narHash": "sha256-f9QC2KKiNReZDG2yyKAtDZh0rSK2Xp1wkPzKbHeQVRU=", "owner": "Mic92", "repo": "sops-nix", - "rev": "8d215e1c981be3aa37e47aeabd4e61bb069548fd", + "rev": "9fcfabe085281dd793589bdc770a2e577a3caa5d", "type": "github" }, "original": { @@ -309,11 +345,11 @@ "spectrum": { "flake": false, "locked": { - "lastModified": 1746869549, - "narHash": "sha256-BKZ/yZO/qeLKh9YqVkKB6wJiDQJAZNN5rk5NsMImsWs=", + "lastModified": 1754675037, + "narHash": "sha256-afS08F7lfMUBR4qrBxinN1kuxu+DoHQ5TPNVp9VS/OA=", "ref": "refs/heads/main", - "rev": "d927e78530892ec8ed389e8fae5f38abee00ad87", - "revCount": 862, + "rev": "586577f3015397afacd83bc185454f4cc3c8028f", + "revCount": 955, "type": "git", "url": "https://spectrum-os.org/git/spectrum" }, diff --git a/flake.nix b/flake.nix index d6b35f8..682f169 100644 --- a/flake.nix +++ b/flake.nix @@ -13,9 +13,12 @@ disko.inputs.nixpkgs.follows = "nixpkgs"; microvm.url = "github:astro/microvm.nix"; microvm.inputs.nixpkgs.follows = "nixpkgs"; + nixos-secrets.url = "git+ssh://forgejo@git.garage.systems/jml/nixos-secrets.git?shallow=1"; + #nixos-secrets.flake = false; # TODO: Why does flake need to be false? + #nixos-secrets.inputs.nixpkgs.follows = "nixpkgs"; }; # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument - outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, microvm, ...}: + outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, microvm, nixos-secrets, ...}: let mkSystem = (import ./lib { inherit nixpkgs home-manager inputs; @@ -31,8 +34,12 @@ }; lithium = mkSystem { hostname = "lithium"; - # extraModules = [ inputs.sops-nix.nixosModules.sops ]; - extraModules = [ microvm.nixosModules.host ]; + #specialArgs = {inherit inputs;}; + extraModules = [ + inputs.sops-nix.nixosModules.sops + inputs.nixos-secrets.nixosModules.private-config + ]; + #extraModules = [ microvm.nixosModules.host ]; users = [ "jml" "breakglass" diff --git a/hosts/lithium/configuration.nix b/hosts/lithium/configuration.nix index 80cd057..ab3a8d6 100644 --- a/hosts/lithium/configuration.nix +++ b/hosts/lithium/configuration.nix @@ -1,6 +1,6 @@ { config, pkgs, lib, ... }: { - sops.defaultSopsFile = ./secrets/common.yaml; + #sops.defaultSopsFile = ./secrets/common.yaml; networking.hostName = "lithium"; networking.domain = lib.mkForce config.vars.domain; environment.systemPackages = with pkgs; [ diff --git a/hosts/lithium/default.nix b/hosts/lithium/default.nix index 8834b37..8eb2f37 100644 --- a/hosts/lithium/default.nix +++ b/hosts/lithium/default.nix @@ -16,6 +16,7 @@ ./hardware.nix ./configuration.nix ./semi-secret-vars.nix + ./services/caddy.nix ./services/tailscale.nix ./services/kanidm.nix @@ -25,12 +26,18 @@ ./services/miniflux ./services/forgejo.nix + ./services/immich.nix + + ./services/calibre-web.nix + # Monitoring ./services/monitoring + ./services/smartd.nix # Game Servers ./services/palworld + # TODO: Add Karakeep with yt-dlp + https://news.ycombinator.com/item?id=45595084 # Services running in virtual machines #./microvms diff --git a/hosts/lithium/microvms/default.nix b/hosts/lithium/microvms/default.nix new file mode 100644 index 0000000..3467e4c --- /dev/null +++ b/hosts/lithium/microvms/default.nix @@ -0,0 +1,18 @@ +{ config, pkgs, lib, ... }: +{ + microvm.autostart = [ + "palworld-server" + ]; + + microvm = { + interfaces = [ + { type = "user"; id = "main-net"; } + { type = "macvtap"; id = "vm-palworld"; } + ]; + + # Interface Name on the Host + # Ethernet Address of MicroVM's interface. + # Locally administered have one of 2/6/A/E in the second nibble. + #interfaces = [{type = "tap";id = "vm-palworld";mac = "02:00:00:00:00:01";}]; + }; +} diff --git a/hosts/lithium/microvms/palworld/default.nix b/hosts/lithium/microvms/palworld/default.nix new file mode 100644 index 0000000..f20e293 --- /dev/null +++ b/hosts/lithium/microvms/palworld/default.nix @@ -0,0 +1,107 @@ +{ config, pkgs, lib, ... }: +{ + # Host Firewall + networking.firewall.allowedUDPPorts = [ 8211 ]; + #networking.nat = { + #enable = true; + #enableIPv6 = true; + #externalInterface = "eth0"; + #internalInterfaces = [ "microvm" ]; + #}; + + microvm.vms.palworld-server = { + # Basic Requirements + # https://docs.palworldgame.com/getting-started/requirements + #hypervisor = "qemu"; + vcpu = 4; + memory = 16348; + + # Networking + interfaces = [{ type = "user"; id = "main-net"; }]; + + # Interface Name on the Host + # Ethernet Address of MicroVM's interface. + # Locally administered have one of 2/6/A/E in the second nibble. + #interfaces = [{type = "tap";id = "vm-palworld";mac = "02:00:00:00:00:01";}]; + #forwardPorts = [ + #{ proto = "udp"; from = "host"; host.port = 8211; guest.port = 8211; } + # Optional: If you need RCON or other ports, add them here + # { proto = "tcp"; from = "host"; host.port = 25575; guest.port = 25575; } + #]; + + # Persistent Data + sharedDirectories = [ + { + source = "/var/lib/palworld-data"; + target = "/var/lib/palworld-server"; + readonly = false; + } + ]; + + # VM NixOS Configuration + config = { + imports = [ pkgs.nixosModules.notDetected ]; + + networking.hostName = "palworld-vm"; + time.timeZone = "America/Chicago"; + + environment.systemPackages = with pkgs; [ + steamcmd + #glibc + #gnumake + #cff + ]; + + # Pre-VM-Start + binScripts.tap-up = lib.mkAfter '' + ${lib.getExe' pkgs.iproute2 "ip"} link set dev 'vm-ixp-as11201p' master 'ixp-peering' + ''; + + # Service Definition + systemd.services.palworld-dedicated = { + description = "Palworld Dedicated Server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + serviceConfig = { + Type = "simple"; + User = "palworld"; + Group = "palworld"; + # Working Directory points to where steamcmd installs the server + WorkingDirectory = "/var/lib/palworld-server/Pal/Binaries/Win64"; + ExecStart = '' + ${pkgs.steam-run}/bin/steam-run ${pkgs.bash}/bin/bash -c '\ + ${pkgs.steamcmd}/bin/steamcmd \ + +force_install_dur /var/lib/palworld-server \ + +login anonymous \ + +app_update 2394010 validate \ + +quit \ + && \ + ./PalServer.sh -userperfthreads -NoAsyncLoadingThread -UseNvidiaServers -nosteamclient \ + -Players=8 -Port=8211 -queryport=27015 -PublicPort=8211 -PublicIP=\"\" -RCONEnabled=False + ' + ''; + Restart = "on-failure"; + RestartSec = "5s"; + LimitNPROC = 10000; + LimitNOFILE = 100000; + }; + }; + + # User and Group Configuration + users.users.palworld = { + isSystem = true; + group = "palworld"; + createHome = false; + }; + users.groups.palworld = {}; + + # Firewall Configuration + networking.firewall.allowedUDPPorts = [ 8211 ]; + + # Ensure correct permissions for shared directory + systemd.tmpfiles.rules = [ + "d /var/lib/palworld-server 0755 palworld palworld -" + ]; + }; + }; +} diff --git a/hosts/lithium/microvms/valheim.nix b/hosts/lithium/microvms/valheim.nix new file mode 100644 index 0000000..e4a2f89 --- /dev/null +++ b/hosts/lithium/microvms/valheim.nix @@ -0,0 +1,50 @@ +{ config, lib, pkgs, ... }: +{ + microvm.vms.valheim = { + autoStart = true; + memorySize = 4096; + vcpu = 2; + + forwardPorts = [ + { from = "host"; hostPort = 2456; guestPort = 2456; proto = "udp"; } + { from = "host"; hostPort = 2457; guestPort = 2457; proto = "udp"; } + ]; + + # NOTE: For games with large save files, choose a path in "/tank" for + # storage. + sharedDirectories = [ + { + hostPath = "/srv/game-data-valheim"; + guestPath = "/data"; + tag = "valheim-data"; + readOnly = false; + } + ]; + + packages = [ pkgs.steamcmd pkgs.steam-run ]; + + users.users.valheim = { + isNormalUser = true; + home = "/home/valheim"; + extraGroups = [ "wheel" ]; + }; + + systemd.services.valheim = { + description = "Valheim Dedicated Server"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + workingDirectory = "/data"; + ExecStart = '' + ${pkgs.steam-run}/bin/steam-run ./valheim_server.x86_64 \ + -name "Valheim NixOS" \ + -port 2456 \ + -world "FlatEarth" \ + -password "secret" \ + -public 1 + ''; + Restart = "always"; + User = "valheim"; + }; + }; + }; +} diff --git a/hosts/lithium/private-config.nix b/hosts/lithium/private-config.nix new file mode 100644 index 0000000..da79603 --- /dev/null +++ b/hosts/lithium/private-config.nix @@ -0,0 +1,8 @@ +{ inputs, ... }: +# let secretsPath = builtins.toString inputs.nixos-secrets; in +{ + #imports = [ inputs.nixos-secrets.nixosModules.private-config ]; + + # Enables a whole littany of private settings. + private-config.enable = true; +} diff --git a/hosts/lithium/secrets/common.yaml b/hosts/lithium/secrets/common.yaml index 341bc36..e02b06c 100644 --- a/hosts/lithium/secrets/common.yaml +++ b/hosts/lithium/secrets/common.yaml @@ -1,27 +1,30 @@ 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] + admin-password: ENC[AES256_GCM,data:Hvmo6YG2ZCoYdQOBOyPiS2XAm6I=,iv:qKu5vlT0HEqK3Mx3zgAA0OUA+B63rEXnq/P059mrweI=,tag:K+iTc8R30ClP8egzIEtXKA==,type:str] + idm-admin-password: ENC[AES256_GCM,data:Dvz2o6gY/G3igJFhaIQ4gj/OG/8=,iv:hDE+y8SKqRU8tNxnd7q4CE3GfOHOkMcODpqc43KiPfc=,tag:fU8AyFokVUhERUvi6W6bYw==,type:str] +forgejo-admin-password: ENC[AES256_GCM,data:d7a2pzSpaeZ0CQ==,iv:XB6Y41egclWzmyZe3g2Z9U1NcCilw3VTZNlym94h3IU=,tag:vR6jrXiBciPXzUmvxHzQNw==,type:str] +miniflux: + oauth2_client_secret: ENC[AES256_GCM,data:tZk6Ru5MQk+VJ/ulZNtKirL2lfLmOeVKsDbJfLly1SBwXC6HdjBx+yAFCc7YVX+2,iv:GIIMhV/sIALjoUZsMMXAJl968owAlULJ1JLpShqa3RM=,tag:c2i+LvGJKQm82fsUEHF/BA==,type:str] sops: age: - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5cFlReGMxV1R3QW1Vd1RU - WTgzNm5tbGhld3RMTGpMU1M2eVdoU0hmZGtNCmZLSTNOMk9IMDh6K2svRmRveGw3 - dlFUZ2lzTDBJWnBSTEhVTmVDOHVTdW8KLS0tIDhLWVZWSVJYM2x4YTlZWWZZZVNh - T2drb0p6TjZrZldpU0VUd0xmcVJUSk0KMjX3vr/74/HU7fmulefUHiNzwX8LcAes - ob3fabhMk9lmbuQk21rpoWbz3PNTfCQH63q+h7gLJTCCW2ISTvh/KQ== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4WUlyeStvZ28xVmV4VlNK + d1J1Z0twaTFzSEFENit0S210eTJFYTR1c1FRCnQvcFRCMUtFMkJxUDlRUTNxcTlK + dE5aM3U4Y0xvRE5jZlhrbjVtVk5rOHMKLS0tIHZISVlVcW9yT3hWcUtsVmN5TmRv + bXk5aSs4Wk9nM1p5d3FVSFBFKzVYZVEKYP2KQZIYm+zuI6OTfy85cEhj3gJWoKNu + jxd8vxwSbDmsXQK+mT8MsA9s+A9AhzGcZQ0rIQM/yKWFKSXt4kJ9rg== -----END AGE ENCRYPTED FILE----- - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl enc: | -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpK3VvNUhHNmJUQVZlREJl - c1oyZWx4ekNEM0VqL3NKanNmSmZtQXNpcWdVCmpWcklLVnhWUisvcGZzV1NHN3p4 - bW4wL09wL01XaHpveGdmbU4rbEp5NmsKLS0tIElhQVRmS05xUmJIZlI0S1dyWGhV - OGtKdHVwbWY2akJTQkF4YzlnNWQzNU0K81PyJ1tOvwOohNu9iUkS8vE7UXFRnJab - 8OLHtzX7FrkIH8rO2D5vEL9gPmxUtNKc9Ad3sndQls/yfg4wJAYedA== + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHQk1kYjU1bXZ0aUc3cGVQ + N1hwclNpRkJWQlVhaU9EOEFNRkRQMmhLakNjCjAwbE1UYkxxbzNxQjV5Y1I0TU0r + cmZBUTZsTzMxZmFZZUxnRmw3T205aDAKLS0tIGdJTHBHVmk4TmlBQ1RHYkJ3aWw3 + bktSejFIdS8wS2R4RHRFMEwwb2pBN1kK8EoLo1E/DiFmpCf/v0kGLPcqIB1qZDd1 + Uf7ccMFqvQH8wGVuyqqwiZ2SconvK7hHC5U9qgi6bZa/t4aW8eeU/g== -----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] + lastmodified: "2025-10-03T06:48:03Z" + mac: ENC[AES256_GCM,data:tglsrKi8Ydifc08LLA/KHzqWI3u9+Tn9kkERI3XKp/vSy4a90T2fU9f/lcyYbOXXuOOCL364wYq7ETmsTzOmb5Eo2Wtcu9Hsn820rLXuxNu7kyz9os/0eL/IThrPQtKov4/IdzoGQCqZvd9kcxTN1UPlRnd9aiHwsKmoFFFNZlE=,iv:y9+JQRXZf/6GabaQ1nQk3dL7qKMQxyzvIsXU2yVmlZo=,tag:klmWeIP068BpsSi8u/tE4A==,type:str] unencrypted_suffix: _unencrypted version: 3.10.2 diff --git a/hosts/lithium/services/README.md b/hosts/lithium/services/README.md new file mode 100644 index 0000000..0bf9c37 --- /dev/null +++ b/hosts/lithium/services/README.md @@ -0,0 +1,11 @@ +# hosts/lithium/services + +The idea is that each `*.nix` or each `./*/default.nix` file would contain all +necessary details for a service to bring itself up and be running. + +One thing I have overlooked thus far is nothing tests for the existence of a +reverse proxy and bails out if one isn't available. Practically if caddy isn't +running, most of these services should also not run, or at the very least, the +blocks pertaining to setting up reverse proxy details don't need to run. + +There's a way of doing that with things like lib.mkDefault and so forth. diff --git a/hosts/lithium/services/acme-dns.nix b/hosts/lithium/services/acme-dns.nix new file mode 100644 index 0000000..9377497 --- /dev/null +++ b/hosts/lithium/services/acme-dns.nix @@ -0,0 +1,65 @@ +{ config, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + certDir = config.security.acme.certs."${homelabDomain}".directory; +in +{ + sops.secrets."cloudflare/dns_api_token" = { + mode = "0440"; + group = config.services.caddy.group; + restartUnits = [ "caddy.service" "ddclient.service" ]; + }; + + + # TODO: Consider defining reverse proxy all in one location. + # All the ports and domains would be visible in one place. + security.acme = { + acceptTerms = true; + defaults = { + # NOTE: Uncomment the following line for testing, comment for production. + server = "https://acme-staging-v02.api.letsencrypt.org/directory"; + dnsProvider = "cloudflare"; + dnsResolver = "1.1.1.1:53"; + dnsPropagationCheck = true; + credentialFiles = { + CLOUDFLARE_DNS_API_TOKEN_FILE = config.sops.secrets."cloudflare/dns_api_token".path; + }; + group = config.services.caddy.group; + #reloadServices = [ "caddy" ]; + email = "admin+acme@${homelabDomain}"; # NOTE: This email is /dev/null; + #keyType = "ec384"; + }; + }; + + services.ddclient = { + enable = true; + protocol = "cloudflare"; + usev4 = "webv4, webv4=https://cloudflare.com/cdn-cgi/trace, web-skip='ip='"; + username = "token"; + #secretsFile = config.sops.secrets."cloudflare/dns_api_token".path; + passwordFile = config.sops.secrets."cloudflare/dns_api_token".path; + zone = homelabDomain; + domains = [ + homelabDomain + "*.${homelabDomain}" + "id.${homelabDomain}" + "status.${homelabDomain}" + "grafana.${homelabDomain}" + "feeds.${homelabDomain}" + "git.${homelabDomain}" + "tv.${homelabDomain}" + "demo.${homelabDomain}" # Testing to see if the DNS record is set. + ]; + }; + + # NOTE: Issue a single cert /w subdomain wildcard + # At the expense of individual service security, some public details about + # attack surface remain slightly more private in https://crt.sh/ + security.acme.certs."${homelabDomain}" = { + #group = config.services.caddy.group; + domain = "${homelabDomain}"; + extraDomainNames = [ "*.${homelabDomain}" ]; + }; + # Nginx useACMEHost provides the DNS-01 challenge. + # security.acme.certs."${homelabDomain}".directory +} diff --git a/hosts/lithium/services/audiobookshelf.nix b/hosts/lithium/services/audiobookshelf.nix new file mode 100644 index 0000000..92cf710 --- /dev/null +++ b/hosts/lithium/services/audiobookshelf.nix @@ -0,0 +1,20 @@ +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + svcDomain = "audiobooks.${homelabDomain}"; + svcPort = config.services.audiobookshelf.port; # Prevent a Conflict +in +{ + services.caddy.virtualHosts."${svcDomain}".extraConfig = '' + reverse_proxy :${svcPort} + ''; + + services.audiobookshelf = { + enable = true; + openFirewall = true; + port = 8000; + + # NOTE: Path to AudioBookShelf config & metadata inside of `/var/lib` + dataDir = "audiobookshelf"; + }; +} diff --git a/hosts/lithium/services/caddy.nix b/hosts/lithium/services/caddy.nix index 86a39cf..862c7ce 100644 --- a/hosts/lithium/services/caddy.nix +++ b/hosts/lithium/services/caddy.nix @@ -1,13 +1,22 @@ -{ config, pkgs, ... }: +{ inputs, config, pkgs, lib, ... }: +let + homelabDomain = inputs.nixos-secrets.homelabDomain; + certDir = config.security.acme.certs."${homelabDomain}".directory; +in { - sops.secrets.caddy_env = { - sopsFile = ../secrets/caddy.env; - format = "dotenv"; + services.nginx.enable = lib.mkForce false; + + sops.secrets.cloudflare_env = { mode = "0440"; - owner = config.services.caddy.user; + sopsFile = "${inputs.nixos-secrets}/lithium/cloudflare.env"; + format = "dotenv"; group = config.services.caddy.group; restartUnits = [ "caddy.service" ]; }; + + # TODO: Revert to using Caddy DNS for the whole thing. + # TODO: Add another cloudflare DDNS provider. + # TODO: Add Metrics with Prometheus & Grafana services.caddy = { enable = true; package = pkgs.caddy.withPlugins { @@ -16,26 +25,33 @@ "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: Built on 9/30/2025 + hash = "sha256-xuwNkxZop+RnzFtM9DEwah95nPSyx8KgM+Eu4EJ9kqI="; }; # 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; + + environmentFile = config.sops.secrets.cloudflare_env.path; + # NOTE: DNS provider settings + # https://caddy.community/t/how-to-use-dns-provider-modules-in-caddy-2/8148 globalConfig = '' - # acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN} + #acme_dns cloudflare {$CLOUDFLARE_DNS_API_TOKEN} dynamic_dns { - provider cloudflare {env.CLOUDFLARE_API_TOKEN} + provider cloudflare {$CLOUDFLARE_DNS_API_TOKEN} + check_interval 30m + ttl 5m domains { - ${config.networking.domain} @ + ${homelabDomain} @ } dynamic_domains } ''; + }; - networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall = { + allowedTCPPorts = [ 80 443 ]; + allowedUDPPorts = [ 443 ]; + }; + } diff --git a/hosts/lithium/services/calibre-web.nix b/hosts/lithium/services/calibre-web.nix index 44f8baf..38cafb5 100644 --- a/hosts/lithium/services/calibre-web.nix +++ b/hosts/lithium/services/calibre-web.nix @@ -1,11 +1,13 @@ { inputs, config, pkgs, lib, ... }: let homelabDomain = inputs.nixos-secrets.homelabDomain; - certDir = config.security.acme.certs."${homelabDomain}".directory; + #certDir = config.security.acme.certs."${homelabDomain}".directory; svcDomain = "books.${homelabDomain}"; svcHttpPort = config.services.calibre-web.listen.port; web_data_dir = "calibre-web"; + # TODO: I want the actual media stored in the tank. library_path = "/tank/media/library/books"; + #library_path = "/var/lib/calibre-library"; in { # TODO: This isn't the right place for this, but we need to guarantee that a @@ -14,19 +16,25 @@ in users.groups.media = {}; services.caddy.virtualHosts."${svcDomain}".extraConfig = '' - reverse_proxy :${toString svcHttpPort} - encode { - zstd - gzip - minimum_length 1024 - } + reverse_proxy localhost:8883 ''; + # reverse_proxy :${toString svcHttpPort} + # encode { + # zstd + # gzip + # minimum_length 1024 + # } + # ''; + + # NOTE: Needs some manual setup in Web-UI and I ecountered issues connecting even with firewall enabled. + # The following command is what I used to forward the port: + # ssh -f -N -L localhost:8883:localhost:8883 jml@lithium services.calibre-web = { enable = true; - listen.port = 8083; + listen.port = 8883; # NOTE: Don't need to open calibre-web port, it's served by reverse_proxy - openFirewall = false; + openFirewall = true; # TODO: Temporarily opened to allow configuration from inside my network. user = "calibre-web"; group = "calibre-web"; @@ -38,6 +46,7 @@ in options = { enableBookUploading = true; enableBookConversion = true; + # NOTE: If I don't already have an extant calibreLibrary, I need to leave this null or the app won't launch. calibreLibrary = library_path; }; }; diff --git a/hosts/lithium/services/forgejo.nix b/hosts/lithium/services/forgejo.nix index 3cec1fa..2f6377f 100644 --- a/hosts/lithium/services/forgejo.nix +++ b/hosts/lithium/services/forgejo.nix @@ -41,6 +41,7 @@ in server = { DOMAIN = svcDomain; ROOT_URL = "https://${svcDomain}"; + HTTP_PORT = 3000; }; # NOTE: Actions support is based on: https://github.com/nektos/act #actions = { @@ -49,6 +50,7 @@ in #}; actions.ENABLED = false; # NOTE: Registration is handled with kanidm. + # Registration button link is at /user/sign_up service = { REGISTER_EMAIL_CONFIRM = false; DISABLE_REGISTRATION = false; @@ -87,13 +89,15 @@ in services.kanidm.provision.systems.oauth2.forgejo = { displayName = "forgejo"; # TODO: Get this from Forgejo - originUrl = "https://git.${homelabDomain}/user/oauth2/${homelabDomain}/callback"; + # originUrl = "https://git.${homelabDomain}/user/oauth2/${homelabDomain}/callback"; + originUrl = "${config.services.forgejo.settings.server.ROOT_URL}/user/oauth2/kanidm/callback"; originLanding = "https://git.${homelabDomain}/"; #basicSecretFile = "TODO!SETME"; scopeMaps."git.users" = [ "openid" "email" "profile" + "groups" ]; # WARNING: PKCE is currently not supported by gitea/forgejo, # see https://github.com/go-gitea/gitea/issues/21376 @@ -137,5 +141,5 @@ in # TODO: Consider automatically creating admin account and password... # https://wiki.nixos.org/wiki/Forgejo#Ensure_users # Might be necessary to generate a token for kanidm - #sops.secrets.forgejo-admin-password.owner = "forgejo"; + sops.secrets."forgejo/admin-password".owner = "forgejo"; } diff --git a/hosts/lithium/services/forgejo/actions-runner.nix b/hosts/lithium/services/forgejo/actions-runner.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lithium/services/forgejo/default.nix b/hosts/lithium/services/forgejo/default.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lithium/services/forgejo/forgejo.nix b/hosts/lithium/services/forgejo/forgejo.nix new file mode 100644 index 0000000..e69de29 diff --git a/hosts/lithium/services/game_servers.nix b/hosts/lithium/services/game_servers.nix new file mode 100644 index 0000000..0cc2929 --- /dev/null +++ b/hosts/lithium/services/game_servers.nix @@ -0,0 +1,42 @@ +{ pkgs, ... }: +{ + # TODO + # systemd.services..serviceConfig.{MemoryMax,CPUQuota} + systemd.services.valheim-server = { + description = "Valheim dedicated server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + }; + + serviceConfig = { + Type = "simple"; + User = "valheim"; + Group = "valheim"; + ExecStart = "${pkgs.steamcmd}/bin/steamcmd +login anonymous +force_install_dir /home/valheim/server +app_update 896660 validate +exit && /home/valheim/server/valheim_server.x86_64"; + }; + + users.users.valheim = { + isSystemUser = true; + group = "valheim"; + home = "/home/valheim"; + }; + users.groups.valheim = {}; + + networking.firewall = { + allowedTCPPorts = [ 7777 2456 ]; + allowedUDPPorts = [ 7777 2457 ]; + }; + + services.restic.backups.gameservers = { + user = "root"; + # TODO: Pick a real backup directory. + repository = "/backup/gameservers"; + paths = [ + "/var/lib/terraria" + "/home/valheim/server" + ]; + timeConfig = { + OnCalendar = "daily"; + }; + }; +} diff --git a/hosts/lithium/services/grafana.nix b/hosts/lithium/services/grafana.nix deleted file mode 100644 index 0dddf2b..0000000 --- a/hosts/lithium/services/grafana.nix +++ /dev/null @@ -1,24 +0,0 @@ -{ config, pkgs, ... }: -let - svcDomain = "grafana.${config.networking.domain}"; - svcPort = config.services.grafana.settings.server.http_port; -in -{ - services.caddy.virtualHosts."${svcDomain}".extraConfig = '' - reverse_proxy :${svcPort} - ''; - - services.grafana = { - enable = true; - settings = { - server = { - http_addr = "127.0.0.1"; - http_port = 3000; - enforce_domain = true; - enable_gzip = true; - domain = svcDomain; - }; - analytics.reporting_enabled = false; # NOTE: Disable Telemetry - }; - }; -} diff --git a/hosts/lithium/services/home-assistant.nix b/hosts/lithium/services/home-assistant.nix new file mode 100644 index 0000000..ba87895 --- /dev/null +++ b/hosts/lithium/services/home-assistant.nix @@ -0,0 +1,7 @@ +{ config, pkgs, ... }: +{ + services.home-assistant = { + enable = true; + openFirewall = true; + }; +} diff --git a/hosts/lithium/services/immich.nix b/hosts/lithium/services/immich.nix index 1c71665..6226ade 100644 --- a/hosts/lithium/services/immich.nix +++ b/hosts/lithium/services/immich.nix @@ -4,29 +4,47 @@ let svcDomain = "photos.${homelabDomain}"; photoStorageDir = "/tank/shares/photos"; svcPort = config.services.immich.port; + # https://docs.immich.app/install/config-file/ + jsonSettings = { + server.externalDomain = "https://${svcDomain}"; + oauth = { + enabled = true; + issuerUrl = "https://"; # TODO: the kanidm url? + clientId = "immich"; + clientSecret = config.sops.placeholder."immich/oauth2_client_secret"; + scope = "openid email profile"; + signingAlgorithm = "ES256"; + storageLabelClaim = "email"; + buttonText = "Login with Kanidm"; + autoLaunch = true; + mobileOverrideEnabled = true; + mobileRedirectUri = "https://${svcDomain}/api/oauth/mobile-redirect/"; + }; + }; in { # NOTE: The following repo contains a highly mature immich setup on nixos. # https://github.com/xinyangli/nixos-config/blob/a8b5bea68caea573801ccfdb8ceacb7a8f2b0190/machines/agate/services/immich.nix services.caddy.virtualHosts."${svcDomain}".extraConfig = '' - reverse_proxy :${svcPort} + reverse_proxy :${toString svcPort} ''; # NOTE: Primarily to contain DB_PASSWORD to make it possible to backup and restore the DB. - sops.secrets.immich_env = { - sopsFile = ../../secrets/immich.env; - format = "dotenv"; + # sops.secrets.immich_env = { + # sopsFile = ../../secrets/immich.env; + # format = "dotenv"; + # mode = "0440"; + # owner = "immich"; + # group = "immich"; + # restartUnits = [ "immich.service" ]; + # }; + sops.secrets."immich/oauth2_client_secret" = { }; + sops.templates."immich.json" = { mode = "0440"; - owner = "immich"; - group = "immich"; - restartUnits = [ "immich.service" ]; - }; - sops.secrets."immich/oauth2_client_secret" = { - owner = "immich"; - group = "kanidm"; - mode = "0440"; - restartUnits = [ "immich.service" "kanidm.service" ]; + owner = config.services.immich.user; + group = config.services.immich.group; + content = builtins.toJSON jsonSettings; }; users.users.immich = { @@ -45,27 +63,12 @@ in enable = true; openFirewall = true; port = 2283; # default - secretsFile = config.sops.secrets."immich_secrets.env".path; + #secretsFile = config.sops.secrets.immich_env.path; # TODO: Build this directory with permissions for the immich user. mediaLocation = "/tank/shares/photos"; - - # https://docs.immich.app/install/config-file/ - settings = { - # TODO: Setup OAuth with Kanidm - oauth = { - enabled = true; - issuerUrl = "https://"; # TODO: the kanidm url? - clientId = "immich"; - clientSecret = config.sops.placeholder."immich/oauth2_client_secret"; - scope = "openid email profile"; - signingAlgorithm = "ES256"; - storageLabelClaim = "email"; - buttonText = "Login with Kanidm"; - autoLaunch = true; - mobileOverrideEnabled = true; - mobileRedirectUri = "https://${svcDomain}/api/oauth/mobile-redirect/"; - }; + environment = { + IMMICH_CONFIG_FILE = config.sops.templates."immich.json".path; }; }; diff --git a/hosts/lithium/services/kanidm.nix b/hosts/lithium/services/kanidm.nix index 066652f..a302749 100644 --- a/hosts/lithium/services/kanidm.nix +++ b/hosts/lithium/services/kanidm.nix @@ -1,33 +1,91 @@ -{ config, pkgs, lib, ... }: +{ inputs, 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"; + homelabDomain = inputs.nixos-secrets.homelabDomain; + svcDomain = "id.${homelabDomain}"; + kanidmCertDir = "/var/lib/kanidm/certs"; + caddyCertStore = "${config.services.caddy.dataDir}/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/${svcDomain}"; + #kcertloc = "${caddyCertsStore}/${svcDomain}/"; + certRenewalScript = pkgs.writeShellScript "copy-kanidm-cert-hook" '' + set -Eeuo pipefail + mkdir -p ${kanidmCertDir} + cp ${caddyCertStore}/${svcDomain}.crt ${kanidmCertDir}/cert.pem + cp ${caddyCertStore}/${svcDomain}.key ${kanidmCertDir}/key.pem + + chown kanidm:kanidm ${kanidmCertDir}/*.pem + + ${pkgs.systemd}/bin/systemctl restart kanidm.service + ''; + kanidmCertCopier = "kanidm-cert-copier"; in { + # NOTE: Domains are serious when they are the root of identity/authnz. + # Recommendation from Kanidm docs for "Maximum" security is to maintain + # Both `example.com` and `id.example-auth.com`, the latter for idm infra exclusively. + # I consider that to be untenable and even more risky. + # The next recommendation is to follow a pattern like so + # id.example.com + # australia.id.example.com + # id-test.example.com + # australia.id-test.example.com + + # 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 { + header_up Host {host} + header_up X-Real-IP {http.request.header.CF-Connecting-IP} transport http { tls_server_name ${svcDomain} } } ''; - # NOTE: Attempted kludge due to caddy generating (and therefore owning the certs) + # NOTE: Cleanup old rules + # systemd.tmpfiles.rules = lib.filter(rule: ! (lib.strings.hasPrefix "C ${kanidmCertDir}" rule)) config.systemd.tmpfiles.rules; 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" + "d ${kanidmCertDir} 0750 kanidm kanidm -" ]; - systemd.services.kanidm = { - after = [ "systemd-tmpfiles-setup.service" ]; - requires = [ "caddy.service" "systemd-tmpfiles-setup.service" ]; + # NOTE: Include automation for copying cert files on renewal. + # systemd.services.caddy.serviceConfig = { + # ExecStartPost = [ + # "${certRenewalScript}/bin/copy-kanidm-cert-hook" + # ]; + # ExecReload = [ + # "${pkgs.caddy}/bin/caddy reload --config ${config.services.caddy.configFile}" + # "${certRenewalScript}/bin/copy-kanidm-cert-hook" + # ]; + # }; + systemd.services.${kanidmCertCopier} = { + description = "Copy Caddy certificates for Kanidm"; + requires = [ "caddy.service" ]; + after = [ "caddy.service" ]; + + serviceConfig = { + Type = "oneshot"; + User = "root"; + ExecStart = "${certRenewalScript}"; + }; }; + # systemd.services.caddy.wantedBy = [ "multi-user.target" ]; + # systemd.services.caddy.wants = [ kanidmCertCopier ]; + systemd.services.caddy.reloadTriggers = [ kanidmCertCopier ]; + systemd.timers.kanidm-cert-copier-daily = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnBootSec = "5min"; + OnCalendar = "daily"; + Unit = kanidmCertCopier; + }; + }; + + + # systemd.services.kanidm = { + # after = [ kanidmCertCopier ]; + # requires = [ kanidmCertCopier ]; + # }; users.users.kanidm.extraGroups = [ "caddy" ]; @@ -43,21 +101,25 @@ in }; }; + services.kanidm = { - package = pkgs.kanidmWithSecretProvisioning; + package = pkgs.kanidmWithSecretProvisioning_1_7; 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"; + tls_chain = "${kanidmCertDir}/cert.pem"; + tls_key = "${kanidmCertDir}/key.pem"; + # tls_chain = "${caddyCertStore}/${svcDomain}.crt"; + # tls_key = "${caddyCertStore}/${svcDomain}.key"; # NOTE: Optional Settings + # TODO: Configure the rest of the binding properly, should be 363 and maybe 8443 ldapbindaddress = "127.0.0.1:3636"; # For Jellyfin LDAP integration. - # trust_x_forwarded_for = true; + #trust_x_forwarded_for = true; }; enableClient = true; @@ -74,6 +136,7 @@ in home_alias = "name"; }; + # TODO: Migrate the secrets from here to `nixos-secrets` # 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. @@ -82,7 +145,9 @@ in # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#onboarding-a-new-person--resetting-credentials provision = { enable = true; - autoRemove = false; + autoRemove = true; + acceptInvalidCerts = true; + adminPasswordFile = config.sops.secrets."kanidm/admin-password".path; idmAdminPasswordFile = config.sops.secrets."kanidm/idm-admin-password".path; @@ -98,6 +163,8 @@ in "git.users" "git.admins" "tv.users" + "immich.users" + "miniflux.users" ]; }; }; @@ -107,6 +174,8 @@ in "git.admins" = {}; "tv.users" = {}; "tv.admins" = {}; + "immich.users" = {}; + "miniflux.users" = {}; }; }; }; diff --git a/hosts/lithium/services/miniflux/default.nix b/hosts/lithium/services/miniflux/default.nix index a109874..bd92af4 100644 --- a/hosts/lithium/services/miniflux/default.nix +++ b/hosts/lithium/services/miniflux/default.nix @@ -1,7 +1,8 @@ { config, pkgs, ... }: let - svcDomain = "feeds.${config.networking.domain}"; - svcPort = "8080"; + homelabDomain = config.networking.domain; + svcDomain = "feeds.${homelabDomain}"; + svcPort = "8081"; # Prevent a Conflict in { services.caddy.virtualHosts."${svcDomain}".extraConfig = '' @@ -22,32 +23,57 @@ in group = "miniflux"; restartUnits = [ "miniflux.service" ]; }; - services.kanidm.provision = { - groups = {}; - systems.oauth2.miniflux = { - displayName = "Miniflux Feed Reader"; - originUrl = "https://${fqdn}/callback"; - public = true; # enforces PKCE - preferShortUsername = true; - scopeMaps.pages_users = ["openid" "email" "profile"]; - claimMaps."${permissionsMap}".valuesByGroup.pages_admin = ["admin"]; - }; + sops.secrets."miniflux/oauth2_client_secret" = { + owner = "miniflux"; + group = "kanidm"; + mode = "0440"; + restartUnits = [ "miniflux.service" "kanidm.service" ]; }; + #services.kanidm.provision = { + #groups = {}; + #systems.oauth2.miniflux = { + #displayName = "Miniflux Feed Reader"; + #originUrl = "https://${fqdn}/callback"; + #public = true; # enforces PKCE + #preferShortUsername = true; + #scopeMaps.pages_users = ["openid" "email" "profile"]; + #claimMaps."${permissionsMap}".valuesByGroup.pages_admin = ["admin"]; + #}; + #}; # NOTE: Currently requires some web-interface configuration services.miniflux = { enable = true; adminCredentialsFile = config.sops.secrets.miniflux_env.path; config = { BASE_URL = "https://${svcDomain}"; - CREATE_ADMIN = 0; - DISABLE_LOCAL_AUTH = 1; + #CREATE_ADMIN = 0; + #DISABLE_LOCAL_AUTH = 1; OAUTH2_PROVIDER = "oidc"; - OAUTH2_OIDC_PROVIDER_NAME = "Kanidm"; - OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://id.${config.networking.domain}"; + OAUTH2_CLIENT_ID = "miniflux"; + OAUTH2_CLIENT_SECRET_FILE = config.sops.secrets."miniflux/oauth2_client_secret".path; OAUTH2_REDIRECT_URL = "https://${svcDomain}/oauth2/oidc/callback"; - OAUTH2_USER_CREATION = 1; + OAUTH2_OIDC_DISCOVERY_ENDPOINT = "https://id.${homelabDomain}/oauth2/openid/miniflux"; + #OAUTH2_USER_CREATION = 1; CLEANUP_FREQUENCY = 48; LISTEN_ADDR = "localhost:${svcPort}"; }; }; + + + services.kanidm.provision.systems.oauth2.miniflux = { + displayName = "miniflux"; + originUrl = "https://${svcDomain}/oauth2/oidc/callback"; + originLanding = "https://${svcDomain}/"; + basicSecretFile = config.sops.secrets."miniflux/oauth2_client_secret".path; + scopeMaps."miniflux.users" = [ + "openid" + "email" + "profile" + "groups" + ]; + # WARNING: PKCE is currently not supported by gitea/forgejo, + # see https://github.com/go-gitea/gitea/issues/21376 + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + }; } diff --git a/hosts/lithium/services/monitoring/README.md b/hosts/lithium/services/monitoring/README.md new file mode 100644 index 0000000..93c1ca8 --- /dev/null +++ b/hosts/lithium/services/monitoring/README.md @@ -0,0 +1,14 @@ +# hosts/lithium/services/monitoring + +This is a Grafana/Prometheus Monitoring Stack. +Why? Basically for the sake of it. + +## Diagram + +```mermaid +```` + +## References + +- https://gist.github.com/rickhull/895b0cb38fdd537c1078a858cf15d63e +- https://xeiaso.net/blog/prometheus-grafana-loki-nixos-2020-11-20/ diff --git a/hosts/lithium/services/monitoring/grafana.nix b/hosts/lithium/services/monitoring/grafana.nix index 7ba0206..afc986e 100644 --- a/hosts/lithium/services/monitoring/grafana.nix +++ b/hosts/lithium/services/monitoring/grafana.nix @@ -1,6 +1,8 @@ -{ config, pkgs, ... }: +{ inputs, config, pkgs, ... }: let - svcDomain = "grafana.${config.networking.domain}"; + homelabDomain = inputs.nixos-secrets.homelabDomain; + #svcDomain = "grafana.${config.networking.domain}"; + svcDomain = "grafana.${homelabDomain}"; svcPort = config.services.grafana.settings.server.http_port; in { diff --git a/hosts/lithium/services/monitoring/loki-local-config.yaml b/hosts/lithium/services/monitoring/loki-local-config.yaml new file mode 100644 index 0000000..919a718 --- /dev/null +++ b/hosts/lithium/services/monitoring/loki-local-config.yaml @@ -0,0 +1,4 @@ +auth_enabled: false + +server: + http_listen_port: 3100 diff --git a/hosts/lithium/services/monitoring/loki.nix b/hosts/lithium/services/monitoring/loki.nix new file mode 100644 index 0000000..448cc37 --- /dev/null +++ b/hosts/lithium/services/monitoring/loki.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + services.loki = { + enable = true; + #configFile = "./loki-local-config.yaml"; + # Nix Object representing the data that might otherwise be in a YAML config + # https://github.com/grafana/loki/blob/main/cmd/loki/loki-local-config.yaml + configuration = { + auth_enabled = false; + server = { + + }; + }; + }; +} diff --git a/hosts/lithium/services/monitoring/prometheus.nix b/hosts/lithium/services/monitoring/prometheus.nix index 51be2ea..84d818c 100644 --- a/hosts/lithium/services/monitoring/prometheus.nix +++ b/hosts/lithium/services/monitoring/prometheus.nix @@ -1,8 +1,8 @@ { config, pkgs, ... }: -#let +let #svcDomain = "status.${config.networking.domain}"; - #svcPort = config.services.prometheus.exporters.node.port; -#in + svcPort = config.services.prometheus.exporters.node.port; +in { #services.caddy.virtualHosts."${svcDomain}".extraConfig = '' #reverse_proxy :${svcPort} @@ -10,20 +10,27 @@ services.prometheus = { enable = true; + port = 9090; #globalConfig.scrape_interval = "10s"; # "1m" - #scrapeConfigs = [ - #{ - #job_name = "node"; - #static_configs = [{ - # targets = [ "localhost:${toString svcPort}" ]; - #}]; - #} - #]; + + exporters = { + # Export data about this host + node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9091; + }; + }; + + # Read data from the export + scrapeConfigs = [ + { + job_name = "node-lithium"; + static_configs = [{ + targets = [ "localhost:${toString svcPort}" ]; + }]; + } + ]; }; - #services.prometheus.exporters.node = { - #enable = true; - #port = 9000; - #enabledCollectors = [ "systemd" ]; - #}; } diff --git a/hosts/lithium/services/old-kanidm.nix b/hosts/lithium/services/old-kanidm.nix new file mode 100644 index 0000000..0bce514 --- /dev/null +++ b/hosts/lithium/services/old-kanidm.nix @@ -0,0 +1,79 @@ +{ config, pkgs, lib, ... }: +let + cfg = config.services.kanidm; + authDomain = "auth.${config.networking.domain}"; + certsDir = config.security.acme.certs."${authDomain}".directory; +in +{ + # TODO: Pull in the appropriate sops-nix secrets and get this baby rolling. + # https://github.com/search?q=language%3ANix+services.kanidm&type=code + services.kanidm = { + # NOTE: Pin a specific kanidm version, we don't want issues from auto-updating. + package = pkgs.kanidm_1_6; + enableServer = true; + + # TODO: Initial kanidm setup. + # I sort of want users to be able to create their own accounts and what I + # don't want is for any of their account information to be leaked here as + # it can be used for remote logins. + # So kanidm accounts aside from the administration will be "impure". + # I vastly prefer people being able to set their own credentials: + # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#onboarding-a-new-person--resetting-credentials + provision = { + enable = true; + autoRemove = false; + # TODO: Add secrets from `sops-nix`. + adminPasswordFile = "TODO!SETME"; + idmAdminPasswordFile = "TODO!SETME"; + + persons = { + # https://kanidm.github.io/kanidm/stable/accounts/authentication_and_credentials.html#resetting-person-account-credentials + # Needs to be a member of idm_people_admins and idm_high_privilege to prevent idm_service_desk from tampering. + zenware = { + displayName = "zenware"; + legalName = "zenware"; + mailAddresses = [ "zenware@${config.networking.domain} "]; + groups = [ + "idm_high_privilege" + "git.users" + "git.admins" + ]; + }; + # TODO: Make an idm_service_desk account. + }; + groups = { + # This group is `git` because it could be forgejo, gitea, etc. + "git.users" = {}; + "git.admins" = {}; + }; + systems.oauth2 = { + forgejo = { + displayName = "forgejo"; + originUrl = "TODO!SETME"; + originLanding = "TODO!SETME"; + basicSecretFile = "TODO!SETME"; + scopeMaps."git.users" = [ + "openid" + "email" + "profile" + ]; + # WARNING: PKCE is currently not supported by gitea/forgejo, + # see https://github.com/go-gitea/gitea/issues/21376 + allowInsecureClientDisablePkce = true; + preferShortUsername = true; + claimMaps.groups = { + joinType = "array"; + valuesByGroup."git.admins" = [ "admin" ]; + }; + }; + }; + }; + + #enableClient = false; + clientSettings = { + uri = "https://${authDomain}"; + verify_hostnames = true; + verify_ca = true; + }; + }; +} diff --git a/hosts/lithium/services/palworld/default.nix b/hosts/lithium/services/palworld/default.nix index e36823d..29a70f7 100644 --- a/hosts/lithium/services/palworld/default.nix +++ b/hosts/lithium/services/palworld/default.nix @@ -34,13 +34,15 @@ in ''; WorkingDirectory = "/home/palworld"; Restart = "always"; - RuntimeMaxSec = "1d"; + RuntimeMaxSec = "1d"; # NOTE: This thing has memory leaks, restart to save our selves. User = "palworld"; }; }; # NOTE: Config is stashed at the following directory. # /home/palworld/.steam/steam/Steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini + # TODO: There are benefits to including the meat of the configuration inside the 'nix' file. + # Namely that it will result in actually updating the config when I rebuild. environment.etc."palworld/PalWorldSettings.ini" = { target = "/home/palworld/.steam/steam/Steamapps/common/PalServer/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini"; text = palworldSettings; diff --git a/hosts/lithium/services/smartd.nix b/hosts/lithium/services/smartd.nix index 40bb159..69999db 100644 --- a/hosts/lithium/services/smartd.nix +++ b/hosts/lithium/services/smartd.nix @@ -1,32 +1,39 @@ -{ }: +{ config, ... }: { services.smartd = { enable = true; devices = [ { - device = "ata-CT500MX500SSD1_2206E607D6AA"; + device = "/dev/disk/by-id/ata-CT500MX500SSD1_2206E607D6AA"; } { - device = "ata-CT500MX500SSD1_2206E607D728"; + device = "/dev/disk/by-id/ata-CT500MX500SSD1_2206E607D728"; } { - device = "ata-ST16000NM001G-2KK103_ZL2B73HT"; + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL2B73HT"; } { - device = "ata-ST16000NM001G-2KK103_ZL2PSELL"; + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL2PSELL"; } { - device = "ata-ST16000NM001G-2KK103_ZL2B4RSM"; + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL2B4RSM"; } { - device = "ata-ST16000NM001G-2KK103_ZL23XYMM"; + device = "/dev/disk/by-id/ata-ST16000NM001G-2KK103_ZL23XYMM"; } { - device = "nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244331X"; + device = "/dev/disk/by-id/nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244331X"; } { - device = "nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244303V"; + device = "/dev/disk/by-id/nvme-Samsung_SSD_960_EVO_500GB_S3X4NB0K244303V"; } ]; }; + + services.prometheus.exporters.smartctl = { + enable = config.services.smartd.enable; + openFirewall = config.services.smartd.enable; + # https://github.com/prometheus-community/smartctl_exporter?tab=readme-ov-file#why-is-root-required-cant-i-add-a-user-to-the-disk-group + user = "root"; + }; } diff --git a/hosts/lithium/services/uptime-kuma.nix b/hosts/lithium/services/uptime-kuma.nix index c9669eb..096beb1 100644 --- a/hosts/lithium/services/uptime-kuma.nix +++ b/hosts/lithium/services/uptime-kuma.nix @@ -13,6 +13,8 @@ in enable = true; # NOTE: NixOS Attributes here resolve into these ENV vars: # https://github.com/louislam/uptime-kuma/wiki/Environment-Variables - # settings = {}; + settings = { + PORT = "4000"; + }; }; } diff --git a/hosts/lithium/sops.nix b/hosts/lithium/sops.nix index 23bee33..ce45efa 100644 --- a/hosts/lithium/sops.nix +++ b/hosts/lithium/sops.nix @@ -1,13 +1,15 @@ -{ inputs, config, ... }: +{ inputs, ... }: let secretsPath = builtins.toString inputs.nixos-secrets; in { - imports = [ - inputs.sops-nix.nixosModules.sops - ]; + #imports = [ inputs.sops-nix.nixosModules.sops ]; sops = { - defaultSopsFile = "${secretsPath}/${config.hostname}/secrets.yaml"; + #defaultSopsFile = "${secretsPath}/${config.hostname}/secrets.yaml"; + #defaultSopsFile = "${secretsPath}/global/secrets.yaml"; + # TODO: Make this test the hostname. + #defaultSopsFile = "${secretsPath}/lithium/secrets/common.yaml"; + defaultSopsFile = "${secretsPath}/lithium/secrets.yaml"; }; } diff --git a/hosts/titanium/default.nix b/hosts/titanium/default.nix index 23d9076..bdc3d2f 100644 --- a/hosts/titanium/default.nix +++ b/hosts/titanium/default.nix @@ -7,11 +7,11 @@ ../../modules/nixos/desktop.nix ../../modules/nixos/gaming.nix inputs.nixos-hardware.nixosModules.asus-rog-strix-x570e - #./hardware.nix + ./hardware.nix ./configuration.nix ./nvidia.nix ./secure-boot.nix - inputs.disko.nixosModules.disko - ./disko.nix + #inputs.disko.nixosModules.disko + #./disko.nix ]; } diff --git a/lib/default.nix b/lib/default.nix index 3926ed9..db5a123 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -33,6 +33,7 @@ in nixpkgs.lib.nixosSystem { inherit system; + specialArgs = { inherit inputs hostname; }; modules = [ hostModule ] ++ userModules ++ extraModules diff --git a/localnotes.md b/localnotes.md new file mode 100644 index 0000000..13756cd --- /dev/null +++ b/localnotes.md @@ -0,0 +1,37 @@ + + +Run disko first, then install. + +```bash +sudo nix --experimental-features "nix-command flakes" run github:nix-community/disko -- --mode disko /path/to/disko.nix +sudo nixos-install --root /mnt --no-root-passwd --flake .#titanium +``` + +need to comment out lanzaboote stuff to get it working... :( +then re-enable it after the system is online again. + + +There is clearly some kind of quirk about boot drives. +We're going to try again, and double-check reading through config this time. + +I've already partitioned the drive(s) with disko, but I don't have a reason not to do it again. + +There is some reason why if I import disko into my nixos config it creates a conflict between the name of the drives. + +```bash +/dev/crypt/mapper +# and a full uuid path +``` + +I figured it out, after you have the disk paths and stuff setup with `disko` you no longer need to maintain them in `hardware-configuration.nix` +Which.. is actually quite nice to be honest. + + + +## Some Ideas to consider + +- https://github.com/Sveske-Juice/declarative-jellyfin +- https://docs.clan.lol +- fido2 luks cryptenroll + - https://discourse.nixos.org/t/using-fido2-luks-with-yubikey-pin/15484 +- https://github.com/nix-community/nixhelm/ diff --git a/localsecrets.yaml b/localsecrets.yaml new file mode 100644 index 0000000..ec09dc6 --- /dev/null +++ b/localsecrets.yaml @@ -0,0 +1,24 @@ +cloudflare_api_token: ENC[AES256_GCM,data:IqZ2LkBUyboO9494G3LPFn8prx48SDFluz6u4KDzQfQxTyqiVkORRQ==,iv:5iSnHMFHOEXDxt5/fSQ/83OzG2iU6LQ9OCnah5Qnj1A=,tag:zBQvE9KvW195mLtwjFKWqQ==,type:str] +cloudflare: + api_token: ENC[AES256_GCM,data:ZkiVQeVFHQ==,iv:402yjlUkamfzgAqMQCChR+ui4nsA625GidVIwCOc8bM=,tag:xErz+vXV8en2c3WdHfqUsg==,type:str] + email: ENC[AES256_GCM,data:AnI4i1ar70FvyLzVqiElJTbZ6V12Tw==,iv:VYoK2Q2XmleP2SV9Axy8JPTrPeLjnJBkhaXVuCWGUtA=,tag:uxB9JQJWUwoIQ1QtpbvT8Q==,type:str] +env: + domain_name: ENC[AES256_GCM,data:sGpnauqZ2LSY+Hf34eA=,iv:V1OOAo9zoEAkXDLL2la6DF+FoCj4Lzqg88dbHHSqcXs=,tag:C+0yaNo/TwAtym7NSxNnyA==,type:str] +yubico: + id: ENC[AES256_GCM,data:n80pw3A=,iv:pS/T3JGbVQkmYJ6EnwcdITe9J8knVBJiEn8njxPzAcM=,tag:gwg5pl6ugfBH4qwpcr1cjA==,type:int] + secret_key: ENC[AES256_GCM,data:kax8+XHJwpqFtRdKpkRR5sFhsKawlT7Ru92Umw==,iv:wSs4wdAkHyacKUmIxGfn8KDv1A8yW6E+0eBuXnOzhMA=,tag:Y6Om1OShD6s3dBALseN/qQ==,type:str] +tailscale: + auth_key: ENC[AES256_GCM,data:lIT80TrYfqMa8k6wsxC5BV6sBg6PCw5+AJaUtMhfJuXTIOz48PZKpCFq5z76TenpGpYT1vdqfCGd8Z1UfA==,iv:5LCWydaBX0ap5VScmjSm/QLtkeYy7u0ImVXoaY8URZs=,tag:dZV4s026eS4ME68ET+JxGw==,type:str] +vrising_server_name: ENC[AES256_GCM,data:guRSn4xsGFJ0,iv:spCO2OuFr2JmFL+qboq2dwrpxb7KufxtscZI8/3r9SQ=,tag:qbFV4IIiFmEQW72So6pm7A==,type:str] +valheim_server_name: ENC[AES256_GCM,data:PJV694YqSnOkBw==,iv:yIjgunzkiVdO1pUuAOtKcRI2zhBSb2sfDfM5WrPsVa8=,tag:I18ugPusdBoADlSxYzIYNw==,type:str] +kanidm: + bind_password: ENC[AES256_GCM,data:l9nP,iv:Qtk6hGj+RnLfsNBRp4QHpCo/Oxq+EdVu62xmClPbPNk=,tag:7PRHrMT5kJdtqV2xXZPzZg==,type:int] +tailscale: + auth_key: ENC[AES256_GCM,data:RFno,iv:wG8XyXMQt/BLjp3jW0j509cDmF/V+UqGAFCjJ3twQ3k=,tag:5z1krKBPDWlZGvHleS4rPA==,type:int] +gitea: + secret_key: ENC[AES256_GCM,data:u5EV,iv:UdQaFFC2Rh0aDbqzHdowhTmxrKbOhWEmGmUEjkOUrg4=,tag:MfB6Jbc3IPc8h4VAd4urEg==,type:int] + internal_token: ENC[AES256_GCM,data:K1tX,iv:MhM1IURTet1e919eI9NpitEdfG8WRB33E4GsCmcSDro=,tag:146dEI1/Bj+w5Ul+Sbt9bw==,type:int] + db_password: ENC[AES256_GCM,data:muy+,iv:e0drAD03om5xAmLOUa4IxTFHQ5U1xeK+fgDOhATnMU8=,tag:JVorF+C4+ENhFZ7/0QSwrQ==,type:int] + oauth_client_secret: ENC[AES256_GCM,data:hVM95DQxfS9Af/z+C5AgjpcoHBs=,iv:pq4lXNYXzFIaNUWhmCV5EwD4icjziCWVqpSuIg1FzZQ=,tag:z/lxukCKwgriNLqqeHDFuQ==,type:str] +jellyfin: + oauth_client_secret: ENC[AES256_GCM,data:IQI6FfOga+3bmf+B+/vpGao=,iv:lC/zbax5mgzQBRNIIbeviWBXtMKSegKFJlHdY+bCSyo=,tag:g0BUqfHZrJB2gJUIjLjnuA==,type:str] diff --git a/modules/nixos/desktop.nix b/modules/nixos/desktop.nix index 7251a84..5e4a3c2 100644 --- a/modules/nixos/desktop.nix +++ b/modules/nixos/desktop.nix @@ -5,7 +5,8 @@ xdg-desktop-portal-gtk xdg-desktop-portal-hyprland xwayland - rofi-wayland + #rofi-wayland + rofi waybar hyprpaper kitty # hyprland default term diff --git a/pkgs/mv7-udev-rules/package.nix b/pkgs/mv7-udev-rules/package.nix new file mode 100644 index 0000000..32e03bb --- /dev/null +++ b/pkgs/mv7-udev-rules/package.nix @@ -0,0 +1,38 @@ +{ + lib, + stdenv, + fetchFromGitHub, +}: + +# Based on: +# https://github.com/NixOS/nixpkgs/blob/nixos-25.05/pkgs/by-name/zs/zsa-udev-rules/package.nix + +stdenv.mkDerivation { + pname = "mv7-udev-rules"; + version = "unstable-2025-06-20"; + + src = fetchFromGitHub { + owner = "zenware"; + repo = "mv7-udev-rules"; + rev = "000000000000000000000000000000000"; + hash = "sha256-0000000000000000000000000"; + }; + + # Only copy udev rules + dontConfigure = true; + dontBuild = true; + dontFixup = true; + + installPhase = '' + mkdir -p $out/lib/udev/rules.d + cp dist/linux64/99-mv7-mic.rules $out/lib/udev/rules.d/ + ''; + + meta = with lib; { + description = "udev rules for MV7 devices"; + license = licenses.mit; + maintainers = with maintainers; [ zenware ]; + platforms = platforms.linux; + homepage = "https://github.com/zenware/mv7-udev-rules"; + }; +} diff --git a/secrets/global.yaml b/secrets/global.yaml new file mode 100644 index 0000000..893df2b --- /dev/null +++ b/secrets/global.yaml @@ -0,0 +1,36 @@ +cloudflare_api_token: ENC[AES256_GCM,data:IqZ2LkBUyboO9494G3LPFn8prx48SDFluz6u4KDzQfQxTyqiVkORRQ==,iv:5iSnHMFHOEXDxt5/fSQ/83OzG2iU6LQ9OCnah5Qnj1A=,tag:zBQvE9KvW195mLtwjFKWqQ==,type:str] +kanidm: + bind_password: ENC[AES256_GCM,data:l9nP,iv:Qtk6hGj+RnLfsNBRp4QHpCo/Oxq+EdVu62xmClPbPNk=,tag:7PRHrMT5kJdtqV2xXZPzZg==,type:int] +tailscale: + auth_key: ENC[AES256_GCM,data:RFno,iv:wG8XyXMQt/BLjp3jW0j509cDmF/V+UqGAFCjJ3twQ3k=,tag:5z1krKBPDWlZGvHleS4rPA==,type:int] +gitea: + secret_key: ENC[AES256_GCM,data:u5EV,iv:UdQaFFC2Rh0aDbqzHdowhTmxrKbOhWEmGmUEjkOUrg4=,tag:MfB6Jbc3IPc8h4VAd4urEg==,type:int] + internal_token: ENC[AES256_GCM,data:K1tX,iv:MhM1IURTet1e919eI9NpitEdfG8WRB33E4GsCmcSDro=,tag:146dEI1/Bj+w5Ul+Sbt9bw==,type:int] + db_password: ENC[AES256_GCM,data:muy+,iv:e0drAD03om5xAmLOUa4IxTFHQ5U1xeK+fgDOhATnMU8=,tag:JVorF+C4+ENhFZ7/0QSwrQ==,type:int] + oauth_client_secret: ENC[AES256_GCM,data:hVM95DQxfS9Af/z+C5AgjpcoHBs=,iv:pq4lXNYXzFIaNUWhmCV5EwD4icjziCWVqpSuIg1FzZQ=,tag:z/lxukCKwgriNLqqeHDFuQ==,type:str] +jellyfin: + oauth_client_secret: ENC[AES256_GCM,data:IQI6FfOga+3bmf+B+/vpGao=,iv:lC/zbax5mgzQBRNIIbeviWBXtMKSegKFJlHdY+bCSyo=,tag:g0BUqfHZrJB2gJUIjLjnuA==,type:str] +sops: + age: + - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuOTRKeDNjSEdnQ2ZRNnI3 + dzZJc0xJdFFOUk9tWDJRcHZZSXVUMkpRQUc0CjhGWkNYR1daR2VWT2JOQUFZVlJO + ZGswSU5vaDJLWm5INXp5MlVQYjBCUzQKLS0tIDlrZjN6SGFnNDY4TEN6NjlPN01Y + dGRsTVpBMGVaVytpTm55WEIzNVpHTDQK8p9yexr9L7TwBPu/jKZkdDD2GOt9+nkK + 6tcckBjVx/SUIs7U0qbE6DkzCXIWo2Ce5hsk4RE1p91Y4vocaMPxYA== + -----END AGE ENCRYPTED FILE----- + - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyZUI5VFp5R1Z1SU5XSEtt + QndNajRsR0VyOTUrNjljcnlVRW8vRnVid1hjCmhraVA1anFEdUJoa0lMNm5RcjFE + b1o3bzBpRm83VVhWQy94NXNqSjJSekUKLS0tIGNaQno3RzEyYlNPT0RsNzEzaUd6 + c2tIcEx4VGpIVXZzcEJoUTRGRjdSTjAKk4C6PQiAZpunDmNitkrTBq6PqRe53mZB + ehF6fL7DTveVwWq02csekQdi7hXShkoH7EEMw1LrEe6IP7oJbvZ3jw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-06-04T13:43:02Z" + mac: ENC[AES256_GCM,data:Kd+9kPRgwfdJh9rMADopqJyocPg4M3hnvW8LYxV8jcoOGvuK+rBPu0rQF30ZGUq0i7LG7WiqN+m7nDTrl6KcO4WN4IyTqLJ/lheOLiBTpbUv68VEYPEbTEkvTMrfhsaCNk3AUuUI34cle+k9Q0/QgNenVx7yH77VzR3aiYH/hzA=,iv:s6+V8wTYTE6Q28Kyjb2NlyoGRvUaliaeJAn6htQ1Xwo=,tag:ZkO/mKZ/Dk1jit6qgTxzMA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/secrets/temp.yaml b/secrets/temp.yaml new file mode 100644 index 0000000..d6bf591 --- /dev/null +++ b/secrets/temp.yaml @@ -0,0 +1,56 @@ +#ENC[AES256_GCM,data:dqhy221XOImoFPMsVz3eFipnQZRxDvoXAWRW4gT/UKqmJrsZp/CgmISo/yx7d3Y+Otk2mZHPmi8=,iv:jPJ3jL7heD721vNnGveNUNdOOwJngCFFbaKHxQxwu1w=,tag:EX/SqAJa9H1KMUnJHvwBbw==,type:comment] +#ENC[AES256_GCM,data:2QAMIK1AD8iEVsBl/tEiWAAjjpMzjvnVpoIa8h60KSCEsU8nycqndOPCLq3BOJGK0a5qITm0,iv:HOJ0tFMEY+99aDXdWjiHLXhpssSEMuMhby/n2W/0HqA=,tag:bEZ+IruPQYNj8rJXn3kbvA==,type:comment] +cloudflare: + api_token: ENC[AES256_GCM,data:ZkiVQeVFHQ==,iv:402yjlUkamfzgAqMQCChR+ui4nsA625GidVIwCOc8bM=,tag:xErz+vXV8en2c3WdHfqUsg==,type:str] + email: ENC[AES256_GCM,data:AnI4i1ar70FvyLzVqiElJTbZ6V12Tw==,iv:VYoK2Q2XmleP2SV9Axy8JPTrPeLjnJBkhaXVuCWGUtA=,tag:uxB9JQJWUwoIQ1QtpbvT8Q==,type:str] +#ENC[AES256_GCM,data:qcSPXWftLd3ojT2kQrqsZFuIzRSk7otMj+DA945UYvrut1O6mjYrzKwf/IyHUmlaDFh7kenPXgGDwm5VU9w=,iv:wRGpS4aeMO9tpF4vHE6sKMt1LA9YcLW8+G7VBWwYMOo=,tag:VEDXurG64aT43pi0lKLN1w==,type:comment] +env: + domain_name: ENC[AES256_GCM,data:sGpnauqZ2LSY+Hf34eA=,iv:V1OOAo9zoEAkXDLL2la6DF+FoCj4Lzqg88dbHHSqcXs=,tag:C+0yaNo/TwAtym7NSxNnyA==,type:str] +#ENC[AES256_GCM,data:IYmlxtKW06u6orlQii4IfB45O88ofznUvuuzYt0=,iv:YdDbHxqG/Nd9CF9l/BBMEO28VYnTiKvkdXxTbMJjRG8=,tag:y0rADtZhmdYZjiax9YvJzg==,type:comment] +yubico: + id: ENC[AES256_GCM,data:n80pw3A=,iv:pS/T3JGbVQkmYJ6EnwcdITe9J8knVBJiEn8njxPzAcM=,tag:gwg5pl6ugfBH4qwpcr1cjA==,type:int] + secret_key: ENC[AES256_GCM,data:kax8+XHJwpqFtRdKpkRR5sFhsKawlT7Ru92Umw==,iv:wSs4wdAkHyacKUmIxGfn8KDv1A8yW6E+0eBuXnOzhMA=,tag:Y6Om1OShD6s3dBALseN/qQ==,type:str] +#ENC[AES256_GCM,data:Zwum1QmpeQUb4PIxdqY=,iv:stOFFRpaR+kHIfADKS/o//K1+oQ+Y9ANNp5LbrbgW9c=,tag:hUdnj2menajZhM7yuRs0aQ==,type:comment] +tailscale: + auth_key: ENC[AES256_GCM,data:lIT80TrYfqMa8k6wsxC5BV6sBg6PCw5+AJaUtMhfJuXTIOz48PZKpCFq5z76TenpGpYT1vdqfCGd8Z1UfA==,iv:5LCWydaBX0ap5VScmjSm/QLtkeYy7u0ImVXoaY8URZs=,tag:dZV4s026eS4ME68ET+JxGw==,type:str] +#ENC[AES256_GCM,data:TBtQO7kI+rfcy2XlpYCIAkviKS0=,iv:JjLLJqDMFmHtrqgIH9xVlJ6gbeFT7g74kFL8nZH+nCk=,tag:rUpKWnstKtqbJbGLk9dQfw==,type:comment] +vrising_server_name: ENC[AES256_GCM,data:guRSn4xsGFJ0,iv:spCO2OuFr2JmFL+qboq2dwrpxb7KufxtscZI8/3r9SQ=,tag:qbFV4IIiFmEQW72So6pm7A==,type:str] +valheim_server_name: ENC[AES256_GCM,data:PJV694YqSnOkBw==,iv:yIjgunzkiVdO1pUuAOtKcRI2zhBSb2sfDfM5WrPsVa8=,tag:I18ugPusdBoADlSxYzIYNw==,type:str] +example_key: ENC[AES256_GCM,data:RPKzGyhQVMt53UIrbg==,iv:WdJEIrcLjqwyaEiXAOGoGihp0tgr3P0j+coQThRSAqM=,tag:efPXuh06+ZEyRAY6M8O6Vg==,type:str] +#ENC[AES256_GCM,data:hwNzDeFecGqtr1gCdxQ2Dg==,iv:fvPKS3tH5i+HdJhGxJz7Bf0nM/DZDqGYFy23/CTQq14=,tag:ieLl2TJuIj0mPzAHlZeWKw==,type:comment] +example_array: + - ENC[AES256_GCM,data:Wh1JeEYh5XIXqxCi/kc=,iv:3MH0nBTXkYWSf2FTSJAelSR0jPHhsp0AEPH3bq1v6WM=,tag:pGs/aD013fzjgX1mzFWSeQ==,type:str] + - ENC[AES256_GCM,data:0mIilx8XdDOg5oRxcrA=,iv:Tm6E3M8hi3HqTxO/vFO3GVlZ8IgUKjAliYbHwh4SEqw=,tag:g9u7zaBENVdcloWpj6jxBg==,type:str] +example_number: ENC[AES256_GCM,data:5M+hN39uq5hn7A==,iv:vxWdPRafSZ4LYKgjDK8hrqwb7mMjLDxf7/mcb9Fe4r8=,tag:YmTtnwCcnX+xVs09XFLQfA==,type:float] +example_booleans: + - ENC[AES256_GCM,data:AtfqPA==,iv:/Hsubc6st3Htaidi634RAndd9Rl2Ldetzm+YfZ2Vu0o=,tag:TqC6nn7cAWffzuWk0e2tCw==,type:bool] + - ENC[AES256_GCM,data:nkbswos=,iv:FBM0yr8MdotAWwxyD6aHhYPjINDeJ5Yu3PRQAg6ey/8=,tag:oCgE9qJHRNLDboO80dOjgw==,type:bool] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1mv8xtvkuuw3hphq5ytaekz7p8a4kht79uajyhy534uy9e5472fhqj5zpxu + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5cGxrQkpqTGJiaGNtenVG + Y2JhVVpDenhuS050SU9hald0RlRRdGpIK3owCkxSNVAzTVNlbmNGSjNZRVlYb3E3 + RVM0ZUVmNkJDRW1NcFpzcjR3QndTaGcKLS0tIElUSCsyQmF1cW52UnVsQlZVT1E0 + OUNLVk1uNWJNbUNRS1d0Q3FIYXFTZGcKRRK5AO8fQ835zNUDoseBAMPEIxlmAxXT + kv82umpkOyAKQe4opDrxdaJQwoT4nYqdr26ZXCEhajNo1sit9j1z/g== + -----END AGE ENCRYPTED FILE----- + - recipient: age148yre4vaxp6lm59rft24te46szawqyguf8znkrtpq7ud8tpteauqxkwyjl + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBmcUVsQU9MNHExd0QyWlZ2 + eVVFd1h4WXJyb0lERFFFbWlqQzFGUFJMT3lJCk1iNXRlVTJjaVBjNjB2LzRIcUdr + dk01QU1hbXZwSk50SXhyWlY3WTM4SEEKLS0tIE95eDEydkExVkU1RUNkVUh0TnU4 + cGpKVCt3dnVOcTYycDNGeVNFWTQvM28KNbvMhnu/kee2lvEqzTeg7708H+HwxSlD + hR4rWnf/lvA66DIFP7RQN0neouC3mD71irlhAYTWV9h3J9/0z/De1A== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-06-02T20:31:13Z" + mac: ENC[AES256_GCM,data:YaTn5x0jBvM9Yjj53IClYX11zIYZlrp95IbljXX3E5GJApTL4Mkigv1sPJXwq4jJ67JCQL3bdmLMyvWDfuLd1deVtG1LXD4NFYxFaeUXWgBfPs2IW3l/JakU6kliluZRwe5hwhCNIb/+7t9948HLq5MDIaLU2PDeASK/wySOYno=,iv:3D4o66NrUlxFagO80LSyei8BsKyb6dYN75eHs/MhOpw=,tag:3oNBSmZwGkv8MJduv4Sr8w==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.2 diff --git a/users/jay/default.nix b/users/jay/default.nix new file mode 100644 index 0000000..d91cd38 --- /dev/null +++ b/users/jay/default.nix @@ -0,0 +1,16 @@ +{ pkgs, lib, ... }: +{ + users.users.jay = { + home = + if pkgs.stdenv.isLinux then + lib.mkDefault "/home/jay" + else if pkgs.stdenv.isDarwin then + lib.mkDefault "/Users/jay" + else + abort "Unsupported OS"; + } // lib.optionalAttrs pkgs.stdenv.isLinux { + isNormalUser = true; + extraGroups = [ "networkmanager" "wheel" ]; + # hashedPassword = ""; + }; +} diff --git a/users/jay/home.nix b/users/jay/home.nix new file mode 100644 index 0000000..2b8f6d0 --- /dev/null +++ b/users/jay/home.nix @@ -0,0 +1,68 @@ +{ pkgs, lib, ... }: +{ + # NOTE: This file contains options that resolve under home-manager.users. + home.stateVersion = "25.05"; + + home.sessionVariables = { + EDITOR = "hx"; + }; + home = { + username = "jay"; + homeDirectory = + if pkgs.stdenv.isLinux then + lib.mkDefault "/home/jay" + else if pkgs.stdenv.isDarwin then + lib.mkDefault "/Users/jay" + else + abort "Unsupported OS"; + }; + home.packages = with pkgs; [ ] + # linux only + # TODO: Add a test for linux + desktop environment + ++ (lib.optionals pkgs.stdenv.isLinux [ + tree + cfspeedtest + ripgrep + helix + nil + ]) + # linux + desktop manager + #++ (lib.optionals (pkgs.stdenv.isLinux && osConfig.services.desktopManager.enabled != null) + #[ + # firefox + #]) + # darwin only + ++ (lib.optionals pkgs.stdenv.isDarwin [ + cfspeedtest + ripgrep + ]); + + programs.fish.enable = true; + # TODO: Get that working again. + #users.users.jml.shell = pkgs.fish; + + programs = { + bat.enable = true; + fzf.enable = true; + jq.enable = true; + btop.enable = true; + }; + + programs.git = { + enable = true; + userName = "Jay Looney"; + userEmail = "jay.m.looney@gmail.com"; + aliases = { + ol = "log --oneline"; + }; + ignores = [ "*~" "*.swp" ]; + extraConfig = { + push.default = "simple"; + credential.helper = "cache --timeout=7200"; + init.defaultBranch = "main"; + log.decorate = "full"; + log.date = "iso"; + merge.conflictStyle = "diff3"; + }; + }; +} From 5981f4a023ec13b5a374e1be2af01c7b6ab1ad76 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Sun, 2 Nov 2025 10:10:28 -0600 Subject: [PATCH 04/30] feat: add gitignore for `result/` dirs --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f295f42 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +result +result-* \ No newline at end of file From 836a31c11901a1c49b2c99803449ebb23b867d8e Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Thu, 6 Nov 2025 00:37:26 -0600 Subject: [PATCH 05/30] feat: Add CMake3 overlays to keep game emulation software working. --- overlays/default.nix | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 overlays/default.nix diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..f981c72 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,40 @@ +{ nixpkgs }: + let + fixCmake = pkg: pkg.overrideAttrs (old: { + cmakeFlakes = (old.cmakeFlags or []) ++ [ + (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") + ]; + }); + cmake3Overlay = final: prev: + nixpkgs.lib.mapAttrs ( + n: pkg: + pkg.overrideAttrs (old: { + cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; + }) + ) { + inherit (prev) hpipm; + }; + libretroCmake3Overlay = final: prev: { + libretro = prev.libretro // { + thepowdertoy = prev.libretro.thepowdertoy.overrideAttrs(old: { + cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; + }); + + tic80 = prev.libretro.tic80.overrideAttrs(old: { + cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; + }); + + citra = prev.libretro.citra.overrideAttrs(old: { + cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; + }); + + dolphin = prev.libretro.dolphin.overrideAttrs(old: { + cmakeFlags = old.cmakeFlags or [ ] ++ [ (nixpkgs.lib.cmakeFeature "CMAKE_POLICY_VERSION_MINIMUM" "3.10") ]; + }); + }; + }; +in +[ + cmake3Overlay + libretroCmake3Overlay +] From fa5323584250be24b47236eb2875689ab735a3fb Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Thu, 6 Nov 2025 00:39:15 -0600 Subject: [PATCH 06/30] feat: Add stylix and expose mkSystem via 'lib' --- flake.lock | 30 +++++++++++++++--------------- flake.nix | 10 ++++++++-- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/flake.lock b/flake.lock index a50ca1f..6886548 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1757508292, - "narHash": "sha256-7lVWL5bC6xBIMWWDal41LlGAG+9u2zUorqo3QCUL4p4=", + "lastModified": 1758287904, + "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", "owner": "nix-community", "repo": "disko", - "rev": "146f45bee02b8bd88812cfce6ffc0f933788875a", + "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", "type": "github" }, "original": { @@ -101,11 +101,11 @@ ] }, "locked": { - "lastModified": 1749499854, - "narHash": "sha256-V1BgwiX8NjbRreU6LC2EzmuqFSQAHhoSeNlYJyZ40NE=", + "lastModified": 1760130406, + "narHash": "sha256-GKMwBaFRw/C1p1VtjDz4DyhyzjKUWyi1K50bh8lgA2E=", "owner": "nix-community", "repo": "home-manager", - "rev": "1df816c407d3a5090c8496c9b00170af7891f021", + "rev": "d305eece827a3fe317a2d70138f53feccaf890a1", "type": "github" }, "original": { @@ -142,11 +142,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1749195551, - "narHash": "sha256-W5GKQHgunda/OP9sbKENBZhMBDNu2QahoIPwnsF6CeM=", + "lastModified": 1760106635, + "narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "4602f7e1d3f197b3cb540d5accf5669121629628", + "rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", "type": "github" }, "original": { @@ -157,11 +157,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1749285348, - "narHash": "sha256-frdhQvPbmDYaScPFiCnfdh3B/Vh81Uuoo0w5TkWmmjU=", + "lastModified": 1760038930, + "narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=", "owner": "nixos", "repo": "nixpkgs", - "rev": "3e3afe5174c561dee0df6f2c2b2236990146329f", + "rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3", "type": "github" }, "original": { @@ -252,11 +252,11 @@ ] }, "locked": { - "lastModified": 1747603214, - "narHash": "sha256-lAblXm0VwifYCJ/ILPXJwlz0qNY07DDYdLD+9H+Wc8o=", + "lastModified": 1759635238, + "narHash": "sha256-UvzKi02LMFP74csFfwLPAZ0mrE7k6EiYaKecplyX9Qk=", "owner": "Mic92", "repo": "sops-nix", - "rev": "8d215e1c981be3aa37e47aeabd4e61bb069548fd", + "rev": "6e5a38e08a2c31ae687504196a230ae00ea95133", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b4a67f8..57fbeb6 100644 --- a/flake.nix +++ b/flake.nix @@ -11,15 +11,20 @@ sops-nix.inputs.nixpkgs.follows = "nixpkgs"; disko.url = "github:nix-community/disko"; disko.inputs.nixpkgs.follows = "nixpkgs"; + stylix.url = "github:nix-community/stylix"; + stylix.inputs.nixpkgs.follows = "nixpkgs"; }; # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument - outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, ...}: + outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, stylix, ...}: let mkSystem = (import ./lib { inherit nixpkgs home-manager inputs; }).mkSystem; in { + lib = { + mkSystem = mkSystem; + }; # NOTE: Run `nix flake show` to see what this flake has to offer. # TODO: Enable automated formatting with something like numtide/treefmt-nix nixosConfigurations = { @@ -40,7 +45,8 @@ users = [ "jml" ]; - extraModules = []; + #extraModules = [ (import ./overlays) ]; + extraModules = [ stylix.nixosModules.stylix ]; }; # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` # https://github.com/nix-community/nixos-generators From 2d3168d438d45c6e531bff6440ce1d211d8c7a80 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Sat, 8 Nov 2025 09:17:26 -0600 Subject: [PATCH 07/30] feat: remove git-agecrypt / semi-secret-vars --- .gitattributes | 1 - git-agecrypt.toml | 2 -- hosts/lithium/README.md | 29 +++++++++++++++++++---------- hosts/lithium/default.nix | 1 - hosts/lithium/semi-secret-vars.nix | 8 -------- 5 files changed, 19 insertions(+), 22 deletions(-) delete mode 100644 .gitattributes delete mode 100644 git-agecrypt.toml delete mode 100644 hosts/lithium/semi-secret-vars.nix diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 072eb55..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -hosts/lithium/semi-secret-vars.nix filter=git-agecrypt diff=git-agecrypt diff --git a/git-agecrypt.toml b/git-agecrypt.toml deleted file mode 100644 index b2ff6dc..0000000 --- a/git-agecrypt.toml +++ /dev/null @@ -1,2 +0,0 @@ -[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 index 1cdad59..a73e9e8 100644 --- a/hosts/lithium/README.md +++ b/hosts/lithium/README.md @@ -7,20 +7,29 @@ This is my primary homelab host/NAS, previously powered by TrueNAS Scale/k3s. Even with fully declarative Nix/Nixpkgs/NixOS at the end of the day there are still some actions that need to be taken manually. -- secrets configuration (both for SOPS and git-agecrypt semi-secrets) +- secrets configuration for `sops-nix` - kanidm user management - tailscale auth key - jellyfin configuration via web-ui -## Semi-Secrets +## Secrets and "Private Information" -`semi-secret-vars.nix` is using [git-agecrypt](https://github.com/vlaci/git-agecrypt) -and following a pattern I discovered here: - - https://github.com/nyawox/arcanum/blob/4629dfba1bc6d4dd2f4cf45724df81289230b61a/var/README.md - - https://github.com/vlaci/git-agecrypt +Originally I had used two providers of secrets, `sops-nix` and `git-agecrypt`, +and the reasoning for that was, with `git-agecrypt` I could directly encrypt an +entire `.nix` file, and use it to conceal an arbitrary amount of my nix config. +The #1 thing I was using it for was hiding details about the domain names that +power various services. I know that's not real security, and domains aren't +really private, but server logs prove that not including a domain in a GH repo +means you get dramatically fewer spurious requests. -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. +The reason for using `git-agecrypt` against a whole nix file like that was most +importantly because it allowed me to *just use nix variables*. Compared to the +invocationss SOPS & `sops-nix` require, it can be a lot more simple for setting +values like a domain name. -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. +Now I'm going all in on `sops-nix` as the exclusive manager of secrets, and +maintaining a separate flake which contains private nix configuration details. +There are still issues with this, and now my overall nix config is essentially +fractured between "flake-A" and "flake-B", which gives me all the same issues +that any other software project faces with that arrangement. But I dislike +using `git-agecrypt` even more than I dislike those problems. diff --git a/hosts/lithium/default.nix b/hosts/lithium/default.nix index 4a02b76..61582b1 100644 --- a/hosts/lithium/default.nix +++ b/hosts/lithium/default.nix @@ -5,7 +5,6 @@ inputs.sops-nix.nixosModules.sops ./hardware.nix ./configuration.nix - ./semi-secret-vars.nix ./services/caddy.nix ./services/tailscale.nix ./services/kanidm.nix diff --git a/hosts/lithium/semi-secret-vars.nix b/hosts/lithium/semi-secret-vars.nix deleted file mode 100644 index 1598e07..0000000 --- a/hosts/lithium/semi-secret-vars.nix +++ /dev/null @@ -1,8 +0,0 @@ -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 From dbe24af09c56652a1ad92300e90be8f0942eb33e Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Sat, 8 Nov 2025 14:04:50 -0600 Subject: [PATCH 08/30] chore: remove domain decl from lithium --- hosts/lithium/configuration.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/hosts/lithium/configuration.nix b/hosts/lithium/configuration.nix index 5023ef1..a18dc08 100644 --- a/hosts/lithium/configuration.nix +++ b/hosts/lithium/configuration.nix @@ -2,7 +2,6 @@ { sops.defaultSopsFile = ./secrets/common.yaml; networking.hostName = "lithium"; - networking.domain = config.vars.domain; environment.systemPackages = with pkgs; [ zfs ]; From 8821aafbbad1209f4b07d9276d7b5a3cebed1f54 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Mon, 10 Nov 2025 13:45:45 -0600 Subject: [PATCH 09/30] feat: add support for specialArgs to mkSystem --- lib/default.nix | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/default.nix b/lib/default.nix index 3926ed9..65ee05a 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,19 +1,32 @@ { nixpkgs, home-manager, inputs, ... }: +let + allOverlays = import (../overlays) { inherit nixpkgs; }; +in { # It's not really that I care about whether a system is a desktop system or # a server system, but moreso that I care about whether a system is headless or not. # I also care about things like if it's darwin, or wsl. + # TODO: Expand this to actually make use of extraSpecialArgs and pass special + # args to the relevant places. mkSystem = { hostname, system ? "x86_64-linux", users ? [], - extraModules ? [] + extraModules ? [], + extraSpecialArgs ? {} }: let - hostModule = import ../hosts/${hostname} { inherit inputs; }; + pkgs_with_overlays = import nixpkgs { + inherit system; + overlays = allOverlays; + }; + hostModule = import ../hosts/${hostname} { + inherit inputs; + pkgs = pkgs_with_overlays; + }; userModules = map (name: import ../users/${name} { - pkgs = nixpkgs.legacyPackages.${system}; + pkgs = pkgs_with_overlays; lib = nixpkgs.lib; } ) users; @@ -26,13 +39,18 @@ name = name; value = import ../users/${name}/home.nix { username = name; - pkgs = nixpkgs.legacyPackages.${system}; + pkgs = pkgs_with_overlays; lib = nixpkgs.lib; }; }) homeUserNames); in nixpkgs.lib.nixosSystem { inherit system; + # pkgs = import inputs.nixpkgs { + # inherit system; + # overlays = allOverlays; + # config = { allowUnfree = true; nvidia.acceptLicense = true; }; + # }; modules = [ hostModule ] ++ userModules ++ extraModules @@ -43,5 +61,8 @@ home-manager.users = homeUsers; } ] else []); + specialArgs = { + inherit inputs hostname; + } // extraSpecialArgs; }; } From cfb0a9930620ae0e72dc8d8d362d6e9d5973c21d Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Mon, 10 Nov 2025 13:50:58 -0600 Subject: [PATCH 10/30] chore: update titanium game-emulation --- hosts/titanium/game-emulation.nix | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hosts/titanium/game-emulation.nix b/hosts/titanium/game-emulation.nix index 28b6c99..b970492 100644 --- a/hosts/titanium/game-emulation.nix +++ b/hosts/titanium/game-emulation.nix @@ -17,7 +17,7 @@ let mgba # GameBoy / Color / Advance melonds # Nintendo DS citra # Nintendo 3DS - + # Sony swanstation #duckstation # PlayStation @@ -35,11 +35,13 @@ in { environment.systemPackages = [ retroarchWithCores + #pkgs.retroarch-full #pkgs.emulationstation-de pkgs.gnome-bluetooth ]; hardware.xone.enable = true; # Xbox Controller Driver + hardware.xpadneo.enable = true; # Xbox Controller Driver hardware.enableAllFirmware = true; hardware.bluetooth = { enable = true; From f061c20021f142f8a450c4168dcca3adef38f16b Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Mon, 10 Nov 2025 13:58:46 -0600 Subject: [PATCH 11/30] chore: titanium snapshot --- flake.lock | 369 ++++++++++++++++++++++++++---- flake.nix | 2 +- hosts/titanium/README.md | 20 ++ hosts/titanium/configuration.nix | 2 +- hosts/titanium/default.nix | 30 ++- hosts/titanium/hardware.nix | 34 +-- hosts/titanium/secure-boot.nix | 3 +- modules/nixos/desktop/calibre.nix | 15 +- modules/nixos/desktop/default.nix | 8 +- modules/nixos/gaming.nix | 33 +-- users/jml/home.nix | 165 ++++++++++++- 11 files changed, 579 insertions(+), 102 deletions(-) create mode 100644 hosts/titanium/README.md diff --git a/flake.lock b/flake.lock index 6886548..87bf043 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,80 @@ { "nodes": { + "base16": { + "inputs": { + "fromYaml": "fromYaml" + }, + "locked": { + "lastModified": 1755819240, + "narHash": "sha256-qcMhnL7aGAuFuutH4rq9fvAhCpJWVHLcHVZLtPctPlo=", + "owner": "SenchoPens", + "repo": "base16.nix", + "rev": "75ed5e5e3fce37df22e49125181fa37899c3ccd6", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "base16.nix", + "type": "github" + } + }, + "base16-fish": { + "flake": false, + "locked": { + "lastModified": 1754405784, + "narHash": "sha256-l9xHIy+85FN+bEo6yquq2IjD1rSg9fjfjpyGP1W8YXo=", + "owner": "tomyun", + "repo": "base16-fish", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", + "type": "github" + }, + "original": { + "owner": "tomyun", + "repo": "base16-fish", + "rev": "23ae20a0093dca0d7b39d76ba2401af0ccf9c561", + "type": "github" + } + }, + "base16-helix": { + "flake": false, + "locked": { + "lastModified": 1752979451, + "narHash": "sha256-0CQM+FkYy0fOO/sMGhOoNL80ftsAzYCg9VhIrodqusM=", + "owner": "tinted-theming", + "repo": "base16-helix", + "rev": "27cf1e66e50abc622fb76a3019012dc07c678fac", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-helix", + "type": "github" + } + }, + "base16-vim": { + "flake": false, + "locked": { + "lastModified": 1732806396, + "narHash": "sha256-e0bpPySdJf0F68Ndanwm+KWHgQiZ0s7liLhvJSWDNsA=", + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-vim", + "rev": "577fe8125d74ff456cf942c733a85d769afe58b7", + "type": "github" + } + }, "crane": { "locked": { - "lastModified": 1731098351, - "narHash": "sha256-HQkYvKvaLQqNa10KEFGgWHfMAbWBfFp+4cAgkut+NNE=", + "lastModified": 1754269165, + "narHash": "sha256-0tcS8FHd4QjbCVoxN9jI+PjHgA4vc/IjkUSp+N3zy0U=", "owner": "ipetkov", "repo": "crane", - "rev": "ef80ead953c1b28316cc3f8613904edc2eb90c28", + "rev": "444e81206df3f7d92780680e45858e31d2f07a08", "type": "github" }, "original": { @@ -22,11 +90,11 @@ ] }, "locked": { - "lastModified": 1758287904, - "narHash": "sha256-IGmaEf3Do8o5Cwp1kXBN1wQmZwQN3NLfq5t4nHtVtcU=", + "lastModified": 1762276996, + "narHash": "sha256-TtcPgPmp2f0FAnc+DMEw4ardEgv1SGNR3/WFGH0N19M=", "owner": "nix-community", "repo": "disko", - "rev": "67ff9807dd148e704baadbd4fd783b54282ca627", + "rev": "af087d076d3860760b3323f6b583f4d828c1ac17", "type": "github" }, "original": { @@ -35,14 +103,30 @@ "type": "github" } }, + "firefox-gnome-theme": { + "flake": false, + "locked": { + "lastModified": 1758112371, + "narHash": "sha256-lizRM2pj6PHrR25yimjyFn04OS4wcdbc38DCdBVa2rk=", + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "rev": "0909cfe4a2af8d358ad13b20246a350e14c2473d", + "type": "github" + }, + "original": { + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", "owner": "edolstra", "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", "type": "github" }, "original": { @@ -59,11 +143,11 @@ ] }, "locked": { - "lastModified": 1730504689, - "narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=", + "lastModified": 1754091436, + "narHash": "sha256-XKqDMN1/Qj1DKivQvscI4vmHfDfvYR2pfuFOJiCeewM=", "owner": "hercules-ci", "repo": "flake-parts", - "rev": "506278e768c2a08bec68eb62932193e341f55c90", + "rev": "67df8c627c2c39c41dbec76a1f201929929ab0bd", "type": "github" }, "original": { @@ -72,6 +156,43 @@ "type": "github" } }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "stylix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1756770412, + "narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "4524271976b625a4a605beefd893f270620fd751", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "fromYaml": { + "flake": false, + "locked": { + "lastModified": 1731966426, + "narHash": "sha256-lq95WydhbUTWig/JpqiB7oViTcHFP8Lv41IGtayokA8=", + "owner": "SenchoPens", + "repo": "fromYaml", + "rev": "106af9e2f715e2d828df706c386a685698f3223b", + "type": "github" + }, + "original": { + "owner": "SenchoPens", + "repo": "fromYaml", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -94,6 +215,23 @@ "type": "github" } }, + "gnome-shell": { + "flake": false, + "locked": { + "lastModified": 1748186689, + "narHash": "sha256-UaD7Y9f8iuLBMGHXeJlRu6U1Ggw5B9JnkFs3enZlap0=", + "owner": "GNOME", + "repo": "gnome-shell", + "rev": "8c88f917db0f1f0d80fa55206c863d3746fa18d0", + "type": "github" + }, + "original": { + "owner": "GNOME", + "ref": "48.2", + "repo": "gnome-shell", + "type": "github" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -101,11 +239,11 @@ ] }, "locked": { - "lastModified": 1760130406, - "narHash": "sha256-GKMwBaFRw/C1p1VtjDz4DyhyzjKUWyi1K50bh8lgA2E=", + "lastModified": 1762787259, + "narHash": "sha256-t2U/GLLXHa2+kJkwnFNRVc2fEJ/lUfyZXBE5iKzJdcs=", "owner": "nix-community", "repo": "home-manager", - "rev": "d305eece827a3fe317a2d70138f53feccaf890a1", + "rev": "37a3d97f2873e0f68711117c34d04b7c7ead8f4e", "type": "github" }, "original": { @@ -126,27 +264,27 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1737639419, - "narHash": "sha256-AEEDktApTEZ5PZXNDkry2YV2k6t0dTgLPEmAZbnigXU=", + "lastModified": 1762205063, + "narHash": "sha256-If6vQ+KvtKs3ARBO9G3l+4wFSCYtRBrwX1z+I+B61wQ=", "owner": "nix-community", "repo": "lanzaboote", - "rev": "a65905a09e2c43ff63be8c0e86a93712361f871e", + "rev": "88b8a563ff5704f4e8d8e5118fb911fa2110ca05", "type": "github" }, "original": { "owner": "nix-community", - "ref": "v0.4.2", + "ref": "v0.4.3", "repo": "lanzaboote", "type": "github" } }, "nixos-hardware": { "locked": { - "lastModified": 1760106635, - "narHash": "sha256-2GoxVaKWTHBxRoeUYSjv0AfSOx4qw5CWSFz2b+VolKU=", + "lastModified": 1762463231, + "narHash": "sha256-hv1mG5j5PTbnWbtHHomzTus77pIxsc4x8VrMjc7+/YE=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "9ed85f8afebf2b7478f25db0a98d0e782c0ed903", + "rev": "52113c4f5cfd1e823001310e56d9c8d0699a6226", "type": "github" }, "original": { @@ -157,11 +295,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1760038930, - "narHash": "sha256-Oncbh0UmHjSlxO7ErQDM3KM0A5/Znfofj2BSzlHLeVw=", + "lastModified": 1762596750, + "narHash": "sha256-rXXuz51Bq7DHBlfIjN7jO8Bu3du5TV+3DSADBX7/9YQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "0b4defa2584313f3b781240b29d61f6f9f7e0df3", + "rev": "b6a8526db03f735b89dd5ff348f53f752e7ddc8e", "type": "github" }, "original": { @@ -171,19 +309,28 @@ "type": "github" } }, - "nixpkgs-stable": { + "nur": { + "inputs": { + "flake-parts": [ + "stylix", + "flake-parts" + ], + "nixpkgs": [ + "stylix", + "nixpkgs" + ] + }, "locked": { - "lastModified": 1730741070, - "narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "d063c1dd113c91ab27959ba540c0d9753409edf3", + "lastModified": 1758998580, + "narHash": "sha256-VLx0z396gDCGSiowLMFz5XRO/XuNV+4EnDYjdJhHvUk=", + "owner": "nix-community", + "repo": "NUR", + "rev": "ba8d9c98f5f4630bcb0e815ab456afd90c930728", "type": "github" }, "original": { - "owner": "NixOS", - "ref": "nixos-24.05", - "repo": "nixpkgs", + "owner": "nix-community", + "repo": "NUR", "type": "github" } }, @@ -197,15 +344,14 @@ "nixpkgs": [ "lanzaboote", "nixpkgs" - ], - "nixpkgs-stable": "nixpkgs-stable" + ] }, "locked": { - "lastModified": 1731363552, - "narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=", + "lastModified": 1750779888, + "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=", "owner": "cachix", "repo": "pre-commit-hooks.nix", - "rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0", + "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d", "type": "github" }, "original": { @@ -221,7 +367,8 @@ "lanzaboote": "lanzaboote", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", - "sops-nix": "sops-nix" + "sops-nix": "sops-nix", + "stylix": "stylix" } }, "rust-overlay": { @@ -232,11 +379,11 @@ ] }, "locked": { - "lastModified": 1731897198, - "narHash": "sha256-Ou7vLETSKwmE/HRQz4cImXXJBr/k9gp4J4z/PF8LzTE=", + "lastModified": 1761791894, + "narHash": "sha256-myRIDh+PxaREz+z9LzbqBJF+SnTFJwkthKDX9zMyddY=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "0be641045af6d8666c11c2c40e45ffc9667839b5", + "rev": "59c45eb69d9222a4362673141e00ff77842cd219", "type": "github" }, "original": { @@ -252,11 +399,11 @@ ] }, "locked": { - "lastModified": 1759635238, - "narHash": "sha256-UvzKi02LMFP74csFfwLPAZ0mrE7k6EiYaKecplyX9Qk=", + "lastModified": 1762659808, + "narHash": "sha256-2Kv2mANf+FRisqhpfeZ8j9firBxb23ZvEXwdcunbpGI=", "owner": "Mic92", "repo": "sops-nix", - "rev": "6e5a38e08a2c31ae687504196a230ae00ea95133", + "rev": "524312bc62e3f34bd9231a2f66622663d3355133", "type": "github" }, "original": { @@ -264,6 +411,136 @@ "repo": "sops-nix", "type": "github" } + }, + "stylix": { + "inputs": { + "base16": "base16", + "base16-fish": "base16-fish", + "base16-helix": "base16-helix", + "base16-vim": "base16-vim", + "firefox-gnome-theme": "firefox-gnome-theme", + "flake-parts": "flake-parts_2", + "gnome-shell": "gnome-shell", + "nixpkgs": [ + "nixpkgs" + ], + "nur": "nur", + "systems": "systems", + "tinted-foot": "tinted-foot", + "tinted-kitty": "tinted-kitty", + "tinted-schemes": "tinted-schemes", + "tinted-tmux": "tinted-tmux", + "tinted-zed": "tinted-zed" + }, + "locked": { + "lastModified": 1762264356, + "narHash": "sha256-QVfC53Ri+8n3e7Ujx9kq6all3+TLBRRPRnc6No5qY5w=", + "owner": "nix-community", + "repo": "stylix", + "rev": "647bb8dd96a206a1b79c4fd714affc88b409e10b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "stylix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "tinted-foot": { + "flake": false, + "locked": { + "lastModified": 1726913040, + "narHash": "sha256-+eDZPkw7efMNUf3/Pv0EmsidqdwNJ1TaOum6k7lngDQ=", + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-foot", + "rev": "fd1b924b6c45c3e4465e8a849e67ea82933fcbe4", + "type": "github" + } + }, + "tinted-kitty": { + "flake": false, + "locked": { + "lastModified": 1735730497, + "narHash": "sha256-4KtB+FiUzIeK/4aHCKce3V9HwRvYaxX+F1edUrfgzb8=", + "owner": "tinted-theming", + "repo": "tinted-kitty", + "rev": "de6f888497f2c6b2279361bfc790f164bfd0f3fa", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-kitty", + "type": "github" + } + }, + "tinted-schemes": { + "flake": false, + "locked": { + "lastModified": 1757716333, + "narHash": "sha256-d4km8W7w2zCUEmPAPUoLk1NlYrGODuVa3P7St+UrqkM=", + "owner": "tinted-theming", + "repo": "schemes", + "rev": "317a5e10c35825a6c905d912e480dfe8e71c7559", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "schemes", + "type": "github" + } + }, + "tinted-tmux": { + "flake": false, + "locked": { + "lastModified": 1757811970, + "narHash": "sha256-n5ZJgmzGZXOD9pZdAl1OnBu3PIqD+X3vEBUGbTi4JiI=", + "owner": "tinted-theming", + "repo": "tinted-tmux", + "rev": "d217ba31c846006e9e0ae70775b0ee0f00aa6b1e", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "tinted-tmux", + "type": "github" + } + }, + "tinted-zed": { + "flake": false, + "locked": { + "lastModified": 1757811247, + "narHash": "sha256-4EFOUyLj85NRL3OacHoLGEo0wjiRJzfsXtR4CZWAn6w=", + "owner": "tinted-theming", + "repo": "base16-zed", + "rev": "824fe0aacf82b3c26690d14e8d2cedd56e18404e", + "type": "github" + }, + "original": { + "owner": "tinted-theming", + "repo": "base16-zed", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 57fbeb6..c0586ac 100644 --- a/flake.nix +++ b/flake.nix @@ -5,7 +5,7 @@ nixos-hardware.url = "github:nixos/nixos-hardware"; home-manager.url = "github:nix-community/home-manager"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; - lanzaboote.url = "github:nix-community/lanzaboote/v0.4.2"; + lanzaboote.url = "github:nix-community/lanzaboote/v0.4.3"; lanzaboote.inputs.nixpkgs.follows = "nixpkgs"; sops-nix.url = "github:Mic92/sops-nix"; sops-nix.inputs.nixpkgs.follows = "nixpkgs"; diff --git a/hosts/titanium/README.md b/hosts/titanium/README.md new file mode 100644 index 0000000..51e0057 --- /dev/null +++ b/hosts/titanium/README.md @@ -0,0 +1,20 @@ +# titanium + +This is my primary workstation / gaming pc. +It will generally be the most out of sync with the repo, as there will be a lot +of software I experiment with, which I simply forget to commit here. Everything +of importance will find it's way to this repo. + +## Non-Deterministic Post-Install Steps + +Rearrange Monitors in Gnome Display Settings + +Use a fido2 key (YubiKey) to decrypt luks +```bash +sudo -E -s systemd-cryptenroll --fido2-device=auto /dev/disk/by-partlabel/disk-main-luks +``` + +## Installing Remotely +```bash +nix run github:nix-community/nixos-anywhere -- --flake .#titanium +``` diff --git a/hosts/titanium/configuration.nix b/hosts/titanium/configuration.nix index ea4519f..acc06b8 100644 --- a/hosts/titanium/configuration.nix +++ b/hosts/titanium/configuration.nix @@ -16,5 +16,5 @@ services.openssh.enable = true; services.tailscale.enable = true; networking.firewall.trustedInterfaces = [ "tailscale0" ]; - system.stateVersion = "25.05"; + system.stateVersion = "25.11"; } diff --git a/hosts/titanium/default.nix b/hosts/titanium/default.nix index 23d9076..8cece0c 100644 --- a/hosts/titanium/default.nix +++ b/hosts/titanium/default.nix @@ -1,17 +1,41 @@ -{ inputs, ... }: +{ inputs, pkgs, ... }: +let + nixpkgs = inputs.nixpkgs; +in { nixpkgs.config.allowUnfree = true; + nixpkgs.overlays = (import (../../overlays) {inherit nixpkgs;}); imports = [ ../../modules/nixos/base.nix ../../modules/nixos/audio.nix - ../../modules/nixos/desktop.nix + ../../modules/nixos/desktop ../../modules/nixos/gaming.nix inputs.nixos-hardware.nixosModules.asus-rog-strix-x570e - #./hardware.nix + ./hardware.nix ./configuration.nix ./nvidia.nix + inputs.lanzaboote.nixosModules.lanzaboote ./secure-boot.nix inputs.disko.nixosModules.disko ./disko.nix + ./game-emulation.nix + #./meetings.nix ]; + + zw.gaming.enable = true; + + stylix = { + #enable = true; + # catppuccin-mocha + base16Scheme = "${pkgs.base16-schemes}/share/themes/catppuccin-mocha.yaml"; + # image = ./path.png; polarity = "dark"; # /etc/stylix/palette.html + # TODO: Add Atkinson Hyperlegible Next, Mono, and also a good Serif font. + # https://search.nixos.org/packages?channel=unstable&show=atkinson-hyperlegible-next&query=atkinson + # fonts = { + # serif = {}; + # sansSerif = {}; + # monospace = {}; + # emoji = {}; + # }; + }; } diff --git a/hosts/titanium/hardware.nix b/hosts/titanium/hardware.nix index a2a8362..4204ed2 100644 --- a/hosts/titanium/hardware.nix +++ b/hosts/titanium/hardware.nix @@ -8,41 +8,43 @@ [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; + boot.initrd.systemd.enable = true; + #boot.initrd.luks.devices.FOO.crypttabExtraOpts = ["fido2-device=auto"]; + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; boot.extraModulePackages = [ ]; fileSystems."/" = - { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; + { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; fsType = "btrfs"; options = [ "subvol=root" ]; }; - boot.initrd.luks.devices."crypted".device = "/dev/disk/by-uuid/0ccc4028-c27e-4259-ade9-a2b2081722cb"; + #boot.initrd.luks.devices."crypted".device = "/dev/disk/by-uuid/16b8ccb6-0102-4348-bb1b-d8d68bfb4d23"; + + fileSystems."/nix" = + { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; + fsType = "btrfs"; + options = [ "subvol=nix" ]; + }; fileSystems."/.swapvol" = - { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; + { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; fsType = "btrfs"; options = [ "subvol=swap" ]; }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/219D-4579"; - fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; - }; - fileSystems."/home" = - { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; + { #device = "/dev/disk/by-uuid/bac9b4de-d201-4008-9e97-3954417aab65"; fsType = "btrfs"; options = [ "subvol=home" ]; }; - fileSystems."/nix" = - { device = "/dev/disk/by-uuid/0b3de117-c34f-4cc6-81db-5b84ea46cd51"; - fsType = "btrfs"; - options = [ "subvol=nix" ]; + fileSystems."/boot" = + { #device = "/dev/disk/by-uuid/E076-75D6"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; }; swapDevices = [ ]; @@ -54,7 +56,7 @@ networking.useDHCP = lib.mkDefault true; # networking.interfaces.enp4s0.useDHCP = lib.mkDefault true; # networking.interfaces.enp5s0.useDHCP = lib.mkDefault true; - # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true; + # networking.interfaces.tailscale0.useDHCP = lib.mkDefault true; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; diff --git a/hosts/titanium/secure-boot.nix b/hosts/titanium/secure-boot.nix index 82f4d98..be6cc79 100644 --- a/hosts/titanium/secure-boot.nix +++ b/hosts/titanium/secure-boot.nix @@ -1,5 +1,4 @@ -{ pkgs, lib, inputs, ... }: { - imports = with inputs; [ lanzaboote.nixosModules.lanzaboote ]; +{ pkgs, lib, ... }: { environment.systemPackages = [ pkgs.sbctl ]; boot.loader.systemd-boot.enable = lib.mkForce false; boot.lanzaboote.enable = true; diff --git a/modules/nixos/desktop/calibre.nix b/modules/nixos/desktop/calibre.nix index e4c1c6c..bcc4cea 100644 --- a/modules/nixos/desktop/calibre.nix +++ b/modules/nixos/desktop/calibre.nix @@ -3,22 +3,15 @@ imports = []; options = { - zw-calibre = { + zw.calibre = { enable = lib.mkEnableOption "Enable Calibre"; }; }; - + config = { - config.allowUnfreePredigate = pkg: builtins.elem (lib.getName pkg) [ - "calibre" - "unrar" - ]; - + # NOTE: Without unrar support we can't open ".cbr" files. environment.systemPackages = with pkgs; [ - (calibre.override { - unrarSupport = true; - }) - unrar + calibre ]; services.udisks2.enable = true; diff --git a/modules/nixos/desktop/default.nix b/modules/nixos/desktop/default.nix index 7251a84..56e89f7 100644 --- a/modules/nixos/desktop/default.nix +++ b/modules/nixos/desktop/default.nix @@ -1,11 +1,17 @@ { pkgs, ... }: { + imports = [ + ./calibre.nix + ]; + + zw.calibre.enable = true; + environment.systemPackages = with pkgs; [ yubikey-personalization xdg-desktop-portal-gtk xdg-desktop-portal-hyprland xwayland - rofi-wayland + rofi waybar hyprpaper kitty # hyprland default term diff --git a/modules/nixos/gaming.nix b/modules/nixos/gaming.nix index 68b2946..69dcd1b 100644 --- a/modules/nixos/gaming.nix +++ b/modules/nixos/gaming.nix @@ -1,17 +1,24 @@ { config, lib, pkgs, ... }: { - environment.systemPackages = with pkgs; [ - mangohud - protonup-qt - lutris - bottles - heroic - ]; - programs.steam = { - enable = true; - remotePlay.openFirewall = true; - localNetworkGameTransfers.openFirewall = true; - protontricks.enable = true; - gamescopeSession.enable = true; + #imports = []; + options = { + zw.gaming.enable = lib.mkEnableOption "Enable Gaming"; + }; + + config = lib.mkIf config.zw.gaming.enable { + environment.systemPackages = with pkgs; [ + mangohud + protonup-qt + # lutris # TODO: Having an issue after flake update + bottles + heroic + ]; + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + localNetworkGameTransfers.openFirewall = true; + protontricks.enable = true; + gamescopeSession.enable = true; + }; }; } diff --git a/users/jml/home.nix b/users/jml/home.nix index e6170c6..a26b392 100644 --- a/users/jml/home.nix +++ b/users/jml/home.nix @@ -49,7 +49,7 @@ # Matrix Chat Apps element-desktop.enable = true; - nheko.settings = true; + #nheko.settings = true; # Additions from Windows obsidian.enable = true; @@ -144,15 +144,48 @@ }; }; + # TODO: figure out how to get config.programs..enable style + # internal references inside this file. + # There's some quirks with how this is used in lib/default.nix + programs.jujutsu = { + enable = true; + #enableFishIntegration = true; + settings = { + user = { + name = "Jay Looney"; + email = "jay.m.looney@gmail.com"; + }; + }; + }; + programs.git = { enable = true; - userName = "Jay Looney"; - userEmail = "jay.m.looney@gmail.com"; - aliases = { - ol = "log --oneline"; - }; - ignores = [ "*~" "*.swp" ]; - extraConfig = { + settings = { + user = { + name = "Jay Looney"; + email = "jay.m.looney@gmail.com"; + }; + + # Aliases Inspired by the following: + # https://joel-hanson.github.io/posts/05-useful-git-aliases-for-a-productive-workflow/ + # https://gist.github.com/mwhite/6887990 + aliases = { + la = "!git config -l | grep alias | cut -c 7-"; + s = "status -s"; + co = "checkout"; + cob = "checkout -b"; + del = "branch -D"; + ol = "log --oneline"; + + br = "branch --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(contents:subject) %(color:green)(%(committerdate:relative)) [%(authorname)]' --sort=-committerdate"; + save = "!git add -A && git commit -m 'chore: commit save point'"; + undo = "reset HEAD~1 --mixed"; + done = "!git push origin HEAD"; + lg = "!git log --pretty=format:\"%C(magenta)%h%Creset -%C(red)%d%Creset %s %C(dim green)(%cr) [%an]\" --abbrev-commit -30"; + a = "add"; + ap = "add -p"; + }; + push.default = "simple"; credential.helper = "cache --timeout=7200"; init.defaultBranch = "main"; @@ -160,7 +193,123 @@ log.date = "iso"; merge.conflictStyle = "diff3"; }; + # Cribbed from: https://github.com/gitattributes/gitattributes + attributes = [ + # Auto detect files and perform LF normalization + "* text=auto" + # Documents + "*.bibtex text diff=bibtex" + "*.doc diff=astextplain" + "*.DOC diff=astextplain" + "*.docx diff=astextplain" + "*.DOCX diff=astextplain" + "*.dot diff=astextplain" + "*.DOT diff=astextplain" + "*.pdf diff=astextplain" + "*.PDF diff=astextplain" + "*.rtf diff=astextplain" + "*.RTF diff=astextplain" + "*.md text diff=markdown" + "*.mdx text diff=markdown" + "*.tex text diff=tex" + "*.adoc text" + "*.textile text" + "*.mustache text" + "*.csv text eol=crlf" + "*.tab text" + "*.tsv text" + "*.txt text" + "*.sql text" + "*.epub diff=astextplain" + + # Graphics + "*.png binary" + "*.jpg binary" + "*.jpeg binary" + "*.gif binary" + "*.tif binary" + "*.tiff binary" + "*.ico binary" + # SVG treated as text by default. + "*.svg text" + # If you want to treat it as binary, + # use the following line instead. + # *.svg binary + "*.eps binary" + + # Scripts + "*.bash text eol=lf" + "*.fish text eol=lf" + "*.ksh text eol=lf" + "*.sh text eol=lf" + "*.zsh text eol=lf" + # These are explicitly windows files and should use crlf + "*.bat text eol=crlf" + "*.cmd text eol=crlf" + "*.ps1 text eol=crlf" + + # Serialisation + "*.json text" + "*.toml text" + "*.xml text" + "*.yaml text" + "*.yml text" + + # Archives + "*.7z binary" + "*.bz binary" + "*.bz2 binary" + "*.bzip2 binary" + "*.gz binary" + "*.lz binary" + "*.lzma binary" + "*.rar binary" + "*.tar binary" + "*.taz binary" + "*.tbz binary" + "*.tbz2 binary" + "*.tgz binary" + "*.tlz binary" + "*.txz binary" + "*.xz binary" + "*.Z binary" + "*.zip binary" + "*.zst binary" + + # Text files where line endings should be preserved + "*.patch -text" + + # Exclude files from exporting + ".gitattributes export-ignore" + ".gitignore export-ignore" + ".gitkeep export-ignore" + ]; + # TODO: Merge Gitignores from here: https://github.com/github/gitignore/tree/main/Global + ignores = [ + "*~" + "*.swp" + ]; }; + programs.emacs = { + enable = true; + # package = (pkgs.emacs30.pkgs.withPackages (epkgs: [ + # epkgs.treesit-grammars.with-grammars (grammars: [ + # grammars.tree-sitter-bash + # ]) + # epkgs.pretty-sha-path + # ])); + extraConfig = '' + (setq standard-indent 2) + ''; + }; + + programs.vscode = { + enable = true; + mutableExtensionsDir = true; # mutually exclusive to programs.vscode.profiles + profiles.default.userSettings = { + "[nix]"."editor.tabSize" = 2; + }; + }; # services.podman.enable = true; } From cccad986fe04085c9884de17147a723e3eb636fc Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Thu, 10 Jul 2025 08:53:27 -0500 Subject: [PATCH 12/30] feat: add a new laptop host (Asus Zenbook 3) --- flake.nix | 4 +++ hosts/cobalt/configuration.nix | 29 +++++++++++++++++ hosts/cobalt/default.nix | 11 +++++++ hosts/cobalt/hardware-configuration.nix | 41 +++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 hosts/cobalt/configuration.nix create mode 100644 hosts/cobalt/default.nix create mode 100644 hosts/cobalt/hardware-configuration.nix diff --git a/flake.nix b/flake.nix index c0586ac..1c2fa13 100644 --- a/flake.nix +++ b/flake.nix @@ -48,6 +48,10 @@ #extraModules = [ (import ./overlays) ]; extraModules = [ stylix.nixosModules.stylix ]; }; + cobalt = mkSystem { + hostname = "cobalt"; + users = [ "jml" ]; + }; # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` # https://github.com/nix-community/nixos-generators installIso = nixpkgs.lib.nixosSystem { diff --git a/hosts/cobalt/configuration.nix b/hosts/cobalt/configuration.nix new file mode 100644 index 0000000..bea1e3c --- /dev/null +++ b/hosts/cobalt/configuration.nix @@ -0,0 +1,29 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + networking.hostName = "cobalt"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + networking.networkmanager.enable = true; + + # Desktop stuff specific to this device + services.xserver.enable = true; + services.xserver.displayManager.lightdm.enable = true; + services.xserver.desktopManager.pantheon.enable = true; + services.xserver.xkb = { + layout = "us"; + variant = ""; + }; + + fonts.packages = with pkgs; [ + nerd-fonts.fira-code + nerd-fonts.iosevka + atkinson-hyperlegible + ]; + + + system.stateVersion = "25.05"; +} diff --git a/hosts/cobalt/default.nix b/hosts/cobalt/default.nix new file mode 100644 index 0000000..bffc73e --- /dev/null +++ b/hosts/cobalt/default.nix @@ -0,0 +1,11 @@ +{ inputs, ... }: +{ + imports = [ + ../../modules/nixos/base.nix + ../../modules/nixos/audio.nix + #../../modules/nixos/desktop.nix + # https://github.com/NixOS/nixos-hardware/blob/master/README.md#using-nix-flakes-support + ./hardware-configuration.nix + ./configuration.nix + ]; +} diff --git a/hosts/cobalt/hardware-configuration.nix b/hosts/cobalt/hardware-configuration.nix new file mode 100644 index 0000000..da7f0e2 --- /dev/null +++ b/hosts/cobalt/hardware-configuration.nix @@ -0,0 +1,41 @@ +# 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" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/959b3c06-58a2-45be-b2d6-275c489c31f8"; + fsType = "ext4"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/2EC2-D03D"; + fsType = "vfat"; + options = [ "fmask=0077" "dmask=0077" ]; + }; + + swapDevices = + [ { device = "/dev/disk/by-uuid/0239ee2a-484b-4a17-b1e9-02fd35df851f"; } + ]; + + # 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.enp0s20f0u1u3.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp2s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} From fcde6762f5872b20cdd4c982e208c57916437f47 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Thu, 11 Sep 2025 16:07:28 -0500 Subject: [PATCH 13/30] feat: include disko script for main desktop machine --- flake.nix | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index 1c2fa13..1bfd0d4 100644 --- a/flake.nix +++ b/flake.nix @@ -45,8 +45,20 @@ users = [ "jml" ]; - #extraModules = [ (import ./overlays) ]; - extraModules = [ stylix.nixosModules.stylix ]; + extraModules = [ + #(import ./overlays) + #stylix.nixosModules.stylix + { nixpkgs.config.allowUnfree = true; } + lanzaboote.nixosModules.lanzaboote + disko.nixosModules.disko + ./hosts/titanium/disko.nix + ({ pkgs, lib, ... }: { + environment.systemPackages = [ pkgs.sbctl ]; + boot.loader.systemd-boot.enable = lib.mkForce false; + boot.lanzaboote.enable = true; + boot.lanzaboote.pkiBundle = "/var/lib/sbctl"; + }) + ]; }; cobalt = mkSystem { hostname = "cobalt"; From b8cd94925e62e915ed9ffc52a2bd26d1412181b5 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 10:32:02 -0600 Subject: [PATCH 14/30] cobalt snapshot --- hosts/cobalt/README.md | 21 +++++++++++++++++++++ hosts/cobalt/default.nix | 6 ++++++ 2 files changed, 27 insertions(+) create mode 100644 hosts/cobalt/README.md diff --git a/hosts/cobalt/README.md b/hosts/cobalt/README.md new file mode 100644 index 0000000..5f1169c --- /dev/null +++ b/hosts/cobalt/README.md @@ -0,0 +1,21 @@ + +Device Specific Hardware Details` +```shell +[nix-shell:~]$ lspci -nn +00:00.0 Host bridge [0600]: Intel Corporation Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers [8086:5904] (rev 02) +00:02.0 VGA compatible controller [0300]: Intel Corporation HD Graphics 620 [8086:5916] (rev 02) +00:04.0 Signal processing controller [1180]: Intel Corporation Xeon E3-1200 v5/E3-1500 v5/6th Gen Core Processor Thermal Subsystem [8086:1903] (rev 02) +00:14.0 USB controller [0c03]: Intel Corporation Sunrise Point-LP USB 3.0 xHCI Controller [8086:9d2f] (rev 21) +00:14.2 Signal processing controller [1180]: Intel Corporation Sunrise Point-LP Thermal subsystem [8086:9d31] (rev 21) +00:15.0 Signal processing controller [1180]: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #0 [8086:9d60] (rev 21) +00:15.1 Signal processing controller [1180]: Intel Corporation Sunrise Point-LP Serial IO I2C Controller #1 [8086:9d61] (rev 21) +00:16.0 Communication controller [0780]: Intel Corporation Sunrise Point-LP CSME HECI #1 [8086:9d3a] (rev 21) +00:17.0 SATA controller [0106]: Intel Corporation Sunrise Point-LP SATA Controller [AHCI mode] [8086:9d03] (rev 21) +00:1c.0 PCI bridge [0604]: Intel Corporation Sunrise Point-LP PCI Express Root Port #1 [8086:9d10] (rev f1) +00:1c.5 PCI bridge [0604]: Intel Corporation Sunrise Point-LP PCI Express Root Port #6 [8086:9d15] (rev f1) +00:1f.0 ISA bridge [0601]: Intel Corporation Sunrise Point-LP LPC Controller [8086:9d58] (rev 21) +00:1f.2 Memory controller [0580]: Intel Corporation Sunrise Point-LP PMC [8086:9d21] (rev 21) +00:1f.3 Audio device [0403]: Intel Corporation Sunrise Point-LP HD Audio [8086:9d71] (rev 21) +00:1f.4 SMBus [0c05]: Intel Corporation Sunrise Point-LP SMBus [8086:9d23] (rev 21) +02:00.0 Network controller [0280]: Intel Corporation Wireless 8260 [8086:24f3] (rev 3a) +``` diff --git a/hosts/cobalt/default.nix b/hosts/cobalt/default.nix index bffc73e..b28af35 100644 --- a/hosts/cobalt/default.nix +++ b/hosts/cobalt/default.nix @@ -5,7 +5,13 @@ ../../modules/nixos/audio.nix #../../modules/nixos/desktop.nix # https://github.com/NixOS/nixos-hardware/blob/master/README.md#using-nix-flakes-support + # TODO: This module doesn't exist yet. + #inputs.nixos-hardware.nixosModules.asus-zenbook-ux390u + /home/jml/Workspace/nixos-hardware/asus/zenbook/ux390ua ./hardware-configuration.nix ./configuration.nix + ../../modules/nixos/gaming.nix ]; + + zw.gaming.enable = true; } From ad89d183fe1b49724f73669c054a5cf45eeafa7c Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 11:53:26 -0600 Subject: [PATCH 15/30] feat: neovim configuration with nvf --- users/jml/home.nix | 265 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 240 insertions(+), 25 deletions(-) diff --git a/users/jml/home.nix b/users/jml/home.nix index a26b392..f056c62 100644 --- a/users/jml/home.nix +++ b/users/jml/home.nix @@ -1,4 +1,10 @@ -{ username, pkgs, lib, ... }: +{ + username, + pkgs, + lib, + inputs, + ... +}: { nixpkgs.config.allowUnfree = true; # The following line is needed if I start using hyprland Home Manager Module @@ -10,8 +16,8 @@ sessionVariables = { EDITOR = "hx"; }; - - homeDirectory = + + homeDirectory = if pkgs.stdenv.isLinux then lib.mkDefault "/home/${username}" else if pkgs.stdenv.isDarwin then @@ -19,24 +25,26 @@ else abort "Unsupported OS"; }; - home.packages = with pkgs; [ ] - # linux only - # TODO: Add a test for linux + desktop environment - ++ (lib.optionals pkgs.stdenv.isLinux [ - cfspeedtest - helix - nil - ]) - # linux + desktop manager - #++ (lib.optionals (pkgs.stdenv.isLinux && osConfig.services.desktopManager.enabled != null) - #[ - # firefox - #]) - # darwin only - ++ (lib.optionals pkgs.stdenv.isDarwin [ - cfspeedtest - ripgrep - ]); + home.packages = + with pkgs; + [ ] + # linux only + # TODO: Add a test for linux + desktop environment + ++ (lib.optionals pkgs.stdenv.isLinux [ + cfspeedtest + helix + nil + ]) + # linux + desktop manager + #++ (lib.optionals (pkgs.stdenv.isLinux && osConfig.services.desktopManager.enabled != null) + #[ + # firefox + #]) + # darwin only + ++ (lib.optionals pkgs.stdenv.isDarwin [ + cfspeedtest + ripgrep + ]); programs = { fish.enable = true; @@ -100,7 +108,7 @@ Cryptomining = true; Fingerprinting = true; }; - + Homepage.StartPage = "previous-session"; FirefoxHome = { Search = true; @@ -133,12 +141,12 @@ id = 0; name = "default"; isDefault = true; - settings = { + settings = { "widget.disable-workspace-management" = true; }; search = { force = true; - default = "ddg"; # DuckDuckGo + default = "ddg"; # DuckDuckGo }; }; }; @@ -147,6 +155,7 @@ # TODO: figure out how to get config.programs..enable style # internal references inside this file. # There's some quirks with how this is used in lib/default.nix + # TODO: Use mergiraf for conflict resolution in jj too. programs.jujutsu = { enable = true; #enableFishIntegration = true; @@ -158,6 +167,8 @@ }; }; + # TODO: Configure Mergiraf + # https://mergiraf.org/introduction.html programs.git = { enable = true; settings = { @@ -191,6 +202,7 @@ init.defaultBranch = "main"; log.decorate = "full"; log.date = "iso"; + # NOTE: Initially diff3 was for me, now it's for me and mergiraf automation. merge.conflictStyle = "diff3"; }; # Cribbed from: https://github.com/gitattributes/gitattributes @@ -304,9 +316,212 @@ ''; }; + # TODO: Implement support for at least + # Nix, Python, Rust, Golang + # TODO: Sort out why TF, `.nix` files tabs are cooked in neovim rn. + # It corrects things on document save, but this line for example started with an 8-long tabstop + programs.nvf = { + enable = true; + # When using the Home-Manager Module for nvf, the settings go into the following attribute set. + # https://notashelf.github.io/nvf/index.xhtml#sec-hm-flakes + settings.vim = { + viAlias = true; + vimAlias = true; + + # TODO: For some reason spellcheck is having a very difficult time getting + # a wordlist. + #spellcheck = { + # enable = true; + # programmingWordlist.enable = true; + #}; + + lsp = { + enable = true; + formatOnSave = true; + lspkind.enable = false; + lightbulb.enable = true; + lspsaga.enable = false; + trouble.enable = true; + lspSignature.enable = false; + otter-nvim.enable = true; + nvim-docs-view.enable = true; + }; + + languages = { + enableDAP = true; + enableExtraDiagnostics = true; + enableFormat = true; + enableTreesitter = true; + + nix = { + enable = true; + lsp.enable = true; + lsp.server = "nixd"; + extraDiagnostics.enable = true; + format.enable = true; + format.type = "nixfmt"; + treesitter.enable = true; + }; + markdown.enable = true; + typst.enable = true; + + assembly.enable = true; + bash.enable = true; + clang.enable = true; + + python.enable = true; + rust = { + enable = true; + # TODO: null_ls is now deprecated. + # https://github.com/NotAShelf/nvf/issues/1175 + # https://github.com/NotAShelf/nvf/blob/main/.github/CONTRIBUTING.md + crates.enable = true; + }; + go.enable = true; + zig.enable = true; + + ts.enable = true; + html.enable = true; + css.enable = true; + sql.enable = true; + }; + + visuals = { + nvim-scrollbar.enable = true; # Configurable Visual Scrollbar (Can pair with Cursor, ALE, Diagnostics, Gitsigns, and hlslens) + nvim-web-devicons.enable = true; # Nerdfont Icons for use by other plugins + nvim-cursorline.enable = true; # Highlight Words & Lines on the cursor + cinnamon-nvim.enable = true; # Smooth Scrolling for any movement command. + fidget-nvim.enable = true; # UI for Notifications & LSP Progress Messages + + highlight-undo.enable = true; # Highlight changed text after any non-insert actions + indent-blankline.enable = true; # Indentation Guides + }; + + statusline = { + lualine = { + # Fancy Status Line + enable = true; + theme = "catppuccin"; + }; + }; + + theme = { + enable = true; + name = "catppuccin"; + style = "mocha"; + transparent = false; + }; + + autopairs.nvim-autopairs.enable = true; # Pair up ", {, (, etc. + # blink-cmp is a compiled rust binary while nvim-cmp is a pure lua plugin... + autocomplete.blink-cmp.enable = true; + # Code Snippets Engine /w support for Lua, VSCode, and SnipMate snippets. + snippets.luasnip.enable = true; + + filetree.neo-tree.enable = true; # Filesystem tree sidebar... + tabline.nvimBufferline.enable = true; # Shows buffers as tabs at the top. + treesitter.context.enable = true; + binds = { + whichKey.enable = true; # Shows your available keybindings in a popup + cheatsheet.enable = true; # Searchable in-editor cheatsheet that uses Telescope + }; + telescope.enable = true; # Fuzzy Finder, central to many other plugins. + + git = { + enable = true; + gitsigns.enable = true; # Git Info in Buffers + Gutters + gitsigns.codeActions.enable = false; + neogit.enable = true; # Interactive Git + }; + + # TODO: Consider switching to `minimap-nvim` for rust-based minimap. + # codewindow may be tightly integrated with treesitter though... + minimap.codewindow.enable = true; + dashboard.alpha.enable = true; # Greeter + notify.nvim-notify.enable = true; # Fancy Configurable Notification Manager + projects.project-nvim.enable = true; + + utility = { + ccc.enable = true; # Color Picker + diffview-nvim.enable = true; + icon-picker.enable = true; + surround.enable = true; # Change Surrounding Delimiter pairs `ysiw)` + leetcode-nvim.enable = true; # Allow solving LeetCode problems directly inside neovim + multicursors.enable = true; # Edit with multiple cursors simultaneously + smart-splits.enable = true; # Split-Pane Management + undotree.enable = true; # Undo history visualizer + nvim-biscuits.enable = true; # Shows the start of a code block from the bottom + + motion = { + # NOTE: https://github.com/smoka7/hop.nvim + hop.enable = true; # EasyMotion like, allowing you to jump anywhere in the document with as few keystrokes as possible + leap.enable = true; # Jump to anywhere visible + # TODO: I sort of hate how precognition injects itself in virtual + # lines, but I do like that it can be used to give a reminder. + precognition.enable = false; # Helps with discovering motions to navigate your current buffer + }; + images.img-clip.enable = true; + }; + + # TODO: Get Obsidian Working. + notes = { + # obsidian.enable = true; # neovim fails to build with this enabled. + mind-nvim.enable = true; + todo-comments.enable = true; + }; + + terminal = { + toggleterm = { + enable = true; + lazygit.enable = true; + }; + }; + + ui = { + borders.enable = true; + noice.enable = true; + colorizer.enable = true; + modes-nvim.enable = false; # this looks terrible with catppuccin + illuminate.enable = true; + breadcrumbs = { + enable = true; + navbuddy.enable = true; + }; + smartcolumn = { + enable = true; + setupOpts.custom_colorcolumn = { + nix = "110"; + ruby = "120"; + java = "130"; + go = [ + "90" + "130" + ]; + }; + }; + fastaction.enable = true; + }; + + assistant = { + chatgpt.enable = false; + copilot = { + enable = false; + cmp.enable = true; + }; + codecompanion-nvim.enable = false; + # avante-nvim.enable = true; + }; + + session.nvim-session-manager.enable = true; # Save sessions to reopen later + gestures.gesture-nvim.enable = false; # mouse gesture support? + comments.comment-nvim.enable = true; # Fancy commenting + presence.neocord.enable = true; # Discord Rich Presence + }; + }; + programs.vscode = { enable = true; - mutableExtensionsDir = true; # mutually exclusive to programs.vscode.profiles + mutableExtensionsDir = true; # mutually exclusive to programs.vscode.profiles profiles.default.userSettings = { "[nix]"."editor.tabSize" = 2; }; From 7f361458edcad1719cdcf80e2cac856006133520 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 11:54:12 -0600 Subject: [PATCH 16/30] feat: add home-manager as a system package when my user is present --- users/jml/default.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/users/jml/default.nix b/users/jml/default.nix index 592e6ba..69afa40 100644 --- a/users/jml/default.nix +++ b/users/jml/default.nix @@ -1,6 +1,9 @@ { pkgs, lib, ... }: { programs.fish.enable = true; + environment.systemPackages = [ + pkgs.home-manager + ]; users.users.jml = { shell = pkgs.fish; home = From 5339eeebce9a546a6f7b3dc34ddb4f0eaf7da39e Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 11:56:03 -0600 Subject: [PATCH 17/30] feat: add gamemode and gamescope /w CAP_SYS_NICE --- modules/nixos/gaming.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/nixos/gaming.nix b/modules/nixos/gaming.nix index 69dcd1b..1e86c7e 100644 --- a/modules/nixos/gaming.nix +++ b/modules/nixos/gaming.nix @@ -5,11 +5,12 @@ zw.gaming.enable = lib.mkEnableOption "Enable Gaming"; }; + # https://wiki.nixos.org/wiki/Category:Gaming config = lib.mkIf config.zw.gaming.enable { environment.systemPackages = with pkgs; [ mangohud protonup-qt - # lutris # TODO: Having an issue after flake update + lutris # TODO: Having an issue after flake update bottles heroic ]; @@ -20,5 +21,11 @@ protontricks.enable = true; gamescopeSession.enable = true; }; + + programs.gamemode.enable = true; + programs.gamescope = { + enable = true; + capSysNice = true; + }; }; } From b792e801c58aaeb7f4fce6d27e7a854701451357 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 15:35:57 -0600 Subject: [PATCH 18/30] chore: fix a typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ec089f..e2a9b9e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## Overview -This repository maanges **multiple NixOS systems** using a shared modular configuration. +This repository manages **multiple NixOS systems** using a shared modular configuration. It's designed to be **secure, composable, and automated** using modern Nix tooling. - **Laptop ("neon")**: Portable KVM/Swiss-Army Knife From e3e28fa662ecf19f3e8f5013334045fc2c6f7496 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 15:40:37 -0600 Subject: [PATCH 19/30] horribly cobble together the ability to use both home-manager switch and nixos-rebuild switch against the same flake --- flake.lock | 120 +++++++++++++++++++++++++++++++----- flake.nix | 155 +++++++++++++++++++++++++++-------------------- lib/default.nix | 157 +++++++++++++++++++++++++++++++----------------- 3 files changed, 296 insertions(+), 136 deletions(-) diff --git a/flake.lock b/flake.lock index 87bf043..0bc246f 100644 --- a/flake.lock +++ b/flake.lock @@ -135,6 +135,22 @@ "type": "github" } }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1751685974, + "narHash": "sha256-NKw96t+BgHIYzHUjkTK95FqYRVKB8DHpVhefWSz/kTw=", + "ref": "refs/heads/main", + "rev": "549f2762aebeff29a2e5ece7a7dc0f955281a1d1", + "revCount": 92, + "type": "git", + "url": "https://git.lix.systems/lix-project/flake-compat.git" + }, + "original": { + "type": "git", + "url": "https://git.lix.systems/lix-project/flake-compat.git" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -157,6 +173,27 @@ } }, "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "nvf", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1760948891, + "narHash": "sha256-TmWcdiUUaWk8J4lpjzu4gCGxWY6/Ok7mOK4fIFfBuU4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "864599284fc7c0ba6357ed89ed5e2cd5040f0c04", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { "inputs": { "nixpkgs-lib": [ "stylix", @@ -239,11 +276,11 @@ ] }, "locked": { - "lastModified": 1762787259, - "narHash": "sha256-t2U/GLLXHa2+kJkwnFNRVc2fEJ/lUfyZXBE5iKzJdcs=", + "lastModified": 1762964643, + "narHash": "sha256-RYHN8O/Aja59XDji6WSJZPkJpYVUfpSkyH+PEupBJqM=", "owner": "nix-community", "repo": "home-manager", - "rev": "37a3d97f2873e0f68711117c34d04b7c7ead8f4e", + "rev": "827f2a23373a774a8805f84ca5344654c31f354b", "type": "github" }, "original": { @@ -278,13 +315,28 @@ "type": "github" } }, + "mnw": { + "locked": { + "lastModified": 1758834834, + "narHash": "sha256-Y7IvY4F8vajZyp3WGf+KaiIVwondEkMFkt92Cr9NZmg=", + "owner": "Gerg-L", + "repo": "mnw", + "rev": "cfbc7d1cc832e318d0863a5fc91d940a96034001", + "type": "github" + }, + "original": { + "owner": "Gerg-L", + "repo": "mnw", + "type": "github" + } + }, "nixos-hardware": { "locked": { - "lastModified": 1762463231, - "narHash": "sha256-hv1mG5j5PTbnWbtHHomzTus77pIxsc4x8VrMjc7+/YE=", + "lastModified": 1762847253, + "narHash": "sha256-BWWnUUT01lPwCWUvS0p6Px5UOBFeXJ8jR+ZdLX8IbrU=", "owner": "nixos", "repo": "nixos-hardware", - "rev": "52113c4f5cfd1e823001310e56d9c8d0699a6226", + "rev": "899dc449bc6428b9ee6b3b8f771ca2b0ef945ab9", "type": "github" }, "original": { @@ -295,11 +347,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1762596750, - "narHash": "sha256-rXXuz51Bq7DHBlfIjN7jO8Bu3du5TV+3DSADBX7/9YQ=", + "lastModified": 1762977756, + "narHash": "sha256-4PqRErxfe+2toFJFgcRKZ0UI9NSIOJa+7RXVtBhy4KE=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b6a8526db03f735b89dd5ff348f53f752e7ddc8e", + "rev": "c5ae371f1a6a7fd27823bc500d9390b38c05fa55", "type": "github" }, "original": { @@ -334,6 +386,30 @@ "type": "github" } }, + "nvf": { + "inputs": { + "flake-compat": "flake-compat_2", + "flake-parts": "flake-parts_2", + "mnw": "mnw", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1762622004, + "narHash": "sha256-NpzzgaoMK8aRHnndHWbYNKLcZN0r1y6icCoJvGoBsoE=", + "owner": "notashelf", + "repo": "nvf", + "rev": "09470524a214ed26633ddc2b6ec0c9bf31a8b909", + "type": "github" + }, + "original": { + "owner": "notashelf", + "repo": "nvf", + "type": "github" + } + }, "pre-commit-hooks-nix": { "inputs": { "flake-compat": [ @@ -367,6 +443,7 @@ "lanzaboote": "lanzaboote", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", + "nvf": "nvf", "sops-nix": "sops-nix", "stylix": "stylix" } @@ -399,11 +476,11 @@ ] }, "locked": { - "lastModified": 1762659808, - "narHash": "sha256-2Kv2mANf+FRisqhpfeZ8j9firBxb23ZvEXwdcunbpGI=", + "lastModified": 1763069729, + "narHash": "sha256-A91a+K0Q9wfdPLwL06e/kbHeAWSzPYy2EGdTDsyfb+s=", "owner": "Mic92", "repo": "sops-nix", - "rev": "524312bc62e3f34bd9231a2f66622663d3355133", + "rev": "a2bcd1c25c1d29e22756ccae094032ab4ada2268", "type": "github" }, "original": { @@ -419,13 +496,13 @@ "base16-helix": "base16-helix", "base16-vim": "base16-vim", "firefox-gnome-theme": "firefox-gnome-theme", - "flake-parts": "flake-parts_2", + "flake-parts": "flake-parts_3", "gnome-shell": "gnome-shell", "nixpkgs": [ "nixpkgs" ], "nur": "nur", - "systems": "systems", + "systems": "systems_2", "tinted-foot": "tinted-foot", "tinted-kitty": "tinted-kitty", "tinted-schemes": "tinted-schemes", @@ -461,6 +538,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "tinted-foot": { "flake": false, "locked": { diff --git a/flake.nix b/flake.nix index 1bfd0d4..9af0fff 100644 --- a/flake.nix +++ b/flake.nix @@ -13,73 +13,96 @@ disko.inputs.nixpkgs.follows = "nixpkgs"; stylix.url = "github:nix-community/stylix"; stylix.inputs.nixpkgs.follows = "nixpkgs"; + + #obsidian-nvim.url = "github:epwalsh/obsidian.nvim"; + nvf = { + url = "github:notashelf/nvf"; + inputs.nixpkgs.follows = "nixpkgs"; + #inputs.obsidian-nvim.follows = "obsidian-nvim"; + }; }; # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument - outputs = inputs@{self, nixpkgs, nixos-hardware, home-manager, sops-nix, lanzaboote, disko, stylix, ...}: - let - mkSystem = (import ./lib { - inherit nixpkgs home-manager inputs; - }).mkSystem; - in - { - lib = { - mkSystem = mkSystem; + outputs = + inputs@{ + self, + nixpkgs, + nixos-hardware, + home-manager, + sops-nix, + lanzaboote, + disko, + stylix, + nvf, + ... + }: + let + zwLib = import ./lib { + inherit nixpkgs home-manager inputs; + }; + mkSystem = zwLib.mkSystem; + mkHome = zwLib.mkHome; + mkHomeConfigs = zwLib.mkHomeConfigs; + + # NOTE: Currently these are exclusively user-profiles which use home-manager. + # Their home-manager specific declarations are at ../users/${username}/home.nix + system = "x86_64-linux"; # TODO: Improve this from only static x86 to dynamic. + homeUserProfiles = { + jml = mkHome { + inherit system; # inputs; + username = "jml"; + extraModules = [ nvf.homeManagerModules.default ]; + }; + }; + in + { + lib = { + mkSystem = mkSystem; + }; + # NOTE: Run `nix flake show` to see what this flake has to offer. + # TODO: Enable automated formatting with something like numtide/treefmt-nix + nixosConfigurations = { + neon = mkSystem { + hostname = "neon"; + users = [ "jml" ]; + }; + lithium = mkSystem { + hostname = "lithium"; + # extraModules = [ inputs.sops-nix.nixosModules.sops ]; + users = [ + "jml" + "breakglass" + ]; + }; + titanium = mkSystem { + hostname = "titanium"; + users = [ + "jml" + ]; + homeUsers = { + jml = homeUserProfiles.jml.module; + }; + #extraModules = [ (import ./overlays) ]; + # NOTE: If I'm using a home-manager configuration on a given host, + # I also need to include the relevant modules. + # TODO: Can I instead self-reference the homeConfigurations in this flake? + extraModules = [ + stylix.nixosModules.stylix + ]; + }; + # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` + # https://github.com/nix-community/nixos-generators + installIso = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + ]; + specialArgs = { inherit inputs; }; + }; + }; + + # For Debugging: `home-manager build --flake .` or `nix build .#homeConfigurations."jml".activationPackage` + # `home-manager switch --flake .#jml` + # https://nix-community.github.io/home-manager/options.xhtml + homeConfigurations = mkHomeConfigs homeUserProfiles; }; - # NOTE: Run `nix flake show` to see what this flake has to offer. - # TODO: Enable automated formatting with something like numtide/treefmt-nix - nixosConfigurations = { - neon = mkSystem { - hostname = "neon"; - users = [ "jml" ]; - }; - lithium = mkSystem { - hostname = "lithium"; - # extraModules = [ inputs.sops-nix.nixosModules.sops ]; - users = [ - "jml" - "breakglass" - ]; - }; - titanium = mkSystem { - hostname = "titanium"; - users = [ - "jml" - ]; - extraModules = [ - #(import ./overlays) - #stylix.nixosModules.stylix - { nixpkgs.config.allowUnfree = true; } - lanzaboote.nixosModules.lanzaboote - disko.nixosModules.disko - ./hosts/titanium/disko.nix - ({ pkgs, lib, ... }: { - environment.systemPackages = [ pkgs.sbctl ]; - boot.loader.systemd-boot.enable = lib.mkForce false; - boot.lanzaboote.enable = true; - boot.lanzaboote.pkiBundle = "/var/lib/sbctl"; - }) - ]; - }; - cobalt = mkSystem { - hostname = "cobalt"; - users = [ "jml" ]; - }; - # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` - # https://github.com/nix-community/nixos-generators - installIso = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" - ]; - specialArgs = {inherit inputs;}; - }; - }; - homeConfigurations = { - "jml" = home-manager.lib.homeManagerConfiguration { - modules = [ - ./users/jml/home.nix - ]; - }; - }; - }; } diff --git a/lib/default.nix b/lib/default.nix index 65ee05a..f3d2ac9 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,68 +1,113 @@ -{ nixpkgs, home-manager, inputs, ... }: +{ + nixpkgs, + home-manager, + inputs, + ... +}: let allOverlays = import (../overlays) { inherit nixpkgs; }; -in -{ - # It's not really that I care about whether a system is a desktop system or - # a server system, but moreso that I care about whether a system is headless or not. - # I also care about things like if it's darwin, or wsl. - # TODO: Expand this to actually make use of extraSpecialArgs and pass special - # args to the relevant places. - mkSystem = { - hostname, - system ? "x86_64-linux", - users ? [], - extraModules ? [], - extraSpecialArgs ? {} - }: - let - pkgs_with_overlays = import nixpkgs { + getPkgs = + system: + import nixpkgs { inherit system; overlays = allOverlays; }; - hostModule = import ../hosts/${hostname} { - inherit inputs; - pkgs = pkgs_with_overlays; - }; - userModules = map (name: - import ../users/${name} { - pkgs = pkgs_with_overlays; - lib = nixpkgs.lib; - } - ) users; - - homeUserNames = builtins.filter (name: - builtins.pathExists ../users/${name}/home.nix - ) users; - - homeUsers = nixpkgs.lib.listToAttrs (map (name: { - name = name; - value = import ../users/${name}/home.nix { - username = name; - pkgs = pkgs_with_overlays; - lib = nixpkgs.lib; +in +{ + mkSystem = + { + hostname, + system ? "x86_64-linux", + users ? [ ], + extraModules ? [ ], + homeUsers ? { }, + extraSpecialArgs ? { }, + }: + let + pkgs_with_overlays = import nixpkgs { + inherit system; + overlays = allOverlays; }; - }) homeUserNames); - in + hostModule = import ../hosts/${hostname} { + inherit inputs; + pkgs = pkgs_with_overlays; + }; + userModules = map ( + name: + import ../users/${name} { + pkgs = pkgs_with_overlays; + lib = nixpkgs.lib; + } + ) users; + + formattedHomeUsers = nixpkgs.lib.mapAttrs (username: moduleList: { + imports = moduleList; + }) homeUsers; + in nixpkgs.lib.nixosSystem { inherit system; - # pkgs = import inputs.nixpkgs { - # inherit system; - # overlays = allOverlays; - # config = { allowUnfree = true; nvidia.acceptLicense = true; }; - # }; - modules = [ hostModule ] - ++ userModules - ++ extraModules - ++ (if homeUserNames != [] then [ - home-manager.nixosModules.home-manager - { - home-manager.backupFileExtension = "hm-bak"; - home-manager.users = homeUsers; - } - ] else []); + modules = [ + hostModule + ] + ++ userModules + ++ extraModules + ++ ( + if homeUsers != { } then + [ + home-manager.nixosModules.home-manager + { + #home-manager.useGlobalPkgs = true; # NOTE: Incompatible with nixpkgs.{config,overlays} + home-manager.useUserPackages = true; + home-manager.backupFileExtension = "hm-bak"; + + # Directly inject the module lists? (isn't this the problem?) + home-manager.users = formattedHomeUsers; + home-manager.extraSpecialArgs = { inherit inputs; }; + } + ] + else + [ ] + ); specialArgs = { inherit inputs hostname; - } // extraSpecialArgs; + } + // extraSpecialArgs; }; + + getUserHomeModule = + username: pkgs: inputs: + import ../users/${username}/home.nix { + inherit username pkgs inputs; + lib = nixpkgs.lib; + }; + + /** + This function returns an attribute set { module, config }. + */ + mkHome = + { + username, + system ? "x86_64-linux", + extraModules ? [ ], + }: + let + pkgs_with_overlays = getPkgs system; + moduleList = [ + (import ../users/${username}/home.nix { + inherit inputs username; + pkgs = pkgs_with_overlays; + lib = nixpkgs.lib; + }) + ] + ++ extraModules; + in + { + module = moduleList; + config = home-manager.lib.homeManagerConfiguration { + pkgs = pkgs_with_overlays; + modules = moduleList; + }; + }; + + mkHomeConfigs = userProfiles: nixpkgs.lib.mapAttrs (username: profile: profile.config) userProfiles; } From 2cfac91660ebfe20cb33edb9d1e93bfa88ce1311 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 18:39:51 -0600 Subject: [PATCH 20/30] snapshot of some host updates --- hosts/lithium/services/kanidm.nix | 2 +- hosts/neon/default.nix | 2 +- hosts/titanium/configuration.nix | 5 ++++- hosts/titanium/game-emulation.nix | 4 ++-- hosts/titanium/hardware.nix | 1 + hosts/titanium/meetings.nix | 4 ++++ hosts/titanium/nvidia.nix | 5 ++++- 7 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 hosts/titanium/meetings.nix diff --git a/hosts/lithium/services/kanidm.nix b/hosts/lithium/services/kanidm.nix index 066652f..b8b96de 100644 --- a/hosts/lithium/services/kanidm.nix +++ b/hosts/lithium/services/kanidm.nix @@ -44,7 +44,7 @@ in }; services.kanidm = { - package = pkgs.kanidmWithSecretProvisioning; + package = pkgs.kanidmWithSecretProvisioning_1_7; enableServer = true; serverSettings = { # NOTE: Required to start the server: https://kanidm.github.io/kanidm/stable/server_configuration.html diff --git a/hosts/neon/default.nix b/hosts/neon/default.nix index 6d3d3e0..bfe9f0c 100644 --- a/hosts/neon/default.nix +++ b/hosts/neon/default.nix @@ -3,7 +3,7 @@ imports = [ ../../modules/nixos/base.nix ../../modules/nixos/audio.nix - ../../modules/nixos/desktop.nix + ../../modules/nixos/desktop # https://github.com/NixOS/nixos-hardware/blob/master/README.md#using-nix-flakes-support inputs.nixos-hardware.nixosModules.gpd-pocket-3 # override from nixos-hardware diff --git a/hosts/titanium/configuration.nix b/hosts/titanium/configuration.nix index acc06b8..45987c6 100644 --- a/hosts/titanium/configuration.nix +++ b/hosts/titanium/configuration.nix @@ -6,9 +6,12 @@ environment.systemPackages = with pkgs; [ sbctl # Secure-Boot helix nil # nice for editing '.nix' - discord + (discord.override { withVencord = true; }) signal-desktop obs-studio + halloy # IRC + gimp3 + nyxt # browser ]; # Hardware Specific programs... #programs.ryzen-monitor-ng.enable = true; diff --git a/hosts/titanium/game-emulation.nix b/hosts/titanium/game-emulation.nix index b970492..e0ba3d2 100644 --- a/hosts/titanium/game-emulation.nix +++ b/hosts/titanium/game-emulation.nix @@ -15,8 +15,8 @@ let mupen64plus # Nintendo 64 - Maybe simple64 some day. dolphin # GameCube mgba # GameBoy / Color / Advance - melonds # Nintendo DS - citra # Nintendo 3DS + #melonds # Nintendo DS + #citra # Nintendo 3DS # Sony diff --git a/hosts/titanium/hardware.nix b/hosts/titanium/hardware.nix index 4204ed2..a11bb78 100644 --- a/hosts/titanium/hardware.nix +++ b/hosts/titanium/hardware.nix @@ -13,6 +13,7 @@ boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-amd" ]; + # boot.blacklistedKernelModules = [ "nouveau" ]; boot.extraModulePackages = [ ]; fileSystems."/" = diff --git a/hosts/titanium/meetings.nix b/hosts/titanium/meetings.nix new file mode 100644 index 0000000..ed827ec --- /dev/null +++ b/hosts/titanium/meetings.nix @@ -0,0 +1,4 @@ +{ ... }: +{ + programs.zoom-us.enable = true; +} diff --git a/hosts/titanium/nvidia.nix b/hosts/titanium/nvidia.nix index 66b3fa2..af7717f 100644 --- a/hosts/titanium/nvidia.nix +++ b/hosts/titanium/nvidia.nix @@ -14,9 +14,12 @@ # https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/linux/nvidia-x11/generic.nix#L65 nixpkgs.config.nvidia.acceptLicense = true; hardware.nvidia = { + # TODO: Consider legacy drivers. + # https://discourse.nixos.org/t/cant-use-nvidia-offload-mode/27791/8 package = config.boot.kernelPackages.nvidiaPackages.latest; modesetting.enable = true; - open = true; + # Open Source Drivers: https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus + open = false; nvidiaSettings = true; powerManagement.enable = false; powerManagement.finegrained = false; From 54f361da9e1ce8ca2fbacde299e8cb03864dc53f Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 18:45:03 -0600 Subject: [PATCH 21/30] excluding a local scratch notes file from the source tree --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f295f42..64b28b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ result -result-* \ No newline at end of file +result-* +localnotes.md \ No newline at end of file From 02f530c6b9756d4cc6af044f03c2d67e7779a886 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 18:46:09 -0600 Subject: [PATCH 22/30] exclude qcow2 files from source tree --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 64b28b9..f2ccda5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ result result-* -localnotes.md \ No newline at end of file +localnotes.md +*.qcow2 \ No newline at end of file From d8591cb70d4884540eca0e9649582fd28dc90e03 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 22:14:03 -0600 Subject: [PATCH 23/30] another cobalt snapshot, moving towards niri --- hosts/cobalt/configuration.nix | 16 ++++++++++++++-- modules/nixos/desktop/default.nix | 7 +------ modules/nixos/fonts.nix | 8 ++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 modules/nixos/fonts.nix diff --git a/hosts/cobalt/configuration.nix b/hosts/cobalt/configuration.nix index bea1e3c..12627dd 100644 --- a/hosts/cobalt/configuration.nix +++ b/hosts/cobalt/configuration.nix @@ -9,10 +9,22 @@ # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. networking.networkmanager.enable = true; + + #services.displayManager.sddm.enable = true; + services.displayManager.defaultSession = "xfce"; + services.displayManager.sessionPackages = [ pkgs.niri ]; + #services.sysc-greet.enable = true; + programs.niri.package = pkgs.niri; + + services.xserver.desktopManager = { + xterm.enable = false; + xfce.enable = true; + }; + # Desktop stuff specific to this device services.xserver.enable = true; - services.xserver.displayManager.lightdm.enable = true; - services.xserver.desktopManager.pantheon.enable = true; + #services.xserver.displayManager.lightdm.enable = true; + #services.xserver.desktopManager.pantheon.enable = true; services.xserver.xkb = { layout = "us"; variant = ""; diff --git a/modules/nixos/desktop/default.nix b/modules/nixos/desktop/default.nix index 56e89f7..4f29d78 100644 --- a/modules/nixos/desktop/default.nix +++ b/modules/nixos/desktop/default.nix @@ -2,6 +2,7 @@ { imports = [ ./calibre.nix + ./fonts.nix ]; zw.calibre.enable = true; @@ -37,10 +38,4 @@ }; # screen sharing /w hyp services.dbus.enable = true; - - fonts.packages = with pkgs; [ - nerd-fonts.fira-code - nerd-fonts.iosevka - atkinson-hyperlegible - ]; } diff --git a/modules/nixos/fonts.nix b/modules/nixos/fonts.nix new file mode 100644 index 0000000..e39de7a --- /dev/null +++ b/modules/nixos/fonts.nix @@ -0,0 +1,8 @@ +{pkgs}: +{ + fonts.packages = with pkgs; [ + nerd-fonts.fira-code + nerd-fonts.iosevka + atkinson-hyperlegible + ]; +} \ No newline at end of file From e680174e2c5e083c140f061d97c64d2b72c08b59 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 22:15:57 -0600 Subject: [PATCH 24/30] feat: add noctalia --- flake.nix | 10 +++++++ modules/nixos/desktop/niri/default.nix | 36 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 modules/nixos/desktop/niri/default.nix diff --git a/flake.nix b/flake.nix index 9af0fff..0913d80 100644 --- a/flake.nix +++ b/flake.nix @@ -20,6 +20,16 @@ inputs.nixpkgs.follows = "nixpkgs"; #inputs.obsidian-nvim.follows = "obsidian-nvim"; }; + + quickshell = { + url = "github:outfoxxed/quickshell"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + noctalia = { + url = "github:noctalia-dev/noctalia-shell"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.quickshell.follows = "quickshell"; + }; }; # https://nix.dev/tutorials/nix-language.html#named-attribute-set-argument outputs = diff --git a/modules/nixos/desktop/niri/default.nix b/modules/nixos/desktop/niri/default.nix new file mode 100644 index 0000000..8359fe4 --- /dev/null +++ b/modules/nixos/desktop/niri/default.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, inputs, ... }: +{ + # Opinionated Niri Setup - https://yalter.github.io/niri/Important-Software.html + # Consider: https://github.com/sodiboo/niri-flake + + # NOTE: Rather than individual components, I'm going to start with a complete desktop shell if possible. + # According to the docs there's a few options: https://yalter.github.io/niri/Getting-Started.html#desktop-environments + # LXQt, many parts of XFCE, COSMIC + `cosmic-ext-extra-sessions` + # And what I actually want to try out is one of DankMaterialShell or Noctalia + programs.niri.enable = true; + + environments.systemPackages = with pkgs; [ + inputs.noctalia.packages.${system}.default + xwayland-satellite + fuzzel + kitty + fastfetch + ] + + # Notification Daemon + #services.mako.enable = true; + #services.mako.settings.default-timeout = 3000; + + # Portal - https://wiki.archlinux.org/title/XDG_Desktop_Portal#List_of_backends_and_interfaces + + # Authentication Agent (polkit) + #security.polkit.enable = lib.mkDefault true; + + # Xwayland + # https://github.com/Supreeeme/xwayland-satellite + #programs.xwayland.enable = lib.mkDefault true; + + # Screencasting - https://yalter.github.io/niri/Screencasting.html + # Needs D-Bus, pipewire, `xdg-desktop-portal-gnome`? Or a portal from the above table with screencasting support + +} \ No newline at end of file From d296101aaa5ac8375acc1904c60f39ebe916ebf3 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 22:16:57 -0600 Subject: [PATCH 25/30] testing cobalt niri --- hosts/cobalt/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/hosts/cobalt/default.nix b/hosts/cobalt/default.nix index b28af35..c1b5ef5 100644 --- a/hosts/cobalt/default.nix +++ b/hosts/cobalt/default.nix @@ -11,6 +11,7 @@ ./hardware-configuration.nix ./configuration.nix ../../modules/nixos/gaming.nix + ../../modules/nixos/desktop/niri ]; zw.gaming.enable = true; From ca7511dc8229cfd0ab4fca7e74887e630894a723 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 23:19:26 -0600 Subject: [PATCH 26/30] fix: re-add missing cobalt host definition --- flake.lock | 42 ++++++++++++++++++++++++++++++++++++++++++ flake.nix | 4 ++++ 2 files changed, 46 insertions(+) diff --git a/flake.lock b/flake.lock index 0bc246f..97d3db0 100644 --- a/flake.lock +++ b/flake.lock @@ -361,6 +361,26 @@ "type": "github" } }, + "noctalia": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1764122160, + "narHash": "sha256-JZ51AW7zKgqlZp+oqt3Y7thglv23TPjgG1XiGBFWhr8=", + "owner": "noctalia-dev", + "repo": "noctalia-shell", + "rev": "3c5dfd87db582bf9056d83f41d53b90ba08023c6", + "type": "github" + }, + "original": { + "owner": "noctalia-dev", + "repo": "noctalia-shell", + "type": "github" + } + }, "nur": { "inputs": { "flake-parts": [ @@ -436,6 +456,26 @@ "type": "github" } }, + "quickshell": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1764045583, + "narHash": "sha256-W24ReyRrhOKTKIsuAMkY5hnVlCufGoONM79sjUoyQkk=", + "owner": "outfoxxed", + "repo": "quickshell", + "rev": "e9bad67619ee9937a1bbecfc6ad3b4231d2ecdc3", + "type": "github" + }, + "original": { + "owner": "outfoxxed", + "repo": "quickshell", + "type": "github" + } + }, "root": { "inputs": { "disko": "disko", @@ -443,7 +483,9 @@ "lanzaboote": "lanzaboote", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", + "noctalia": "noctalia", "nvf": "nvf", + "quickshell": "quickshell", "sops-nix": "sops-nix", "stylix": "stylix" } diff --git a/flake.nix b/flake.nix index 0913d80..8fe78ea 100644 --- a/flake.nix +++ b/flake.nix @@ -99,6 +99,10 @@ stylix.nixosModules.stylix ]; }; + cobalt = mkSystem { + hostname = "cobalt"; + users = [ "jml" ]; + }; # `nix build .#nixosConfigurations.installIso.config.system.build.isoImage` # https://github.com/nix-community/nixos-generators installIso = nixpkgs.lib.nixosSystem { From 3353c915176d8b4cc95ce5f934a1223ede8118c7 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 25 Nov 2025 23:20:43 -0600 Subject: [PATCH 27/30] fix: missing semicolon --- modules/nixos/desktop/niri/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nixos/desktop/niri/default.nix b/modules/nixos/desktop/niri/default.nix index 8359fe4..15776b5 100644 --- a/modules/nixos/desktop/niri/default.nix +++ b/modules/nixos/desktop/niri/default.nix @@ -15,7 +15,7 @@ fuzzel kitty fastfetch - ] + ]; # Notification Daemon #services.mako.enable = true; From f2d2b00fe79a2504d975267ef434f0e0cbabddd0 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Wed, 26 Nov 2025 00:51:48 -0600 Subject: [PATCH 28/30] fix: typo --- modules/nixos/desktop/niri/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nixos/desktop/niri/default.nix b/modules/nixos/desktop/niri/default.nix index 15776b5..a91b1f8 100644 --- a/modules/nixos/desktop/niri/default.nix +++ b/modules/nixos/desktop/niri/default.nix @@ -9,7 +9,7 @@ # And what I actually want to try out is one of DankMaterialShell or Noctalia programs.niri.enable = true; - environments.systemPackages = with pkgs; [ + environment.systemPackages = with pkgs; [ inputs.noctalia.packages.${system}.default xwayland-satellite fuzzel From 26f35df7ad69714b03a77da498a11df8bb1db098 Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Wed, 26 Nov 2025 18:25:11 -0600 Subject: [PATCH 29/30] refactor: moving some desktop environment stuff around --- hosts/cobalt/configuration.nix | 15 --------------- hosts/cobalt/default.nix | 3 ++- modules/nixos/desktop/calibre.nix | 3 ++- modules/nixos/desktop/default.nix | 3 +++ modules/nixos/desktop/niri/default.nix | 4 ++++ modules/nixos/desktop/xfce/default.nix | 9 +++++++++ 6 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 modules/nixos/desktop/xfce/default.nix diff --git a/hosts/cobalt/configuration.nix b/hosts/cobalt/configuration.nix index 12627dd..79d1f95 100644 --- a/hosts/cobalt/configuration.nix +++ b/hosts/cobalt/configuration.nix @@ -10,21 +10,6 @@ networking.networkmanager.enable = true; - #services.displayManager.sddm.enable = true; - services.displayManager.defaultSession = "xfce"; - services.displayManager.sessionPackages = [ pkgs.niri ]; - #services.sysc-greet.enable = true; - programs.niri.package = pkgs.niri; - - services.xserver.desktopManager = { - xterm.enable = false; - xfce.enable = true; - }; - - # Desktop stuff specific to this device - services.xserver.enable = true; - #services.xserver.displayManager.lightdm.enable = true; - #services.xserver.desktopManager.pantheon.enable = true; services.xserver.xkb = { layout = "us"; variant = ""; diff --git a/hosts/cobalt/default.nix b/hosts/cobalt/default.nix index c1b5ef5..61dcaa5 100644 --- a/hosts/cobalt/default.nix +++ b/hosts/cobalt/default.nix @@ -11,7 +11,8 @@ ./hardware-configuration.nix ./configuration.nix ../../modules/nixos/gaming.nix - ../../modules/nixos/desktop/niri + ../../modules/nixos/desktop/xfce + #../../modules/nixos/desktop/niri ]; zw.gaming.enable = true; diff --git a/modules/nixos/desktop/calibre.nix b/modules/nixos/desktop/calibre.nix index bcc4cea..5fa97d5 100644 --- a/modules/nixos/desktop/calibre.nix +++ b/modules/nixos/desktop/calibre.nix @@ -14,7 +14,8 @@ calibre ]; - services.udisks2.enable = true; + services.udisks2.enable = true; # Required for eReader Support }; # NOTE: Consider adding https://github.com/nydragon/calibre-plugins + # especially for DeDRM } diff --git a/modules/nixos/desktop/default.nix b/modules/nixos/desktop/default.nix index 4f29d78..ff03a1c 100644 --- a/modules/nixos/desktop/default.nix +++ b/modules/nixos/desktop/default.nix @@ -5,6 +5,9 @@ ./fonts.nix ]; + # TODO: Add options for enabling/switching between different Desktop Environments. + options = {}; + zw.calibre.enable = true; environment.systemPackages = with pkgs; [ diff --git a/modules/nixos/desktop/niri/default.nix b/modules/nixos/desktop/niri/default.nix index a91b1f8..e239697 100644 --- a/modules/nixos/desktop/niri/default.nix +++ b/modules/nixos/desktop/niri/default.nix @@ -17,6 +17,10 @@ fastfetch ]; + services.displayManager.sessionPackages = [ pkgs.niri ]; + programs.niri.package = pkgs.niri; + + # Notification Daemon #services.mako.enable = true; #services.mako.settings.default-timeout = 3000; diff --git a/modules/nixos/desktop/xfce/default.nix b/modules/nixos/desktop/xfce/default.nix new file mode 100644 index 0000000..cae144b --- /dev/null +++ b/modules/nixos/desktop/xfce/default.nix @@ -0,0 +1,9 @@ +{}: +{ + services.displayManager.defaultSession = "xfce"; + services.xserver.desktopManager = { + xterm.enable = false; + xfce.enable = true; + }; + +} \ No newline at end of file From aa4a8347ece933ac82442bffb64e1a4415465fcc Mon Sep 17 00:00:00 2001 From: Jay Looney Date: Tue, 2 Dec 2025 15:07:14 -0600 Subject: [PATCH 30/30] Refining `modules/nixos/base.nix` to make sense for more machines There is a few additional changes due to typos introduced while working on other stuff. --- .vscode/settings.json | 3 ++ hosts/cobalt/boot.nix | 6 ++++ hosts/cobalt/default.nix | 1 + hosts/lithium/boot.nix | 6 ++++ hosts/lithium/default.nix | 1 + hosts/neon/boot.nix | 6 ++++ hosts/neon/default.nix | 1 + modules/nixos/base.nix | 52 +++++++++++++++++-------------- modules/nixos/desktop/default.nix | 7 +++-- modules/nixos/fonts.nix | 2 +- users/jml/home.nix | 11 +++++-- 11 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 hosts/cobalt/boot.nix create mode 100644 hosts/lithium/boot.nix create mode 100644 hosts/neon/boot.nix diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..205df23 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.enabled": false +} \ No newline at end of file diff --git a/hosts/cobalt/boot.nix b/hosts/cobalt/boot.nix new file mode 100644 index 0000000..e1f16ff --- /dev/null +++ b/hosts/cobalt/boot.nix @@ -0,0 +1,6 @@ +{}: +{ + # Default to systemd-boot + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +} \ No newline at end of file diff --git a/hosts/cobalt/default.nix b/hosts/cobalt/default.nix index 61dcaa5..d60b1f2 100644 --- a/hosts/cobalt/default.nix +++ b/hosts/cobalt/default.nix @@ -1,6 +1,7 @@ { inputs, ... }: { imports = [ + ./boot.nix ../../modules/nixos/base.nix ../../modules/nixos/audio.nix #../../modules/nixos/desktop.nix diff --git a/hosts/lithium/boot.nix b/hosts/lithium/boot.nix new file mode 100644 index 0000000..e1f16ff --- /dev/null +++ b/hosts/lithium/boot.nix @@ -0,0 +1,6 @@ +{}: +{ + # Default to systemd-boot + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +} \ No newline at end of file diff --git a/hosts/lithium/default.nix b/hosts/lithium/default.nix index 61582b1..30fbf84 100644 --- a/hosts/lithium/default.nix +++ b/hosts/lithium/default.nix @@ -1,6 +1,7 @@ { inputs, ... }: { imports = [ + ./boot.nix ../../modules/nixos/base.nix inputs.sops-nix.nixosModules.sops ./hardware.nix diff --git a/hosts/neon/boot.nix b/hosts/neon/boot.nix new file mode 100644 index 0000000..e1f16ff --- /dev/null +++ b/hosts/neon/boot.nix @@ -0,0 +1,6 @@ +{}: +{ + # Default to systemd-boot + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; +} \ No newline at end of file diff --git a/hosts/neon/default.nix b/hosts/neon/default.nix index bfe9f0c..231f6da 100644 --- a/hosts/neon/default.nix +++ b/hosts/neon/default.nix @@ -1,6 +1,7 @@ { inputs, ... }: { imports = [ + ./boot.nix ../../modules/nixos/base.nix ../../modules/nixos/audio.nix ../../modules/nixos/desktop diff --git a/modules/nixos/base.nix b/modules/nixos/base.nix index 036a5c9..d273887 100644 --- a/modules/nixos/base.nix +++ b/modules/nixos/base.nix @@ -1,18 +1,23 @@ { config, pkgs, lib, ... }: { nixpkgs.config.allowUnfree = true; + # TODO: Consider adding a randomized delay. + nix.gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; + }; nix.settings = { + auto-optimise-store = true; experimental-features = [ "nix-command" "flakes" ]; }; - # Default to systemd-boot - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; - # https://datatracker.ietf.org/doc/html/rfc8375 - networking.domain = "home.arpa"; + networking.domain = lib.mkDefault "home.arpa"; - time.timeZone = "America/Chicago"; + # TODO: Consider enabling automatic-timezoned on laptops that move between TZs + time.timeZone = lib.mkDefault "America/Chicago"; + services.automatic-timezoned.enable = lib.mkDefault false; i18n.defaultLocale = "en_US.UTF-8"; i18n.extraLocaleSettings = { @@ -73,38 +78,39 @@ ]; # Render colors # TODO: Figure out how to represent those termcap sequences properly. - #LESS_TERMCAP_mb=$'\E[1;31m' # begin bold - #LESS_TERMCAP_md=$'\E[1;36m' # begin blink - #LESS_TERMCAP_me=$'\E[0m' # reset bold/blink - #LESS_TERMCAP_so=$'\E[01;44;33m' # begin reverse video - #LESS_TERMCAP_se=$'\E[0m' # reset reverse video - #LESS_TERMCAP_us=$'\E[1;32m' # begin underline - #LESS_TERMCAP_ue=$'\E[0m' # reset underline + LESS_TERMCAP_mb="\E[1;31m"; # begin bold + LESS_TERMCAP_md="\E[1;36m"; # begin blink + LESS_TERMCAP_me="\E[0m"; # reset bold/blink + LESS_TERMCAP_so="\E[01;44;33m"; # begin reverse video + LESS_TERMCAP_se="\E[0m"; # reset reverse video + LESS_TERMCAP_us="\E[1;32m"; # begin underline + LESS_TERMCAP_ue="\E[0m"; # reset underline }; }; git.enable = true; htop.enable = true; - command-not-found.enable = false; bat.enable = true; bandwhich.enable = true; + command-not-found.enable = false; + #nix-index.enable = true; + nano.enable = false; neovim = { enable = true; defaultEditor = true; - viAlias = true; vimAlias = true; - - withRuby = true; - withPython3 = true; - withNodeJs = true; - - #configure = {}; }; }; - # Services running on all machines - services.avahi.enable = true; # zeroconf/mDNS(.local) + services.openssh.enable = lib.mkDefault false; + # services.openssh = { + # enable = true; + # settings = { + # PasswordAuthentication = false; + # PermitRootLogin = "no"; + # }; + # }; } diff --git a/modules/nixos/desktop/default.nix b/modules/nixos/desktop/default.nix index ff03a1c..6c76134 100644 --- a/modules/nixos/desktop/default.nix +++ b/modules/nixos/desktop/default.nix @@ -2,12 +2,14 @@ { imports = [ ./calibre.nix - ./fonts.nix + ../fonts.nix ]; # TODO: Add options for enabling/switching between different Desktop Environments. - options = {}; + # options = {}; + # NOTE: Calibre is enabled this way because it also needs udisks2 for e-readers + # Ideally I move it somewhere else anyway. zw.calibre.enable = true; environment.systemPackages = with pkgs; [ @@ -41,4 +43,5 @@ }; # screen sharing /w hyp services.dbus.enable = true; + services.avahi.enable = true; # zeroconf/mDNS(.local) } diff --git a/modules/nixos/fonts.nix b/modules/nixos/fonts.nix index e39de7a..7d3eca8 100644 --- a/modules/nixos/fonts.nix +++ b/modules/nixos/fonts.nix @@ -1,4 +1,4 @@ -{pkgs}: +{ pkgs, ... }: { fonts.packages = with pkgs; [ nerd-fonts.fira-code diff --git a/users/jml/home.nix b/users/jml/home.nix index f056c62..e2fa5eb 100644 --- a/users/jml/home.nix +++ b/users/jml/home.nix @@ -73,6 +73,11 @@ helix.enable = true; zoxide.enable = true; fd.enable = true; + + difftastic.enable = true; + difftastic.git.enable = true; + difftastic.git.diffToolMode = true; + mergiraf.enable = true; }; programs.starship = { @@ -522,9 +527,9 @@ programs.vscode = { enable = true; mutableExtensionsDir = true; # mutually exclusive to programs.vscode.profiles - profiles.default.userSettings = { - "[nix]"."editor.tabSize" = 2; - }; + # profiles.default.userSettings = { + # "[nix]"."editor.tabSize" = 2; + # }; }; # services.podman.enable = true; }