Files
nixos/modules/services/webserver.nix

157 lines
4.0 KiB
Nix

{ lib, config, ... }:
let
cfg = config.services.webserver;
types = {
location = lib.types.submodule {
options = {
proxyPort = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
};
root = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
};
basicAuthFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
};
extraConfig = lib.mkOption {
type = lib.types.str;
default = "";
};
};
};
vhost = lib.types.submodule {
options = {
proxyBuffering = lib.mkOption {
type = lib.types.bool;
default = true;
};
locations = lib.mkOption {
type = lib.types.attrsOf types.location;
};
tailscaleAuth = lib.mkOption {
type = lib.types.bool;
default = false;
};
extraConfig = lib.mkOption {
type = lib.types.lines;
default = "";
};
};
};
};
tailscaleAuthVhosts = lib.attrNames (
lib.filterAttrs (name: { tailscaleAuth, ... }: tailscaleAuth) cfg.vHosts
);
in
{
options.services.webserver = {
enable = lib.mkEnableOption "Enable nginx";
acme = {
dnsChallenge = lib.mkEnableOption "Enable DNS challenge";
dnsProvider = lib.mkOption {
type = lib.types.str;
default = "hetzner";
};
};
vHosts = lib.mkOption {
type = lib.types.attrsOf types.vhost;
default = { };
};
tailscaleAuth.expectedTailnet = lib.mkOption {
type = lib.types.str;
default = "";
};
};
config = lib.mkIf cfg.enable {
services = {
nginx = {
enable = lib.mkDefault true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedBrotliSettings = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
tailscaleAuth = {
enable = (lib.length tailscaleAuthVhosts) > 0;
virtualHosts = tailscaleAuthVhosts;
expectedTailnet = cfg.tailscaleAuth.expectedTailnet;
};
virtualHosts = lib.mapAttrs (
_:
{
proxyBuffering,
locations,
extraConfig,
...
}:
{
forceSSL = true;
enableACME = true;
http2 = true;
acmeRoot = lib.mkIf cfg.acme.dnsChallenge null;
extraConfig = lib.concatLines [
(lib.optionalString (!proxyBuffering) "proxy_buffering off;")
"charset utf-8;"
extraConfig
];
locations = lib.mapAttrs (
_:
{
proxyPort,
extraConfig,
root,
basicAuthFile,
}:
lib.mergeAttrsList [
{ inherit extraConfig root basicAuthFile; }
(
if (lib.isInt proxyPort) then
{
proxyWebsockets = true;
proxyPass = "http://localhost:${toString proxyPort}";
}
else
{ }
)
]
) locations;
}
) cfg.vHosts;
};
octodns.records = lib.filterAttrs (name: _: name != config.networking.domain) (
lib.mapAttrs' (
fqdn:
{ tailscaleAuth, ... }:
{
name = lib.removeSuffix ".${config.networking.domain}" fqdn;
value = {
CNAME =
if tailscaleAuth then { target = "ts.${config.networking.domain}."; } else { toRoot = true; };
};
}
) cfg.vHosts
);
};
security.acme = {
acceptTerms = true;
defaults = {
email = "admin@j.repomaa.com";
dnsProvider = lib.mkIf cfg.acme.dnsChallenge cfg.acme.dnsProvider;
};
};
modules.firewall.allInterfaces = [ "web" ];
};
}