{
  modulesPath,
  lib,
  pkgs,
  config,
  inputs',
  ...
}:
let
  inherit (lib.my) mkVHost;
in
{
  imports = [
    (modulesPath + "/profiles/qemu-guest.nix")
    ./disk-config.nix
    ./forgejo
    ./headscale
    ./fail2ban.nix
  ];

  age.secrets = {
    couchdb.file = ../../secrets/couchdb.age;
    rustypaste = {
      file = ../../secrets/rustypaste.age;
      owner = "rustypaste";
      group = "rustypaste";
    };
    forgejo-runner-token.file = ../../secrets/forgejo-runner-token.age;
    acme = {
      owner = if config.security.acme.useRoot then "root" else "acme";
      file = ../../secrets/acme.age;
    };
  };

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

  virtualisation.docker.enable = true;

  modules = {
    server.rustypaste = {
      enable = true;
      package = inputs'.nur.packages.rustypaste;
      authTokenFile = config.age.secrets.rustypaste.path;
      settings = {
        server = {
          url = "https://rusty.ccnlc.eu";
          max_content_length = "1000MB";
          timeout = "30s";
          expose_version = false;
          expose_list = false;
          handle_spaces = "replace";
        };
        paste = {
          random_url = {
            type = "petname";
            words = 3;
            separator = "-";
          };
          default_extension = "txt";
          mime_blacklist = [
            "application/x-dosexec"
            "application/java-archive"
            "application/java-vm"
          ];
          duplicate_files = false;
          default_expiry = "1h";
          delete_expired_files = {
            enabled = true;
            interval = "1h";
          };
        };
      };
    };

    services.tailscale = {
      enable = true;
      tags = [ "server" ];
      extraFlags = [ "--accept-dns=false" ]; # Want to disable that since *server* can't access the private dns... for now
    };
  };

  networking = {
    nftables.enable = true;
    firewall = {
      enable = true;
      allowedTCPPorts = [
        80 # for acme challenges
        443
      ];
    };
  };

  age.identityPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];

  security = {
    polkit.enable = true;

    acme = {
      acceptTerms = true;
      defaults = {
        email = "contact@ccnlc.eu";
        dnsProvider = "ovh";
        environmentFile = config.age.secrets.acme.path;
      };
    };
  };

  services = {
    fail2ban.enable = true;
    headscale.enable = true;

    nginx = {
      package = pkgs.nginxQuic;
      enable = true;
      recommendedProxySettings = true;
      recommendedTlsSettings = true;
      clientMaxBodySize = "100M";
      virtualHosts = builtins.listToAttrs [
        (mkVHost "rusty.ccnlc.eu" 8000 true)
        (mkVHost "hedgedoc.ccnlc.eu" 4739 true)
      ];
    };

    endlessh = {
      enable = true;
      port = 22;
      openFirewall = true;
    };
  };

  services.hedgedoc = {
    enable = true;
    settings = {
      domain = "hedgedoc.ccnlc.eu";
      host = "0.0.0.0";
      port = 4739;
      protocolUseSSL = true;
      allowEmailRegister = false;
    };
  };

  system.stateVersion = "24.11";
}