{
  config,
  lib,
  pkgs,
  fn,
  ...
}:
with lib;
mkIf (elem "nextcloud" config.machine.services) {
  services =
    let
      cfg = config.machine;
      inherit ((findFirst (s: s.service == "nextcloud") cfg cfg.vHosts)) domain;
    in
    {
      nextcloud = {
        enable = true;
        home = "/var/lib/nextcloud";
        hostName = domain;
        https = true;
        maxUploadSize = "1024M";
        package = pkgs.nextcloud30;
        config = {
          adminuser = mkDefault (elemAt cfg.administrators 0).name;
          adminpassFile = config.sops.secrets."services/nextcloud/adminPass".path;
          dbtype = "mysql";
          dbhost = "localhost:3306";
          dbuser = "nextcloud";
          dbpassFile = config.sops.secrets."services/nextcloud/dbPass".path;
          dbname = "nextcloud";
        };
        settings = {
          trusted_domains = cfg.extraDomains;
        };
        caching = {
          apcu = true;
          memcached = true;
          redis = false;
        };
        phpOptions = {
          "opcache.interned_strings_buffer" = "16";
        };
      };
      # Turn Server used for nextcloud-talk
      # This stuff is still untested.
      coturn = mkIf (elem "nextcloud-talk" config.machine.services) {
        # TLS is not needed as WebRTC is already encrypted.
        enable = true;
        realm = domain;
        listening-port = 3478;
        use-auth-secret = true;
        extraConfig = ''
          fingerprint
          total-quota=100
          bps-capacity=0
          stale-nonce
          no-multicast-peers
        '';
      };
    };
  sops.secrets =
    fn.sopsHelper (name: "services/nextcloud/${name}")
      [
        "adminPass"
        "dbPass"
      ]
      {
        owner = "nextcloud";
        group = "nextcloud";
      };
}