# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
#
# SPDX-License-Identifier: Apache-2.0

{ depot, lib, pkgs, config, ... }:
let
  vhostsConfig = {
    int = rec {
      proxy = _apply (value: { locations."/".proxyPass = value; }) {
        "deluge.int.lukegb.com" = "http://localhost:8112";
        "radarr.int.lukegb.com" = "http://localhost:7878";
        "sonarr.int.lukegb.com" = "http://localhost:8989";
      };
      serve = _apply (value: { root = value; }) {
        "int.lukegb.com" = depot.web.int;
        "logged-out.int.lukegb.com" = depot.web.logged-out-int;
      };
      other = _apply lib.id {
        "content.int.lukegb.com" = {
          listen = [{
            addr = "[${config.my.ip.tailscale6}]";
            port = 80;
          } {
            addr = config.my.ip.tailscale;
            port = 80;
          } {
            addr = "[${config.my.ip.tailscale6}]";
            port = 18081;
          } {
            addr = config.my.ip.tailscale;
            port = 18081;
          }];
          locations."/" = {
            alias = "/store/content/";
            extraConfig = ''
              autoindex on;
            '';
          };
        };
      };
      _apply = f: builtins.mapAttrs (name: value: lib.recursiveUpdate hostBase (f value));
    };
  };
  vhosts = vhostsConfig.int.proxy // vhostsConfig.int.serve // vhostsConfig.int.other;
  hostBase = {
    listen = [{
      addr = config.my.ip.tailscale;
      port = 80;
    } {
      addr = "[${config.my.ip.tailscale6}]";
      port = 80;
    }];
  };
in {
  imports = [
    ../lib/zfs.nix
    ../lib/bgp.nix
    ../lib/coredns/default.nix
    ../lib/deluge.nix
    ../lib/plex.nix
  ];

  boot.initrd.availableKernelModules = [
    "xhci_pci"
    "ahci"
    "nvme"
    "usbhid"
    "usb_storage"
    "sd_mod"
    "sr_mod"
  ];
  boot.kernelModules = [ "kvm-intel" ];

  powerManagement.cpuFreqGovernor = lib.mkDefault "performance";

  fileSystems = let
    zfs = device: {
      device = device;
      fsType = "zfs";
    };
  in {
    "/" = zfs "zfast/local/root";
    "/nix" = zfs "zfast/local/nix";
    "/persist" = zfs "zfast/safe/persist";
    "/home" = zfs "zfast/safe/home";
    "/store" = zfs "zslow/local/store";

    "/boot" = {
      device = "/dev/disk/by-label/ESP";
      fsType = "vfat";
    };
  };

  nix.settings.max-jobs = lib.mkDefault 12;

  # Use systemd-boot.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;

  # Networking!
  networking = {
    hostName = "clouvider-fra01";
    domain = "as205479.net";
    hostId = "9e983570";

    nameservers = [
      "2001:4860:4860::8888"
      "2001:4860:4860::8844"
      "8.8.8.8"
      "8.8.4.4"
    ];
    defaultGateway = {
      address = "193.228.196.56";
      interface = "enp1s0";
    };
    defaultGateway6 = {
      address = "2a0f:93c0:0:22::1";
      interface = "enp1s0";
    };
    interfaces.enp1s0 = {
      ipv4.addresses = [{ address = "193.228.196.57"; prefixLength = 31; }];
      ipv6.addresses = [{ address = "2a0f:93c0:0:22::2"; prefixLength = 126; }];
    };
    firewall.allowPing = true;
    firewall.allowedTCPPorts = [
      4001  # ipfs
    ];
    firewall.allowedUDPPorts = [
      4001  # ipfs
    ];
  };
  my.ip.tailscale = "100.75.142.119";
  my.ip.tailscale6 = "fd7a:115c:a1e0:ab12:4843:cd96:624b:8e77";
  my.coredns.bind = [ "enp1s0" "tailscale0" "127.0.0.1" "::1" ];

  # Define a user account.
  users.mutableUsers = false;
  users.users = {
    sonarr.extraGroups = [ "deluge" "content" ];
    radarr.extraGroups = [ "deluge" "content" ];
  } // (lib.setAttrByPath [ config.services.nginx.user "extraGroups" ] [ "acme" ]);

  services.openssh.hostKeys = [
    {
      path = "/persist/etc/ssh/ssh_host_ed25519_key";
      type = "ed25519";
    }
    {
      path = "/persist/etc/ssh/ssh_host_rsa_key";
      type = "rsa";
      bits = 4096;
    }
  ];

  services.sonarr = {
    enable = true;
  };
  services.radarr = {
    enable = true;
  };

  services.nginx = {
    enable = true;
    virtualHosts = vhosts;
  };

  services.kubo = {
    enable = true;
    settings = {
      Discovery.MDNS.Enabled = false;
      Swarm.DisableNatPortMap = true;
      Experimental.FilestoreEnabled = true;
    };
    dataDir = "/store/ipfs";
  };

  system.stateVersion = "20.09";
}