# Module that enables remote builds. This is a client configuration.
{ pkgs, lib, config, secret, ... }: with lib; let
	cfg = config.module.builder;

	serverKeyPath = "/root/.nixbuilder";
in {
	options = {
		module.builder = {
			server.enable = mkEnableOption "This is a builder server.";
			client.enable = mkEnableOption "This is a builder client.";
		};
	};

	config = mkMerge [
		(mkIf cfg.server.enable {
			# Service that generates new key on boot if not present.
			# Don't forget to add new key to secret.ssh.buildKeys.
			systemd.services.generate-nix-cache-key = {
				wantedBy = [ "multi-user.target" ];
				serviceConfig.Type = "oneshot";
				path = [ pkgs.nix ];
				script = ''
					[[ -f "${serverKeyPath}/private-key" ]] && exit
					mkdir ${serverKeyPath} || true
					nix-store --generate-binary-cache-key "nixbuilder-1" "${serverKeyPath}/private-key" "${serverKeyPath}/public-key"
					nix store sign --all -k "${serverKeyPath}/private-key"
				'';
			};

			# Add `nixbuilder` restricted user.
			users.groups.nixbuilder = {};
			users.users.nixbuilder = {
				openssh.authorizedKeys.keys = secret.ssh.buildKeys;
				description  = "Nix Remote Builder";
				isNormalUser = true;
				createHome   = lib.mkForce false;
				uid          = 1234;
				home         = "/";
				group        = "nixbuilder";
			};

			# Sign store automatically.
			# Sign existing store with: nix store sign --all -k /path/to/secret-key-file
			nix.settings = {
				trusted-users    = [ "nixbuilder" ];
				secret-key-files = [ "${serverKeyPath}/private-key" ];
			};
		})

		(mkIf cfg.client.enable {
			# NOTE: Requires host private key to be present in secret.ssh.builderKeys.
			nix.buildMachines = [{
				hostName = "nixbuilder";
				protocol = "ssh-ng";
				systems  = [
					"x86_64-linux"
					"i686-linux"
					"aarch64-linux"
				];
				maxJobs     = 1;
				speedFactor = 2;
				mandatoryFeatures = [ ];
				supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
			}];
			nix.distributedBuilds = true;
			nix.settings = let
				substituters = [ "ssh-ng://nixbuilder" ];
			in {
				substituters = mkForce substituters;
				trusted-substituters = substituters ++ [ "https://cache.nixos.org/" ];
				builders-use-substitutes = true;
				max-jobs = 0;
				trusted-public-keys = [ secret.ssh.builderKey ];
				# require-sigs = false;
				# substitute = false;
			};
		})
	];
}