diff --git a/home/programs/terminal/tools/default.nix b/home/programs/terminal/tools/default.nix index 6ece1ab..00fcb55 100644 --- a/home/programs/terminal/tools/default.nix +++ b/home/programs/terminal/tools/default.nix @@ -12,5 +12,6 @@ _: { ./btop.nix ./bottom.nix ./bat.nix + ./nix-index.nix ]; } diff --git a/home/programs/terminal/tools/git/default.nix b/home/programs/terminal/tools/git/default.nix index 4452029..2bb104d 100644 --- a/home/programs/terminal/tools/git/default.nix +++ b/home/programs/terminal/tools/git/default.nix @@ -17,7 +17,7 @@ in userEmail = myGitConf.userEmail; signing = { - signByDefault = myGitConf.signing.enabled; + signByDefault = myGitConf.signing.enable; key = myGitConf.signing.key; }; diff --git a/home/programs/terminal/tools/nix-index.nix b/home/programs/terminal/tools/nix-index.nix new file mode 100644 index 0000000..5b4df13 --- /dev/null +++ b/home/programs/terminal/tools/nix-index.nix @@ -0,0 +1,12 @@ +{ config, ... }: { + programs = { + # nix-index is a file database for nixpkgs + # this provides `nix-locate` command. + nix-index = { + enable = true; + # Attempt to find the package that contains the non-existent command + enableBashIntegration = config.programs.bash.enable; + enableZshIntegration = config.programs.zsh.enable; + }; + }; +} diff --git a/hosts/default.nix b/hosts/default.nix index 40a5834..4dcd9eb 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -16,6 +16,7 @@ in ./vbox_nix inputs.home-manager.nixosModules.home-manager inputs.impermanence.nixosModules.impermanence + inputs.lanzaboote.nixosModules.lanzaboote ] ++ shared; }; diff --git a/hosts/herugrim/default.nix b/hosts/herugrim/default.nix index ecffaed..7a9b9bb 100644 --- a/hosts/herugrim/default.nix +++ b/hosts/herugrim/default.nix @@ -59,6 +59,13 @@ hasTPM = true; }; + security = { + auditd = { + enable = true; + autoPrune.enable = true; + }; + }; + workstation = { printing.enable = true; }; @@ -70,7 +77,7 @@ userName = "ItsDrike"; userEmail = "itsdrike@protonmail.com"; signing = { - enabled = true; + enable = true; key = "FA2745890B7048C0"; }; }; diff --git a/hosts/vbox_nix/default.nix b/hosts/vbox_nix/default.nix index 1da37a6..e87f939 100644 --- a/hosts/vbox_nix/default.nix +++ b/hosts/vbox_nix/default.nix @@ -22,19 +22,48 @@ system = { hostname = "vboxnix"; username = "itsdrike"; + + impermanence = { + root.enable = false; + autoWipeBtrfs.enable = false; + }; + + boot = { + secure-boot.enable = false; + tmpOnTmpfs = false; + }; }; + device = { - type = "desktop"; - virtual-machine = true; + roles = { + type = "desktop"; + virtual-machine = true; + }; cpu.type = "amd"; + hasTPM = false; }; + + security = { + auditd = { + enable = true; + autoPrune.enable = true; + }; + }; + + workstation = { + printing.enable = false; + }; + home-manager = { enable = true; stateVersion = "23.11"; git = { userName = "ItsDrike"; userEmail = "itsdrike@protonmail.com"; - signing.key = "FA2745890B7048C0"; + signing = { + enable = true; + key = "FA2745890B7048C0"; + }; }; }; }; diff --git a/options/default.nix b/options/default.nix index 5385c36..3853e45 100644 --- a/options/default.nix +++ b/options/default.nix @@ -4,5 +4,6 @@ _: { ./home ./system ./workstation + ./security ]; } diff --git a/options/home/git.nix b/options/home/git.nix index f9d6b4c..b9f148a 100644 --- a/options/home/git.nix +++ b/options/home/git.nix @@ -15,7 +15,7 @@ in }; signing = { - enabled = mkEnableOption '' + enable = mkEnableOption '' git commit signing. Requires `myOptions.home-manager.git.signing.key` to be set. ''; diff --git a/options/security/auditd.nix b/options/security/auditd.nix new file mode 100644 index 0000000..fccb222 --- /dev/null +++ b/options/security/auditd.nix @@ -0,0 +1,61 @@ +{ lib, config, ... }: with lib; let + inherit (lib) mkEnableOption mkOption literalExpression types; +in +{ + options.myOptions.security.auditd = { + enable = mkEnableOption "the audit daemon."; + autoPrune = { + enable = mkEnableOption '' + automatic pruning of audit logs. + + Enabling this is HEAVILY recommended, as audit logs + can grow very large very quickly. + ''; + + size = mkOption { + type = types.int; + default = 524288000; # roughly 500MB + description = '' + The maximum size of the audit log in bytes. + + The default is 500MB. + ''; + }; + + schedule = mkOption { + type = types.str; + default = "daily"; + example = "weekly"; + description = "How often cleaning is triggered. Passed to systemd.time"; + }; + }; + + extraFiles = mkOption { + default = []; + type = types.listOf types.path; + example = literalExpression ''["/etc/nix/id_rsa"]''; + description = '' + Additional files in root to link to persistent storage. + ''; + }; + + extraDirectories = mkOption { + default = []; + type = types.listOf types.path; + example = literalExpression ''["/etc/nix/id_rsa"]''; + description = '' + Additional directories in root to link to persistent storage. + ''; + }; + + persistentMountPoint = mkOption { + default = "/persist"; + description = '' + Path to a persistent directory (usually a mount point to a + standalone partition / subvolume), which will hold the persistent + system state files. + ''; + }; + }; +} + diff --git a/options/security/default.nix b/options/security/default.nix new file mode 100644 index 0000000..015276a --- /dev/null +++ b/options/security/default.nix @@ -0,0 +1,5 @@ +{ + imports = [ + ./auditd.nix + ]; +} diff --git a/options/system/impermanence.nix b/options/system/impermanence.nix index fece564..732f5da 100644 --- a/options/system/impermanence.nix +++ b/options/system/impermanence.nix @@ -85,4 +85,13 @@ in }; }; }; + + config = { + assertions = [ + { + assertion = cfg.autoWipeBtrfs.enable -> cfg.root.enable; + message = "myOptions.system.impermanence.autoWipeBtrfs requires myOptions.system.impermanence.root to be enabled."; + } + ]; + }; } diff --git a/system/roles/workstation/programs/default.nix b/system/roles/workstation/programs/default.nix index 5ad52c9..661d81a 100644 --- a/system/roles/workstation/programs/default.nix +++ b/system/roles/workstation/programs/default.nix @@ -1,5 +1,6 @@ { imports = [ ./misc.nix + ./physlock.nix ]; } diff --git a/system/roles/workstation/programs/physlock.nix b/system/roles/workstation/programs/physlock.nix new file mode 100644 index 0000000..b692160 --- /dev/null +++ b/system/roles/workstation/programs/physlock.nix @@ -0,0 +1,8 @@ +{ + # Screen locker which works across all virtual terminals + # Use `systemctl start physlock` to securely lock the screen + services.physlock = { + enable = true; + lockMessage = "System is locked..."; + }; +} diff --git a/system/shared/default.nix b/system/shared/default.nix index 5ed5a2c..a93ddac 100644 --- a/system/shared/default.nix +++ b/system/shared/default.nix @@ -6,6 +6,7 @@ _: { ./nix ./environment ./impermanence + ./security ./programs.nix ./system.nix ./network.nix diff --git a/system/shared/programs.nix b/system/shared/programs.nix index d9eeaf9..9e00d59 100644 --- a/system/shared/programs.nix +++ b/system/shared/programs.nix @@ -1,10 +1,17 @@ -{ +{lib, ...}: let + inherit (lib) mkForce; +in { - # Install an actually usable system-wide editor - programs.neovim = { - enable = true; - defaultEditor = true; - vimAlias = true; - viAlias = true; + programs = { + # Explicitly disable nano, it sucks and I don't want it + nano.enable = mkForce false; + + # Install an actually usable system-wide editor + neovim = { + enable = true; + defaultEditor = true; + vimAlias = true; + viAlias = true; + }; }; } diff --git a/system/shared/security/apparmor.nix b/system/shared/security/apparmor.nix new file mode 100644 index 0000000..716c4c4 --- /dev/null +++ b/system/shared/security/apparmor.nix @@ -0,0 +1,60 @@ +{ config, pkgs, ... }: { + services.dbus.apparmor = "enabled"; + + environment.systemPackages = with pkgs; [ + apparmor-pam + apparmor-utils + apparmor-parser + apparmor-profiles + apparmor-bin-utils + apparmor-kernel-patches + libapparmor + ]; + + # apparmor configuration + security.apparmor = { + enable = true; + + # whether to enable AppArmor cache + # in /var/cache/apparmor + enableCache = true; + + # whether to kill processes which have an AppArmor profile enabled + # but are not confined (AppArmor can only confine new processes) + killUnconfinedConfinables = true; + + # packages to be added to AppArmor's include path + packages = [pkgs.apparmor-profiles]; + + # AppArmor policies + policies = { + "default_deny" = { + enforce = false; + enable = false; + profile = '' + profile default_deny /** {} + ''; + }; + + "sudo" = { + enforce = false; + enable = false; + profile = '' + ${pkgs.sudo}/bin/sudo { + file /** rwlkUx + } + ''; + }; + + "nix" = { + enforce = false; + enable = false; + profile = '' + ${config.nix.package}/bin/nix { + unconfined + } + ''; + }; + }; + }; +} diff --git a/system/shared/security/auditd.nix b/system/shared/security/auditd.nix new file mode 100644 index 0000000..3691d6f --- /dev/null +++ b/system/shared/security/auditd.nix @@ -0,0 +1,52 @@ +{ config, lib, ... }: let + inherit (lib) mkIf; + + cfg = config.myOptions.security.auditd; +in { + config = mkIf cfg.enable { + security = { + auditd.enable = true; + audit = { + enable = true; + # maximum number of outstanding audit buffers allowed + # exceeding this is considered a failure and handled in + # a manner specified by failureMode + backlogLimit = 8192; + # how to handle critical errors in the auditing system + failureMode = "printk"; # "silent" | "printk" | "panic" + rules = [ + "-a exit,always -F arch=b64 -S execve" + ]; + }; + }; + + systemd = mkIf cfg.autoPrune.enable { + # Systemd timer to clean /var/log/audit.log on configured schedule + timers."clean-audit-log" = { + description = "Periodically clean audit log"; + wantedBy = ["timers.target"]; + timerConfig = { + OnCalendar = cfg.autoPrune.schedule; + Persistent = true; + }; + }; + + # clean audit log if it's larger than the configured size + services."clean-audit-log" = { + script = '' + set -eu + if [[ $(stat -c "%s" /var/log/audit/audit.log) -gt ${builtins.toString cfg.autoPrune.size} ]]; then + echo "Clearing Audit Log"; + rm -rvf /var/log/audit/audit.log; + echo "Done!" + fi + ''; + + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + }; + }; + }; +} diff --git a/system/shared/security/default.nix b/system/shared/security/default.nix new file mode 100644 index 0000000..f2f6476 --- /dev/null +++ b/system/shared/security/default.nix @@ -0,0 +1,7 @@ +{ + imports = [ + ./apparmor.nix + ./auditd.nix + ./polkit.nix + ]; +} diff --git a/system/shared/security/polkit.nix b/system/shared/security/polkit.nix new file mode 100644 index 0000000..ac8d279 --- /dev/null +++ b/system/shared/security/polkit.nix @@ -0,0 +1,14 @@ +{ config, lib, ... }: { + security.polkit = { + enable = true; + debug = lib.mkDefault true; + + # Have polkit log all actions, if debug is enabled + extraConfig = lib.mkIf config.security.polkit.debug '' + /* Log authorization checks. */ + polkit.addRule(function(action, subject) { + polkit.log("user " + subject.user + " is attempting action " + action.id + " from PID " + subject.pid); + }); + ''; + }; +} diff --git a/system/shared/services/default.nix b/system/shared/services/default.nix index 4a85a49..b0a0fe2 100644 --- a/system/shared/services/default.nix +++ b/system/shared/services/default.nix @@ -5,5 +5,7 @@ _: { ./logrotate.nix ./oomd.nix ./thermald.nix + ./journald.nix + ./fstrim.nix ]; } diff --git a/system/shared/services/fstrim.nix b/system/shared/services/fstrim.nix new file mode 100644 index 0000000..01bda11 --- /dev/null +++ b/system/shared/services/fstrim.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: let + inherit (lib.modules) mkIf; +in { + # if lvm is enabled, then tell it to issue discards + # (this is good for SSDs and has almost no downsides on HDDs, so + # it's a good idea to enable it unconditionally) + environment.etc."lvm/lvm.conf".text = mkIf config.services.lvm.enable '' + devices { + issue_discards = 1 + } + ''; + + # discard blocks that are not in use by the filesystem, good for SSDs + services.fstrim = { + # we may enable this unconditionally across all systems becuase it's performance + # impact is negligible on systems without a SSD - which means it's a no-op with + # almost no downsides aside from the service firing once per week + enable = true; + + # the default value, good enough for average-load systems + interval = "weekly"; + }; + + # tweak fstim service to run only when on AC power + # and to be nice to other processes + # (this is a good idea for any service that runs periodically) + systemd.services.fstrim = { + unitConfig.ConditionACPower = true; + + serviceConfig = { + Nice = 19; + IOSchedulingClass = "idle"; + }; + }; +} diff --git a/system/shared/services/journald.nix b/system/shared/services/journald.nix new file mode 100644 index 0000000..ac97726 --- /dev/null +++ b/system/shared/services/journald.nix @@ -0,0 +1,9 @@ +{ + # Limit systemd journal size, as the default is unlimited and + # journals get big really fast + services.journald.extraConfig = '' + SystemMaxUse=100M + RuntimeMaxUse=50M + SystemMaxFileSize=50M + ''; +}