{ config, hostRegistry, lib, pkgs, ... }:
let
  webroot = "/var/www";
in
{
  microvm = {
    vcpu = 4;
    mem = 2 * 1024; # drone-ssh-runner clones the git repo which requires some RAM
  };
  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";
  networking.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 = "${webroot}/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 = ''
              add_header Content-Type application/json;
            '';
          };
          "~ ^/.well-known/matrix/client" = {
            return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.c3d2.de\"}}'";
            extraConfig = ''
              add_header "Content-Type" application/json;
              add_header "Access-Control-Allow-Origin" *;
            '';
          };

          # 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 = "${webroot}/c3d2/datenspuren";
        extraConfig = ''
          index index.html;
          rewrite ^/$ /2023/ 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 = "${webroot}/c3d2/autotopia";
        extraConfig = ''
          index index.html;
          rewrite ^/$ /2020/ redirect;
        '';
      };

      # temporary redirects for outdated domains
      "dezentrale-jahresendveranstaltungen.fyi" = {
        serverAliases = [
          "rc3.c3d2.de"
          "www.dezentrale-jahresendveranstaltungen.fyi"
        ];
        enableACME = true;
        forceSSL = true;
        locations."/".return = "301 https://datenspuren.de";
      };
    };
  };
  # Gemini server
  services.agate = {
    enable = true;
    addresses = [
      # sysctl net.ipv6.bindv6only = 0
      "[::]:1965"
    ];
    certificatesDir = "/var/lib/agate/certificates";
    contentDir = "/var/gemini";
    language = "de";
  };

  systemd.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";
      };
    };
    telm10 = {
      path = with pkgs; [ telme10 ];
      serviceConfig.AmbientCapabilities = "CAP_NET_BIND_SERVICE";
    };
  };

  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; [
          libxslt
          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 ${webroot}/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";
  };
}
