{
  config,
  lib,
  pkgs,
  home-manager,
  ...
}:

{
  imports = [
    ./roles/2ship2harkinian
    ./roles/alacritty
    ./roles/ansible
    ./roles/ares
    ./roles/bluetooth
    ./roles/boot
    ./roles/chromecast
    ./roles/chromium
    ./roles/distributed_build
    ./roles/docker
    ./roles/ecc
    ./roles/emacs
    ./roles/firefox
    ./roles/firewall
    ./roles/flux
    ./roles/fonts
    ./roles/gcloud
    ./roles/git
    ./roles/global_options
    ./roles/gnuplot
    ./roles/gpg
    ./roles/graphics
    ./roles/hydra
    ./roles/iso
    ./roles/iso_mount
    ./roles/kanshi
    ./roles/kodi
    ./roles/kubernetes
    ./roles/latex
    ./roles/launch_keyboard
    ./roles/lvfs
    ./roles/media
    ./roles/memtest86
    ./roles/network
    ./roles/nix_index
    ./roles/nix_worker
    ./roles/nvme
    ./roles/optimized_build
    ./roles/pcsx2
    ./roles/python
    ./roles/qemu
    ./roles/reset
    ./roles/rpcs3
    ./roles/rust
    ./roles/shikane
    ./roles/shipwright
    ./roles/sm64ex
    ./roles/sops
    ./roles/sound
    ./roles/ssh
    ./roles/steam
    ./roles/steam_run_free
    ./roles/sway
    ./roles/tekton
    ./roles/terraform
    ./roles/thunderbolt
    ./roles/vnc_client
    ./roles/vscode
    ./roles/wasm
    ./roles/waybar
    ./roles/wireguard
    ./roles/zfs
    ./roles/zrepl
    ./roles/zsh
    ./util/unfree_polyfill
  ];

  nix.settings.experimental-features = [
    "nix-command"
    "flakes"
  ];
  nix.settings.trusted-users = [ "@wheel" ];

  # boot.kernelPackages = pkgs.linuxPackages_6_11;
  hardware.enableRedistributableFirmware = true;

  # Use nixos-rebuild-ng
  # system.rebuild.enableNg = true;

  # Keep outputs so we can build offline.
  nix.extraOptions = ''
    keep-outputs = true
    keep-derivations = true
  '';

  # Technically only needed when building the ISO because nix detects ZFS in the filesystem list normally. I basically always want this so I'm just setting it to always be on.
  boot.supportedFilesystems.zfs = true;
  # TODO: Is this different from boot.supportedFilesystems = [ "zfs" ]; ?

  services.getty = {
    autologinUser = "talexander"; # I use full disk encryption so the user password is irrelevant.
    autologinOnce = true;
  };
  users.mutableUsers = false;
  users.users.talexander = {
    isNormalUser = true;
    createHome = true; # https://github.com/NixOS/nixpkgs/issues/6481
    group = "talexander";
    extraGroups = [ "wheel" ];
    uid = 11235;
    packages = with pkgs; [
      tree
    ];
    # Generate with `mkpasswd -m scrypt`
    hashedPassword = "$7$CU..../....VXvNQ8za3wSGpdzGXNT50/$HcFtn/yvwPMCw4888BelpiAPLAxe/zU87fD.d/N6U48";
    openssh.authorizedKeys.keys = [
      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGu+k5lrirokdW5zVdRVBOqEOAvAPlIkG/MdJNc9g5ky"
      "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIEI6mu6I5Jp+Ib0vJxapGHbEShZjyvzV8jz5DnzDrI39AAAABHNzaDo="
      "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAFNcSXwvy+brYTOGo56G93Ptuq2MmZsjvRWAfMqbmMLAAAABHNzaDo="
    ];
  };
  users.groups.talexander.gid = 11235;
  home-manager.users.talexander =
    { pkgs, ... }:
    {
      # The state version is required and should stay at the version you
      # originally installed.
      home.stateVersion = "24.11";
    };

  home-manager.users.root =
    { pkgs, ... }:
    {
      # The state version is required and should stay at the version you
      # originally installed.
      home.stateVersion = "24.11";
    };

  # Automatic garbage collection
  nix.gc = lib.mkIf (!config.me.buildingIso) {
    # Runs nix-collect-garbage --delete-older-than 5d
    automatic = true;
    persistent = true;
    dates = "weekly";
    # randomizedDelaySec = "14m";
    options = "--delete-older-than 30d";
  };
  nix.settings.auto-optimise-store = !config.me.buildingIso;

  # Use doas instead of sudo
  security.doas.enable = true;
  security.doas.wheelNeedsPassword = false;
  security.sudo.enable = false;
  security.doas.extraRules = [
    {
      # Retain environment (for example NIX_PATH)
      keepEnv = true;
      persist = true; # Only ask for a password the first time.
    }
  ];

  environment.systemPackages = with pkgs; [
    wget
    mg
    rsync
    libinput
    htop
    tmux
    file
    usbutils # for lsusb
    pciutils # for lspci
    ripgrep
    strace
    ltrace
    trace-cmd # ftrace
    tcpdump
    git-crypt
    gnumake
    ncdu
    nix-tree
    libarchive # bsdtar
    lsof
    doas-sudo-shim # To support --use-remote-sudo for remote builds
    dmidecode # Read SMBIOS information.
    ipcalc
    gptfdisk # for cgdisk
    nix-output-monitor # For better view into nixos-rebuild
    nix-serve-ng # Serve nix store over http
  ];

  services.openssh = {
    enable = true;
    settings = {
      PasswordAuthentication = false;
      KbdInteractiveAuthentication = false;
    };
    hostKeys = [
      {
        path = "/persist/ssh/ssh_host_ed25519_key";
        type = "ed25519";
      }
      {
        path = "/persist/ssh/ssh_host_rsa_key";
        type = "rsa";
        bits = 4096;
      }
    ];
  };

  environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
    hideMounts = true;
    directories = [
      "/var/lib/iwd" # Wifi settings
      "/var/lib/nixos" # Contains user information (uids/gids)
      "/var/lib/systemd" # Systemd state directory for random seed, persistent timers, core dumps, persist hardware state like backlight and rfkill
      "/var/log/journal" # Logs, alternatively set `services.journald.storage = "volatile";` to write to /run/log/journal
    ];
    files = [
      "/etc/machine-id" # Systemd unique machine id "otherwise, the system journal may fail to list earlier boots, etc"
      "/etc/ssh/ssh_host_rsa_key"
      "/etc/ssh/ssh_host_rsa_key.pub"
      "/etc/ssh/ssh_host_ed25519_key"
      "/etc/ssh/ssh_host_ed25519_key.pub"
    ];
    users.talexander = {
      directories = [
        {
          directory = "persist";
          user = "talexander";
          group = "talexander";
          mode = "0700";
        }
      ];
    };
  };

  # Write a list of the currently installed packages to /etc/current-system-packages
  environment.etc."current-system-packages".text =
    let
      packages = builtins.map (p: "${p.name}") config.environment.systemPackages;
      sortedUnique = builtins.sort builtins.lessThan (lib.unique packages);
      formatted = builtins.concatStringsSep "\n" sortedUnique;
    in
    formatted;

  # environment.etc."system-packages-with-source".text = builtins.concatStringsSep "\n\n" (
  #   builtins.map (
  #     x: x.file + "\n" + builtins.concatStringsSep "\n" (builtins.map (s: "  " + s) x.value)
  #   ) config.environment.systemPackages.definitionsWithLocations
  # );

  # nixpkgs.overlays = [
  #   (final: prev: {
  #     nix = pkgs-unstable.nix;
  #   })
  # ];

  # nixpkgs.overlays = [
  #   (final: prev: {
  #     foot = throw "foo";
  #   })
  # ];

  # Copy the NixOS configuration file and link it from the resulting system
  # (/run/current-system/configuration.nix). This is useful in case you
  # accidentally delete configuration.nix.
  # system.copySystemConfiguration = true;

  # This option defines the first version of NixOS you have installed on this particular machine,
  # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
  #
  # Most users should NEVER change this value after the initial install, for any reason,
  # even if you've upgraded your system to a new NixOS release.
  #
  # This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
  # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
  # to actually do that.
  #
  # This value being lower than the current NixOS release does NOT mean your system is
  # out of date, out of support, or vulnerable.
  #
  # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
  # and migrated your data accordingly.
  #
  # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion .
  system.stateVersion = "24.11"; # Did you read the comment?

}