summaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
authorTim Keller <tjk@tjkeller.xyz>2025-08-30 12:31:28 -0500
committerTim Keller <tjk@tjkeller.xyz>2025-08-30 12:31:28 -0500
commit9da942ba47d34210e86a1a709e802eda5c3b95db (patch)
treef7434c4b4c9b8e5271220c11f9b802815c3519c7 /users
parentc3c3d6f1fd19a5da015c9a9d3ae5c54f2d177be0 (diff)
downloadnixos-9da942ba47d34210e86a1a709e802eda5c3b95db.tar.xz
nixos-9da942ba47d34210e86a1a709e802eda5c3b95db.zip
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.
Diffstat (limited to 'users')
-rw-r--r--users/default.nix5
-rw-r--r--users/timmy/default.nix100
-rw-r--r--users/timmy/hosts.nix16
-rw-r--r--users/timmy/localization.nix5
-rw-r--r--users/timmy/nas.nix35
-rw-r--r--users/timmy/printing.nix39
-rw-r--r--users/timmy/resources/secrets/hashed-root-password.yaml25
-rw-r--r--users/timmy/resources/secrets/wpa_supplicant-conf.yaml16
-rw-r--r--users/timmy/user.nix22
-rw-r--r--users/timmy/wifi.nix38
10 files changed, 301 insertions, 0 deletions
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";
+ };
+ };
+ };
+}