diff --git a/modules/base/fish.nix b/modules/base/fish.nix index 01b25bc..5013cd4 100644 --- a/modules/base/fish.nix +++ b/modules/base/fish.nix @@ -1,4 +1,7 @@ { pkgs, ... }: { + # Fish is a Unix shell with a focus on interactivity and usability. Fish is + # designed to give the user features by default, rather than by + # configuration. # https://nixos.wiki/wiki/Fish # https://nixos.wiki/wiki/Command_Shell @@ -23,16 +26,15 @@ # Add fish to the list of permissible login shells for user accounts environment.shells = with pkgs; [ fish ]; - # Enabling fish in both NixOS and home manager is required to pick - # up completions and environment variables set by NixOS nixpkgs _and_ - # home manager modules at the same time. - # As a test, the environment variables from + # Enabling fish in both NixOS and home manager is required to pick up + # completions and environment variables set by NixOS nixpkgs _and_ home + # manager modules at the same time. As a test, the environment variables from # $ nix repl # > :lf . # > :p nixosConfigurations.omega.config.home-manager.users.caspervk.home.sessionVariables # > :p nixosConfigurations.omega.config.home-manager.users.caspervk.home.sessionVariablesExtra - # should be available in the desktop environment's shell. - # See https://nix-community.github.io/home-manager/index.html#_why_are_the_session_variables_not_set. + # should be available in the desktop environment's shell. See + # https://nix-community.github.io/home-manager/index.html#_why_are_the_session_variables_not_set. home-manager.users.caspervk = { programs.fish.enable = true; }; diff --git a/modules/base/git.nix b/modules/base/git.nix index 353f2ff..0a71f06 100644 --- a/modules/base/git.nix +++ b/modules/base/git.nix @@ -1,4 +1,6 @@ { home-manager, ... }: { + # Git version control system. + # https://nixos.wiki/wiki/Git home-manager.users.caspervk = { programs.git = { @@ -6,6 +8,8 @@ userName = "Casper V. Kristensen"; userEmail = "casper@vkristensen.dk"; + # Delta is a syntax-highlighting pager for git, diff, and grep output + # https://github.com/dandavison/delta delta = { enable = true; options = { diff --git a/modules/base/home-manager.nix b/modules/base/home-manager.nix index 8448827..4fa4afd 100644 --- a/modules/base/home-manager.nix +++ b/modules/base/home-manager.nix @@ -1,7 +1,16 @@ { config, home-manager, ... }: { - # https://nix-community.github.io/home-manager/index.html#sec-flakes-nixos-module + # Like NixOS manages the system configuration, Home Manager manages the user + # environment. + # + # A lot of people split their configuration into home/ and nixos/, and import + # both directly in flake.nix, but on a single-user system I find more value + # in a structure based on the program or service rather than the + # implementation-specific details of where the output is saved to disk. + # https://nix-community.github.io/home-manager/ # https://nixos.wiki/wiki/Home_Manager + # https://nix-community.github.io/home-manager/options.html + # Import Home Manager to make it part of the NixOS configuration imports = [ home-manager.nixosModules.home-manager ]; @@ -10,11 +19,13 @@ # Use the same nixpkgs as the system useGlobalPkgs = true; - # Install packages to /etc/profiles instead of $HOME/.nix-profile, not sure why + # Install packages to /etc/profiles instead of $HOME/.nix-profile. + # According to the Home Manager documentation, this option may become the + # default in the future, so it's probably a good idea. useUserPackages = true; + # Define the user and path Home Manager should manage users.caspervk = { - # Define the user and path Home Manager should manage home = with config.users.users; { username = caspervk.name; homeDirectory = caspervk.home; diff --git a/modules/base/impermanence.nix b/modules/base/impermanence.nix index d23d7f4..e952925 100644 --- a/modules/base/impermanence.nix +++ b/modules/base/impermanence.nix @@ -1,17 +1,29 @@ -{ impermanence, pkgs, ... }: { - # The impermanence module bind-mounts persistent files and directories, stored in /nix/persist, into the tmpfs root - # partition on startup. For example: /nix/persist/etc/machine-id is mounted to /etc/machine-id. +{ impermanence, ... }: { + # Impermanence in NixOS is where the root directory isn't permanent, but gets + # wiped every reboot (such as by mounting it as tmpfs). Such a setup is + # possible because NixOS only needs /boot and /nix in order to boot, all + # other system files are simply links to files in /nix. + + # The impermanence module bind-mounts persistent files and directories, + # stored in /nix/persist, into the tmpfs root partition on startup. For + # example: /nix/persist/etc/machine-id is mounted to /etc/machine-id. # https://github.com/nix-community/impermanence # https://nixos.wiki/wiki/Impermanence + # https://elis.nu/blog/2020/05/nixos-tmpfs-as-root/ imports = [ impermanence.nixosModules.impermanence ]; - # We *don't* want to use tmpfs for /tmp in case we have to put big files there. Instead, we mount it to the disk and - # instruct systemd to clean it on boot. + # We *don't* want to use tmpfs for /tmp in case we have to put big files + # there. Instead, we mount it to the disk and instruct systemd to clean it on + # boot. + # TODO: There might be a way to configure /tmp to be in-memory storage until + # it gets too big. boot.tmp.cleanOnBoot = true; + # Each module will configure the paths they need persisted. Here we define + # some general system paths that don't really fit anywhere else. environment.persistence."/nix/persist" = { hideMounts = true; directories = [ @@ -25,7 +37,7 @@ ]; users.caspervk = { directories = [ - "/" # entire home directory + "/" # entire home directory (TODO) ]; }; }; diff --git a/modules/base/network.nix b/modules/base/network.nix index da4fad5..89265d3 100644 --- a/modules/base/network.nix +++ b/modules/base/network.nix @@ -1,6 +1,10 @@ { ... }: { + # https://nixos.wiki/wiki/Networking + # https://nixos.wiki/wiki/Systemd-networkd + networking = { firewall = { + # Allow some ports for ad-hoc use allowedTCPPorts = [ 1234 1337 8000 8080 ]; allowedUDPPorts = [ 1234 1337 8000 8080 ]; }; @@ -10,14 +14,23 @@ # TODO: these systemd networkd settings will be the default once # https://github.com/NixOS/nixpkgs/pull/202488 is merged. networking.useNetworkd = true; - systemd.network = { - enable = true; - wait-online.anyInterface = true; - }; + systemd.network.enable = true; + # systemd-resolved provides DNS resolution to local applications through + # D-Bus, NSS, and a local stub resolver on 127.0.0.53. It implements caching + # and DNSSEC validation. We configure it to only, and always, use + # dns.caspervk.net over TLS. By the way, it's surprisingly hard to get the + # system to always follow the custom DNS servers rather than the + # DHCP-provided ones. Check the traffic with: + # sudo tcpdump -n --interface=any '(udp port 53) or (tcp port 853)' + # https://nixos.wiki/wiki/Encrypted_DNS + # https://nixos.wiki/wiki/Systemd-resolved services.resolved = { enable = true; dnssec = "true"; + # Resolved falls back to DNS servers operated by American internet + # surveillance and adtech companies by default. No thanks, I'd rather have + # no DNS at all. fallbackDns = [ "159.69.4.2#dns.caspervk.net" "2a01:4f8:1c0c:70d1::1#dns.caspervk.net" ]; extraConfig = '' DNS=159.69.4.2#dns.caspervk.net 2a01:4f8:1c0c:70d1::1#dns.caspervk.net @@ -25,5 +38,6 @@ ''; }; + # vnStat keeps a log of hourly, daily and monthly network traffic services.vnstat.enable = true; } diff --git a/modules/base/ripgrep.nix b/modules/base/ripgrep.nix index 0b31fdf..845224b 100644 --- a/modules/base/ripgrep.nix +++ b/modules/base/ripgrep.nix @@ -1,9 +1,14 @@ { home-manager, ... }: { + # ripgrep is a line-oriented search tool that recursively searches the + # current directory for a regex pattern. + # https://github.com/BurntSushi/ripgrep home-manager.users.caspervk = { programs.ripgrep = { enable = true; arguments = [ + # Search case-insensitively by defaylt if the pattern is all lowercase. + # Use --case-sensitive or -s to override. "--smart-case" ]; }; diff --git a/modules/base/ssh.nix b/modules/base/ssh.nix index c963594..13a572a 100644 --- a/modules/base/ssh.nix +++ b/modules/base/ssh.nix @@ -1,6 +1,8 @@ { ... }: { services.openssh = { enable = true; + # Security by obscurity? Nah, but it certainly reduces the logs volume. + # Also, port 222 still requires root to bind. ports = [ 222 ]; settings = { PasswordAuthentication = false; diff --git a/modules/base/users.nix b/modules/base/users.nix index 3525996..3c6fc1c 100644 --- a/modules/base/users.nix +++ b/modules/base/users.nix @@ -2,13 +2,20 @@ users = { # Don't allow imperative modifications to users (incompatible with impermanence) mutableUsers = false; + users = { root = { + # TODO: The passwordfile is manually generated during the initial setup + # to avoid (hashed) secrets in the public git repo. It should replaced + # with a proper secret management scheme, such as agenix. passwordFile = "/nix/persist/passwordfile"; }; caspervk = { isNormalUser = true; description = "Casper V. Kristensen"; + # TODO: The passwordfile is manually generated during the initial setup + # to avoid (hashed) secrets in the public git repo. It should replaced + # with a proper secret management scheme, such as agenix. passwordFile = "/nix/persist/passwordfile"; extraGroups = [ "networkmanager" diff --git a/modules/desktop/alacritty.nix b/modules/desktop/alacritty.nix index bc906ae..bf1b8bf 100644 --- a/modules/desktop/alacritty.nix +++ b/modules/desktop/alacritty.nix @@ -1,4 +1,5 @@ { home-manager, ... }: { + # Terminal emulator # https://wiki.archlinux.org/title/Alacritty home-manager.users.caspervk = { @@ -6,6 +7,9 @@ enable = true; settings = { key_bindings = [ + # It's easy to open a new terminal using Mod+Enter in sway, but it + # always opens in the home directly. This binds Control+Shift+Enter + # to open a new terminal in the current directory. { key = "Return"; mods = "Control|Shift"; action = "SpawnNewInstance"; } ]; }; diff --git a/modules/desktop/clipman.nix b/modules/desktop/clipman.nix index 7ad4db6..bd66931 100644 --- a/modules/desktop/clipman.nix +++ b/modules/desktop/clipman.nix @@ -1,4 +1,8 @@ { home-manager, lib, pkgs, ... }: { + # Clipboard manager. It can help persist clipboard contents after closing an + # application - which otherwise isn't supported in Wayland - but that breaks + # rich content copying in general. Therefore, we only use it for clipboard + # history with wofi as a frontend. # https://github.com/yory8/clipman home-manager.users.caspervk = { @@ -6,7 +10,8 @@ enable = true; }; - # The home manager module doesn't use --no-persist, but it is required if you want to copy images + # The home manager module doesn't use --no-persist, but it is required if + # you want to copy images. See: # https://github.com/yory8/clipman/issues/59 # https://github.com/nix-community/home-manager/blob/master/modules/services/clipman.nix systemd.user.services.clipman = { diff --git a/modules/desktop/network.nix b/modules/desktop/network.nix index 815686d..59d5065 100644 --- a/modules/desktop/network.nix +++ b/modules/desktop/network.nix @@ -1,5 +1,7 @@ { lib, ... }: { networking = { + # It's a little too much to define every WiFi network declaratively. + # Instead, we enable NetworkManager and the nmtui interface. networkmanager = { enable = true; dns = lib.mkForce "none"; diff --git a/modules/desktop/ssh.nix b/modules/desktop/ssh.nix index c515931..e3f5d62 100644 --- a/modules/desktop/ssh.nix +++ b/modules/desktop/ssh.nix @@ -1,9 +1,13 @@ { home-manager, ... }: { - # # https://nix-community.github.io/home-manager/options.html + # https://nix-community.github.io/home-manager/options.html home-manager.users.caspervk = { programs.ssh = { enable = true; + # ControlMaster enables the sharing of multiple sessions over a single + # network connection. When enabled, additional sessions to the same host + # will reuse the master session's connection rather than initiating a new + # one. This is especially useful when using SCP. controlMaster = "yes"; matchBlocks = { "delta" = { @@ -27,6 +31,8 @@ }; }; extraConfig = '' + # Add ssh keys to the agent the first time we unlock them so we don't + # have to type the password all the time. AddKeysToAgent yes ''; }; diff --git a/modules/desktop/syncthing.nix b/modules/desktop/syncthing.nix index b52f1a8..8a59e56 100644 --- a/modules/desktop/syncthing.nix +++ b/modules/desktop/syncthing.nix @@ -1,11 +1,20 @@ { ... }: { + # Syncthing is a continuous file synchronization program. It synchronizes + # files between two or more computers in real time. It's basically a + # self-hosted Dropbox for Linux users, but without FTP, curlftpfs, and SVN. # https://nixos.wiki/wiki/Syncthing services.syncthing = { enable = true; user = "caspervk"; group = "users"; + # The directory where synchronised directories will exist dataDir = "/home/caspervk"; + # Devices ignore their own IDs, allowing for a single configuration. + # TODO: Syncthing generates a private key and ID the first time it is + # started. On first install, add the devices' ID here and apply to the + # other ones. When we get a proper secret management scheme, such as + # agenix, the private keys should be managed declaratively as well. devices = { "lambda" = { id = "WES3JH4-S34HTC5-42YZHUJ-MX3Z6PA-PFO72KA-YIJMDOB-GQWZXZ3-I7BBTAS";