{ pkgs, lib, config, ... }:
let
  netns = "calyx";
  inherit (config.services) openvpn;
  apiUrl = "https://api.calyx.net:4430/3/cert";
  ca = pkgs.fetchurl {
    url = "https://calyx.net/ca.crt";
    hash = "sha256-NKLkpjjeGMN07htuWydBMQ03ytxF9CLm8SLNl3IPPGc=";
    curlOpts = ["-k"];
  } + "";
  key-cert = "/run/openvpn-${netns}/key+cert.pem";
in
{
services.openvpn.servers.${netns} = {
  inherit netns;
  settings = {
    remote =
      # new-york
      ["162.247.73.193"] ++
      [];
    port = "443";
    proto = "tcp";
    inherit ca;
    key = key-cert;
    cert = key-cert;

    auth = "SHA1";
    cipher = "AES-128-CBC";
    client = true;
    dev = "ov-${netns}";
    dev-type = "tun";
    keepalive = "10 30";
    nobind = true;
    persist-key = true;
    persist-tun = true;
    remote-cert-tls = "server";
    reneg-sec = 0;
    script-security = 2;
    tls-cipher = "DHE-RSA-AES128-SHA";
    tls-client = true;
    tun-ipv6 = true;
    up-restart = true;
    verb = 3;
  };
};
systemd.services."openvpn-${netns}" = {
  preStart = ''
    (
    set -ex
    ${pkgs.curl}/bin/curl -X POST --cacert ${ca} -o ${key-cert} -Ls ${apiUrl}
    chmod 700 ${key-cert}
    )
  '';
  serviceConfig = {
    RuntimeDirectory = [ "openvpn-${netns}" ];
    RuntimeDirectoryMode = "0700";
  };
};
networking.nftables.ruleset = ''
  add rule inet filter fw2net meta skuid root tcp dport 443 counter accept comment "OpenVPN Calyx"
  add rule inet filter fw2net meta skuid root tcp dport 4430 counter accept comment "OpenVPN Calyx (API)"
'';
services.netns.namespaces.${netns} = {
  nftables = lib.mkBefore ''
    table inet filter {
      include "${../../../../networking/nftables/filter.txt}"
      chain input {
        type filter hook input priority filter
        policy drop
        iifname lo accept
        jump check-tcp
        ct state { established, related } accept
        jump accept-connectivity-input
        jump check-broadcast
        ct state invalid drop
      }
      chain forward {
        type filter hook forward priority filter
        policy drop
        jump accept-connectivity-forward
      }
      chain output {
        type filter hook output priority filter
        policy drop
        oifname lo accept
        ct state { related, established } accept
        jump accept-connectivity-output
      }
    }
  '';
};
}