Merge branch 'main' into feat/headscale
This commit is contained in:
commit
9803eebb1d
2 changed files with 65 additions and 2 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# Nginx Reverse Proxy Module
|
||||
# Provides: Nginx with automatic Let's Encrypt certificates and security headers
|
||||
# Provides: Nginx with automatic Let's Encrypt certificates, security headers, and rate limiting
|
||||
#
|
||||
# Usage:
|
||||
# myModules.nginx = {
|
||||
|
|
@ -32,6 +32,28 @@ in
|
|||
description = "Email address for Let's Encrypt registration";
|
||||
};
|
||||
|
||||
rateLimit = {
|
||||
enable = lib.mkEnableOption "Nginx rate limiting";
|
||||
|
||||
zone = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "10m";
|
||||
description = "Size of the shared memory zone for rate limiting";
|
||||
};
|
||||
|
||||
requests = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 10;
|
||||
description = "Number of requests allowed per second (burst applies on top)";
|
||||
};
|
||||
|
||||
burst = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 20;
|
||||
description = "Maximum burst of requests allowed beyond the rate";
|
||||
};
|
||||
};
|
||||
|
||||
domains = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule {
|
||||
options = {
|
||||
|
|
@ -52,6 +74,26 @@ in
|
|||
description = "Content-Security-Policy header value. Set to null to omit.";
|
||||
};
|
||||
|
||||
rateLimit = {
|
||||
enable = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.bool;
|
||||
default = null;
|
||||
description = "Enable rate limiting for this vhost. Defaults to global rateLimit.enable.";
|
||||
};
|
||||
|
||||
requests = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
default = null;
|
||||
description = "Requests per second for this vhost. Defaults to global rateLimit.requests.";
|
||||
};
|
||||
|
||||
burst = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.int;
|
||||
default = null;
|
||||
description = "Burst size for this vhost. Defaults to global rateLimit.burst.";
|
||||
};
|
||||
};
|
||||
|
||||
extraLocations = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule {
|
||||
options = {
|
||||
|
|
@ -98,6 +140,14 @@ in
|
|||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
|
||||
# Rate limiting zones (one per domain for per-domain limits)
|
||||
commonHttpConfig = lib.optionalString cfg.rateLimit.enable ''
|
||||
# Global rate limiting zone
|
||||
limit_req_zone $binary_remote_addr zone=global:10m rate=${toString cfg.rateLimit.requests}r/s;
|
||||
# Limit connection flooding
|
||||
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
|
||||
'';
|
||||
|
||||
virtualHosts = lib.mapAttrs' (domain: opts: {
|
||||
name = domain;
|
||||
value = {
|
||||
|
|
@ -127,7 +177,12 @@ in
|
|||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString opts.port}";
|
||||
extraConfig = opts.extraConfig;
|
||||
extraConfig = opts.extraConfig + lib.optionalString (if opts.rateLimit.enable != null then opts.rateLimit.enable else cfg.rateLimit.enable) ''
|
||||
# Rate limiting
|
||||
limit_req zone=global burst=${toString (if opts.rateLimit.burst != null then opts.rateLimit.burst else cfg.rateLimit.burst)} nodelay;
|
||||
limit_conn connlimit 30;
|
||||
limit_req_status 429;
|
||||
'';
|
||||
};
|
||||
} // lib.mapAttrs' (locPath: locOpts: {
|
||||
name = locPath;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue