{ 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-zLs7TRXrHlPjqdaBN1cmbB062XhKs4cv5ajmrkg4O8s=";
      curlOptsList = [ "-k" ];
    } + "";
  key-cert = "/run/openvpn-${netns}/key+cert.pem";
in
{
  services.openvpn.servers.${netns} = {
    inherit netns;
    settings = {
      remote =
        # new-york (vpn2.calyx.net)
        [ "162.247.72.193" ] ++
        [ ];
      remote-random = true;
      port = "443";
      proto = "tcp";
      inherit ca;
      key = key-cert;
      cert = key-cert;

      auth = "SHA1";
      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 = "TLS-DHE-RSA-WITH-AES-128-CBC-SHA";
      tls-client = true;
      up-restart = true;
      verb = 3;
    };
  };
  systemd.services."openvpn-${netns}" = {
    after = [ "network-online.target" ];
    preStart = ''
      (
      set -ex
      ${pkgs.curl}/bin/curl -X POST --cacert ${ca} -o ${key-cert} -vLs ${apiUrl}
      chmod 700 ${key-cert}
      )
    '';
    serviceConfig = {
      RuntimeDirectory = [ "openvpn-${netns}" ];
      RuntimeDirectoryMode = "0700";
    };
  };
  networking.nftables.ruleset = ''
    table inet filter {
      chain output-net {
        skuid root tcp dport https counter accept comment "OpenVPN Calyx"
        skuid root tcp dport 4430 counter accept comment "OpenVPN Calyx (API)"
      }
    }
  '';
  services.netns.namespaces.${netns} = {
    nftables = lib.mkBefore ''
      include "${../networking/nftables.txt}"
      table inet filter {
        chain output-lan {
          meta l4proto { udp, tcp } th dport domain counter accept comment "DNS"
          log prefix "calyx: output-lan: " counter drop
        }
        chain output-net {
          tcp dport { http, https } counter accept comment "HTTP"
          log prefix "calyx: output-net: " counter drop
        }
        chain output {
          ip daddr 10.0.0.0/8 counter goto output-lan
          ip daddr 172.16.0.0/12 counter goto output-lan
          ip daddr 192.168.0.0/16 counter goto output-lan
          ip daddr 224.0.0.0/3 counter goto output-lan
          jump output-net
          log prefix "calyx: output: " counter drop
        }
      }
    '';
  };
}