From 9da942ba47d34210e86a1a709e802eda5c3b95db Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sat, 30 Aug 2025 12:31:28 -0500 Subject: refactor users activation. refactor home manager config to match nixos conf and move tjkeller archetypes to users/timmy. update many of the exising home manager configs to be nicer and better organized. profile archetypes now include homeconfigs which can be enabled per user, and are setup using a new mkProfileArchetype function. --- .sops.yaml | 4 +- archetypes/default.nix | 2 - archetypes/profiles/desktop/default.nix | 46 ++++-- archetypes/profiles/headless/default.nix | 19 ++- archetypes/tjkeller/default.nix | 10 -- archetypes/tjkeller/hosts.nix | 16 --- archetypes/tjkeller/localization.nix | 5 - archetypes/tjkeller/nas.nix | 35 ----- archetypes/tjkeller/printing.nix | 39 ----- .../resources/secrets/hashed-root-password.yaml | 25 ---- .../resources/secrets/wpa_supplicant-conf.yaml | 16 --- archetypes/tjkeller/user.nix | 22 --- archetypes/tjkeller/wifi.nix | 38 ----- archetypes/users/primary.nix | 37 ----- flake.nix | 36 ++--- home-manager/clone-repos.nix | 47 ++++++ home-manager/default.nix | 25 ++-- home-manager/firefox.nix | 159 +++++++++++---------- home-manager/git.nix | 7 - home-manager/gtk-bookmarks.nix | 17 --- home-manager/home-cleanup.nix | 3 + home-manager/htop.nix | 82 ++++++----- home-manager/initial-home-setup.nix | 22 --- home-manager/mint-theme.nix | 43 ++++++ home-manager/pcmanfm.nix | 17 ++- home-manager/qt-gtk-theme.nix | 15 ++ .../resources/activation-scripts/clone-repos.sh | 17 +-- home-manager/theme-st.nix | 49 +++++-- home-manager/theme.nix | 101 ------------- home-manager/userdirs.nix | 5 - home-manager/wallpapers.nix | 13 +- hosts/optiplex/configuration.nix | 37 +++-- hosts/optiplex/home.nix | 4 +- lib/default.nix | 3 + lib/mkprofile.nix | 22 +++ nixos/secrets.nix | 6 +- nixos/services/cgit.nix | 76 ++++++---- nixos/services/gitea.nix | 28 ++-- nixos/services/searxng.nix | 11 +- users/default.nix | 5 + users/timmy/default.nix | 100 +++++++++++++ users/timmy/hosts.nix | 16 +++ users/timmy/localization.nix | 5 + users/timmy/nas.nix | 35 +++++ users/timmy/printing.nix | 39 +++++ .../resources/secrets/hashed-root-password.yaml | 25 ++++ .../resources/secrets/wpa_supplicant-conf.yaml | 16 +++ users/timmy/user.nix | 22 +++ users/timmy/wifi.nix | 38 +++++ 49 files changed, 774 insertions(+), 686 deletions(-) delete mode 100644 archetypes/tjkeller/default.nix delete mode 100644 archetypes/tjkeller/hosts.nix delete mode 100644 archetypes/tjkeller/localization.nix delete mode 100644 archetypes/tjkeller/nas.nix delete mode 100644 archetypes/tjkeller/printing.nix delete mode 100644 archetypes/tjkeller/resources/secrets/hashed-root-password.yaml delete mode 100644 archetypes/tjkeller/resources/secrets/wpa_supplicant-conf.yaml delete mode 100644 archetypes/tjkeller/user.nix delete mode 100644 archetypes/tjkeller/wifi.nix delete mode 100644 archetypes/users/primary.nix create mode 100644 home-manager/clone-repos.nix delete mode 100644 home-manager/git.nix delete mode 100644 home-manager/gtk-bookmarks.nix create mode 100644 home-manager/home-cleanup.nix delete mode 100644 home-manager/initial-home-setup.nix create mode 100644 home-manager/mint-theme.nix create mode 100644 home-manager/qt-gtk-theme.nix delete mode 100644 home-manager/theme.nix delete mode 100644 home-manager/userdirs.nix create mode 100644 lib/default.nix create mode 100644 lib/mkprofile.nix create mode 100644 users/default.nix create mode 100644 users/timmy/default.nix create mode 100644 users/timmy/hosts.nix create mode 100644 users/timmy/localization.nix create mode 100644 users/timmy/nas.nix create mode 100644 users/timmy/printing.nix create mode 100644 users/timmy/resources/secrets/hashed-root-password.yaml create mode 100644 users/timmy/resources/secrets/wpa_supplicant-conf.yaml create mode 100644 users/timmy/user.nix create mode 100644 users/timmy/wifi.nix diff --git a/.sops.yaml b/.sops.yaml index 897d7c7..2a6aa9b 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -2,13 +2,13 @@ keys: - &general age1w80rc0dnuu8nw99gw64c596qqetm78jdnsqajr0u7ephykekr39qfz8vnv - &flex-wg-router age1f0tmpy2nam58skmznjyqd3zf54rxtfrk6fda0vlpq9y3yg6wac7sjf0vja creation_rules: - - path_regex: secrets/hashed-root-password.yaml + - path_regex: timmy/resources/secrets/hashed-root-password.yaml key_groups: - age: - *general - *flex-wg-router - - path_regex: secrets/wpa_supplicant-conf.yaml + - path_regex: timmy/resources/secrets/wpa_supplicant-conf.yaml key_groups: - age: - *general diff --git a/archetypes/default.nix b/archetypes/default.nix index f201fc3..52e5eaa 100644 --- a/archetypes/default.nix +++ b/archetypes/default.nix @@ -9,7 +9,5 @@ ./profiles/desktop ./profiles/headless - - ./users/primary.nix ]; } diff --git a/archetypes/profiles/desktop/default.nix b/archetypes/profiles/desktop/default.nix index d9a7dc7..7ca1e7c 100644 --- a/archetypes/profiles/desktop/default.nix +++ b/archetypes/profiles/desktop/default.nix @@ -1,12 +1,7 @@ { lib, config, pkgs, ... }: let mkDesktop = lib.mkOverride 920; - cfg = config._archetypes.profiles.desktop; -in { - options._archetypes.profiles.desktop = { - enable = lib.mkEnableOption "enable desktop profile"; - }; - config = lib.mkIf cfg.enable { + nixosConfig = { _archetypes.collections = { desktop = { utilities.enable = mkDesktop true; @@ -22,10 +17,6 @@ in { fonts.enable = mkDesktop true; }; - _archetypes.users.primary = { - enable = mkDesktop true; - }; - security = { _doas.enable = mkDesktop true; }; @@ -45,9 +36,42 @@ in { tlp.enable = mkDesktop true; # Ensure video group can change backlight - udev.extraRules = '' + udev.extraRules = mkDesktop '' SUBSYSTEM=="backlight", ACTION=="add", RUN+="${pkgs.coreutils}/bin/chgrp video /sys/class/backlight/%k/brightness", RUN+="${pkgs.coreutils}/bin/chmod g+w /sys/class/backlight/%k/brightness" ''; }; }; + + homeConfig = { + gtk = { + enable = mkDesktop true; + _mintTheme.enable = mkDesktop true; + font.name = mkDesktop "sans-serif"; + cursorTheme.name = mkDesktop "Adwaita"; + }; + + qt._gtkPlatformTheme.enable = mkDesktop true; + + fonts.fontconfig = { + enable = mkDesktop true; + defaultFonts = { + # These fonts are added above in fonts collection + sansSerif = mkDesktop [ "Inter" ]; + monospace = mkDesktop [ "CommitMono" ]; + }; + }; + + programs = { + _pcmanfm.openAsRootOption.enable = mkDesktop true; + firefox._configure = mkDesktop true; + htop._configure = mkDesktop true; + }; + + home._repos = { + enable = mkDesktop true; + desktop = mkDesktop true; + }; + }; +in { + imports = [ (lib._mkProfileArchetype "desktop" nixosConfig homeConfig) ]; } diff --git a/archetypes/profiles/headless/default.nix b/archetypes/profiles/headless/default.nix index ef17db0..b391076 100644 --- a/archetypes/profiles/headless/default.nix +++ b/archetypes/profiles/headless/default.nix @@ -1,22 +1,13 @@ { lib, config, ... }: let mkHeadless = lib.mkOverride 910; - cfg = config._archetypes.profiles.headless; -in { - options._archetypes.profiles.headless = { - enable = lib.mkEnableOption "enable headless profile"; - }; - config = lib.mkIf cfg.enable { + nixosConfig = { _archetypes.collections = { development = { utilities.enable = mkHeadless true; }; }; - _archetypes.users = { - primary.enable = mkHeadless true; - }; - security = { _doas.enable = mkHeadless true; }; @@ -29,4 +20,12 @@ in { _ssh.enable = mkHeadless true; }; }; + + homeConfig = { + home._repos = { + enable = mkHeadless true; + }; + }; +in { + imports = [ (lib._mkProfileArchetype "headless" nixosConfig homeConfig) ]; } diff --git a/archetypes/tjkeller/default.nix b/archetypes/tjkeller/default.nix deleted file mode 100644 index 6a9bbd9..0000000 --- a/archetypes/tjkeller/default.nix +++ /dev/null @@ -1,10 +0,0 @@ -{ - imports = [ - ./hosts.nix - ./localization.nix - ./nas.nix - ./printing.nix - ./user.nix - ./wifi.nix - ]; -} diff --git a/archetypes/tjkeller/hosts.nix b/archetypes/tjkeller/hosts.nix deleted file mode 100644 index 66c6ccc..0000000 --- a/archetypes/tjkeller/hosts.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ - networking.hosts = { - "192.168.1.9" = [ "optiplex" ]; - "192.168.1.30" = [ "localgit" ]; - "192.168.1.11" = [ "truenas-home" ]; - "192.168.77.11" = [ "truenas-office" ]; - "192.168.77.8" = [ "publicgit" "tjkeller" ]; - "192.168.77.3" = [ "devel" ]; - "173.9.253.3" = [ - "git.tjkeller.xyz" - "piped.tjkeller.xyz" - "search.tjkeller.xyz" - "tjkeller.xyz" - ]; - }; -} diff --git a/archetypes/tjkeller/localization.nix b/archetypes/tjkeller/localization.nix deleted file mode 100644 index 8313f07..0000000 --- a/archetypes/tjkeller/localization.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ - time.timeZone = "America/Chicago"; - i18n.defaultLocale = "en_US.UTF-8"; - services.xserver.xkb.layout = "us"; -} diff --git a/archetypes/tjkeller/nas.nix b/archetypes/tjkeller/nas.nix deleted file mode 100644 index 1ed0ca3..0000000 --- a/archetypes/tjkeller/nas.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ lib, config, ... } : -let - cfg = config._archetypes.tjkeller.nas; - mkNetworkFileSystem = device: automount: { - device = "${device}"; - fsType = "nfs"; - options = [ "defaults" ] ++ lib.optionals (!automount) [ "noauto" ]; - }; -in { - options._archetypes.tjkeller.nas = { - enable = lib.mkEnableOption "enable network shares"; - home = { - enable = lib.mkEnableOption "enable home network shares"; - automount = lib.mkEnableOption "automount home network shares"; - }; - office = { - enable = lib.mkEnableOption "enable office network shares"; - automount = lib.mkEnableOption "automount home network shares"; - }; - }; - - config = lib.mkIf cfg.enable { - fileSystems = lib.optionalAttrs cfg.home.enable { - "/media/Storage/Media" = mkNetworkFileSystem "truenas-home:/mnt/Storage/Media" cfg.home.automount; - "/media/Storage/Backups" = mkNetworkFileSystem "truenas-home:/mnt/Storage/Backups" cfg.home.automount; - "/media/Storage/Tapes" = mkNetworkFileSystem "truenas-home:/mnt/Storage/Backups/Tapes" cfg.home.automount; - "/media/Family Photos" = mkNetworkFileSystem "truenas-home:/mnt/Media/Photos" cfg.home.automount; - } // lib.optionalAttrs cfg.office.enable { - "/media/chexx/chexx" = mkNetworkFileSystem "truenas-office:/mnt/Storage/chexx" cfg.office.automount; - "/media/chexx/tkdocs" = mkNetworkFileSystem "truenas-office:/mnt/Storage/Users/Tim-Keller" cfg.office.automount; - "/media/chexx/scans" = mkNetworkFileSystem "truenas-office:/mnt/Storage/Scans" cfg.office.automount; - }; - # TODO auto mkdirz - }; -} diff --git a/archetypes/tjkeller/printing.nix b/archetypes/tjkeller/printing.nix deleted file mode 100644 index d5cceab..0000000 --- a/archetypes/tjkeller/printing.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ lib, config, pkgs, ... }: { - config = lib.mkIf config.services.printing.enable { - # Printer drivers - services.printing.drivers = [ - pkgs.epson-escpr2 - pkgs.workcentre-7800-series - ]; - - # Scanning programs - environment.systemPackages = with pkgs; [ - epsonscan2 - ]; - - # Printers - networking.hosts = { - "192.168.1.35" = [ "Epson_ET-8500" ]; - "192.168.77.40" = [ "Xerox_WorkCentre_7855" ]; - }; - - # Add printers to cups - hardware.printers.ensurePrinters = [ - { - name = "Epson_ET-8500"; - description = "Epson ET-8500"; - location = "Home"; - deviceUri = "ipp://Epson_ET-8500:631/ipp/print"; - model = "epson-inkjet-printer-escpr2/Epson-ET-8500_Series-epson-escpr2-en.ppd"; - } - #{ - # name = "Xerox_WorkCentre_7855"; - # description = "Xerox WorkCentre 7855"; - # location = "Office"; - # deviceUri = "ipp://Xerox_WorkCentre_7855:631/ipp/print"; - # model = "everywhere IPP Everywhere"; - #} - ]; - hardware.printers.ensureDefaultPrinter = "Epson_ET-8500"; - }; -} diff --git a/archetypes/tjkeller/resources/secrets/hashed-root-password.yaml b/archetypes/tjkeller/resources/secrets/hashed-root-password.yaml deleted file mode 100644 index a42fd42..0000000 --- a/archetypes/tjkeller/resources/secrets/hashed-root-password.yaml +++ /dev/null @@ -1,25 +0,0 @@ -hashed-root-password: ENC[AES256_GCM,data:7Qgoeb/6JPNupkHCBEzCs0FMP2cDEw972bjCRWeMrBrAMZzLsZc3Mbv03s1zLztUp6Ie93R5lVsamxKPUnaPt+Tnr/l+0E9aTmt7j7L6UzmWr12nj3FHxxTSU9ief6+ioIk+S4eICJspIQ==,iv:VoWP4qBCGzuYRpQw4nilUXByJ+ZwyZR/BdKowi+53DM=,tag:x6A00VCm8BEOhtv/WySXrQ==,type:str] -sops: - age: - - recipient: age1w80rc0dnuu8nw99gw64c596qqetm78jdnsqajr0u7ephykekr39qfz8vnv - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2Z3dTbW1GUzgyRUwyZGtF - alZSeFBmdEdhNER3UEtGRGd4MnliK1l1eGpJCm80SHFNZ3NZOTNxVkM4R3ZLY005 - OFVtUGN3OXZJblRxOFNMOFhsV25CS0EKLS0tIEE5SG5NekxWbytXY2xNeUN6TWhG - RldJZms3RDFuRk40ck42Mkd5RTd4YVUKgyWE8Cs0yLO/82w2muGWTlcjY86BVSUy - bFeIcQT33dEPiNUmynTqEGpN2NVQbfVDw17QbA9GNhGClanTTXmX4A== - -----END AGE ENCRYPTED FILE----- - - recipient: age1f0tmpy2nam58skmznjyqd3zf54rxtfrk6fda0vlpq9y3yg6wac7sjf0vja - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxcUprWjBXTVlidTRwMEZ6 - WHE4dWp6OWtybkFCaTkyY2JyaWYrRHNhZWtNCi9xamwreEsyVFdnWWhJeUVsdUpT - UHlkRVJZZTEvMDluTWNJSnRSUXN6Q0kKLS0tIHNsQk92SUd2ekowY0hvQi9LNjIx - Q0oxVFNtRkpZTlVHeEY3YXFoSlc4Zk0K7RaqH/Qf2dTPBuCz9DH0xgU+Tq8ATKUq - tfAuuAU9HBtLFiZjhWsZmj5XUy5Z18IiUKDIxlw41mNtbcsUnjm30w== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-17T22:34:07Z" - mac: ENC[AES256_GCM,data:B95HuJC2o8B+P1f9kAtJTcSty7YSAByuqe/Xs6ce6780p05FuzWM5X9bwvwsYXngGNKqCHksWf50UXzJ3eyc6y4ISxdxljAv2FmJFKw4NkfGaOMiRLlGPMn1uFpOtkRT+qL0+mupWG/Ap3zcpbxjsDx46PUur+e6yRxlAHw8mGw=,iv:DYobhWK+4+7vOog7BrBASiHrEzzz0P6zqgWxexfcLG8=,tag:skGwUpDEB8e3TCjrxs5peA==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/archetypes/tjkeller/resources/secrets/wpa_supplicant-conf.yaml b/archetypes/tjkeller/resources/secrets/wpa_supplicant-conf.yaml deleted file mode 100644 index 2fd7a0e..0000000 --- a/archetypes/tjkeller/resources/secrets/wpa_supplicant-conf.yaml +++ /dev/null @@ -1,16 +0,0 @@ -wpa_supplicant-conf: ENC[AES256_GCM,data:QoHQhTuEsSCW/K2ArOzNMfpSV7RtyTgezg4bM6eyNwhBhuJ/fCExzrniZtFzZ3zfs+ROFOYYxkx5lu4N/AQ6xEdCjJ3DYKHpeveqQ3GcWaldDr6aUDxLnBmLGBgSskGoOOANCwGvXGtFsChlCah02/W3YIhLWKIC1pfw1t9ANw9ErtLt7Fxt8TphJ1n9KdCXCJCMFrDjWDTrvbDzrvkJh6EGJIoaXuJSN+9asKrFvTwXyvHPbJmw8ZRbYgtlJtv5c1Q+PZoMtEeBRI/q2y/xUX5nvhnyy3HO1CaZPq+2XP9w+Zz90PyehVvbFVSl3V3Wg3rg9uu/c1rRGgfNkVJSHdhN+7nWYobSI28uoA8L9oXono9mNYwfcN2c4R6xwW9yOH72KabKRbD0Qq0mXcwNjU0HNneqvnMFURbDVstWmKt39gHg2xoZkG774EEDdXBAmKe5nbj0wVk8TBPWPcyR8gQ3uQrXPElqC7CWHMvajzi/hq02gmzkq1DAiheVWHxVmSQUUP3M52vvFBDdWip4X7IM3r5H4uBmcF6wGHl7JS+okDno5BuInIXvrApDV3rTqnam7YeQZao9pbx8WRWg/ZQFUysiXf9tcAl4ror71+SLKa5MfeP9AV431DbcsrIS1XQ=,iv:7qdltuNvesslz32SfEXqu9WFu2uGOGg1sjfskfqfXnk=,tag:N1RhL1M9YtDlvxLBRC2gAg==,type:str] -sops: - age: - - recipient: age1w80rc0dnuu8nw99gw64c596qqetm78jdnsqajr0u7ephykekr39qfz8vnv - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxdXBUWXEvRU85Tk1lNWgz - ZHpENjdudmRuaEJIeVRHOHlDbWNzK0tQMGs4CmV6MVBpdE5PMTBWMm1PcDVFQ2VM - b0IwWDFxLy8xYUcxRVZFSEsyYlBFS1UKLS0tIHpCbDQ0a29TZlVFTGp4aXJCSmJ4 - ZGxqMFQ1NDk1OHJIOUd0cVV0dzNNQlkKzYX36u0rEq6dMTCJf6OON6LzcEEnAB5A - +M9t3OKUUNtwgksjBUEwqBLJ1sU9amijpK63GUxwp74YDtsb0YXHiw== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-07-17T22:33:44Z" - mac: ENC[AES256_GCM,data:leJsAdcWFE0EA1syXfd7yDu1Ct+vTkKiHUEc46O31uUeaWVFwgH8EKC0ImqiHMgbDJv+a9UHm7GtsWy1aMQNVRBXL3R2HbNQkOqGkIIdGsrrbjslQl8UwI7wx1g2P3ORhlGRYXTscDUl53+e4i3YrYOEDDPL5EAWuQEWldJXLZc=,iv:banL6qqV2EqfZFKHn5dawUq95Ima06z8H6Kso1qRdcA=,tag:g6M95M6bT4UPTfiEZT4ljw==,type:str] - unencrypted_suffix: _unencrypted - version: 3.10.2 diff --git a/archetypes/tjkeller/user.nix b/archetypes/tjkeller/user.nix deleted file mode 100644 index 2695549..0000000 --- a/archetypes/tjkeller/user.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ lib, config, pkgs, userDetails, ... }: let - cfg = config._archetypes.tjkeller.setPasswords; - hashedPasswordFile = config.sops.secrets.hashed-root-password.path; -in { - options._archetypes.tjkeller.setPasswords = { - enable = lib.mkEnableOption "set users password. requires hashed root password from sops"; - }; - - config = lib.mkIf cfg.enable { - # Load hashed root password secret - sops.secrets.hashed-root-password = { - sopsFile = ./resources/secrets/hashed-root-password.yaml; - neededForUsers = true; - }; - - # Apply password file - users.users = { - root = { inherit hashedPasswordFile; }; - ${userDetails.username} = lib.mkIf config._archetypes.users.primary.enable { inherit hashedPasswordFile; }; - }; - }; -} diff --git a/archetypes/tjkeller/wifi.nix b/archetypes/tjkeller/wifi.nix deleted file mode 100644 index 32b6ef8..0000000 --- a/archetypes/tjkeller/wifi.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ lib, config, ... }: let - cfg = config._archetypes.tjkeller.wifi; -in { - options._archetypes.tjkeller.wifi = { - enable = lib.mkEnableOption "enables wifi"; - }; - - config = lib.mkIf cfg.enable { - networking.wireless = { - enable = true; # Enables wireless support via wpa_supplicant. - userControlled.enable = true; - allowAuxiliaryImperativeNetworks = true; # Networks defined in aux imperitive networks (/etc/wpa_supplicant.conf) - }; - - # Load wpa_supplicant.conf secret config - sops.secrets.wpa_supplicant-conf = { - sopsFile = ./resources/secrets/wpa_supplicant-conf.yaml; - }; - - # Link /etc/wpa_supplicant.conf -> secret config - environment.etc."wpa_supplicant.conf" = { - source = config.sops.secrets.wpa_supplicant-conf.path; - }; - - # This service is a workaround to ensure that secrets are available on - # reboot when the secret keys are on a separate subvolume - systemd.services.npcnix-force-rebuild-sops-hack = { - wantedBy = [ "multi-user.target" ]; - before = [ "wpa_supplicant.service" ]; - serviceConfig = { - ExecStart = "/run/current-system/activate"; - Type = "oneshot"; - Restart = "on-failure"; # because oneshot - RestartSec = "10s"; - }; - }; - }; -} diff --git a/archetypes/users/primary.nix b/archetypes/users/primary.nix deleted file mode 100644 index a29c3b8..0000000 --- a/archetypes/users/primary.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ lib, config, pkgs, userDetails, ... }: let - cfg = config._archetypes.users.primary; -in { - options._archetypes.users.primary = { - enable = lib.mkEnableOption "create primary user"; - autologin.enable = lib.mkEnableOption "enables getty automatic login"; - }; - - config = lib.mkIf cfg.enable { - # Enable zsh - programs.zsh.enable = true; - - # Setup normal user - users.users.${userDetails.username} = { - home = userDetails.home; - description = userDetails.fullname; - isNormalUser = true; - shell = pkgs.zsh; - extraGroups = [ - "nixbld" - "video" - "wheel" - ] ++ lib.optionals config.hardware.i2c.enable [ - "i2c" - ] ++ lib.optionals config.virtualisation.libvirtd.enable [ - "libvirtd" - ] ++ lib.optionals config.virtualisation.docker.enable [ - "docker" - ]; - }; - - # Configure automatic login with getty - services.getty = lib.mkIf cfg.autologin.enable { - autologinUser = userDetails.username; - }; - }; -} diff --git a/flake.nix b/flake.nix index 007bd8e..c9e7d41 100644 --- a/flake.nix +++ b/flake.nix @@ -18,49 +18,33 @@ rec { }; }; - outputs = { nixpkgs, home-manager, arkenfox, ... }@inputs : + outputs = { nixpkgs, ... }@inputs : let system = "x86_64-linux"; - #pkgs = nixpkgs.legacyPackages.${system}; - userDetails = { - username = "timmy"; - email = "tjk@tjkeller.xyz"; - fullname = "Tim Keller"; - home = "/home/${userDetails.username}"; - userDirs = with userDetails; { - desktop = "${home}"; - download = "${home}/dls"; - documents = "${home}/docs"; - pictures = "${home}/pics"; - }; - sshPublicKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDnsnAWcz46OVi1MWSxpOIUtUvwalijDwvW+oEvNjzep" ]; - }; - homeStateVersion = "24.05"; # Lowest of systems is fine + extLib = nixpkgs.lib.extend (final: prev: import ./lib); mkNixosConfiguration = hostname: nixpkgs.lib.nixosSystem { inherit system; specialArgs = { inherit inputs; inherit hostname; - inherit userDetails; + lib = extLib; }; modules = [ ./hosts/${hostname}/configuration.nix - ./nixos + ./hosts/${hostname}/hardware-configuration.nix ./archetypes + ./nixos ./pkgs - home-manager.nixosModules.home-manager { + ./users + inputs.sops-nix.nixosModules.sops + inputs.home-manager.nixosModules.home-manager { home-manager = { backupFileExtension = "backup"; # In case file is overwritten useGlobalPkgs = true; useUserPackages = true; - users.${userDetails.username} = import ./home-manager; - extraSpecialArgs = { - inherit userDetails; - inherit homeStateVersion; - }; sharedModules = [ - arkenfox.hmModules.arkenfox - ./hosts/${hostname}/home.nix + inputs.arkenfox.hmModules.arkenfox + ./home-manager ]; }; } diff --git a/home-manager/clone-repos.nix b/home-manager/clone-repos.nix new file mode 100644 index 0000000..8499760 --- /dev/null +++ b/home-manager/clone-repos.nix @@ -0,0 +1,47 @@ +{ config, lib, pkgs, ... }: let + cfg = config.home._repos; + # TODO MAKE OPTIONS + server = "https://git.tjkeller.xyz/"; + docs = config.xdg.userDirs.documents; + dotConfig = config.xdg.configHome; + bin = "$HOME/.local/bin"; + cloneMissing = repo: source: target: ''clonemissing "${repo}" "${source}" "${target}"''; +in { + options.home._repos = { + enable = lib.mkEnableOption "clone git repos"; + desktop = lib.mkEnableOption "clone repos that are for desktop use"; + }; + + config = lib.mkIf cfg.enable { + # TODO look into xdg.configFile. + home.activation = { + cloneRepos = lib.hm.dag.entryAfter ["writeBoundary"] ('' + export PATH="${pkgs.git}/bin:$PATH" + ${builtins.readFile ./resources/activation-scripts/clone-repos.sh} + '' + lib.strings.concatStringsSep "\n" ([ + (cloneMissing "${server}dotconfig" "${docs}/config" dotConfig) + (cloneMissing "${server}nixos" "${docs}/nixos" "") + (cloneMissing "${server}nvim" "${dotConfig}/nvim" "") + (cloneMissing "${server}zsh" "${dotConfig}/zsh" "") + ] ++ lib.optionals cfg.desktop [ + (cloneMissing "${server}scripts" "${docs}/scripts" bin) + (cloneMissing "${server}userscripts" "${docs}/userscripts" "") + (cloneMissing "${server}awesome" "${dotConfig}/awesome" "") + ])); + linkZshProfile = lib.hm.dag.entryAfter ["writeBoundary"] '' + run ln -sf $VERBOSE_ARG ${dotConfig}/zsh/zprofile $HOME/.zprofile + ''; + + # TODO look into xdg.mimeApps.defaultApplications + #mimewiz = lib.mkIf cfg.desktop (lib.hm.dag.entryAfter ["writeBoundary"] '' + # export PATH="${pkgs.xdg-utils}/bin:$PATH" + # export PATH="${dotConfig}/misc:$PATH" + # run mimewiz -i # already verbose + #''); + }; + #home.file.Zprofile = { + # source = "${dotConfig}/zsh/zprofile"; + # target = ".zprofile"; + #}; + }; +} diff --git a/home-manager/default.nix b/home-manager/default.nix index bcd99eb..26c97c2 100644 --- a/home-manager/default.nix +++ b/home-manager/default.nix @@ -1,25 +1,16 @@ -{ lib, userDetails, homeStateVersion, ... }: { - home = { - username = userDetails.username; - homeDirectory = lib.mkForce userDetails.home; - stateVersion = homeStateVersion; - }; - +{ imports = [ + ./clone-repos.nix ./firefox.nix - ./git.nix - ./gtk-bookmarks.nix + ./home-cleanup.nix ./htop.nix - ./initial-home-setup.nix - ./pcmanfm.nix # TODO mk name changeable & doesn't seem to work right now + ./mint-theme.nix + ./pcmanfm.nix + ./qt-gtk-theme.nix ./theme-st.nix - ./theme.nix - ./userdirs.nix ./wallpapers.nix ]; - theme.enable = lib.mkDefault true; - theme.st.enable = lib.mkDefault false; - theme.mint.enable = lib.mkDefault true; - wallpapers.enable = lib.mkDefault false; + # Let Home Manager install and manage itself. + programs.home-manager.enable = true; } diff --git a/home-manager/firefox.nix b/home-manager/firefox.nix index 8aa1af3..811b811 100644 --- a/home-manager/firefox.nix +++ b/home-manager/firefox.nix @@ -1,82 +1,89 @@ -{ lib, pkgs, userDetails, ... }: { - programs.firefox = { - enable = lib.mkDefault true; - arkenfox.enable = true; - profiles = let - search = { - engines = { - "Timmy Search" = { - urls = [{ - template = "https://search.tjkeller.xyz/search"; - params = [ { name = "q"; value = "{searchTerms}"; } ]; - }]; - iconURI = "https://search.tjkeller.xyz/static/themes/simple/img/favicon.svg"; # TODO doesn't seem to work - }; - "Nix Packages" = { - urls = [{ - template = "https://search.nixos.org/packages"; - params = [ { name = "query"; value = "{searchTerms}"; } ]; - }]; - icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; - definedAliases = [ "@np" ]; - }; - "NixOS Options" = { - urls = [{ - template = "https://search.nixos.org/options"; - params = [ { name = "query"; value = "{searchTerms}"; } ]; - }]; - icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; - definedAliases = [ "@no" ]; - }; - }; - default = "Timmy Search"; - privateDefault = "Timmy Search"; - force = true; # Overwrite old - }; - userChrome = builtins.readFile ./resources/firefox/userChrome.css; - arkenfox = { - enable = true; - enableAllSections = true; - "0100"."0102"."browser.startup.page".value = 3; # 0=blank, 1=home, 2=last visited page, 3=resume previous session - "0100"."0103"."browser.startup.homepage".enable = false; - "0100"."0104"."browser.newtabpage.enabled".enable = false; - #"2800"."2811"."privacy.clearOnShutdown.history".enable = false; - }; - settings = { - "browser.compactmode.show" = true; - "browser.uiCustomization.state" = builtins.readFile ./resources/firefox/uiCustomization.json; # Toolbar etc. - "browser.uidensity" = 1; # Compact - "toolkit.legacyUserProfileCustomizations.stylesheets" = true; # userchrome - - "app.normandy.first_run" = false; - "browser.aboutConfig.showWarning" = false; # arkenfox does - #"browser.download.dir" = userDetails.userDirs.downloads; - "browser.newtabpage.activity-stream.feeds.section.topstories" = false; - "browser.newtabpage.activity-stream.feeds.topsites" = false; - "browser.urlbar.suggest.topsites" = false; - "devtools.toolbox.host" = "window"; - "dom.push.enabled" = false; # - "extensions.pocket.enabled" = false; - "general.smoothScroll" = false; +{ config, lib, pkgs, ... }: let + cfg = config.programs.firefox; + search = { + engines = { + "Timmy Search" = { + urls = [{ + template = "https://search.tjkeller.xyz/search"; + params = [ { name = "q"; value = "{searchTerms}"; } ]; + }]; + iconURI = "https://search.tjkeller.xyz/static/themes/simple/img/favicon.svg"; # TODO doesn't seem to work }; - workSettings = settings // { - "extensions.activeThemeID" = "firefox-compact-dark@mozilla.org"; # Use builtin dark theme instead of system theme + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ { name = "query"; value = "{searchTerms}"; } ]; + }]; + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@np" ]; }; - in { - Personal = { - id = 0; - isDefault = true; - inherit search; - inherit userChrome; - inherit arkenfox; - inherit settings; + "NixOS Options" = { + urls = [{ + template = "https://search.nixos.org/options"; + params = [ { name = "query"; value = "{searchTerms}"; } ]; + }]; + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@no" ]; }; - Work = { - id = 1; - inherit search; - inherit userChrome; - inherit arkenfox; - settings = workSettings; + }; + default = "Timmy Search"; + privateDefault = "Timmy Search"; + force = true; # Overwrite old + }; + userChrome = builtins.readFile ./resources/firefox/userChrome.css; + arkenfox = { + enable = true; + enableAllSections = true; + "0100"."0102"."browser.startup.page".value = 3; # 0=blank, 1=home, 2=last visited page, 3=resume previous session + "0100"."0103"."browser.startup.homepage".enable = false; + "0100"."0104"."browser.newtabpage.enabled".enable = false; + #"2800"."2811"."privacy.clearOnShutdown.history".enable = false; + }; + settings = { + "browser.compactmode.show" = true; + "browser.uiCustomization.state" = builtins.readFile ./resources/firefox/uiCustomization.json; # Toolbar etc. + "browser.uidensity" = 1; # Compact + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; # userchrome + + "app.normandy.first_run" = false; + "browser.aboutConfig.showWarning" = false; # arkenfox does + #"browser.download.dir" = userDetails.userDirs.downloads; + "browser.newtabpage.activity-stream.feeds.section.topstories" = false; + "browser.newtabpage.activity-stream.feeds.topsites" = false; + "browser.urlbar.suggest.topsites" = false; + "devtools.toolbox.host" = "window"; + "dom.push.enabled" = false; # + "extensions.pocket.enabled" = false; + "general.smoothScroll" = false; + }; + workSettings = settings // { + "extensions.activeThemeID" = "firefox-compact-dark@mozilla.org"; # Use builtin dark theme instead of system theme + }; +in { + options.programs.firefox = { + _configure = lib.mkEnableOption "configure firefox profiles"; + }; + + config = lib.mkIf cfg._configure { + programs.firefox = { + enable = lib.mkDefault true; + arkenfox.enable = lib.mkDefault true; + profiles = { + Personal = { + id = 0; + isDefault = true; + inherit search; + inherit userChrome; + inherit arkenfox; + inherit settings; + }; + Work = { + id = 1; + inherit search; + inherit userChrome; + inherit arkenfox; + settings = workSettings; + }; }; }; }; diff --git a/home-manager/git.nix b/home-manager/git.nix deleted file mode 100644 index 9d15a90..0000000 --- a/home-manager/git.nix +++ /dev/null @@ -1,7 +0,0 @@ -{ userDetails, ... }: { - programs.git = { - enable = true; - userName = userDetails.fullname; - userEmail = userDetails.email; - }; -} diff --git a/home-manager/gtk-bookmarks.nix b/home-manager/gtk-bookmarks.nix deleted file mode 100644 index 24c6563..0000000 --- a/home-manager/gtk-bookmarks.nix +++ /dev/null @@ -1,17 +0,0 @@ -{ config, lib, userDetails, ... }: { - options = { - additional-gtk-bookmarks = lib.mkOption { - type = with lib.types; listOf str; - default = []; - description = "gtk bookmarks for file managers, etc."; - }; - }; - - config = { - gtk.gtk3.bookmarks = ( - lib.mapAttrsToList (name: path: - "file://${path} ${lib.toUpper (lib.substring 0 1 name)}${lib.substring 1 (-1) name}" - ) userDetails.userDirs - ) ++ config.additional-gtk-bookmarks; - }; -} diff --git a/home-manager/home-cleanup.nix b/home-manager/home-cleanup.nix new file mode 100644 index 0000000..b124342 --- /dev/null +++ b/home-manager/home-cleanup.nix @@ -0,0 +1,3 @@ +{ config, ... }: { + gtk.gtk2.configLocation = "${config.xdg.configHome}/gtk-2.0/gtkrc"; +} diff --git a/home-manager/htop.nix b/home-manager/htop.nix index 523fee8..36ccbac 100644 --- a/home-manager/htop.nix +++ b/home-manager/htop.nix @@ -1,38 +1,46 @@ -{ config, ... }: { - programs.htop.enable = true; - programs.htop.settings = { - fields = with config.lib.htop.fields; [ - PID - USER - 124 # EXE - PERCENT_CPU - PERCENT_MEM - STARTTIME - ELAPSED # time elapsed since process start - IO_READ_RATE - RBYTES # num read bytes - IO_WRITE_RATE - WBYTES # num written bytes - TIME - STIME # sys time - CSTIME # child sys time - NICE - STATE - PRIORITY - 125 # CWD - ]; - } // (with config.lib.htop; leftMeters [ - (bar "AllCPUs2") - (bar "CPU") - (bar "Memory") - (bar "DiskIO") - (bar "NetworkIO") - ]) // (with config.lib.htop; rightMeters [ - (text "Hostname") - (text "Clock") - (text "Uptime") - (text "Battery") - (text "LoadAverage") - (text "Tasks") - ]); +{ config, lib, ... }: let + cfg = config.programs.htop; +in { + options.programs.htop = { + _configure = lib.mkEnableOption "apply sensible defaults to htop"; + }; + + config = lib.mkIf cfg._configure { + programs.htop.enable = lib.mkDefault true; + programs.htop.settings = { + fields = with config.lib.htop.fields; [ + PID + USER + 124 # EXE + PERCENT_CPU + PERCENT_MEM + STARTTIME + ELAPSED # time elapsed since process start + IO_READ_RATE + RBYTES # num read bytes + IO_WRITE_RATE + WBYTES # num written bytes + TIME + STIME # sys time + CSTIME # child sys time + NICE + STATE + PRIORITY + 125 # CWD + ]; + } // (with config.lib.htop; leftMeters [ + (bar "AllCPUs2") + (bar "CPU") + (bar "Memory") + (bar "DiskIO") + (bar "NetworkIO") + ]) // (with config.lib.htop; rightMeters [ + (text "Hostname") + (text "Clock") + (text "Uptime") + (text "Battery") + (text "LoadAverage") + (text "Tasks") + ]); + }; } diff --git a/home-manager/initial-home-setup.nix b/home-manager/initial-home-setup.nix deleted file mode 100644 index 4132386..0000000 --- a/home-manager/initial-home-setup.nix +++ /dev/null @@ -1,22 +0,0 @@ -{ config, lib, pkgs, userDetails, ... }: { - home.activation = { - cloneRepos = lib.hm.dag.entryAfter ["writeBoundary"] '' - export PATH="${config.home.path}/bin:$PATH" - ${builtins.readFile ./resources/activation-scripts/clone-repos.sh} - ''; - linkZshProfile = lib.hm.dag.entryAfter ["writeBoundary"] '' - run ln -sf $VERBOSE_ARG $HOME/.config/zsh/zprofile $HOME/.zprofile - ''; - cleanupHome = lib.hm.dag.entryAfter ["writeBoundary"] '' - run rm -f $VERBOSE_ARG $HOME/{.zcompdump,.zshrc,.zsh_history,.bash_history} - ''; - mimewiz = lib.hm.dag.entryAfter ["writeBoundary"] '' - export PATH="${pkgs.xdg-utils}/bin:$PATH" - export PATH="$HOME/.local/bin/misc:$PATH" - run mimewiz -i # already verbose - ''; - createDirs = lib.hm.dag.entryAfter ["writeBoundary"] '' - run mkdir -p $VERBOSE_ARG ${ lib.concatStringsSep " " (lib.attrValues userDetails.userDirs) } - ''; - }; -} diff --git a/home-manager/mint-theme.nix b/home-manager/mint-theme.nix new file mode 100644 index 0000000..a77be6a --- /dev/null +++ b/home-manager/mint-theme.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.gtk._mintTheme; # gtk.theme type is null or submodule under the hood so gtk.theme._mint, etc. can't be used + transformColorValue = color: dark: + "Mint-Y" + lib.optionalString dark "-Dark" + + lib.optionalString (color != "Green") ("-" + color) + ; +in { + options.gtk._mintTheme = { + enable = lib.mkEnableOption "enables mint theme"; + color = lib.mkOption { + type = lib.types.enum [ + "Aqua" "Blue" "Green" "Grey" "Orange" + "Pink" "Purple" "Red" "Sand" "Teal" + ]; + default = "Green"; + description = "mint-y theme color"; + }; + dark = lib.mkEnableOption "whether to use dark variant of mint theme"; + icons.color = lib.mkOption { + type = lib.types.enum [ + "Aqua" "Blue" "Green" "Grey" "Orange" "Pink" "Purple" "Red" + "Sand" "Teal" + ]; + default = "Aqua"; + description = "mint-y icons color eg. 'Aqua' or 'Red'"; + }; + }; + + config = lib.mkIf cfg.enable { + gtk = { + enable = true; + theme = { + package = pkgs.mint-themes; + name = transformColorValue cfg.color cfg.dark; + }; + iconTheme = { + package = pkgs.mint-y-icons; + name = transformColorValue cfg.icons.color false; + }; + }; + }; +} diff --git a/home-manager/pcmanfm.nix b/home-manager/pcmanfm.nix index 3c70521..a99fb15 100644 --- a/home-manager/pcmanfm.nix +++ b/home-manager/pcmanfm.nix @@ -1,6 +1,15 @@ -{ - home.file.pcmanfm-root = { - target = ".local/share/file-manager/actions/root.desktop"; - source = ./resources/pcmanfm/root.desktop; +{ config, lib, ... }: let + cfg = config.programs._pcmanfm.openAsRootOption; +in { + options.programs._pcmanfm.openAsRootOption = { + enable = lib.mkEnableOption "enable 'open as root' option in pcmanfm right-click menu"; + }; + + config = lib.mkIf cfg.enable { + home.file.pcmanfm-root = { + target = ".local/share/file-manager/actions/root.desktop"; + # FIXME this action uses an absolute path pls fix + source = ./resources/pcmanfm/root.desktop; + }; }; } diff --git a/home-manager/qt-gtk-theme.nix b/home-manager/qt-gtk-theme.nix new file mode 100644 index 0000000..2e53ccc --- /dev/null +++ b/home-manager/qt-gtk-theme.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.qt._gtkPlatformTheme; +in { + options.qt._gtkPlatformTheme = { + enable = lib.mkEnableOption "use gtk theme in qt"; + }; + + config = lib.mkIf cfg.enable { + qt = { + enable = lib.mkDefault true; + platformTheme.name = "gtk3"; + }; + }; +} diff --git a/home-manager/resources/activation-scripts/clone-repos.sh b/home-manager/resources/activation-scripts/clone-repos.sh index eaee4dc..adf8fd7 100644 --- a/home-manager/resources/activation-scripts/clone-repos.sh +++ b/home-manager/resources/activation-scripts/clone-repos.sh @@ -1,7 +1,5 @@ #!/bin/sh -server="https://git.tjkeller.xyz/" - clonemissing() { # pull and return if already existing if [ -d "$2"/.git ]; then @@ -10,21 +8,12 @@ clonemissing() { return fi - # clone to $2 + # clone $1 to $2 run mkdir -p $VERBOSE_ARG "$2" - run git clone $VERBOSE_ARG "$server$1" "$2" + run git clone $VERBOSE_ARG "$1" "$2" - # link to $3 + # link files to $3 [ -z "$3" ] && return run mkdir -p $VERBOSE_ARG "$3" run ln -sf $VERBOSE_ARG "$2"/* "$3" } - -# # repo # clone to # link to -clonemissing scripts $HOME/docs/src/scripts $HOME/.local/bin -clonemissing dotconfig $HOME/docs/src/config $HOME/.config -clonemissing userscripts $HOME/docs/src/userscripts '' -clonemissing nixos $HOME/docs/src/nixos '' -clonemissing awesome $HOME/.config/awesome '' -clonemissing nvim $HOME/.config/nvim '' -clonemissing zsh $HOME/.config/zsh '' diff --git a/home-manager/theme-st.nix b/home-manager/theme-st.nix index 0a06cd0..aa4ddbb 100644 --- a/home-manager/theme-st.nix +++ b/home-manager/theme-st.nix @@ -1,22 +1,41 @@ -{ config, lib, pkgs, ... }: { - options = { - theme.st = { - enable = lib.mkEnableOption "enables theming st with home manager"; - font = lib.mkOption { +{ config, lib, pkgs, ... }: let + cfg = config.programs._st; + generateXftFontString = name: attrs: + name + lib.optionalString lib.attrIsEmpty attrs ( + ":" + builtins.concatStringsSep ":" ( + lib.mapAttrsToList (key: value: "${key}=${value}") attrs + ) + ) + ; + themed-st = pkgs.st.overrideAttrs (old: { + buildInputs = old.buildInputs or [] ++ [ pkgs.makeWrapper ]; + postInstall = old.postInstall or "" + '' + wrapProgram $out/bin/st \ + --add-flags '-f"${generateXftFontString cfg.font.name cfg.font.attrs}"' + ''; + }); +in { + options.programs._st = { + enable = lib.mkEnableOption "enables theming st with home manager"; + font = { + name = lib.mkOption { type = lib.types.str; - default = "JetBrainsMonoNL Nerd Font Mono:size=12:antialias=true:autohint=true"; + example = "JetBrainsMonoNL Nerd Font Mono"; + default = "monospace"; + }; + attrs = { + type = lib.types.attrs; + default = {}; + example = { + size = 12; + antialias = true; + autohint = true; + }; }; }; }; - config = let - themed-st = pkgs.st.overrideAttrs (old: { - buildInputs = old.buildInputs or [] ++ [ pkgs.makeWrapper ]; - postInstall = old.postInstall or "" + '' - wrapProgram $out/bin/st \ - --add-flags '-f"${config.theme.st.font}"' - ''; - }); - in lib.mkIf config.theme.enable { + + config = lib.mkIf cfg.enable { home.packages = [ themed-st ]; }; } diff --git a/home-manager/theme.nix b/home-manager/theme.nix deleted file mode 100644 index 9e4edae..0000000 --- a/home-manager/theme.nix +++ /dev/null @@ -1,101 +0,0 @@ -{ config, lib, pkgs, ... }: -let - transformColorValue = color : - if color == "Green" then "Mint-Y" - else if color == "Dark-Green" then "Mint-Y-Dark" - else "Mint-Y-${color}" - ; -in { - options = { - theme.enable = lib.mkEnableOption "enables theming"; - theme.mint = { - enable = lib.mkEnableOption "enables mint theme"; - # TODO add theme.dark option instead of specifying Dark-Color - theme.color = lib.mkOption { - type = lib.types.enum [ - "Aqua" "Blue" "Green" "Grey" "Orange" "Pink" "Purple" "Red" - "Sand" "Teal" "Dark-Aqua" "Dark-Blue" "Dark-Green" - "Dark-Grey" "Dark-Orange" "Dark-Pink" "Dark-Purple" - "Dark-Red" "Dark-Sand" "Dark-Teal" - ]; - default = "Dark-Aqua"; - description = "mint-y theme color eg. 'Dark-Aqua' or 'Red'"; - }; - icons.color = lib.mkOption { - type = lib.types.enum [ - "Aqua" "Blue" "Green" "Grey" "Orange" "Pink" "Purple" "Red" - "Sand" "Teal" - ]; - default = "Aqua"; - description = "mint-y icons color eg. 'Aqua' or 'Red'"; - }; - }; - theme.font = { - sansSerif = lib.mkOption { - type = lib.types.str; - default = "Inter"; - description = "default sans serif font"; - }; - monospace = lib.mkOption { - type = lib.types.str; - default = "CommitMono"; - description = "default monospace font"; - }; - gtk = { - name = lib.mkOption { - type = lib.types.str; - default = "sans-serif"; - description = "default gtk font"; - }; - size = lib.mkOption { - type = with lib.types; nullOr int; - default = null; - description = "default gtk font size"; - }; - }; - }; - theme.cursor = { - name = lib.mkOption { - type = lib.types.str; - default = "Adwaita"; - description = "gtk cursor theme"; - }; - size = lib.mkOption { - type = with lib.types; nullOr int; - default = null; - description = "gtk cursor size"; - }; - }; - }; - - config = lib.mkIf config.theme.enable { - gtk = { - enable = true; - theme = lib.mkIf config.theme.mint.enable { - package = pkgs.mint-themes; - name = transformColorValue config.theme.mint.theme.color; - }; - iconTheme = lib.mkIf config.theme.mint.enable { - package = pkgs.mint-y-icons; - name = transformColorValue config.theme.mint.icons.color; - }; - font = { - name = config.theme.font.gtk.name; - size = config.theme.font.gtk.size; - }; - cursorTheme = { - name = config.theme.cursor.name; - size = config.theme.cursor.size; - }; - gtk2.configLocation = "${config.xdg.configHome}/gtk-2.0/gtkrc"; - }; - qt = { - enable = true; - platformTheme.name = "gtk3"; - }; - fonts.fontconfig.defaultFonts = { - sansSerif = [ config.theme.font.sansSerif ]; - monospace = [ config.theme.font.monospace ]; - }; - }; -} diff --git a/home-manager/userdirs.nix b/home-manager/userdirs.nix deleted file mode 100644 index 58c1d59..0000000 --- a/home-manager/userdirs.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ userDetails, ... }: { - xdg.userDirs = { - enable = true; - } // userDetails.userDirs; -} diff --git a/home-manager/wallpapers.nix b/home-manager/wallpapers.nix index d7e067a..de64d76 100644 --- a/home-manager/wallpapers.nix +++ b/home-manager/wallpapers.nix @@ -1,10 +1,13 @@ -{ lib, config, pkgs, ... }: { - options = { - wallpapers.enable = lib.mkEnableOption "enables all wallpapers"; +{ lib, config, pkgs, ... }: let + cfg = config.programs._seasonalwallpaper.wallpapers; +in { + options.programs._seasonalwallpaper.wallpapers = { + download = lib.mkEnableOption "enables all wallpapers"; }; - config = lib.mkIf config.wallpapers.enable { - home.file.".local/share/wallpaper" = { + config = lib.mkIf cfg.download { + home.file.wallpapers = { + target = ".local/share/wallpaper"; source = pkgs.fetchzip { url = "https://tjkeller.xyz/permalinks/wallpapers.tar"; hash = "sha256-lhj9wUMZfd0XOrUtWY9HB64oXrS/EjsvsaJHzu4ucFg="; diff --git a/hosts/optiplex/configuration.nix b/hosts/optiplex/configuration.nix index 8a06294..b92b580 100644 --- a/hosts/optiplex/configuration.nix +++ b/hosts/optiplex/configuration.nix @@ -1,16 +1,14 @@ -{ config, lib, pkgs, ... }: { - imports = [ - ./hardware-configuration.nix - ../../archetypes/tjkeller - ]; - +{ config, lib, pkgs, home-manager, ... }: { # Setup bootloader boot._loader.enable = true; # Enable common options _archetypes = { # Use desktop profile - profiles.desktop.enable = true; + profiles.desktop = { + enable = true; + home.users.timmy.enable = true; + }; # Install software collections = { desktop = { @@ -35,14 +33,13 @@ }; }; }; - # Setup user - users.primary = { - enable = true; - autologin.enable = true; - }; - tjkeller = { - nas.enable = true; - }; + }; + + # Enable user timmy + _users.timmy = { + enable = true; + autologin.enable = true; + nas.enable = true; }; # Disable suspend @@ -69,5 +66,15 @@ forceFullCompositionPipeline = true; # Enables vsync }; + # Configure home + home-manager.users.timmy = { + gtk._mintTheme = { + dark = true; + color = "Green"; + icons.color = "Green"; + }; + programs._seasonalwallpaper.wallpapers.download = true; + }; + system.stateVersion = "24.11"; } diff --git a/hosts/optiplex/home.nix b/hosts/optiplex/home.nix index d293ae0..38646b1 100644 --- a/hosts/optiplex/home.nix +++ b/hosts/optiplex/home.nix @@ -1,6 +1,4 @@ -{ ... }: { - imports = [ ../../home-manager ]; - +{ theme.mint.theme.color = "Dark-Green"; theme.mint.icons.color = "Green"; wallpapers.enable = true; diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..01801a2 --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,3 @@ +{ + _mkProfileArchetype = import ./mkprofile.nix; +} diff --git a/lib/mkprofile.nix b/lib/mkprofile.nix new file mode 100644 index 0000000..ec851de --- /dev/null +++ b/lib/mkprofile.nix @@ -0,0 +1,22 @@ +profileName: nixosConfig: homeConfig: { config, lib, ... }: let + cfg = config._archetypes.profiles.${profileName}; + enabledUsers = lib.filterAttrs (user: userCfg: userCfg.enable) cfg.home.users; + homeConfigs = { + home-manager.users = lib.mapAttrs (user: userCfg: homeConfig) enabledUsers; + }; +in { + options._archetypes.profiles.${profileName} = { + enable = lib.mkEnableOption "enable nixos profile ${profileName}"; + home.users = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { + options = { + enable = lib.mkEnableOption "home-manager profile ${profileName} for user"; + }; + }); + default = {}; + description = "enable home-manager profile ${profileName} for user the specified user"; + }; + }; + + config = lib.mkIf cfg.enable (lib.mkMerge [ nixosConfig homeConfigs ]); +} diff --git a/nixos/secrets.nix b/nixos/secrets.nix index 46d8f1e..0691255 100644 --- a/nixos/secrets.nix +++ b/nixos/secrets.nix @@ -1,10 +1,8 @@ -{ inputs, config, pkgs, userDetails, ... }: { - imports = [ inputs.sops-nix.nixosModules.sops ]; - +{ inputs, config, pkgs, ... }: { environment.systemPackages = with pkgs; [ age sops ]; sops = { defaultSopsFormat = "yaml"; - age.sshKeyPaths = [ "${userDetails.home}/.ssh/id_ed25519" "/root/.ssh/id_ed25519" ]; + age.sshKeyPaths = [ "/root/.ssh/id_ed25519" ]; }; } diff --git a/nixos/services/cgit.nix b/nixos/services/cgit.nix index 366c1f8..66de1d8 100644 --- a/nixos/services/cgit.nix +++ b/nixos/services/cgit.nix @@ -1,34 +1,50 @@ -{ lib, pkgs, config, userDetails, ... }: +{ lib, pkgs, config, ... }: let - cfg = config.cgit; + cfg = config.services._cgit; in { - options = { - cgit = { - enable = lib.mkEnableOption "enables cgit service"; - hostAddress = lib.mkOption { - type = lib.types.str; - description = "hostAddress for the container"; - default = "10.0.1.1"; - }; - localAddress = lib.mkOption { - type = lib.types.str; - description = "localAddress for the container"; - default = "10.0.1.2"; - }; - rootTitle = lib.mkOption { - type = lib.types.str; - description = "cgit site title"; - default = ""; - }; - rootDesc = lib.mkOption { - type = lib.types.str; - description = "cgit site description"; - default = ""; + options.services._cgit = { + enable = lib.mkEnableOption "enables cgit service"; + hostAddress = lib.mkOption { + type = lib.types.str; + description = "hostAddress for the container"; + default = "10.0.1.1"; + }; + localAddress = lib.mkOption { + type = lib.types.str; + description = "localAddress for the container"; + default = "10.0.1.2"; + }; + rootTitle = lib.mkOption { + type = lib.types.str; + description = "cgit site title"; + default = ""; + }; + rootDesc = lib.mkOption { + type = lib.types.str; + description = "cgit site description"; + default = ""; + }; + extraConfig = lib.mkOption { + type = lib.types.str; + description = "cgitrc lines inserted verbatim at the end"; + default = ""; + }; + ssh.authorizedKeys = { + keys = lib.mkOption { + type = lib.types.listOf lib.types.singleLineStr; + default = [ ]; + description = '' + see `options.openssh.authorizedKeys.keys`. + ssh authorized keys for git user in container. + ''; }; - extraConfig = lib.mkOption { - type = lib.types.str; - description = "cgitrc lines inserted verbatim at the end"; - default = ""; + keyFiles = lib.mkOption { + type = lib.types.listOf lib.types.path; + default = [ ]; + description = '' + see `options.openssh.authorizedKeys.keyFiles`. + ssh authorized keys for git user in container. + ''; }; }; }; @@ -42,7 +58,7 @@ in { localAddress = cfg.localAddress; specialArgs = { - authorizedKeys = userDetails.sshPublicKeys; + authorizedKeys = cfg.ssh.authorizedKeys; cgitrc = with cfg; { inherit rootTitle; inherit rootDesc; @@ -59,7 +75,7 @@ in { createHome = true; homeMode = "750"; # Allow read permissions for group members shell = pkgs.bash; - openssh.authorizedKeys.keys = authorizedKeys; + openssh = { inherit authorizedKeys; }; }; users.groups.git.members = [ "lighttpd" ]; # Create the git group and add lighttpd user as a member so /srv/git can be served by cgit diff --git a/nixos/services/gitea.nix b/nixos/services/gitea.nix index 32c56db..5586979 100644 --- a/nixos/services/gitea.nix +++ b/nixos/services/gitea.nix @@ -1,20 +1,18 @@ -{ lib, pkgs, config, userDetails, ... }: +{ lib, pkgs, config, ... }: let - cfg = config.gitea; + cfg = config.services._gitea; in { - options = { - gitea = { - enable = lib.mkEnableOption "enables gitea service"; - hostAddress = lib.mkOption { - type = lib.types.str; - description = "hostAddress for the container"; - default = "10.0.1.1"; - }; - localAddress = lib.mkOption { - type = lib.types.str; - description = "localAddress for the container"; - default = "10.0.1.3"; - }; + options.services._gitea = { + enable = lib.mkEnableOption "enables gitea service"; + hostAddress = lib.mkOption { + type = lib.types.str; + description = "hostAddress for the container"; + default = "10.0.1.1"; + }; + localAddress = lib.mkOption { + type = lib.types.str; + description = "localAddress for the container"; + default = "10.0.1.3"; }; }; diff --git a/nixos/services/searxng.nix b/nixos/services/searxng.nix index 8ed632e..f90ad4e 100644 --- a/nixos/services/searxng.nix +++ b/nixos/services/searxng.nix @@ -1,4 +1,5 @@ { pkgs, lib, config, ... }: let + cfg = config.services._searxng; environmentFile = "/run/searx/searxng.env"; generateEnvironmentFile = '' umask 077 @@ -6,12 +7,12 @@ ls /run/searx ''; in { - options = { - searxng.enable = lib.mkEnableOption "enables searxng service"; - searxng.uwsgi.enable = lib.mkEnableOption "enables searxng uwsgi"; + options.services._searxng = { + enable = lib.mkEnableOption "enables searxng service"; + uwsgi.enable = lib.mkEnableOption "enables searxng uwsgi"; }; - config = lib.mkIf config.searxng.enable { + config = lib.mkIf cfg.enable { # Generate secret key systemd.services.searx-environment-file = { description = "Generate environment file with secret key for searx"; @@ -37,7 +38,7 @@ in { inherit environmentFile; # Provides secret key # UWSGI configuration - runInUwsgi = config.searxng.uwsgi.enable; + runInUwsgi = cfg.uwsgi.enable; uwsgiConfig = { socket = "/run/searx/searx.sock"; diff --git a/users/default.nix b/users/default.nix new file mode 100644 index 0000000..8eb5373 --- /dev/null +++ b/users/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./timmy + ]; +} diff --git a/users/timmy/default.nix b/users/timmy/default.nix new file mode 100644 index 0000000..313449d --- /dev/null +++ b/users/timmy/default.nix @@ -0,0 +1,100 @@ +{ lib, config, pkgs, home-manager, ... }: let + cfg = config._users.timmy; + username = "timmy"; + email = "tjk@tjkeller.xyz"; + fullname = "Tim Keller"; + home = "/home/${username}"; + userDirs = { + desktop = "${home}"; + download = "${home}/dls"; + documents = "${home}/docs"; + pictures = "${home}/pics"; + }; + sshKeyPaths = [ "${home}/.ssh/id_ed25519" ]; + sshPublicKeyPaths = lib.map (keyPath: keyPath + ".pub") sshKeyPaths; + sshPublicKeys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDnsnAWcz46OVi1MWSxpOIUtUvwalijDwvW+oEvNjzep" ]; +in { + imports = [ + ./hosts.nix + ./localization.nix + ./nas.nix + ./printing.nix + ./user.nix + ./wifi.nix + ]; + + options._users.timmy = { + enable = lib.mkEnableOption "create user timmy"; + autologin.enable = lib.mkEnableOption "enables getty automatic login"; + }; + + #config = lib.mkIf cfg.enable { + config = { + # Setup zsh + programs.zsh.enable = true; + #environment.systemPackages = [ pkgs.zsh-fast-syntax-highlighting ]; # TODO + + # Setup normal user + users.users.timmy = { + home = home; + description = fullname; + isNormalUser = true; + shell = pkgs.zsh; + extraGroups = [ + "nixbld" + "video" + "wheel" + ] ++ lib.optionals config.hardware.i2c.enable [ + "i2c" + ] ++ lib.optionals config.virtualisation.libvirtd.enable [ + "libvirtd" + ] ++ lib.optionals config.virtualisation.docker.enable [ + "docker" + ]; + }; + + # Configure automatic login with getty + services.getty = lib.mkIf cfg.autologin.enable { + autologinUser = username; + }; + + # Configure sops age key paths since age keys are generated via ssh private key + sops.age = { inherit sshKeyPaths; }; + + # Add authorizedKeys to cgit service + services._cgit.ssh.authorizedKeys = { + keys = sshPublicKeys; + keyFiles = sshPublicKeyPaths; + }; + + # Configure user home + home-manager.users.timmy = { + # Setup home-manager + home = { + username = username; + homeDirectory = home; + stateVersion = "24.05"; + }; + + # Setup userdirs + xdg.userDirs = { + enable = true; + createDirectories = true; + } // userDirs; + + # Setup git + programs.git = { + enable = true; + userName = fullname; + userEmail = email; + }; + + # Setup gtk bookmarks + gtk.gtk3.bookmarks = ( + lib.mapAttrsToList (name: path: + "file://${path} ${lib.toUpper (lib.substring 0 1 name)}${lib.substring 1 (-1) name}" # Make first letter upper case + ) userDirs + ); + }; + }; +} diff --git a/users/timmy/hosts.nix b/users/timmy/hosts.nix new file mode 100644 index 0000000..66c6ccc --- /dev/null +++ b/users/timmy/hosts.nix @@ -0,0 +1,16 @@ +{ + networking.hosts = { + "192.168.1.9" = [ "optiplex" ]; + "192.168.1.30" = [ "localgit" ]; + "192.168.1.11" = [ "truenas-home" ]; + "192.168.77.11" = [ "truenas-office" ]; + "192.168.77.8" = [ "publicgit" "tjkeller" ]; + "192.168.77.3" = [ "devel" ]; + "173.9.253.3" = [ + "git.tjkeller.xyz" + "piped.tjkeller.xyz" + "search.tjkeller.xyz" + "tjkeller.xyz" + ]; + }; +} diff --git a/users/timmy/localization.nix b/users/timmy/localization.nix new file mode 100644 index 0000000..8313f07 --- /dev/null +++ b/users/timmy/localization.nix @@ -0,0 +1,5 @@ +{ + time.timeZone = "America/Chicago"; + i18n.defaultLocale = "en_US.UTF-8"; + services.xserver.xkb.layout = "us"; +} diff --git a/users/timmy/nas.nix b/users/timmy/nas.nix new file mode 100644 index 0000000..8fa28c3 --- /dev/null +++ b/users/timmy/nas.nix @@ -0,0 +1,35 @@ +{ lib, config, ... } : +let + cfg = config._users.timmy.nas; + mkNetworkFileSystem = device: automount: { + device = "${device}"; + fsType = "nfs"; + options = [ "defaults" ] ++ lib.optionals (!automount) [ "noauto" ]; + }; +in { + options._users.timmy.nas = { + enable = lib.mkEnableOption "enable network shares"; + home = { + enable = lib.mkEnableOption "enable home network shares"; + automount = lib.mkEnableOption "automount home network shares"; + }; + office = { + enable = lib.mkEnableOption "enable office network shares"; + automount = lib.mkEnableOption "automount home network shares"; + }; + }; + + config = lib.mkIf cfg.enable { + fileSystems = lib.optionalAttrs cfg.home.enable { + "/media/Storage/Media" = mkNetworkFileSystem "truenas-home:/mnt/Storage/Media" cfg.home.automount; + "/media/Storage/Backups" = mkNetworkFileSystem "truenas-home:/mnt/Storage/Backups" cfg.home.automount; + "/media/Storage/Tapes" = mkNetworkFileSystem "truenas-home:/mnt/Storage/Backups/Tapes" cfg.home.automount; + "/media/Family Photos" = mkNetworkFileSystem "truenas-home:/mnt/Media/Photos" cfg.home.automount; + } // lib.optionalAttrs cfg.office.enable { + "/media/chexx/chexx" = mkNetworkFileSystem "truenas-office:/mnt/Storage/chexx" cfg.office.automount; + "/media/chexx/tkdocs" = mkNetworkFileSystem "truenas-office:/mnt/Storage/Users/Tim-Keller" cfg.office.automount; + "/media/chexx/scans" = mkNetworkFileSystem "truenas-office:/mnt/Storage/Scans" cfg.office.automount; + }; + # TODO auto mkdirz + }; +} diff --git a/users/timmy/printing.nix b/users/timmy/printing.nix new file mode 100644 index 0000000..d5cceab --- /dev/null +++ b/users/timmy/printing.nix @@ -0,0 +1,39 @@ +{ lib, config, pkgs, ... }: { + config = lib.mkIf config.services.printing.enable { + # Printer drivers + services.printing.drivers = [ + pkgs.epson-escpr2 + pkgs.workcentre-7800-series + ]; + + # Scanning programs + environment.systemPackages = with pkgs; [ + epsonscan2 + ]; + + # Printers + networking.hosts = { + "192.168.1.35" = [ "Epson_ET-8500" ]; + "192.168.77.40" = [ "Xerox_WorkCentre_7855" ]; + }; + + # Add printers to cups + hardware.printers.ensurePrinters = [ + { + name = "Epson_ET-8500"; + description = "Epson ET-8500"; + location = "Home"; + deviceUri = "ipp://Epson_ET-8500:631/ipp/print"; + model = "epson-inkjet-printer-escpr2/Epson-ET-8500_Series-epson-escpr2-en.ppd"; + } + #{ + # name = "Xerox_WorkCentre_7855"; + # description = "Xerox WorkCentre 7855"; + # location = "Office"; + # deviceUri = "ipp://Xerox_WorkCentre_7855:631/ipp/print"; + # model = "everywhere IPP Everywhere"; + #} + ]; + hardware.printers.ensureDefaultPrinter = "Epson_ET-8500"; + }; +} diff --git a/users/timmy/resources/secrets/hashed-root-password.yaml b/users/timmy/resources/secrets/hashed-root-password.yaml new file mode 100644 index 0000000..a42fd42 --- /dev/null +++ b/users/timmy/resources/secrets/hashed-root-password.yaml @@ -0,0 +1,25 @@ +hashed-root-password: ENC[AES256_GCM,data:7Qgoeb/6JPNupkHCBEzCs0FMP2cDEw972bjCRWeMrBrAMZzLsZc3Mbv03s1zLztUp6Ie93R5lVsamxKPUnaPt+Tnr/l+0E9aTmt7j7L6UzmWr12nj3FHxxTSU9ief6+ioIk+S4eICJspIQ==,iv:VoWP4qBCGzuYRpQw4nilUXByJ+ZwyZR/BdKowi+53DM=,tag:x6A00VCm8BEOhtv/WySXrQ==,type:str] +sops: + age: + - recipient: age1w80rc0dnuu8nw99gw64c596qqetm78jdnsqajr0u7ephykekr39qfz8vnv + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2Z3dTbW1GUzgyRUwyZGtF + alZSeFBmdEdhNER3UEtGRGd4MnliK1l1eGpJCm80SHFNZ3NZOTNxVkM4R3ZLY005 + OFVtUGN3OXZJblRxOFNMOFhsV25CS0EKLS0tIEE5SG5NekxWbytXY2xNeUN6TWhG + RldJZms3RDFuRk40ck42Mkd5RTd4YVUKgyWE8Cs0yLO/82w2muGWTlcjY86BVSUy + bFeIcQT33dEPiNUmynTqEGpN2NVQbfVDw17QbA9GNhGClanTTXmX4A== + -----END AGE ENCRYPTED FILE----- + - recipient: age1f0tmpy2nam58skmznjyqd3zf54rxtfrk6fda0vlpq9y3yg6wac7sjf0vja + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxcUprWjBXTVlidTRwMEZ6 + WHE4dWp6OWtybkFCaTkyY2JyaWYrRHNhZWtNCi9xamwreEsyVFdnWWhJeUVsdUpT + UHlkRVJZZTEvMDluTWNJSnRSUXN6Q0kKLS0tIHNsQk92SUd2ekowY0hvQi9LNjIx + Q0oxVFNtRkpZTlVHeEY3YXFoSlc4Zk0K7RaqH/Qf2dTPBuCz9DH0xgU+Tq8ATKUq + tfAuuAU9HBtLFiZjhWsZmj5XUy5Z18IiUKDIxlw41mNtbcsUnjm30w== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-07-17T22:34:07Z" + mac: ENC[AES256_GCM,data:B95HuJC2o8B+P1f9kAtJTcSty7YSAByuqe/Xs6ce6780p05FuzWM5X9bwvwsYXngGNKqCHksWf50UXzJ3eyc6y4ISxdxljAv2FmJFKw4NkfGaOMiRLlGPMn1uFpOtkRT+qL0+mupWG/Ap3zcpbxjsDx46PUur+e6yRxlAHw8mGw=,iv:DYobhWK+4+7vOog7BrBASiHrEzzz0P6zqgWxexfcLG8=,tag:skGwUpDEB8e3TCjrxs5peA==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/users/timmy/resources/secrets/wpa_supplicant-conf.yaml b/users/timmy/resources/secrets/wpa_supplicant-conf.yaml new file mode 100644 index 0000000..2fd7a0e --- /dev/null +++ b/users/timmy/resources/secrets/wpa_supplicant-conf.yaml @@ -0,0 +1,16 @@ +wpa_supplicant-conf: ENC[AES256_GCM,data:QoHQhTuEsSCW/K2ArOzNMfpSV7RtyTgezg4bM6eyNwhBhuJ/fCExzrniZtFzZ3zfs+ROFOYYxkx5lu4N/AQ6xEdCjJ3DYKHpeveqQ3GcWaldDr6aUDxLnBmLGBgSskGoOOANCwGvXGtFsChlCah02/W3YIhLWKIC1pfw1t9ANw9ErtLt7Fxt8TphJ1n9KdCXCJCMFrDjWDTrvbDzrvkJh6EGJIoaXuJSN+9asKrFvTwXyvHPbJmw8ZRbYgtlJtv5c1Q+PZoMtEeBRI/q2y/xUX5nvhnyy3HO1CaZPq+2XP9w+Zz90PyehVvbFVSl3V3Wg3rg9uu/c1rRGgfNkVJSHdhN+7nWYobSI28uoA8L9oXono9mNYwfcN2c4R6xwW9yOH72KabKRbD0Qq0mXcwNjU0HNneqvnMFURbDVstWmKt39gHg2xoZkG774EEDdXBAmKe5nbj0wVk8TBPWPcyR8gQ3uQrXPElqC7CWHMvajzi/hq02gmzkq1DAiheVWHxVmSQUUP3M52vvFBDdWip4X7IM3r5H4uBmcF6wGHl7JS+okDno5BuInIXvrApDV3rTqnam7YeQZao9pbx8WRWg/ZQFUysiXf9tcAl4ror71+SLKa5MfeP9AV431DbcsrIS1XQ=,iv:7qdltuNvesslz32SfEXqu9WFu2uGOGg1sjfskfqfXnk=,tag:N1RhL1M9YtDlvxLBRC2gAg==,type:str] +sops: + age: + - recipient: age1w80rc0dnuu8nw99gw64c596qqetm78jdnsqajr0u7ephykekr39qfz8vnv + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxdXBUWXEvRU85Tk1lNWgz + ZHpENjdudmRuaEJIeVRHOHlDbWNzK0tQMGs4CmV6MVBpdE5PMTBWMm1PcDVFQ2VM + b0IwWDFxLy8xYUcxRVZFSEsyYlBFS1UKLS0tIHpCbDQ0a29TZlVFTGp4aXJCSmJ4 + ZGxqMFQ1NDk1OHJIOUd0cVV0dzNNQlkKzYX36u0rEq6dMTCJf6OON6LzcEEnAB5A + +M9t3OKUUNtwgksjBUEwqBLJ1sU9amijpK63GUxwp74YDtsb0YXHiw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-07-17T22:33:44Z" + mac: ENC[AES256_GCM,data:leJsAdcWFE0EA1syXfd7yDu1Ct+vTkKiHUEc46O31uUeaWVFwgH8EKC0ImqiHMgbDJv+a9UHm7GtsWy1aMQNVRBXL3R2HbNQkOqGkIIdGsrrbjslQl8UwI7wx1g2P3ORhlGRYXTscDUl53+e4i3YrYOEDDPL5EAWuQEWldJXLZc=,iv:banL6qqV2EqfZFKHn5dawUq95Ima06z8H6Kso1qRdcA=,tag:g6M95M6bT4UPTfiEZT4ljw==,type:str] + unencrypted_suffix: _unencrypted + version: 3.10.2 diff --git a/users/timmy/user.nix b/users/timmy/user.nix new file mode 100644 index 0000000..2695549 --- /dev/null +++ b/users/timmy/user.nix @@ -0,0 +1,22 @@ +{ lib, config, pkgs, userDetails, ... }: let + cfg = config._archetypes.tjkeller.setPasswords; + hashedPasswordFile = config.sops.secrets.hashed-root-password.path; +in { + options._archetypes.tjkeller.setPasswords = { + enable = lib.mkEnableOption "set users password. requires hashed root password from sops"; + }; + + config = lib.mkIf cfg.enable { + # Load hashed root password secret + sops.secrets.hashed-root-password = { + sopsFile = ./resources/secrets/hashed-root-password.yaml; + neededForUsers = true; + }; + + # Apply password file + users.users = { + root = { inherit hashedPasswordFile; }; + ${userDetails.username} = lib.mkIf config._archetypes.users.primary.enable { inherit hashedPasswordFile; }; + }; + }; +} diff --git a/users/timmy/wifi.nix b/users/timmy/wifi.nix new file mode 100644 index 0000000..9afcbc7 --- /dev/null +++ b/users/timmy/wifi.nix @@ -0,0 +1,38 @@ +{ lib, config, ... }: let + cfg = config._users.timmy.wifi; +in { + options._users.timmy.wifi = { + enable = lib.mkEnableOption "enables wifi"; + }; + + config = lib.mkIf cfg.enable { + networking.wireless = { + enable = true; # Enables wireless support via wpa_supplicant. + userControlled.enable = true; + allowAuxiliaryImperativeNetworks = true; # Networks defined in aux imperitive networks (/etc/wpa_supplicant.conf) + }; + + # Load wpa_supplicant.conf secret config + sops.secrets.wpa_supplicant-conf = { + sopsFile = ./resources/secrets/wpa_supplicant-conf.yaml; + }; + + # Link /etc/wpa_supplicant.conf -> secret config + environment.etc."wpa_supplicant.conf" = { + source = config.sops.secrets.wpa_supplicant-conf.path; + }; + + # This service is a workaround to ensure that secrets are available on + # reboot when the secret keys are on a separate subvolume + systemd.services.npcnix-force-rebuild-sops-hack = { + wantedBy = [ "multi-user.target" ]; + before = [ "wpa_supplicant.service" ]; + serviceConfig = { + ExecStart = "/run/current-system/activate"; + Type = "oneshot"; + Restart = "on-failure"; # because oneshot + RestartSec = "10s"; + }; + }; + }; +} -- cgit v1.2.3