{
  modulesPath,
  pubkeys,
  config,
  ...
}:
{
  imports = [
    (modulesPath + "/profiles/qemu-guest.nix")
    ./disk-config.nix
    ./adguard.nix
    ./calibre-web.nix
    ./prometheus.nix
  ];

  swapDevices = [
    { device = "/dev/disk/by-uuid/cc568199-7a9b-4aa2-83f8-2a63982ff4f1"; }
  ];

  age.secrets = {
    navidrome.file = ../../secrets/navidrome.age;
    adguard-dns-list = {
      file = ../../secrets/adguard-dns-list.age;
      mode = "444";
    };
    freshrss-default-password = {
      file = ../../secrets/freshrss-default-password.age;
      owner = config.services.freshrss.user;
    };
    acme = {
      owner = if config.security.acme.useRoot then "root" else "acme";
      file = ../../secrets/acme.age;
    };
  };

  boot.loader.grub = {
    efiSupport = true;
    efiInstallAsRemovable = true;
  };

  modules = {
    meta = {
      tailscale.ip = "100.64.0.4";
    };
    system.networking.bluetooth.enable = true;
    container = {
      kitchenowl = {
        enable = true;
        version = "v0.6.4";
      };
    };

    server = {
      paperless = {
        enable = true;
        openPort = true;
        settings = {
          PAPERLESS_URL = "https://paperless.ccnlc.eu";
          PAPERLESS_OCR_USER_ARGS = {
            invalidate_digital_signatures = true;
          };
        };
      };

      navidrome = {
        enable = true;
        library = {
          path = "/mnt/music";
          type = "nfs";
          source = {
            ip = "192.168.178.21";
            path = "/mnt/Fort/data/music";
          };
        };
        settings = {
          Address = "0.0.0.0";
          Port = 4533;
        };
      };
    };

    services = {
      tailscale = {
        enable = true;
        isExitNode = true;
        tags = [ "server" ];
      };

      rsync-backup = {
        enable = true;
        modules = [
          {
            sources = [
              "/var/lib/paperless"
              "/var/lib/radicale"
              "/var/lib/navidrome"
              "/var/lib/immich"
              "/var/lib/freshrss"
            ];
            target = {
              location = "shan";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
          {
            sources = [ "/var/lib/paperless" ];
            target = {
              location = "paperless-backup";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
          {
            sources = [ "/var/lib/immich" ];
            target = {
              location = "immich-backup";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
          {
            sources = [ "/mnt/music" ];
            target = {
              location = "music-backup";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
          {
            sources = [ "/mnt/shows" ];
            target = {
              location = "shows-backup";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
          {
            sources = [ "/mnt/movies" ];
            target = {
              location = "movies";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
          {
            sources = [ "/mnt/books" ];
            target = {
              location = "books";
              type = "rsyncd";
              host = "nihilus";
            };
            incremental.enable = true;
          }
        ];
      };
    };
  };
  security = {
    polkit.enable = true;

    acme = {
      acceptTerms = true;
      defaults = {
        email = "dns@ccnlc.eu";
        dnsProvider = "ovh";
        dnsResolver = "9.9.9.9"; # Necessary to avoid failing due to a local dns server
        environmentFile = config.age.secrets.acme.path;
      };

      certs."ccnlc.eu" = {
        group = "nginx";
        extraDomainNames = [ "*.ccnlc.eu" ];
      };
    };
  };

  services.nginx = {
    enable = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;
    clientMaxBodySize = "0";
    virtualHosts =
      let
        mkVHLocal = mkVH "http://localhost";
        mkVH = domain: port: {
          forceSSL = true;
          useACMEHost = "ccnlc.eu";
          locations."/" = {
            proxyPass = "${domain}:${toString port}";
            extraConfig = ''
              proxy_ssl_server_name on;
              proxy_pass_header Authorization;
              proxy_set_header Upgrade $http_upgrade;
              proxy_set_header Connection $http_connection;
              proxy_http_version 1.1;
            '';
          };
        };
      in
      {
        "octoprint.ccnlc.eu" = mkVHLocal config.services.octoprint.port;
        "immich.ccnlc.eu" = mkVHLocal config.services.immich.port;
        "jellyfin.ccnlc.eu" = mkVHLocal 8096;
        "ntfy.ccnlc.eu" = mkVHLocal 9393;
        "dav.ccnlc.eu" = mkVHLocal 5232;
        "assistant.ccnlc.eu" = mkVHLocal config.services.home-assistant.config.http.server_port;
        "kitchenowl.ccnlc.eu" = mkVHLocal config.modules.container.kitchenowl.port;
        "navidrome.ccnlc.eu" = mkVHLocal config.services.navidrome.settings.Port;
        "paperless.ccnlc.eu" = mkVHLocal config.modules.server.paperless.port;
        "fritz.ccnlc.eu" = mkVH "http://192.168.178.1" 80;
        "truenas.ccnlc.eu" = mkVH "https://192.168.178.21" 443;
        "calibre.ccnlc.eu" = mkVHLocal config.services.calibre-web.listen.port;
        "prometheus.ccnlc.eu" = mkVHLocal config.services.prometheus.port;
        "adguard.ccnlc.eu" = mkVHLocal config.services.adguardhome.port;
        "grafana.ccnlc.eu" = mkVHLocal config.services.grafana.settings.server.http_port;
        ${config.services.freshrss.virtualHost} = {
          forceSSL = true;
          useACMEHost = "ccnlc.eu";
        };
      };
  };

  services = {
    openssh = {
      enable = true;
      startWhenNeeded = true;
      settings = {
        PasswordAuthentication = false;
      };
    };

    jellyfin.enable = true;
    immich.enable = true;

    radicale = {
      enable = true;
      # Documentation at <https://radicale.org/v3.html#configuration>
      settings = {
        server = {
          hosts = [ "127.0.0.1:5232" ];
        };
        auth = {
          type = "htpasswd";
          htpasswd_filename = "/etc/radicale/users";
          htpasswd_encryption = "autodetect";
        };
        storage = {
          filesystem_folder = "/var/lib/radicale/collections";
        };
      };
    };

    ntfy-sh = {
      enable = true;
      settings =
        let
          root = "/var/lib/ntfy-sh";
        in
        {
          base-url = "https://ntfy.ccnlc.eu";
          listen-http = "127.0.0.1:9393";
          auth-default-access = "deny-all";
          behind-proxy = true;
          attachment-cache-dir = "${root}/attachments";
          enable-signup = true;
          enable-login = true;
        };
    };

    octoprint = {
      enable = true;
      port = 5000;
    };

    freshrss = {
      enable = true;
      passwordFile = config.age.secrets.freshrss-default-password.path;
      virtualHost = "rss.ccnlc.eu";
      baseUrl = "https://rss.ccnlc.eu";
    };

    home-assistant = {
      enable = true;
      openFirewall = true;
      configWritable = true;
      extraComponents = [
        "tplink_tapo"
        "tplink"
        "default_config"
        "met"
        "esphome"
        "mobile_app"
        "octoprint"
        "jellyfin"
        "iron_os"
        "wake_on_lan"
      ];
      config = {
        default_config = { };
        http = {
          server_port = 8123;
          use_x_forwarded_for = true;
          trusted_proxies = [
            "127.0.0.1"
            "::1"
            "10.89.0.3"
          ];
        };
      };
    };
  };

  networking.firewall.allowedTCPPorts = [
    443
    80
  ];

  fileSystems = {
    "/mnt/shows" = {
      device = "192.168.178.21:/mnt/Fort/data/shows";
      fsType = "nfs";
      options = [
        "x-systemd.automount"
        "ro"
      ];
    };

    "/mnt/movies" = {
      device = "192.168.178.21:/mnt/Fort/data/movies";
      fsType = "nfs";
      options = [
        "x-systemd.automount"
        "ro"
      ];
    };
  };

  users.users.root.openssh.authorizedKeys.keys = [ pubkeys.ny ];

  system.stateVersion = "23.11";
}