2023-08-25 20:53:31 +08:00
|
|
|
inputs:
|
|
|
|
{
|
2024-03-25 11:30:50 +08:00
|
|
|
imports = inputs.localLib.findModules ./.;
|
2023-09-01 21:05:26 +08:00
|
|
|
options.nixos.services.nginx = let inherit (inputs.lib) mkOption types; in
|
|
|
|
{
|
|
|
|
enable = mkOption { type = types.bool; default = false; };
|
2023-11-09 00:51:45 +08:00
|
|
|
# transparentProxy -> https(with proxyProtocol) or transparentProxy -> streamProxy -> https(with proxyProtocol)
|
|
|
|
# https without proxyProtocol listen on private ip, with proxyProtocol listen on all ip
|
2023-11-08 23:44:19 +08:00
|
|
|
# streamProxy listen on private ip
|
|
|
|
# transparentProxy listen on public ip
|
2023-11-11 01:27:01 +08:00
|
|
|
global = mkOption
|
|
|
|
{
|
|
|
|
type = types.anything;
|
|
|
|
readOnly = true;
|
|
|
|
default =
|
|
|
|
{
|
|
|
|
httpsPort = 3065;
|
|
|
|
httpsPortShift = { http2 = 1; proxyProtocol = 2; };
|
2023-11-19 20:47:52 +08:00
|
|
|
httpsLocationTypes = [ "proxy" "static" "php" "return" "cgi" "alias" ];
|
2023-11-11 01:27:01 +08:00
|
|
|
httpTypes = [ "rewriteHttps" "php" ];
|
|
|
|
streamPort = 5575;
|
|
|
|
streamPortShift = { proxyProtocol = 1; };
|
|
|
|
};
|
|
|
|
};
|
2023-09-01 21:05:26 +08:00
|
|
|
transparentProxy =
|
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
# only disable in some rare cases
|
2023-09-01 21:05:26 +08:00
|
|
|
enable = mkOption { type = types.bool; default = true; };
|
2023-12-07 20:00:22 +08:00
|
|
|
externalIp = mkOption { type = types.listOf types.nonEmptyStr; default = [ "0.0.0.0" ]; };
|
2023-11-08 23:44:19 +08:00
|
|
|
# proxy to 127.0.0.1:${specified port}
|
|
|
|
map = mkOption { type = types.attrsOf types.ints.unsigned; default = {}; };
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
streamProxy =
|
|
|
|
{
|
|
|
|
map = mkOption
|
|
|
|
{
|
|
|
|
type = types.attrsOf (types.oneOf
|
|
|
|
[
|
|
|
|
# proxy to specified ip:port without proxyProtocol
|
|
|
|
types.nonEmptyStr
|
|
|
|
(types.submodule { options =
|
|
|
|
{
|
|
|
|
upstream = mkOption
|
|
|
|
{
|
|
|
|
type = types.oneOf
|
|
|
|
[
|
|
|
|
# proxy to specified ip:port with or without proxyProtocol
|
|
|
|
types.nonEmptyStr
|
|
|
|
(types.submodule { options =
|
|
|
|
{
|
|
|
|
address = mkOption { type = types.nonEmptyStr; default = "127.0.0.1"; };
|
2023-11-09 00:51:45 +08:00
|
|
|
# if port not specified, guess from proxyProtocol enabled or not, assume http2 enabled
|
2023-11-08 23:44:19 +08:00
|
|
|
port = mkOption { type = types.nullOr types.ints.unsigned; default = null; };
|
|
|
|
};})
|
|
|
|
];
|
|
|
|
default = {};
|
|
|
|
};
|
2023-11-09 22:19:37 +08:00
|
|
|
proxyProtocol = mkOption { type = types.bool; default = true; };
|
2023-11-08 23:44:19 +08:00
|
|
|
addToTransparentProxy = mkOption { type = types.bool; default = true; };
|
2023-11-09 22:19:37 +08:00
|
|
|
rewriteHttps = mkOption { type = types.bool; default = true; };
|
2023-11-08 23:44:19 +08:00
|
|
|
};})
|
|
|
|
]);
|
|
|
|
default = {};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
https = mkOption
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2023-11-09 22:19:37 +08:00
|
|
|
type = types.attrsOf (types.submodule (siteSubmoduleInputs: { options =
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
2023-11-09 00:51:45 +08:00
|
|
|
global =
|
|
|
|
{
|
2023-11-10 19:24:57 +08:00
|
|
|
configName = mkOption
|
|
|
|
{
|
|
|
|
type = types.nonEmptyStr;
|
|
|
|
default = "https:${siteSubmoduleInputs.config._module.args.name}";
|
|
|
|
};
|
2023-11-09 00:51:45 +08:00
|
|
|
root = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
2023-11-15 20:42:42 +08:00
|
|
|
index = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr (types.oneOf [ (types.enum [ "auto" ]) (types.nonEmptyListOf types.nonEmptyStr) ]);
|
|
|
|
default = null;
|
|
|
|
};
|
2023-11-15 20:59:27 +08:00
|
|
|
charset = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
2023-11-15 11:29:17 +08:00
|
|
|
detectAuth = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr (types.submodule { options =
|
|
|
|
{
|
|
|
|
text = mkOption { type = types.nonEmptyStr; default = "Restricted Content"; };
|
2023-11-15 21:37:20 +08:00
|
|
|
users = mkOption { type = types.nonEmptyListOf types.nonEmptyStr; };
|
2023-11-15 11:29:17 +08:00
|
|
|
};});
|
|
|
|
default = null;
|
|
|
|
};
|
2023-11-09 22:19:37 +08:00
|
|
|
rewriteHttps = mkOption { type = types.bool; default = true; };
|
2023-12-17 21:42:57 +08:00
|
|
|
tlsCert = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
2023-11-09 00:51:45 +08:00
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
listen = mkOption
|
2023-09-16 15:34:27 +08:00
|
|
|
{
|
2023-11-07 16:16:04 +08:00
|
|
|
type = types.attrsOf (types.submodule { options =
|
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
http2 = mkOption { type = types.bool; default = true; };
|
2023-11-11 00:57:49 +08:00
|
|
|
proxyProtocol = mkOption { type = types.bool; default = true; };
|
2023-11-08 23:44:19 +08:00
|
|
|
# if proxyProtocol not enabled, add to transparentProxy only
|
|
|
|
# if proxyProtocol enabled, add to transparentProxy and streamProxy
|
|
|
|
addToTransparentProxy = mkOption { type = types.bool; default = true; };
|
|
|
|
};});
|
|
|
|
default.main = {};
|
|
|
|
};
|
2023-11-09 22:19:37 +08:00
|
|
|
location = mkOption
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
|
|
|
type = types.attrsOf (types.submodule { options =
|
|
|
|
let
|
|
|
|
genericOptions =
|
2023-10-03 21:47:46 +08:00
|
|
|
{
|
2023-11-12 23:35:08 +08:00
|
|
|
# should be set to non null value if global root is null
|
|
|
|
root = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
2023-11-15 11:29:17 +08:00
|
|
|
detectAuth = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr (types.submodule { options =
|
|
|
|
{
|
|
|
|
text = mkOption { type = types.nonEmptyStr; default = "Restricted Content"; };
|
2023-11-15 21:37:20 +08:00
|
|
|
users = mkOption { type = types.nonEmptyListOf types.nonEmptyStr; };
|
2023-11-15 11:29:17 +08:00
|
|
|
};});
|
|
|
|
default = null;
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
};
|
|
|
|
in
|
2023-11-07 16:16:04 +08:00
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
# only one should be specified
|
|
|
|
proxy = mkOption
|
2023-10-03 21:47:46 +08:00
|
|
|
{
|
2023-11-12 23:35:08 +08:00
|
|
|
type = types.nullOr (types.submodule { options =
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-12 23:35:08 +08:00
|
|
|
inherit (genericOptions) detectAuth;
|
2023-11-08 23:44:19 +08:00
|
|
|
upstream = mkOption { type = types.nonEmptyStr; };
|
|
|
|
websocket = mkOption { type = types.bool; default = false; };
|
2023-11-09 22:19:37 +08:00
|
|
|
setHeaders = mkOption
|
|
|
|
{
|
|
|
|
type = types.attrsOf types.str;
|
|
|
|
default.Host = siteSubmoduleInputs.config._module.args.name;
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
# echo -n "username:password" | base64
|
|
|
|
addAuth = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
|
|
|
};});
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
static = mkOption
|
2023-11-07 15:06:51 +08:00
|
|
|
{
|
2023-11-12 23:35:08 +08:00
|
|
|
type = types.nullOr (types.submodule { options =
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-12 23:35:08 +08:00
|
|
|
inherit (genericOptions) detectAuth root;
|
2023-11-15 20:42:42 +08:00
|
|
|
index = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr
|
|
|
|
(types.oneOf [ (types.enum [ "auto" ]) (types.nonEmptyListOf types.nonEmptyStr) ]);
|
|
|
|
default = null;
|
|
|
|
};
|
2023-11-15 20:59:27 +08:00
|
|
|
charset = mkOption { type = types.nullOr types.nonEmptyStr; default = null; };
|
2023-11-16 15:51:47 +08:00
|
|
|
tryFiles = mkOption { type = types.nullOr (types.nonEmptyListOf types.nonEmptyStr); default = null; };
|
2023-11-15 21:37:20 +08:00
|
|
|
webdav = mkOption { type = types.bool; default = false; };
|
2023-11-08 23:44:19 +08:00
|
|
|
};});
|
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
php = mkOption
|
|
|
|
{
|
2023-11-12 23:35:08 +08:00
|
|
|
type = types.nullOr (types.submodule { options =
|
2023-11-16 15:51:47 +08:00
|
|
|
{ inherit (genericOptions) detectAuth root; fastcgiPass = mkOption { type = types.nonEmptyStr; };};});
|
2023-11-08 23:44:19 +08:00
|
|
|
default = null;
|
|
|
|
};
|
2023-11-15 19:30:07 +08:00
|
|
|
return = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr (types.submodule { options =
|
2023-11-16 15:51:47 +08:00
|
|
|
{ return = mkOption { type = types.nonEmptyStr; }; };});
|
2023-11-15 19:30:07 +08:00
|
|
|
default = null;
|
|
|
|
};
|
2023-11-12 23:35:08 +08:00
|
|
|
cgi = mkOption
|
|
|
|
{
|
2023-11-16 15:51:47 +08:00
|
|
|
type = types.nullOr (types.submodule { options = { inherit (genericOptions) detectAuth root; };});
|
2023-11-12 23:35:08 +08:00
|
|
|
default = null;
|
|
|
|
};
|
2023-11-19 20:47:52 +08:00
|
|
|
alias = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr (types.submodule { options =
|
|
|
|
{
|
|
|
|
path = mkOption { type = types.nonEmptyStr; };
|
|
|
|
};});
|
|
|
|
default = null;
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
};});
|
2023-10-04 15:49:23 +08:00
|
|
|
default = {};
|
2023-09-16 15:34:27 +08:00
|
|
|
};
|
2023-11-09 22:19:37 +08:00
|
|
|
};}));
|
2023-09-01 21:05:26 +08:00
|
|
|
default = {};
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
http = mkOption
|
2023-09-15 20:59:18 +08:00
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
type = types.attrsOf (types.submodule (submoduleInputs: { options =
|
2023-09-15 20:59:18 +08:00
|
|
|
{
|
2023-11-09 23:04:28 +08:00
|
|
|
rewriteHttps = mkOption
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
|
|
|
type = types.nullOr (types.submodule { options =
|
2023-09-15 20:59:18 +08:00
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
hostname = mkOption { type = types.nonEmptyStr; default = submoduleInputs.config._module.args.name; };
|
|
|
|
};});
|
|
|
|
default = null;
|
|
|
|
};
|
2023-11-09 00:51:45 +08:00
|
|
|
php = mkOption
|
|
|
|
{
|
|
|
|
type = types.nullOr (types.submodule { options =
|
2023-11-16 15:51:47 +08:00
|
|
|
{ root = mkOption { type = types.nonEmptyStr; }; fastcgiPass = mkOption { type = types.nonEmptyStr; };};});
|
2023-11-09 00:51:45 +08:00
|
|
|
default = null;
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
};}));
|
|
|
|
default = {};
|
2023-09-15 20:59:18 +08:00
|
|
|
};
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
|
|
|
config =
|
|
|
|
let
|
2023-11-09 22:19:37 +08:00
|
|
|
inherit (inputs.lib) mkMerge mkIf mkDefault;
|
2023-11-09 23:04:28 +08:00
|
|
|
inherit (inputs.lib.strings) escapeURL;
|
2023-11-08 23:44:19 +08:00
|
|
|
inherit (inputs.localLib) attrsToList;
|
2023-09-01 21:05:26 +08:00
|
|
|
inherit (inputs.config.nixos.services) nginx;
|
2023-11-07 16:16:04 +08:00
|
|
|
inherit (builtins) map listToAttrs concatStringsSep toString filter attrValues concatLists;
|
2023-11-08 23:44:19 +08:00
|
|
|
concatAttrs = list: listToAttrs (concatLists (map (attrs: attrsToList attrs) list));
|
|
|
|
in mkIf nginx.enable (mkMerge
|
2023-09-01 21:05:26 +08:00
|
|
|
[
|
2023-11-08 23:44:19 +08:00
|
|
|
# generic config
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
|
|
|
services =
|
|
|
|
{
|
|
|
|
nginx =
|
|
|
|
{
|
|
|
|
enable = true;
|
|
|
|
enableReload = true;
|
|
|
|
eventsConfig =
|
|
|
|
''
|
|
|
|
worker_connections 524288;
|
|
|
|
use epoll;
|
|
|
|
'';
|
|
|
|
commonHttpConfig =
|
|
|
|
''
|
|
|
|
geoip2 ${inputs.config.services.geoipupdate.settings.DatabaseDirectory}/GeoLite2-Country.mmdb {
|
|
|
|
$geoip2_data_country_code country iso_code;
|
|
|
|
}
|
|
|
|
log_format http '[$time_local] $remote_addr-$geoip2_data_country_code "$host"'
|
|
|
|
' $request_length $bytes_sent $status "$request" referer: "$http_referer" ua: "$http_user_agent"';
|
|
|
|
access_log syslog:server=unix:/dev/log http;
|
|
|
|
proxy_ssl_server_name on;
|
|
|
|
proxy_ssl_session_reuse off;
|
2024-05-22 13:00:07 +08:00
|
|
|
send_timeout 1d;
|
2023-09-01 21:05:26 +08:00
|
|
|
'';
|
2024-05-22 13:00:07 +08:00
|
|
|
proxyTimeout = "1d";
|
2023-09-01 21:05:26 +08:00
|
|
|
recommendedZstdSettings = true;
|
|
|
|
recommendedTlsSettings = true;
|
|
|
|
recommendedProxySettings = true;
|
|
|
|
recommendedOptimisation = true;
|
|
|
|
recommendedGzipSettings = true;
|
|
|
|
recommendedBrotliSettings = true;
|
|
|
|
clientMaxBodySize = "0";
|
|
|
|
package =
|
|
|
|
let
|
|
|
|
nginx-geoip2 =
|
|
|
|
{
|
|
|
|
name = "ngx_http_geoip2_module";
|
|
|
|
src = inputs.pkgs.fetchFromGitHub
|
|
|
|
{
|
|
|
|
owner = "leev";
|
|
|
|
repo = "ngx_http_geoip2_module";
|
|
|
|
rev = "a607a41a8115fecfc05b5c283c81532a3d605425";
|
|
|
|
hash = "sha256-CkmaeEa1iEAabJEDu3FhBUR7QF38koGYlyx+pyKZV9Y=";
|
|
|
|
};
|
|
|
|
meta.license = [];
|
|
|
|
};
|
|
|
|
in
|
|
|
|
(inputs.pkgs.nginxMainline.override (prev: { modules = prev.modules ++ [ nginx-geoip2 ]; }))
|
|
|
|
.overrideAttrs (prev: { buildInputs = prev.buildInputs ++ [ inputs.pkgs.libmaxminddb ]; });
|
2023-09-15 20:59:18 +08:00
|
|
|
streamConfig =
|
|
|
|
''
|
2023-11-08 23:44:19 +08:00
|
|
|
geoip2 ${inputs.config.services.geoipupdate.settings.DatabaseDirectory}/GeoLite2-Country.mmdb {
|
2023-09-15 20:59:18 +08:00
|
|
|
$geoip2_data_country_code country iso_code;
|
|
|
|
}
|
2023-09-15 21:12:33 +08:00
|
|
|
resolver 8.8.8.8;
|
2023-09-15 20:59:18 +08:00
|
|
|
'';
|
2023-09-15 21:12:33 +08:00
|
|
|
# todo: use host dns
|
|
|
|
resolver.addresses = [ "8.8.8.8" ];
|
2023-09-01 21:05:26 +08:00
|
|
|
};
|
|
|
|
geoipupdate =
|
|
|
|
{
|
|
|
|
enable = true;
|
|
|
|
settings =
|
|
|
|
{
|
|
|
|
AccountID = 901296;
|
|
|
|
LicenseKey = inputs.config.sops.secrets."nginx/maxmind-license".path;
|
|
|
|
EditionIDs = [ "GeoLite2-ASN" "GeoLite2-City" "GeoLite2-Country" ];
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
2024-06-01 00:41:42 +08:00
|
|
|
nixos.services.xray.client.v2ray-forwarder.noproxyTcpPorts = [ 80 443 ];
|
2023-11-08 23:44:19 +08:00
|
|
|
sops.secrets = { "nginx/maxmind-license".owner = inputs.config.users.users.nginx.name; };
|
2023-09-01 21:05:26 +08:00
|
|
|
systemd.services.nginx.serviceConfig =
|
|
|
|
{
|
|
|
|
CapabilityBoundingSet = [ "CAP_NET_ADMIN" ];
|
|
|
|
AmbientCapabilities = [ "CAP_NET_ADMIN" ];
|
|
|
|
LimitNPROC = 65536;
|
|
|
|
LimitNOFILE = 524288;
|
|
|
|
};
|
2023-11-08 23:44:19 +08:00
|
|
|
}
|
|
|
|
# transparentProxy
|
|
|
|
(mkIf nginx.transparentProxy.enable
|
2023-09-01 21:05:26 +08:00
|
|
|
{
|
|
|
|
services.nginx.streamConfig =
|
|
|
|
''
|
2023-09-15 20:59:18 +08:00
|
|
|
log_format transparent_proxy '[$time_local] $remote_addr-$geoip2_data_country_code '
|
|
|
|
'"$ssl_preread_server_name"->$transparent_proxy_backend $bytes_sent $bytes_received';
|
2023-11-09 00:51:45 +08:00
|
|
|
map $ssl_preread_server_name $transparent_proxy_backend {
|
2023-11-08 23:44:19 +08:00
|
|
|
${concatStringsSep "\n " (map
|
|
|
|
(x: ''"${x.name}" 127.0.0.1:${toString x.value};'')
|
|
|
|
(attrsToList nginx.transparentProxy.map))}
|
2023-11-11 01:27:01 +08:00
|
|
|
default 127.0.0.1:${toString (with nginx.global; (httpsPort + httpsPortShift.http2))};
|
2023-09-01 21:05:26 +08:00
|
|
|
}
|
2023-11-09 00:51:45 +08:00
|
|
|
server {
|
2023-11-08 23:44:19 +08:00
|
|
|
${concatStringsSep "\n " (map (ip: "listen ${ip}:443;") nginx.transparentProxy.externalIp)}
|
2023-09-01 21:05:26 +08:00
|
|
|
ssl_preread on;
|
|
|
|
proxy_bind $remote_addr transparent;
|
2023-09-15 20:59:18 +08:00
|
|
|
proxy_pass $transparent_proxy_backend;
|
2023-09-01 21:05:26 +08:00
|
|
|
proxy_connect_timeout 1s;
|
|
|
|
proxy_socket_keepalive on;
|
|
|
|
proxy_buffer_size 128k;
|
2023-09-15 20:59:18 +08:00
|
|
|
access_log syslog:server=unix:/dev/log transparent_proxy;
|
2023-09-01 21:05:26 +08:00
|
|
|
}
|
|
|
|
'';
|
|
|
|
systemd.services.nginx-proxy =
|
|
|
|
let
|
|
|
|
ipset = "${inputs.pkgs.ipset}/bin/ipset";
|
|
|
|
iptables = "${inputs.pkgs.iptables}/bin/iptables";
|
|
|
|
ip = "${inputs.pkgs.iproute}/bin/ip";
|
|
|
|
start = inputs.pkgs.writeShellScript "nginx-proxy.start"
|
|
|
|
(
|
|
|
|
''
|
|
|
|
${ipset} create nginx_proxy_port bitmap:port range 0-65535
|
|
|
|
${iptables} -t mangle -N nginx_proxy_mark
|
|
|
|
${iptables} -t mangle -A OUTPUT -j nginx_proxy_mark
|
|
|
|
${iptables} -t mangle -A nginx_proxy_mark -s 127.0.0.1 -p tcp \
|
|
|
|
-m set --match-set nginx_proxy_port src -j MARK --set-mark 2/2
|
|
|
|
${iptables} -t mangle -N nginx_proxy
|
|
|
|
${iptables} -t mangle -A PREROUTING -j nginx_proxy
|
|
|
|
${iptables} -t mangle -A nginx_proxy -s 127.0.0.1 -p tcp \
|
|
|
|
-m set --match-set nginx_proxy_port src -j MARK --set-mark 2/2
|
|
|
|
${ip} rule add fwmark 2/2 table 200
|
|
|
|
${ip} route add local 0.0.0.0/0 dev lo table 200
|
|
|
|
''
|
2023-11-08 23:44:19 +08:00
|
|
|
+ concatStringsSep "\n " (map
|
2023-09-01 21:05:26 +08:00
|
|
|
(port: ''${ipset} add nginx_proxy_port ${toString port}'')
|
2023-11-08 23:44:19 +08:00
|
|
|
(inputs.lib.unique (attrValues nginx.transparentProxy.map)))
|
2023-09-01 21:05:26 +08:00
|
|
|
);
|
|
|
|
stop = inputs.pkgs.writeShellScript "nginx-proxy.stop"
|
|
|
|
''
|
|
|
|
${iptables} -t mangle -F nginx_proxy_mark
|
|
|
|
${iptables} -t mangle -D OUTPUT -j nginx_proxy_mark
|
|
|
|
${iptables} -t mangle -X nginx_proxy_mark
|
|
|
|
${iptables} -t mangle -F nginx_proxy
|
|
|
|
${iptables} -t mangle -D PREROUTING -j nginx_proxy
|
|
|
|
${iptables} -t mangle -X nginx_proxy
|
|
|
|
${ip} rule del fwmark 2/2 table 200
|
|
|
|
${ip} route del local 0.0.0.0/0 dev lo table 200
|
|
|
|
${ipset} destroy nginx_proxy_port
|
|
|
|
'';
|
|
|
|
in
|
|
|
|
{
|
|
|
|
description = "nginx transparent proxy";
|
|
|
|
after = [ "network.target" ];
|
|
|
|
serviceConfig =
|
|
|
|
{
|
|
|
|
Type = "simple";
|
|
|
|
RemainAfterExit = true;
|
|
|
|
ExecStart = start;
|
|
|
|
ExecStop = stop;
|
|
|
|
};
|
|
|
|
wants = [ "network.target" ];
|
|
|
|
wantedBy= [ "multi-user.target" ];
|
|
|
|
};
|
|
|
|
})
|
2023-11-08 23:44:19 +08:00
|
|
|
# streamProxy
|
2023-09-15 20:59:18 +08:00
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
services.nginx.streamConfig =
|
|
|
|
''
|
|
|
|
log_format stream_proxy '[$time_local] $remote_addr-$geoip2_data_country_code '
|
|
|
|
'"$ssl_preread_server_name"->$stream_proxy_backend $bytes_sent $bytes_received';
|
|
|
|
map $ssl_preread_server_name $stream_proxy_backend {
|
|
|
|
${concatStringsSep "\n " (map
|
|
|
|
(x:
|
|
|
|
let
|
|
|
|
upstream =
|
|
|
|
if (builtins.typeOf x.value.upstream == "string") then
|
|
|
|
x.value.upstream
|
|
|
|
else
|
|
|
|
let
|
2023-11-11 01:27:01 +08:00
|
|
|
port = with nginx.global;
|
2023-11-08 23:44:19 +08:00
|
|
|
if x.value.upstream.port == null then
|
|
|
|
httpsPort + httpsPortShift.http2
|
|
|
|
+ (if x.value.proxyProtocol then httpsPortShift.proxyProtocol else 0)
|
2023-11-10 18:35:22 +08:00
|
|
|
else x.value.upstream.port;
|
2023-11-08 23:44:19 +08:00
|
|
|
in "${x.value.upstream.address}:${toString port}";
|
|
|
|
in ''"${x.name}" "${upstream}";'')
|
|
|
|
(attrsToList nginx.streamProxy.map))}
|
|
|
|
}
|
2023-11-09 00:51:45 +08:00
|
|
|
server {
|
2023-11-11 01:27:01 +08:00
|
|
|
listen 127.0.0.1:${toString nginx.global.streamPort};
|
2023-11-08 23:44:19 +08:00
|
|
|
ssl_preread on;
|
|
|
|
proxy_pass $stream_proxy_backend;
|
|
|
|
proxy_connect_timeout 10s;
|
|
|
|
proxy_socket_keepalive on;
|
|
|
|
proxy_buffer_size 128k;
|
|
|
|
access_log syslog:server=unix:/dev/log stream_proxy;
|
|
|
|
}
|
2023-11-09 00:51:45 +08:00
|
|
|
server {
|
2023-11-11 01:27:01 +08:00
|
|
|
listen 127.0.0.1:${toString (with nginx.global; (streamPort + streamPortShift.proxyProtocol))};
|
2023-11-08 23:44:19 +08:00
|
|
|
proxy_protocol on;
|
|
|
|
ssl_preread on;
|
|
|
|
proxy_pass $stream_proxy_backend;
|
|
|
|
proxy_connect_timeout 10s;
|
|
|
|
proxy_socket_keepalive on;
|
|
|
|
proxy_buffer_size 128k;
|
|
|
|
access_log syslog:server=unix:/dev/log stream_proxy;
|
|
|
|
}
|
|
|
|
'';
|
|
|
|
nixos.services.nginx =
|
2023-09-15 20:59:18 +08:00
|
|
|
{
|
2023-11-08 23:44:19 +08:00
|
|
|
transparentProxy.map = listToAttrs
|
|
|
|
(
|
|
|
|
(map
|
2023-11-11 01:27:01 +08:00
|
|
|
(site: { inherit (site) name; value = nginx.global.streamPort; })
|
2023-11-08 23:44:19 +08:00
|
|
|
(filter
|
|
|
|
(site: (!(site.value.proxyProtocol or false) && (site.value.addToTransparentProxy or true)))
|
|
|
|
(attrsToList nginx.streamProxy.map)))
|
|
|
|
++ (map
|
2023-11-11 01:27:01 +08:00
|
|
|
(site: { inherit (site) name; value = with nginx.global; streamPort + streamPortShift.proxyProtocol; })
|
2023-11-08 23:44:19 +08:00
|
|
|
(filter
|
|
|
|
(site: ((site.value.proxyProtocol or false) && (site.value.addToTransparentProxy or true)))
|
|
|
|
(attrsToList nginx.streamProxy.map)))
|
|
|
|
);
|
|
|
|
http = listToAttrs (map
|
2023-11-09 23:04:28 +08:00
|
|
|
(site: { inherit (site) name; value.rewriteHttps = {}; })
|
2023-11-08 23:44:19 +08:00
|
|
|
(filter (site: site.value.rewriteHttps or false) (attrsToList nginx.streamProxy.map)));
|
|
|
|
};
|
|
|
|
}
|
2023-11-15 11:29:17 +08:00
|
|
|
# https assertions
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
|
|
|
# only one type should be specified in each location
|
2023-11-09 00:51:45 +08:00
|
|
|
assertions =
|
|
|
|
(
|
|
|
|
(map
|
|
|
|
(location:
|
|
|
|
{
|
2023-11-11 01:27:01 +08:00
|
|
|
assertion = (inputs.lib.count
|
|
|
|
(x: x != null)
|
|
|
|
(map (type: location.value.${type}) nginx.global.httpsLocationTypes)) <= 1;
|
2023-11-09 00:51:45 +08:00
|
|
|
message = "Only one type shuold be specified in ${location.name}";
|
|
|
|
})
|
|
|
|
(concatLists (map
|
|
|
|
(site: (map
|
|
|
|
(location: { inherit (location) value; name = "${site.name} ${location.name}"; })
|
2023-11-09 22:19:37 +08:00
|
|
|
(attrsToList site.value.location)))
|
2023-11-09 00:51:45 +08:00
|
|
|
(attrsToList nginx.https))))
|
|
|
|
# root should be specified either in global or in each location
|
|
|
|
++ (map
|
|
|
|
(location:
|
|
|
|
{
|
|
|
|
assertion = (location.value.root or "") != null;
|
|
|
|
message = "Root should be specified in ${location.name}";
|
|
|
|
})
|
|
|
|
(concatLists (map
|
|
|
|
(site: (map
|
|
|
|
(location: { inherit (location) value; name = "${site.name} ${location.name}"; })
|
2023-11-09 22:19:37 +08:00
|
|
|
(attrsToList site.value.location)))
|
2023-11-09 00:51:45 +08:00
|
|
|
(filter (site: site.value.global.root == null) (attrsToList nginx.https)))))
|
|
|
|
);
|
2023-11-15 11:29:17 +08:00
|
|
|
}
|
|
|
|
# https
|
|
|
|
(
|
|
|
|
let
|
|
|
|
# merge different types of locations
|
|
|
|
sites = map
|
2023-11-15 13:01:37 +08:00
|
|
|
(site:
|
2023-10-04 16:20:32 +08:00
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
inherit (site) name;
|
2023-11-15 13:01:37 +08:00
|
|
|
value =
|
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
inherit (site.value) global;
|
|
|
|
listens = attrValues site.value.listen;
|
|
|
|
locations = map
|
|
|
|
(location:
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
inherit (location) name;
|
|
|
|
value =
|
|
|
|
let _ = builtins.head (filter (type: type.value != null) (attrsToList location.value));
|
|
|
|
in _.value // { type = _.name; };
|
2023-11-15 13:01:37 +08:00
|
|
|
})
|
2023-11-15 11:29:17 +08:00
|
|
|
(attrsToList site.value.location);
|
|
|
|
};
|
|
|
|
})
|
|
|
|
(attrsToList nginx.https);
|
|
|
|
in
|
|
|
|
{
|
2023-11-15 19:29:14 +08:00
|
|
|
services =
|
|
|
|
{
|
|
|
|
nginx.virtualHosts = listToAttrs (map
|
|
|
|
(site:
|
2023-11-15 11:29:17 +08:00
|
|
|
{
|
2023-11-15 19:29:14 +08:00
|
|
|
name = site.value.global.configName;
|
|
|
|
value =
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 19:29:14 +08:00
|
|
|
serverName = site.name;
|
|
|
|
root = mkIf (site.value.global.root != null) site.value.global.root;
|
|
|
|
basicAuthFile = mkIf (site.value.global.detectAuth != null)
|
|
|
|
inputs.config.sops.templates."nginx/templates/detectAuth/${escapeURL site.name}-global".path;
|
|
|
|
extraConfig = concatStringsSep "\n"
|
|
|
|
(
|
2023-11-15 19:30:07 +08:00
|
|
|
(
|
|
|
|
let inherit (site.value.global) index; in
|
2023-11-15 20:42:42 +08:00
|
|
|
if (builtins.typeOf index == "list") then [ "index ${concatStringsSep " " index};" ]
|
|
|
|
else if (index == "auto") then [ "autoindex on;" ]
|
|
|
|
else []
|
2023-11-15 19:30:07 +08:00
|
|
|
)
|
|
|
|
++ (
|
|
|
|
let inherit (site.value.global) detectAuth; in
|
|
|
|
if (detectAuth != null) then [ ''auth_basic "${detectAuth.text}"'' ] else []
|
|
|
|
)
|
2023-11-15 20:59:27 +08:00
|
|
|
++ (
|
|
|
|
let inherit (site.value.global) charset; in
|
|
|
|
if (charset != null) then [ "charset ${charset};" ] else []
|
|
|
|
)
|
2023-11-15 19:29:14 +08:00
|
|
|
);
|
|
|
|
listen = map
|
|
|
|
(listen:
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 19:29:14 +08:00
|
|
|
addr = if listen.proxyProtocol then "0.0.0.0" else "127.0.0.1";
|
|
|
|
port = with nginx.global; httpsPort
|
|
|
|
+ (if listen.http2 then httpsPortShift.http2 else 0)
|
|
|
|
+ (if listen.proxyProtocol then httpsPortShift.proxyProtocol else 0);
|
|
|
|
ssl = true;
|
2023-11-22 11:58:58 +08:00
|
|
|
proxyProtocol = listen.proxyProtocol;
|
|
|
|
extraParameters = mkIf listen.http2 [ "http2" ];
|
2023-11-15 19:29:14 +08:00
|
|
|
})
|
|
|
|
site.value.listens;
|
|
|
|
# do not automatically add http2 listen
|
|
|
|
http2 = false;
|
|
|
|
onlySSL = true;
|
2023-12-17 21:42:57 +08:00
|
|
|
useACMEHost = mkIf (site.value.global.tlsCert == null) site.name;
|
|
|
|
sslCertificate = mkIf (site.value.global.tlsCert != null)
|
|
|
|
"${site.value.global.tlsCert}/fullchain.pem";
|
|
|
|
sslCertificateKey = mkIf (site.value.global.tlsCert != null)
|
|
|
|
"${site.value.global.tlsCert}/privkey.pem";
|
2023-11-15 19:29:14 +08:00
|
|
|
locations = listToAttrs (map
|
2023-11-15 13:01:37 +08:00
|
|
|
(location:
|
|
|
|
{
|
|
|
|
inherit (location) name;
|
|
|
|
value =
|
2023-11-12 23:35:08 +08:00
|
|
|
{
|
2023-11-15 19:29:14 +08:00
|
|
|
basicAuthFile = mkIf (location.value.detectAuth or null != null)
|
|
|
|
inputs.config.sops.templates
|
|
|
|
."nginx/templates/detectAuth/${escapeURL site.name}/${escapeURL location.name}".path;
|
|
|
|
root = mkIf (location.value.root or null != null) location.value.root;
|
2023-11-12 23:35:08 +08:00
|
|
|
}
|
2023-11-15 19:29:14 +08:00
|
|
|
// {
|
|
|
|
proxy =
|
2023-11-15 13:01:37 +08:00
|
|
|
{
|
2023-11-15 19:29:14 +08:00
|
|
|
proxyPass = location.value.upstream;
|
|
|
|
proxyWebsockets = location.value.websocket;
|
2023-11-15 13:01:37 +08:00
|
|
|
recommendedProxySettings = false;
|
|
|
|
recommendedProxySettingsNoHost = true;
|
|
|
|
extraConfig = concatStringsSep "\n"
|
|
|
|
(
|
|
|
|
(map
|
|
|
|
(header: ''proxy_set_header ${header.name} "${header.value}";'')
|
2023-11-15 19:29:14 +08:00
|
|
|
(attrsToList location.value.setHeaders))
|
2023-11-15 13:01:37 +08:00
|
|
|
++ (
|
2023-11-15 19:29:14 +08:00
|
|
|
if location.value.detectAuth != null || site.value.global.detectAuth != null
|
2023-11-15 13:01:37 +08:00
|
|
|
then [ "proxy_hide_header Authorization;" ]
|
|
|
|
else []
|
|
|
|
)
|
|
|
|
++ (
|
2023-11-15 19:29:14 +08:00
|
|
|
if location.value.addAuth != null then
|
|
|
|
let authFile = "nginx/templates/addAuth/${location.value.addAuth}";
|
2023-11-15 13:01:37 +08:00
|
|
|
in [ "include ${inputs.config.sops.templates.${authFile}.path};" ]
|
|
|
|
else [])
|
|
|
|
);
|
2023-11-15 19:29:14 +08:00
|
|
|
};
|
|
|
|
static =
|
2023-11-15 13:01:37 +08:00
|
|
|
{
|
2023-11-15 20:42:42 +08:00
|
|
|
index = mkIf (builtins.typeOf location.value.index == "list")
|
|
|
|
(concatStringsSep " " location.value.index);
|
|
|
|
tryFiles = mkIf (location.value.tryFiles != null)
|
|
|
|
(concatStringsSep " " location.value.tryFiles);
|
2023-11-15 20:59:27 +08:00
|
|
|
extraConfig = mkMerge
|
|
|
|
[
|
|
|
|
(mkIf (location.value.index == "auto") "autoindex on;")
|
|
|
|
(mkIf (location.value.charset != null) "charset ${location.value.charset};")
|
2023-11-15 21:37:20 +08:00
|
|
|
(mkIf location.value.webdav
|
|
|
|
''
|
|
|
|
dav_access user:rw group:rw;
|
|
|
|
dav_methods PUT DELETE MKCOL COPY MOVE;
|
|
|
|
dav_ext_methods PROPFIND OPTIONS;
|
|
|
|
create_full_put_path on;
|
|
|
|
'')
|
2023-11-15 20:59:27 +08:00
|
|
|
];
|
2023-11-15 19:29:14 +08:00
|
|
|
};
|
|
|
|
php.extraConfig =
|
|
|
|
''
|
|
|
|
fastcgi_pass ${location.value.fastcgiPass};
|
|
|
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
|
|
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
|
|
include ${inputs.config.services.nginx.package}/conf/fastcgi.conf;
|
|
|
|
'';
|
|
|
|
return.return = location.value.return;
|
|
|
|
cgi.extraConfig =
|
|
|
|
''
|
|
|
|
include ${inputs.config.services.nginx.package}/conf/fastcgi.conf;
|
|
|
|
fastcgi_pass unix:${inputs.config.services.fcgiwrap.socketAddress};
|
|
|
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
|
|
'';
|
2023-11-19 20:47:52 +08:00
|
|
|
alias.alias = location.value.path;
|
2023-11-15 19:29:14 +08:00
|
|
|
}.${location.value.type};
|
2023-11-15 13:01:37 +08:00
|
|
|
})
|
2023-11-15 19:30:07 +08:00
|
|
|
site.value.locations);
|
2023-11-15 19:29:14 +08:00
|
|
|
};
|
|
|
|
})
|
|
|
|
sites);
|
|
|
|
fcgiwrap = mkIf
|
|
|
|
(
|
|
|
|
filter (site: site != []) (map
|
2023-11-15 19:30:07 +08:00
|
|
|
(site: filter (location: location.value.type == "cgi") site.value.locations)
|
2023-11-15 19:29:14 +08:00
|
|
|
sites)
|
|
|
|
!= []
|
|
|
|
)
|
2023-11-16 15:51:47 +08:00
|
|
|
(with inputs.config.users.users.nginx; { enable = true; user = name; inherit group; });
|
2023-11-15 19:29:14 +08:00
|
|
|
};
|
2023-11-15 11:29:17 +08:00
|
|
|
nixos.services =
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
nginx =
|
|
|
|
let
|
|
|
|
# { name = domain; value = listen = { http2 = xxx, proxyProtocol = xxx }; }
|
|
|
|
listens = filter
|
|
|
|
(listen: listen.value.addToTransparentProxy)
|
|
|
|
(concatLists (map
|
2023-11-16 15:51:47 +08:00
|
|
|
(site: map (listen: { inherit (site) name; value = listen; }) site.value.listens)
|
2023-11-15 11:29:17 +08:00
|
|
|
sites));
|
|
|
|
in
|
|
|
|
{
|
|
|
|
transparentProxy.map = listToAttrs (map
|
|
|
|
(site:
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
inherit (site) name;
|
|
|
|
value = with nginx.global; httpsPort + (if site.value.http2 then httpsPortShift.http2 else 0);
|
|
|
|
})
|
|
|
|
(filter (listen: !listen.value.proxyProtocol) listens));
|
|
|
|
streamProxy.map = listToAttrs (map
|
|
|
|
(site:
|
|
|
|
{
|
|
|
|
inherit (site) name;
|
|
|
|
value =
|
|
|
|
{
|
|
|
|
upstream.port = with nginx.global; httpsPort + httpsPortShift.proxyProtocol
|
|
|
|
+ (if site.value.http2 then httpsPortShift.http2 else 0);
|
|
|
|
proxyProtocol = true;
|
|
|
|
rewriteHttps = mkDefault false;
|
|
|
|
};
|
|
|
|
})
|
|
|
|
(filter (listen: listen.value.proxyProtocol) listens));
|
|
|
|
http = listToAttrs (map
|
|
|
|
(site: { inherit (site) name; value.rewriteHttps = {}; })
|
|
|
|
(filter (site: site.value.global.rewriteHttps) sites));
|
|
|
|
};
|
2024-03-23 00:43:44 +08:00
|
|
|
acme.cert = listToAttrs (map
|
|
|
|
(site: { inherit (site) name; value.group = inputs.config.services.nginx.group; })
|
|
|
|
sites);
|
2023-11-08 23:44:19 +08:00
|
|
|
};
|
2023-11-15 11:29:17 +08:00
|
|
|
sops =
|
|
|
|
let
|
|
|
|
detectAuthUsers = concatLists (map
|
|
|
|
(site:
|
|
|
|
(
|
|
|
|
(map
|
|
|
|
(location:
|
|
|
|
{
|
|
|
|
name = "${escapeURL site.name}/${escapeURL location.name}";
|
|
|
|
value = location.value.detectAuth.users;
|
|
|
|
})
|
|
|
|
(filter (location: location.value.detectAuth or null != null) site.value.locations))
|
|
|
|
++ (if site.value.global.detectAuth != null then
|
|
|
|
[ { name = "${escapeURL site.name}-global"; value = site.value.global.detectAuth.users; } ]
|
|
|
|
else [])
|
|
|
|
))
|
|
|
|
sites);
|
|
|
|
addAuth = concatLists (map
|
2023-11-08 23:44:19 +08:00
|
|
|
(site: map
|
|
|
|
(location:
|
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
name = "${escapeURL site.name}/${escapeURL location.name}";
|
|
|
|
value = location.value.addAuth;
|
2023-11-08 23:44:19 +08:00
|
|
|
})
|
2023-11-15 19:30:07 +08:00
|
|
|
(filter (location: location.value.addAuth or null != null) site.value.locations)
|
2023-11-15 11:29:17 +08:00
|
|
|
)
|
|
|
|
sites);
|
|
|
|
in
|
|
|
|
{
|
|
|
|
templates = listToAttrs
|
|
|
|
(
|
|
|
|
(map
|
|
|
|
(detectAuth:
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
name = "nginx/templates/detectAuth/${detectAuth.name}";
|
|
|
|
value =
|
|
|
|
{
|
|
|
|
owner = inputs.config.users.users.nginx.name;
|
|
|
|
content = concatStringsSep "\n" (map
|
|
|
|
(user: "${user}:{PLAIN}${inputs.config.sops.placeholder."nginx/detectAuth/${user}"}")
|
|
|
|
detectAuth.value);
|
|
|
|
};
|
|
|
|
})
|
|
|
|
detectAuthUsers)
|
|
|
|
++ (map
|
|
|
|
(addAuth:
|
2023-11-08 23:44:19 +08:00
|
|
|
{
|
2023-11-15 11:29:17 +08:00
|
|
|
name = "nginx/templates/addAuth/${addAuth.name}";
|
|
|
|
value =
|
|
|
|
{
|
|
|
|
owner = inputs.config.users.users.nginx.name;
|
|
|
|
content =
|
|
|
|
let placeholder = inputs.config.sops.placeholder."nginx/addAuth/${addAuth.value}";
|
|
|
|
in ''proxy_set_header Authorization "Basic ${placeholder}";'';
|
|
|
|
};
|
|
|
|
})
|
|
|
|
addAuth)
|
|
|
|
);
|
|
|
|
secrets = listToAttrs
|
|
|
|
(
|
|
|
|
(map
|
|
|
|
(secret: { name = "nginx/detectAuth/${secret}"; value = {}; })
|
|
|
|
(inputs.lib.unique (concatLists (map (detectAuth: detectAuth.value) detectAuthUsers))))
|
|
|
|
++ (map
|
|
|
|
(secret: { name = "nginx/addAuth/${secret}"; value = {}; })
|
|
|
|
(inputs.lib.unique (map (addAuth: addAuth.value) addAuth)))
|
|
|
|
);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)
|
2023-11-08 23:44:19 +08:00
|
|
|
# http
|
|
|
|
{
|
|
|
|
assertions = map
|
|
|
|
(site:
|
|
|
|
{
|
2023-11-11 01:27:01 +08:00
|
|
|
assertion = (inputs.lib.count (x: x != null) (map (type: site.value.${type}) nginx.global.httpTypes)) <= 1;
|
2023-11-08 23:44:19 +08:00
|
|
|
message = "Only one type shuold be specified in ${site.name}";
|
|
|
|
})
|
|
|
|
(attrsToList nginx.http);
|
|
|
|
services.nginx.virtualHosts = listToAttrs (map
|
|
|
|
(site:
|
|
|
|
{
|
2023-11-10 18:35:22 +08:00
|
|
|
name = "http.${site.name}";
|
2023-11-16 15:51:47 +08:00
|
|
|
value = { serverName = site.name; listen = [ { addr = "0.0.0.0"; port = 80; } ]; }
|
2023-11-09 23:04:28 +08:00
|
|
|
// (if site.value.rewriteHttps != null then
|
2023-11-09 00:51:45 +08:00
|
|
|
{ locations."/".return = "301 https://${site.value.rewriteHttps.hostname}$request_uri"; }
|
|
|
|
else {})
|
|
|
|
// (if site.value.php != null then
|
|
|
|
{
|
|
|
|
extraConfig = "index index.php;";
|
|
|
|
root = site.value.php.root;
|
|
|
|
locations."~ ^.+?.php(/.*)?$".extraConfig =
|
|
|
|
''
|
|
|
|
fastcgi_pass ${site.value.php.fastcgiPass};
|
|
|
|
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
|
|
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
|
|
|
include ${inputs.config.services.nginx.package}/conf/fastcgi.conf;
|
|
|
|
'';
|
|
|
|
}
|
|
|
|
else {});
|
2023-11-08 23:44:19 +08:00
|
|
|
})
|
2023-11-09 00:51:45 +08:00
|
|
|
(attrsToList nginx.http));
|
2023-11-08 23:44:19 +08:00
|
|
|
}
|
|
|
|
]);
|
2023-08-25 20:53:31 +08:00
|
|
|
}
|