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

{
  microvm = {
    # Running on server10 which has 40 threads on 20 cores
    vcpu = 8;
    # drone-ssh-runner clones the git repo into tmpfs which requires some RAM
    mem = 2 * 1024;
  };

  # drone-ssh-runner clones into /tmp which needs to be bigger than the default rootfs tmpfs
  boot.tmp = {
    useTmpfs = true;
    tmpfsSize = "80%";
  };

  c3d2.deployment = {
    # /tmp is to small for drone to clone the repo even with depth
    mounts = lib.mkOptionDefault [ "tmp" ];
    server = "server10";
  };

  system.stateVersion = "22.05";

  networking = {
    hostName = "c3d2-web";
    firewall.allowedTCPPorts = [
      # telme10
      23
      # gemini
      1965
    ];
  };

  security.acme.certs = {
    # agate cannot load modern crypto like "ec256" keys
    "www.c3d2.de".keyType = "rsa4096";
  };

  services.nginx = {
    enable = true;
    virtualHosts = {
      "www.c3d2.de" = {
        default = true;
        serverAliases = [
          "c3d2.de"
          "c3dd.de" "www.c3dd.de" "openpgpkey.c3d2.de"
          "cccdd.de" "www.cccdd.de"
          "dresden.ccc.de" "www.dresden.ccc.de"
          "netzbiotop.org" "www.netzbiotop.org"
        ];
        enableACME = true;
        forceSSL = true;
        root = "/var/www/c3d2";
        extraConfig = ''
          index portal.html index.html;
        '';
        locations = {
          # Mastodon
          "~ ^/\\.well-known/webfinger".return = "301 https://c3d2.social/.well-known/webfinger?resource=acct%3ac3d2%40c3d2.social";

          # Matrix
          "~ ^/\\.well-known/matrix/server" = {
            return = "200 '{\"m.server\": \"matrix.c3d2.de:443\"}'";
            extraConfig = ''
              default_type application/json;
            '';
          };
          "~ ^/\\.well-known/matrix/client" = {
            return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.c3d2.de\"}}'";
            extraConfig = /* nginx */ ''
              default_type application/json;
              add_header "Access-Control-Allow-Origin" *;
            '';
          };

          "~ ^/schule$".return = "307 /schule/";
          "/schule/" = {
            alias = "/var/www/cms-slides/";
            extraConfig = ''
              index index.html;
            '';
          };

          # SpaceAPI
          "/status.png".proxyPass = "http://[${hostRegistry.spaceapi.ip6}]:3000/status.png";
          "/spaceapi.json".proxyPass = "http://[${hostRegistry.spaceapi.ip6}]:3000/spaceapi.json";

          # WKD: Web Key Directory for PGP Keys
          "~ ^/openpgp".extraConfig = ''
            autoindex off;
            default_type  "application/octet-stream";
            add_header    Access-Control-Allow-Origin "* always";
          '';
        };
      };

      "datenspuren.de" = {
        serverAliases = [
          "www.datenspuren.de"
          "ds.c3d2.de" "datenspuren.c3d2.de"
        ];
        enableACME = true;
        forceSSL = true;
        root = "/var/www/c3d2/datenspuren";
        extraConfig = /* nginx */ ''
          index index.html;
          rewrite ^/$ /2024/ redirect;
        '';
        # Mastodon
        locations."~ ^/.well-known/webfinger".return = "301 https://c3d2.social/.well-known/webfinger?resource=acct%3adatenspuren%40c3d2.social";
      };

      "autotopia.c3d2.de" = {
        enableACME = true;
        forceSSL = true;
        root = "/var/www/c3d2/autotopia";
        extraConfig = ''
          index index.html;
          rewrite ^/$ /2020/ redirect;
        '';
      };
    };
  };

  # Gemini server
  services.agate = {
    enable = true;
    addresses = [
      # sysctl net.ipv6.bindv6only = 0
      "[::]:1965"
    ];
    certificatesDir = "/var/lib/agate/certificates";
    contentDir = "/var/www/gemini";
    language = "de";
  };

  systemd = {
    packages = with pkgs; [ telme10 ];
    services = {
      # lets agate access the tls certs
      agate = {
        requires = [ "agate-keys.service" ];
        after = [ "agate-keys.service" ];
        serviceConfig = {
          Group = "keys";
        };
      };
      agate-keys = {
        path = with pkgs; [ openssl ];
        script =
          let
            stateDir = "/var/lib/agate/certificates";
          in
          ''
            mkdir -p ${stateDir}
            openssl x509 \
                -in /var/lib/acme/www.c3d2.de/cert.pem \
                -out ${stateDir}/cert.der \
                -outform DER
            openssl rsa \
                -in /var/lib/acme/www.c3d2.de/key.pem \
                -out ${stateDir}/key.der \
                -outform DER
            chown root:keys ${stateDir}/*
            chmod 0640 ${stateDir}/*
          '';
        serviceConfig = {
          Type = "oneshot";
        };
      };
      telme10 = {
        serviceConfig.AmbientCapabilities = "CAP_NET_BIND_SERVICE";
      };
    };

    sockets.telme10.wantedBy = [ "sockets.target" ];
  };

  users = {
    groups = {
      c3d2-web = { };
      telme10 = { };
    };
    users = {
      c3d2-web = {
        group = "c3d2-web";
        home = "/var/lib/c3d2-web";
        isSystemUser = true;
        openssh.authorizedKeys.keys = [
          "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHIkIN1gi5cX2wV2WuNph/QzVK7vvYkvqnR/P69s36mZ drone@c3d2"
        ];
        packages = with pkgs; [
          (stdenv.mkDerivation {
            pname = "atomic-rsync";
            inherit (rsync) version src meta;

            dontBuild = true;
            dontConfigure = true;

            buildInputs = [ python3 ];

            installPhase = ''
              substituteInPlace support/atomic-rsync \
                --replace /usr/bin/rsync rsync

              install -Dm755 support/atomic-rsync -t $out/bin
            '';
          })
          (libxslt.override { cryptoSupport = true; })
          libxml2
          rsync
          gnumake
        ];
        # otherwise the the drone ssh runner cannot log in
        useDefaultShell = true;
      };
      telme10 = {
        isSystemUser = true;
        group = "telme10";
      };
    };
  };

  systemd.tmpfiles.rules = with config.users.users.c3d2-web; [
    "d /var/www/c3d2 0755 c3d2-web ${group} -"
    "d ${config.services.agate.contentDir} 0755 c3d2-web ${group} -"
    "d ${home} 0700 c3d2-web ${group} -"
  ];

  sops = {
    defaultSopsFile = ./secrets.yaml;
    secrets."c3d2-web/gitea-token".owner = "c3d2-web";
  };
}
