{ config, lib, pkgs, ... }:

with lib;

let
  opts = { name, config, ... }: {
    options = {
      enable = mkOption {
        default = true;
        type = types.bool;
        example = true;
        description = lib.mdDoc "Whether to enable proxy for this bucket";
      };
      bucketName = mkOption {
        type = types.str;
        default = name;
        example = "my-bucket-name";
        description = lib.mdDoc "Name of Google storage bucket";
      };
      address = mkOption {
        type = types.str;
        example = "localhost:3000";
        description = lib.mdDoc "The address of the proxy.";
      };
    };
  };
  enabledProxies = lib.filterAttrs (n: v: v.enable) config.services.nix-store-gcs-proxy;
  mapProxies = function: lib.mkMerge (lib.mapAttrsToList function enabledProxies);
in
{
  options.services.nix-store-gcs-proxy = mkOption {
    type = types.attrsOf (types.submodule opts);
    default = {};
    description = lib.mdDoc ''
      An attribute set describing an HTTP to GCS proxy that allows us to use GCS
      bucket via HTTP protocol.
    '';
  };

  config.systemd.services = mapProxies (name: cfg: {
    "nix-store-gcs-proxy-${name}" = {
      description = "A HTTP nix store that proxies requests to Google Storage";
      wantedBy = ["multi-user.target"];

      startLimitIntervalSec = 10;
      serviceConfig = {
        RestartSec = 5;
        ExecStart = ''
          ${pkgs.nix-store-gcs-proxy}/bin/nix-store-gcs-proxy \
            --bucket-name ${cfg.bucketName} \
            --addr ${cfg.address}
        '';

        DynamicUser = true;

        ProtectSystem = "strict";
        ProtectHome = true;
        PrivateTmp = true;
        PrivateDevices = true;
        PrivateMounts = true;
        PrivateUsers = true;

        ProtectKernelTunables = true;
        ProtectKernelModules = true;
        ProtectControlGroups = true;

        NoNewPrivileges = true;
        LockPersonality = true;
        RestrictRealtime = true;
      };
    };
  });

  meta.maintainers = [ maintainers.mrkkrp ];
}
