{ lib, config, ... }: let inherit (config.networking) domain; root_email = "contact@${domain}"; in { imports = [ ./wireguard.nix ./matrix.nix ./puffer.nix ./gitea.nix ./grafana.nix ./nextcloud.nix ./prometheus.nix # ./mjolnir.nix # ./fail2ban.nix ./email.nix # ./discord-matrix-bridge.nix ./mastodon.nix ./nix_cache.nix # ./auth.nix ./hedgedoc.nix # ./factorio.nix ]; options.serverConfig = let inherit (lib) mkOption types mkEnableOption; in { ports = mkOption { type = types.attrsOf ( types.submodule ( { ... }: { options = { port = mkOption { type = types.int; description = "port to define"; }; open = mkEnableOption "whether to open the port" // { default = true; }; }; } ) ); default = { }; description = "ports associated with services"; }; vhosts = mkOption { type = types.attrsOf ( types.submodule ( { config, ... }: let type_lookup = { proxy = { locations."/".proxyPass = "http://127.0.0.1:${builtins.toString config.port}"; }; redirect = { locations."/".return = "307 https://${domain}"; }; custom = { }; none = { }; }; in { options = { port = mkOption { type = types.int; default = 80; description = "port to redirect to this vhost"; }; host = mkOption { type = types.nonEmptyStr; description = "name if the vhost"; }; accessType = mkOption { type = types.enum (lib.attrNames type_lookup); default = "none"; description = "nginx template to use"; }; extraNginx = mkOption { type = types.attrs; default = type_lookup.${config.accessType}; description = "location definition for nginx"; }; }; } ) ); default = { }; description = "vhosts associated with services"; }; }; config = { networking.firewall.allowedTCPPorts = [ 80 443 ] ++ (lib.mapAttrsToList (n: v: v.port) (lib.filterAttrs (n: v: v.open) config.serverConfig.ports)); # ++ (lib.mapAttrsToList (n: v: v.port) (lib.filterAttrs (n: v: !v.disableWebAccess) config.serverConfig.vhosts)); services.nginx.virtualHosts = { "${domain}" = { forceSSL = true; enableACME = lib.mkForce false; # use the correct cert, not some weird one that matrix-synapse module supplies useACMEHost = domain; locations."/" = { root = "/var/www/${domain}"; }; }; } // (lib.concatMapAttrs (_: host: { "${host.host}" = { serverName = host.host; forceSSL = true; useACMEHost = domain; enableACME = lib.mkForce false; } // host.extraNginx; }) (lib.filterAttrs (n: v: v.accessType != "none") config.serverConfig.vhosts)); serverConfig = { ports = { puffer_sftp_port.port = 5657; gitea_ssh_port.port = 2222; node_exporter = { port = 9002; open = false; }; discord_matrix_bridge_port = { port = 9005; open = false; }; redis_nextcloud_port = { port = 6379; open = false; }; open_ldap_port = { port = 389; open = false; }; }; vhosts = { puffer_host = { port = 8080; host = "puffer.${domain}"; accessType = "proxy"; }; hedgedoc_host = { port = 8048; host = "hedgedoc.${domain}"; accessType = "proxy"; }; tlemap_host = { port = 8100; host = "tlemap.${domain}"; accessType = "proxy"; }; mail_host = { host = "mail.${domain}"; accessType = "redirect"; }; gitea_host = { host = "git.${domain}"; port = 8081; accessType = "proxy"; }; matrix_host = { # accessType = "redirect"; host = "matrix.${domain}"; # port = 8008; }; prometheus_host = { host = "prometheus.${domain}"; port = 9090; accessType = "redirect"; }; grafana_host = { host = "grafana.${domain}"; accessType = "proxy"; port = 8082; }; nextcloud_host = rec { host = "cloud.${domain}"; port = 8083; accessType = "custom"; extraNginx.serverName = host; }; mastodon_host = { host = "mastodon.${domain}"; }; nix_cache_host = { host = "nixcache.${domain}"; port = 5000; accessType = "proxy"; }; auth_host = { host = "auth.${domain}"; port = 38080; accessType = "proxy"; }; }; }; security.acme = { acceptTerms = true; defaults.email = root_email; certs."${domain}" = { webroot = "/var/lib/acme/acme-challenge/"; extraDomainNames = lib.mapAttrsToList (n: v: v.host) config.serverConfig.vhosts; }; }; services.nginx = { # package = pkgs.nginxStable.override { openssl = pkgs.libressl; }; enable = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; }; users.users.nginx.extraGroups = [ "acme" ]; }; }