{ pkgs, lib, config, ... }:
let
  netns = "riseup";
  inherit (config.services) openvpn;
  apiUrl = "https://api.black.riseup.net/3/cert";
  ca = pkgs.fetchurl {
    url = "https://black.riseup.net/ca.crt";
    hash = "sha256-Zdvnfz2k7iWlbgmmcUJrpJZ1dp7o0qXeJhP0HWJD7ro=";
  } + "";
  key-cert = "/run/openvpn-${netns}/key+cert.pem";
in
{
services.openvpn.servers.${netns} = {
  inherit netns;
  settings = {
    remote =
      # amsterdam
      ["212.83.182.127" "212.83.165.160" "212.129.4.141"] ++
      # paris
      #["212.83.146.228" "212.83.143.67" "163.172.126.44"] ++
      # miami
      ["37.218.244.249" "37.218.244.251"] ++
      # montreal
      ["199.58.83.10" "199.58.83.10" "199.58.83.12"] ++
      # new-york
      ["185.220.103.12"] ++
      # seattle
      ["198.252.153.28" "198.252.153.28"] ++
      [];
    remote-random = true;
    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 -e
    ${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 Riseup"
'';
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
      }
    }
  '';
};
}