diff --git a/flake.nix b/flake.nix index d0c2b5e..ccabf0b 100644 --- a/flake.nix +++ b/flake.nix @@ -40,7 +40,18 @@ inherit system; # NOTE: this will only read files that are within git tree # all secrets should go into secrets.nix and secrets/*.age - proj_root = builtins.toString ./.; + proj_root = let + path = builtins.toString ./.; + in { + inherit path; + configs.path = "${path}/native-configs"; + scripts.path = "${path}/scripts"; + secrets.path = "${path}/secrets"; + testdata.path = "${path}/tests"; + modules.path = "${path}/modules"; + hosts.path = "${path}/hosts"; + users.path = "${path}/users"; + }; } _inputs); inputs_w_pkgs = (_lib.recursiveUpdate {inherit pkgs;} inputs); lib = _lib.recursiveUpdate (import ./lib inputs_w_pkgs) _lib; @@ -51,10 +62,19 @@ hosts = (import ./hosts inputs_w_lib); users = (import ./users inputs_w_lib); + # {nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat + # ,pkgs, lib (extended), proj_root} final_inputs = inputs_w_lib; in { - # inherit (hosts) nixosConfigurations; + inherit (hosts) nixosConfigurations; # inherit (users) homeConfigurations; + inherit lib; devShell."${system}" = import ./dev-shell.nix final_inputs; + templates = import ./templates final_inputs; + + unit_tests = (lib.runTests + (import ./lib/test.nix final_inputs) // + {}); + secrets = import ./secrets final_inputs; }; } diff --git a/hosts/bao/default.nix b/hosts/bao/default.nix new file mode 100644 index 0000000..f24f049 --- /dev/null +++ b/hosts/bao/default.nix @@ -0,0 +1,5 @@ +{nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat +,pkgs, lib, proj_root}: { + +} + diff --git a/hosts/default.nix b/hosts/default.nix new file mode 100644 index 0000000..ba9921c --- /dev/null +++ b/hosts/default.nix @@ -0,0 +1,16 @@ +{nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat +,pkgs, lib, proj_root,...}@inputs:{ + nixosConfigurations = { + bao = lib.mkHost { + hostName = "bao"; + nixosBareConfiguration = { + modules = [ + + import ../modules/kde.sys.nix + import ../modules/pulseaudio.sys.nix + import ../modules/storage.perso.sys.nix + ]; + }; + }; + }; +} diff --git a/hosts/lizzi/default.nix b/hosts/lizzi/default.nix new file mode 100644 index 0000000..145cab8 --- /dev/null +++ b/hosts/lizzi/default.nix @@ -0,0 +1,4 @@ +{nixpkgs, agenix, home-manager, flake-utils, nixgl, rust-overlay, flake-compat +,pkgs, lib, proj_root}: { + +} diff --git a/lib/default.nix b/lib/default.nix index 6a529d9..b486571 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,11 +1,12 @@ {pkgs ,nixpkgs ,proj_root +,agenix ,nixosDefaultVersion? "22.05" -,defaultSystem? "x86_64-linux"; +,defaultSystem? "x86_64-linux" ,...}@inputs: let lib = pkgs.lib; - + serde = import ./serde.nix inputs // {inherit lib;}; # procedure = in { # short-hand to create a shell derivation @@ -17,21 +18,31 @@ in { ) {}); # Configures hosts as nixosConfiguration - # [host_T] -> {host_T[int].hostName = type (nixpkgs.lib.nixosConfiguration);} mkHost = {hostName , nixosBareConfiguration + , finalInputs + , users ? {} , nixosVersion? nixosDefaultVersion , system? defaultSystem - , preset? "base"}: # base | minimal - nixpkgs.lib.nixosSystem (nixosBareConfiguration // { + , preset? "base"}: # base | minimal + let + hardwareConfig = hostname: import "${proj_root.hosts.path}/${hostName}/hardware-configuration.nix"; + in nixpkgs.lib.nixosSystem (nixosBareConfiguration // { inherit system; modules = [ { system.stateVersion = nixosVersion; networking.hostName = hostName; + users.users = users; } - import "${proj_root}/modules/base.nix" - import "${proj_root}/modules/tailscale.sys.nix" + { + _module.args = finalInputs; + } + import "${proj_root.modules.path}/secrets.nix" + import "${proj_root.modules.path}/${preset}.sys.nix" ] ++ nixosBareConfiguration.modules; + lib = finalInputs.lib; }); + inherit serde; + inherit (serde) fromYaml fromYamlPath; } diff --git a/lib/serde.nix b/lib/serde.nix new file mode 100644 index 0000000..73d5eed --- /dev/null +++ b/lib/serde.nix @@ -0,0 +1,29 @@ +# Takes care of serializing and deserializing to some formats +# Blame: Pegasust +# TODO: Add to* formats from pkgs.formats.* +{ pkgs +, lib +,... +} @ inputs: +let + yamlToJsonDrv = yamlContent: outputPath: pkgs.callPackage + ({ runCommand }: + # runCommand source: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/trivial-builders.nix#L33 + runCommand outputPath { inherit yamlContent; nativeBuildInputs = [ pkgs.yq ]; } + # run yq which outputs '.' (no filter) on file at yamlPath + # note that $out is passed onto the bash/sh script for execution + '' + echo "$yamlContent" | yq >$out + '') + { }; +in { + # Takes in a yaml string and produces a derivation with translated JSON at $outputPath + # similar to builtins.fromJSON, turns a YAML string to nix attrset + fromYaml = yamlContent: builtins.fromJSON (builtins.readFile (yamlToJsonDrv yamlContent "any_output.json")); + fromYamlPath = yamlPath: builtins.fromJSON ( + builtins.readFile ( + yamlToJsonDrv ( + builtins.readFile yamlPath) + "any-output.json")); + # TODO: fromToml? +} diff --git a/lib/test.nix b/lib/test.nix new file mode 100644 index 0000000..169522e --- /dev/null +++ b/lib/test.nix @@ -0,0 +1,3 @@ +{lib,...}: { + +} diff --git a/modules/base.sys.nix b/modules/base.sys.nix index df60476..6c4e836 100644 --- a/modules/base.sys.nix +++ b/modules/base.sys.nix @@ -6,5 +6,9 @@ ./minimal.sys.nix ./mosh.sys.nix ./tailscale.sys.nix + ./ssh.sys.nix ]; + environment.systemPackages = [pkgs.lm_sensors]; + time.timeZone = "America/Phoenix"; + } diff --git a/modules/kde.sys.nix b/modules/kde.sys.nix index 907bfeb..6744c8e 100644 --- a/modules/kde.sys.nix +++ b/modules/kde.sys.nix @@ -1,8 +1,27 @@ -{pkgs -,lib -,config -,proj_root -,agenix +{ pkgs +, lib }: { environment.noXlibs = lib.mkForce false; + # TODO: wireless networking + + # Enable the X11 windowing system. + services.xserver.enable = true; + # KDE & Plasma 5 + services.xserver.displayManager.sddm.enable = true; + services.xserver.desktopManager.plasma5 = { + enable = true; + excludePackages = let plasma5 = pkgs.libsForQt5; in + [ + plasma5.elisa # audio viewer + plasma5.konsole # I use alacritty instaed + plasma5.plasma-browser-integration + plasma5.print-manager # will enable if I need + plasma5.khelpcenter # why not just write manpages instead :( + # plasma5.ksshaskpass # pls just put prompts on my dear terminal + ]; + }; + + # disables KDE's setting of askpassword + programs.ssh.askPassword = ""; + programs.ssh.enableAskPassword = false; } diff --git a/modules/pipewire.audio.sys.nix b/modules/pipewire.audio.sys.nix new file mode 100644 index 0000000..8c36bee --- /dev/null +++ b/modules/pipewire.audio.sys.nix @@ -0,0 +1,15 @@ +{ + # Sound: pipewire + sound.enable = false; + hardware.pulseaudio.enable = false; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # Might want to use JACK in the future + jack.enable = true; + }; + + security.rtkit.enable = true; +} diff --git a/modules/pulseaudio.sys.nix b/modules/pulseaudio.sys.nix new file mode 100644 index 0000000..3b804f3 --- /dev/null +++ b/modules/pulseaudio.sys.nix @@ -0,0 +1,9 @@ +{ + # Enable sound. (pulse audio) + sound.enable = true; + programs.dconf.enable = true; + hardware.pulseaudio.enable = true; + hardware.pulseaudio.support32Bit = true; + nixpkgs.config.pulseaudio = true; + hardware.pulseaudio.extraConfig = "load-module module-combine-sink"; +} diff --git a/modules/secrets.nix b/modules/secrets.nix index b91057f..9c91dc6 100644 --- a/modules/secrets.nix +++ b/modules/secrets.nix @@ -1,16 +1,19 @@ {agenix ,proj_root}: { + imports = [ + agenix.nixosModule + ]; age.secrets.s3fs = { - file = "${proj_root}/secrets/s3fs.age"; + file = "${proj_root.secrets.path}/s3fs.age"; # mode = "600"; # owner + group only # owner = "hungtr"; # group = "users"; }; age.secrets."s3fs.digital-garden" = { - file = "${proj_root}/secrets/s3fs.digital-garden.age"; + file = "${proj_root.secrets.path}/s3fs.digital-garden.age"; }; age.secrets._nhitrl_cred = { - file = "${proj_root}/secrets/_nhitrl.age"; + file = "${proj_root.secrets.path}/_nhitrl.age"; }; environment.systemPackages = [agenix.defaultPackage.x86_64-linux]; } diff --git a/modules/ssh.sys.nix b/modules/ssh.sys.nix new file mode 100644 index 0000000..1e42a3c --- /dev/null +++ b/modules/ssh.sys.nix @@ -0,0 +1,6 @@ +{ + services.openssh = { + enable = true; + permitRootLogin = false; + }; +} diff --git a/modules/storage.perso.sys.nix b/modules/storage.perso.sys.nix new file mode 100644 index 0000000..e16db18 --- /dev/null +++ b/modules/storage.perso.sys.nix @@ -0,0 +1,110 @@ +# Personal configuration on storage solution +{ pkgs, config, lib }: { + environment.systemPackages = [ + pkgs.s3fs + pkgs.cifs-utils + ]; + + # Sadly, autofs uses systemd, so we can't put it in home-manager + # HACK: need to store secret somewhere so that root can access this + # because autofs may run as root for now, we enforce putting the secret in this monorepo + # TODO: make this configuration nix-less to show that it's 100% data + services.autofs = + let + # confToBackendArg {lol="what"; empty=""; name_only=null;} -> "lol=what,empty=,name_only" + # TODO: change null -> true/false. This allows overriding & better self-documentation + confToBackendArg = conf: (lib.concatStringsSep "," + (lib.mapAttrsToList (name: value: "${name}${lib.optionalString (value != null) "=${value}"}") conf)); + + # mount_dest: path ("wow") + # backend_args: nix attrs representing the arguments to be passed to s3fs + # ({"-fstype" = "fuse"; "use_cache" = "/tmp";}) + # bucket: bucket name (hungtr-hot) + # NOTE: s3 custom provider will be provided inside + # backend_args, so just put the bucket name here + # + #-> "${mount_dest} ${formatted_args} ${s3fs-bin}#${bucket}" + autofs-s3fs_entry = + { mount_dest + , backend_args ? { "-fstype" = "fuse"; } + , bucket + }@inputs: + let + s3fs-exec = "${pkgs.s3fs}/bin/s3fs"; + in + "${mount_dest} ${confToBackendArg backend_args} :${s3fs-exec}\#${bucket}"; + personalStorage = [ + # hungtr-hot @ phoenix is broken :) + # (autofs-s3fs_entry { + # mount_dest = "hot"; + # backend_args = { + # "-fstype" = "fuse"; + # use_cache = "/tmp"; + # del_cache = null; + # allow_other = null; + # url = ''"https://f5i0.ph.idrivee2-32.com"''; + # # TODO: builtins.readFile requires a Git-controlled file + # passwd_file = config.age.secrets.s3fs.path; + # dbglevel = "debug"; # enable this for better debugging info in journalctl + # uid = "1000"; # default user + # gid = "100"; # users + # umask="003"; # others read only, fully shared for users group + # # _netdev = null; # ignored by s3fs (https://github.com/s3fs-fuse/s3fs-fuse/blob/master/src/s3fs.cpp#L4910) + # }; + # bucket = "hungtr-hot"; + # }) + (autofs-s3fs_entry { + mount_dest = "garden"; + backend_args = { + "-fstype" = "fuse"; + use_cache = "/tmp"; + del_cache = null; + allow_other = null; + url = "https://v5h5.la11.idrivee2-14.com"; + passwd_file = config.age.secrets."s3fs.digital-garden".path; + dbglevel = "debug"; # enable this for better debugging info in journalctl + uid = "1000"; # default user + gid = "100"; # users + umask = "003"; # others read only, fully shared for users group + }; + bucket = "digital-garden"; + }) + ( + let args = { + "-fstype" = "cifs"; + credentials = config.age.secrets._nhitrl_cred.path; + user = null; + uid = "1001"; + gid = "100"; + dir_mode = "0777"; + file_mode = "0777"; + }; + in "felia_d ${confToBackendArg args} ://felia.coati-celsius.ts.net/d" + ) + ( + let args = { + "-fstype" = "cifs"; + credentials = config.age.secrets._nhitrl_cred.path; + user = null; + uid = "1001"; + gid = "100"; + dir_mode = "0777"; + file_mode = "0777"; + }; + in "felia_f ${confToBackendArg args} ://felia.coati-celsius.ts.net/f" + ) + ]; + persoConf = pkgs.writeText "auto.personal" (builtins.concatStringsSep "\n" personalStorage); + in + { + enable = true; + # Creates /perso directory with every subdirectory declared by ${personalStorage} + # as of now (might be stale), /perso/hot is the only mount accessible + # that is also managed by s3fs + autoMaster = '' + /perso file:${persoConf} + ''; + timeout = 30; # default: 600, 600 seconds (10 mins) of inactivity => unmount + # debug = true; # writes to more to journalctl + }; +} diff --git a/nix-conf/system/configuration.nix b/nix-conf/system/configuration.nix index 8f867d5..7242c14 100755 --- a/nix-conf/system/configuration.nix +++ b/nix-conf/system/configuration.nix @@ -33,7 +33,7 @@ with lib; }; users.users.root = { # openssh runs in root, no? This is because port < 1024 requires root. - openssh.authorizedKeys.keys = lib.strings.splitString "\n" (builtins.readFile "${proj_root}/ssh/authorized_keys"); + openssh.authorizedKeys.keys = lib.strings.splitString "\n" (builtins.readFile "${proj_root}/native_configs/ssh/authorized_keys"); }; # Some basic programs diff --git a/nix-conf/system/flake.nix b/nix-conf/system/flake.nix index fca0888..caac7c7 100644 --- a/nix-conf/system/flake.nix +++ b/nix-conf/system/flake.nix @@ -211,7 +211,9 @@ ./configuration.nix # automount using s3fs ({config, pkgs, lib, ...}: { - environment.systemPackages = [pkgs.s3fs pkgs.cifs-utils]; # s3fs-fuse + environment.systemPackages = [ + pkgs.s3fs pkgs.cifs-utils pkgs.lm_sensors pkgs.hddtemp + ]; # s3fs-fuse # Sadly, autofs uses systemd, so we can't put it in home-manager # HACK: need to store secret somewhere so that root can access this # because autofs may run as root for now, we enforce putting the secret in this monorepo diff --git a/nix-conf/system/profiles/bao/hardware-configuration.nix b/nix-conf/system/profiles/bao/hardware-configuration.nix index 56e94aa..c29572c 100644 --- a/nix-conf/system/profiles/bao/hardware-configuration.nix +++ b/nix-conf/system/profiles/bao/hardware-configuration.nix @@ -11,7 +11,7 @@ boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; # boot.initrd.kernelModules = [ "amdgpu" ]; boot.initrd.kernelModules = []; - boot.kernelModules = [ "kvm-amd" ]; + boot.kernelModules = [ "kvm-amd" "coretemp"]; boot.extraModulePackages = [ ]; fileSystems."/" = diff --git a/scripts/config-sysnix.sh b/scripts/config-sysnix.sh index 49af659..261aa69 100755 --- a/scripts/config-sysnix.sh +++ b/scripts/config-sysnix.sh @@ -33,7 +33,7 @@ git add "${HARDWARE_CONF}" # Copy ssh/id-rsa details onto ssh/authorized_keys SSH_PRIV="${HOME}/.ssh/id_rsa" SSH_PUB="${SSH_PRIV}.pub" -SSH_DIR="${SCRIPT_DIR}/../ssh" +SSH_DIR="${SCRIPT_DIR}/../native_configs/ssh" if [ ! -f "${SSH_PRIV}" ]; then ssh-keygen -b 2048 -t rsa -f "${SSH_PRIV}" -q -N "" fi diff --git a/secrets.nix b/secrets.nix index 762039d..549ff67 100644 --- a/secrets.nix +++ b/secrets.nix @@ -1,18 +1,10 @@ -let - # user-specific (~/.ssh/id_ed25519.pub) - users = { - "hungtr@bao" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+1+gps6phbZboIb9fH51VNPUCkhSSOAbkI3tq3Ou0Z"; - }; - # System-specific settings (/etc/ssh/ssh_host_ed25519_key.pub) - systems = { - "bao" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBuAaAE7TiQmMH300VRj/pYCri1qPmHjd+y9aX2J0Fs"; - }; - all = users // systems; - # stands for calculus - c_ = builtins; -in { - "system/secrets/s3fs.age".publicKeys = c_.attrValues (all); - "system/secrets/s3fs.digital-garden.age".publicKeys = c_.attrValues (all); - "system/secrets/_nhitrl.age".publicKeys = c_.attrValues (all); - -} +(import + ( + let lock = builtins.fromJSON (builtins.readFile ./flake.lock); in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + { src = ./.; } +).defaultNix.secrets diff --git a/secrets/default.nix b/secrets/default.nix new file mode 100644 index 0000000..4808c6c --- /dev/null +++ b/secrets/default.nix @@ -0,0 +1,18 @@ +# TODO: put ssh keys as user/host config +inputs: let + # user-specific (~/.ssh/id_ed25519.pub) + users = { + "hungtr@bao" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+1+gps6phbZboIb9fH51VNPUCkhSSOAbkI3tq3Ou0Z"; + }; + # System-specific settings (/etc/ssh/ssh_host_ed25519_key.pub) + systems = { + "bao" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBuAaAE7TiQmMH300VRj/pYCri1qPmHjd+y9aX2J0Fs"; + }; + all = users // systems; + # stands for calculus + c_ = builtins; +in { + "system/secrets/s3fs.age".publicKeys = c_.attrValues (all); + "system/secrets/s3fs.digital-garden.age".publicKeys = c_.attrValues (all); + "system/secrets/_nhitrl.age".publicKeys = c_.attrValues (all); +} diff --git a/templates/default.nix b/templates/default.nix new file mode 100644 index 0000000..f83e1ff --- /dev/null +++ b/templates/default.nix @@ -0,0 +1,5 @@ +{pkgs +,lib +, +}: { +}