{ inputs, secrets, nodeName, config, ctucxConfig, lib, pkgs, ... }: let katja-pubkey = builtins.readFile "${pkgs.ctucx-website}/ssh_pubkey.asc"; in { imports = [ ctucxConfig.common ]; boot.loader.efi.canTouchEfiVariables = lib.mkDefault true; boot.loader.systemd-boot.enable = lib.mkDefault true; boot.initrd.kernelModules = [ "ipv6" ]; networking.hostName = lib.mkDefault nodeName; networking.domain = lib.mkDefault "ctu.cx"; i18n.defaultLocale = "en_US.UTF-8"; i18n.supportedLocales = [ "de_DE.UTF-8/UTF-8" "en_US.UTF-8/UTF-8" ]; age.secrets.katjaPassword.file = secrets.allNodes.passwords.katja; age.secrets.acmeTSIGKey.file = secrets."${config.networking.hostName}".acmeTSigKey; system = { nixos.revision = lib.mkIf (inputs.nixpkgs.sourceInfo ? rev) inputs.nixpkgs.sourceInfo.rev; nixos.versionSuffix = ".${lib.substring 0 8 (inputs.nixpkgs.sourceInfo.lastModifiedDate or inputs.nixpkgs.sourceInfo.lastModified or "19700101")}.${inputs.nixpkgs.sourceInfo.shortRev or "dirty"}"; # thanks piegames (https://git.darmstadt.ccc.de/piegames/home-config/-/blob/master/modules/generic.nix#L84) activationScripts.diff = { supportsDryActivation = true; text = '' ${pkgs.nvd}/bin/nvd --color=always --nix-bin-dir=${pkgs.nix}/bin diff "$(readlink /run/current-system)" "$systemConfig" # Ignore "failures" because these tools have weird exit codes ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \ -- "$(readlink /run/current-system)/activate" "$systemConfig/activate" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \ -x "os-release" -x "issue" \ -- "$(readlink /run/current-system)/etc" "$systemConfig/etc" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true ${pkgs.colordiff}/bin/colordiff --nobanner --fakeexitcode --color=always -ur -I '\/nix\/store' \ -x "environment.d" \ -x "hwdb.d" \ -- "$(readlink /run/current-system)/systemd" "$systemConfig/systemd" | ${pkgs.gnugrep}/bin/grep -v "^Binary files" || true ''; }; }; nix = { channel.enable = lib.mkForce false; settings = { auto-optimise-store = true; # Free up to 1GiB whenever there is less than 100MiB left. min-free = toString (100 * 1024 * 1024); max-free = toString (1024 * 1024 * 1024); }; daemonCPUSchedPolicy = lib.mkDefault "idle"; daemonIOSchedClass = lib.mkDefault "idle"; optimise.automatic = lib.mkDefault true; optimise.dates = [ "12:00" "15:00" "18:00" "21:00" ]; gc.automatic = lib.mkDefault true; gc.options = "--delete-older-than 3d"; gc.dates = "18:00"; }; systemd.services = let ctucxCAgetCRL = pkgs.writeShellScript "ctucxCAgetCRL" '' ${lib.getExe pkgs.curl} -s -o /tmp/ctucxCAcrl.der '${( if config.services.step-ca.enable then "http://${config.services.step-ca.settings.insecureAddress}/1.0/crl" else "https://ca.ctu.cx/1.0/crl" )}'; cp ${../../secrets/certs/rootCA.crl} /etc/ctucxCA.crl; ${lib.getExe pkgs.openssl} crl -in /tmp/ctucxCAcrl.der -inform der >> /etc/ctucxCA.crl; ''; in { nginx.onFailure = [ "email-notify@%i.service" ]; ctucxCAgetCRL = { wantedBy = [ "multi-user.target" ]; before = [ "nginx.service" ]; after = lib.mkIf config.services.step-ca.enable [ "step-ca.service" ]; serviceConfig.Type = "oneshot"; serviceConfig.ExecStart = ctucxCAgetCRL; }; ctucxCAupdateCRL = { wantedBy = [ "multi-user.target" ]; after = lib.mkIf config.services.step-ca.enable [ "step-ca.service" ]; startAt = [ "*-*-* *:0/10:00" ]; serviceConfig.Type = "oneshot"; serviceConfig.ExecStart = ctucxCAgetCRL; serviceConfig.ExecStartPost = "${pkgs.systemd}/bin/systemctl reload nginx.service"; }; }; services = { timesyncd.enable = lib.mkDefault true; fstrim.enable = lib.mkDefault true; vnstat.enable = lib.mkDefault true; vnstati.enable = lib.mkDefault config.services.vnstat.enable; journald.extraConfig = "SystemMaxUse=1G"; logind.killUserProcesses = lib.mkDefault true; nginx = { resolver.addresses = lib.mkDefault [ "[2620:fe::fe]" "[2620:fe::9]" "[2606:4700:4700::1111]" "1.1.1.1" "9.9.9.9" ]; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; commonHttpConfig = '' server_names_hash_bucket_size 64; charset utf-8; access_log off; ''; virtualHosts."${config.networking.fqdn}".default = true; }; openssh = { enable = lib.mkDefault true; startWhenNeeded = lib.mkDefault true; ports = [ 22 ]; extraConfig = '' AllowTcpForwarding yes AllowAgentForwarding no AllowStreamLocalForwarding no AuthenticationMethods publickey ''; settings = { AllowUsers = [ "root" "katja" ]; X11Forwarding = false; PermitRootLogin = "without-password"; PasswordAuthentication = false; challengeResponseAuthentication = false; }; }; }; security.acme = { acceptTerms = true; defaults = { email = "letsencrypt@ctu.cx"; keyType = "ec384"; dnsProvider = "rfc2136"; environmentFile = pkgs.writeText "acme-dns-env" '' RFC2136_NAMESERVER=ns1.ctu.cx RFC2136_TSIG_KEY=acme-nix-${config.networking.hostName} RFC2136_TSIG_ALGORITHM=hmac-sha384. ''; credentialFiles = { RFC2136_TSIG_SECRET_FILE = config.age.secrets.acmeTSIGKey.path; }; }; certs."${config.networking.fqdn}" = { group = "nginx"; extraDomainNames = ( config.services.nginx.virtualHosts |> lib.mapAttrsToList (key: config: [ (if config ? serverAliases then config.serverAliases else []) key ]) |> lib.flatten ); }; }; users.mutableUsers = false; users.users.root.openssh.authorizedKeys.keys = [ katja-pubkey ]; users.users.katja = { isNormalUser = true; hashedPasswordFile = config.age.secrets.katjaPassword.path; extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. openssh.authorizedKeys.keys = [ katja-pubkey ]; }; home-manager.users.katja = { home.language = { "base" = "en_US.UTF-8"; "time" = "de_DE.utf8"; "address" = "de_DE.utf8"; "monetary" = "de_DE.utf8"; "paper" = "de_DE.utf8"; }; }; }