Created
September 14, 2021 19:43
-
-
Save prasanthj/a9ae07c7d5003700b6bf2acc866a2c44 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{{ $all := . }} | |
{{ $servers := .Servers }} | |
{{ $cfg := .Cfg }} | |
{{ $IsIPV6Enabled := .IsIPV6Enabled }} | |
{{ $healthzURI := .HealthzURI }} | |
{{ $backends := .Backends }} | |
{{ $proxyHeaders := .ProxySetHeaders }} | |
{{ $addHeaders := .AddHeaders }} | |
# Configuration checksum: {{ $all.Cfg.Checksum }} | |
# setup custom paths that do not require root access | |
pid {{ .PID }}; | |
{{ if $cfg.UseGeoIP2 }} | |
load_module /etc/nginx/modules/ngx_http_geoip2_module.so; | |
{{ end }} | |
{{ if $cfg.EnableBrotli }} | |
load_module /etc/nginx/modules/ngx_http_brotli_filter_module.so; | |
load_module /etc/nginx/modules/ngx_http_brotli_static_module.so; | |
{{ end }} | |
{{ if (shouldLoadInfluxDBModule $servers) }} | |
load_module /etc/nginx/modules/ngx_http_influxdb_module.so; | |
{{ end }} | |
{{ if (shouldLoadAuthDigestModule $servers) }} | |
load_module /etc/nginx/modules/ngx_http_auth_digest_module.so; | |
{{ end }} | |
{{ if (shouldLoadModSecurityModule $cfg $servers) }} | |
load_module /etc/nginx/modules/ngx_http_modsecurity_module.so; | |
{{ end }} | |
{{ if (shouldLoadOpentracingModule $cfg $servers) }} | |
load_module /etc/nginx/modules/ngx_http_opentracing_module.so; | |
{{ end }} | |
daemon off; | |
worker_processes {{ $cfg.WorkerProcesses }}; | |
{{ if gt (len $cfg.WorkerCPUAffinity) 0 }} | |
worker_cpu_affinity {{ $cfg.WorkerCPUAffinity }}; | |
{{ end }} | |
worker_rlimit_nofile {{ $cfg.MaxWorkerOpenFiles }}; | |
{{/* http://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout */}} | |
{{/* avoid waiting too long during a reload */}} | |
worker_shutdown_timeout {{ $cfg.WorkerShutdownTimeout }} ; | |
{{ if not (empty $cfg.MainSnippet) }} | |
{{ $cfg.MainSnippet }} | |
{{ end }} | |
events { | |
multi_accept {{ if $cfg.EnableMultiAccept }}on{{ else }}off{{ end }}; | |
worker_connections {{ $cfg.MaxWorkerConnections }}; | |
use epoll; | |
} | |
http { | |
lua_package_path "/etc/nginx/lua/?.lua;;"; | |
{{ buildLuaSharedDictionaries $cfg $servers }} | |
init_by_lua_block { | |
collectgarbage("collect") | |
-- init modules | |
local ok, res | |
ok, res = pcall(require, "lua_ingress") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
lua_ingress = res | |
lua_ingress.set_config({{ configForLua $all }}) | |
end | |
ok, res = pcall(require, "configuration") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
configuration = res | |
end | |
ok, res = pcall(require, "balancer") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
balancer = res | |
end | |
{{ if $all.EnableMetrics }} | |
ok, res = pcall(require, "monitor") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
monitor = res | |
end | |
{{ end }} | |
ok, res = pcall(require, "certificate") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
certificate = res | |
certificate.is_ocsp_stapling_enabled = {{ $cfg.EnableOCSP }} | |
end | |
ok, res = pcall(require, "plugins") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
plugins = res | |
end | |
-- load all plugins that'll be used here | |
plugins.init({ {{ range $idx, $plugin := $cfg.Plugins }}{{ if $idx }},{{ end }}{{ $plugin | quote }}{{ end }} }) | |
} | |
init_worker_by_lua_block { | |
lua_ingress.init_worker() | |
balancer.init_worker() | |
{{ if $all.EnableMetrics }} | |
monitor.init_worker({{ $all.MonitorMaxBatchSize }}) | |
{{ end }} | |
plugins.run() | |
} | |
{{/* Enable the real_ip module only if we use either X-Forwarded headers or Proxy Protocol. */}} | |
{{/* we use the value of the real IP for the geo_ip module */}} | |
{{ if or (or $cfg.UseForwardedHeaders $cfg.UseProxyProtocol) $cfg.EnableRealIp }} | |
{{ if $cfg.UseProxyProtocol }} | |
real_ip_header proxy_protocol; | |
{{ else }} | |
real_ip_header {{ $cfg.ForwardedForHeader }}; | |
{{ end }} | |
real_ip_recursive on; | |
{{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} | |
set_real_ip_from {{ $trusted_ip }}; | |
{{ end }} | |
{{ end }} | |
{{ if $all.Cfg.EnableModsecurity }} | |
modsecurity on; | |
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf; | |
{{ if $all.Cfg.EnableOWASPCoreRules }} | |
modsecurity_rules_file /etc/nginx/owasp-modsecurity-crs/nginx-modsecurity.conf; | |
{{ else if (not (empty $all.Cfg.ModsecuritySnippet)) }} | |
modsecurity_rules ' | |
{{ $all.Cfg.ModsecuritySnippet }} | |
'; | |
{{ end }} | |
{{ end }} | |
{{ if $cfg.UseGeoIP }} | |
{{/* databases used to determine the country depending on the client IP address */}} | |
{{/* http://nginx.org/en/docs/http/ngx_http_geoip_module.html */}} | |
{{/* this is require to calculate traffic for individual country using GeoIP in the status page */}} | |
geoip_country /etc/nginx/geoip/GeoIP.dat; | |
geoip_city /etc/nginx/geoip/GeoLiteCity.dat; | |
geoip_org /etc/nginx/geoip/GeoIPASNum.dat; | |
geoip_proxy_recursive on; | |
{{ end }} | |
{{ if $cfg.UseGeoIP2 }} | |
# https://github.com/leev/ngx_http_geoip2_module#example-usage | |
{{ range $index, $file := $all.MaxmindEditionFiles }} | |
{{ if eq $file "GeoLite2-Country.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb { | |
$geoip2_country_code source=$remote_addr country iso_code; | |
$geoip2_country_name source=$remote_addr country names en; | |
$geoip2_continent_name source=$remote_addr continent names en; | |
} | |
{{ end }} | |
{{ if eq $file "GeoIP2-Country.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoIP2-Country.mmdb { | |
$geoip2_country_code source=$remote_addr country iso_code; | |
$geoip2_country_name source=$remote_addr country names en; | |
$geoip2_continent_name source=$remote_addr continent names en; | |
} | |
{{ end }} | |
{{ if eq $file "GeoLite2-City.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoLite2-City.mmdb { | |
$geoip2_city_country_code source=$remote_addr country iso_code; | |
$geoip2_city_country_name source=$remote_addr country names en; | |
$geoip2_city source=$remote_addr city names en; | |
$geoip2_postal_code source=$remote_addr postal code; | |
$geoip2_dma_code source=$remote_addr location metro_code; | |
$geoip2_latitude source=$remote_addr location latitude; | |
$geoip2_longitude source=$remote_addr location longitude; | |
$geoip2_time_zone source=$remote_addr location time_zone; | |
$geoip2_region_code source=$remote_addr subdivisions 0 iso_code; | |
$geoip2_region_name source=$remote_addr subdivisions 0 names en; | |
} | |
{{ end }} | |
{{ if eq $file "GeoIP2-City.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoIP2-City.mmdb { | |
$geoip2_city_country_code source=$remote_addr country iso_code; | |
$geoip2_city_country_name source=$remote_addr country names en; | |
$geoip2_city source=$remote_addr city names en; | |
$geoip2_postal_code source=$remote_addr postal code; | |
$geoip2_dma_code source=$remote_addr location metro_code; | |
$geoip2_latitude source=$remote_addr location latitude; | |
$geoip2_longitude source=$remote_addr location longitude; | |
$geoip2_time_zone source=$remote_addr location time_zone; | |
$geoip2_region_code source=$remote_addr subdivisions 0 iso_code; | |
$geoip2_region_name source=$remote_addr subdivisions 0 names en; | |
} | |
{{ end }} | |
{{ if eq $file "GeoLite2-ASN.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoLite2-ASN.mmdb { | |
$geoip2_asn source=$remote_addr autonomous_system_number; | |
$geoip2_org source=$remote_addr autonomous_system_organization; | |
} | |
{{ end }} | |
{{ if eq $file "GeoIP2-ASN.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoIP2-ASN.mmdb { | |
$geoip2_asn source=$remote_addr autonomous_system_number; | |
$geoip2_org source=$remote_addr autonomous_system_organization; | |
} | |
{{ end }} | |
{{ if eq $file "GeoIP2-ISP.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoIP2-ISP.mmdb { | |
$geoip2_isp isp; | |
$geoip2_isp_org organization; | |
} | |
{{ end }} | |
{{ if eq $file "GeoIP2-Connection-Type.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoIP2-Connection-Type.mmdb { | |
$geoip2_connection_type connection_type; | |
} | |
{{ end }} | |
{{ if eq $file "GeoIP2-Anonymous-IP.mmdb" }} | |
geoip2 /etc/nginx/geoip/GeoIP2-Anonymous-IP.mmdb { | |
$geoip2_is_anon source=$remote_addr is_anonymous; | |
$geoip2_is_hosting_provider source=$remote_addr is_hosting_provider; | |
$geoip2_is_public_proxy source=$remote_addr is_public_proxy; | |
} | |
{{ end }} | |
{{ end }} | |
{{ end }} | |
aio threads; | |
aio_write on; | |
tcp_nopush on; | |
tcp_nodelay on; | |
log_subrequest on; | |
reset_timedout_connection on; | |
keepalive_timeout {{ $cfg.KeepAlive }}s; | |
keepalive_requests {{ $cfg.KeepAliveRequests }}; | |
client_body_temp_path /tmp/client-body; | |
fastcgi_temp_path /tmp/fastcgi-temp; | |
proxy_temp_path /tmp/proxy-temp; | |
ajp_temp_path /tmp/ajp-temp; | |
client_header_buffer_size {{ $cfg.ClientHeaderBufferSize }}; | |
client_header_timeout {{ $cfg.ClientHeaderTimeout }}s; | |
large_client_header_buffers {{ $cfg.LargeClientHeaderBuffers }}; | |
client_body_buffer_size {{ $cfg.ClientBodyBufferSize }}; | |
client_body_timeout {{ $cfg.ClientBodyTimeout }}s; | |
http2_max_field_size {{ $cfg.HTTP2MaxFieldSize }}; | |
http2_max_header_size {{ $cfg.HTTP2MaxHeaderSize }}; | |
http2_max_requests {{ $cfg.HTTP2MaxRequests }}; | |
http2_max_concurrent_streams {{ $cfg.HTTP2MaxConcurrentStreams }}; | |
types_hash_max_size 2048; | |
server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }}; | |
server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }}; | |
map_hash_bucket_size {{ $cfg.MapHashBucketSize }}; | |
proxy_headers_hash_max_size {{ $cfg.ProxyHeadersHashMaxSize }}; | |
proxy_headers_hash_bucket_size {{ $cfg.ProxyHeadersHashBucketSize }}; | |
variables_hash_bucket_size {{ $cfg.VariablesHashBucketSize }}; | |
variables_hash_max_size {{ $cfg.VariablesHashMaxSize }}; | |
underscores_in_headers {{ if $cfg.EnableUnderscoresInHeaders }}on{{ else }}off{{ end }}; | |
ignore_invalid_headers {{ if $cfg.IgnoreInvalidHeaders }}on{{ else }}off{{ end }}; | |
limit_req_status {{ $cfg.LimitReqStatusCode }}; | |
limit_conn_status {{ $cfg.LimitConnStatusCode }}; | |
{{ buildOpentracing $cfg $servers }} | |
include /etc/nginx/mime.types; | |
default_type {{ $cfg.DefaultType }}; | |
{{ if $cfg.EnableBrotli }} | |
brotli on; | |
brotli_comp_level {{ $cfg.BrotliLevel }}; | |
brotli_types {{ $cfg.BrotliTypes }}; | |
{{ end }} | |
{{ if $cfg.UseGzip }} | |
gzip on; | |
gzip_comp_level {{ $cfg.GzipLevel }}; | |
gzip_http_version 1.1; | |
gzip_min_length {{ $cfg.GzipMinLength}}; | |
gzip_types {{ $cfg.GzipTypes }}; | |
gzip_proxied any; | |
gzip_vary on; | |
{{ end }} | |
# Custom headers for response | |
{{ range $k, $v := $addHeaders }} | |
more_set_headers {{ printf "%s: %s" $k $v | quote }}; | |
{{ end }} | |
server_tokens {{ if $cfg.ShowServerTokens }}on{{ else }}off{{ end }}; | |
{{ if not $cfg.ShowServerTokens }} | |
more_clear_headers Server; | |
{{ end }} | |
# disable warnings | |
uninitialized_variable_warn off; | |
# Additional available variables: | |
# $namespace | |
# $ingress_name | |
# $service_name | |
# $service_port | |
log_format upstreaminfo {{ if $cfg.LogFormatEscapeJSON }}escape=json {{ end }}'{{ $cfg.LogFormatUpstream }}'; | |
{{/* map urls that should not appear in access.log */}} | |
{{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}} | |
map $request_uri $loggable { | |
{{ range $reqUri := $cfg.SkipAccessLogURLs }} | |
{{ $reqUri }} 0;{{ end }} | |
default 1; | |
} | |
{{ if or $cfg.DisableAccessLog $cfg.DisableHTTPAccessLog }} | |
access_log off; | |
{{ else }} | |
{{ if $cfg.EnableSyslog }} | |
access_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} upstreaminfo if=$loggable; | |
{{ else }} | |
access_log {{ or $cfg.HttpAccessLogPath $cfg.AccessLogPath }} upstreaminfo {{ $cfg.AccessLogParams }} if=$loggable; | |
{{ end }} | |
{{ end }} | |
{{ if $cfg.EnableSyslog }} | |
error_log syslog:server={{ $cfg.SyslogHost }}:{{ $cfg.SyslogPort }} {{ $cfg.ErrorLogLevel }}; | |
{{ else }} | |
error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; | |
{{ end }} | |
{{ buildResolvers $cfg.Resolver $cfg.DisableIpv6DNS }} | |
# See https://www.nginx.com/blog/websocket-nginx | |
map $http_upgrade $connection_upgrade { | |
default upgrade; | |
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} | |
# See http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive | |
'' ''; | |
{{ else }} | |
'' close; | |
{{ end }} | |
} | |
# Reverse proxies can detect if a client provides a X-Request-ID header, and pass it on to the backend server. | |
# If no such header is provided, it can provide a random value. | |
map $http_x_request_id $req_id { | |
default $http_x_request_id; | |
{{ if $cfg.GenerateRequestID }} | |
"" $request_id; | |
{{ end }} | |
} | |
{{ if and $cfg.UseForwardedHeaders $cfg.ComputeFullForwardedFor }} | |
# We can't use $proxy_add_x_forwarded_for because the realip module | |
# replaces the remote_addr too soon | |
map $http_x_forwarded_for $full_x_forwarded_for { | |
{{ if $all.Cfg.UseProxyProtocol }} | |
default "$http_x_forwarded_for, $proxy_protocol_addr"; | |
'' "$proxy_protocol_addr"; | |
{{ else }} | |
default "$http_x_forwarded_for, $realip_remote_addr"; | |
'' "$realip_remote_addr"; | |
{{ end}} | |
} | |
{{ end }} | |
# Create a variable that contains the literal $ character. | |
# This works because the geo module will not resolve variables. | |
geo $literal_dollar { | |
default "$"; | |
} | |
server_name_in_redirect off; | |
port_in_redirect off; | |
ssl_protocols {{ $cfg.SSLProtocols }}; | |
ssl_early_data {{ if $cfg.SSLEarlyData }}on{{ else }}off{{ end }}; | |
# turn on session caching to drastically improve performance | |
{{ if $cfg.SSLSessionCache }} | |
ssl_session_cache builtin:1000 shared:SSL:{{ $cfg.SSLSessionCacheSize }}; | |
ssl_session_timeout {{ $cfg.SSLSessionTimeout }}; | |
{{ end }} | |
# allow configuring ssl session tickets | |
ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }}; | |
{{ if not (empty $cfg.SSLSessionTicketKey ) }} | |
ssl_session_ticket_key /etc/nginx/tickets.key; | |
{{ end }} | |
# slightly reduce the time-to-first-byte | |
ssl_buffer_size {{ $cfg.SSLBufferSize }}; | |
{{ if not (empty $cfg.SSLCiphers) }} | |
# allow configuring custom ssl ciphers | |
ssl_ciphers '{{ $cfg.SSLCiphers }}'; | |
ssl_prefer_server_ciphers on; | |
{{ end }} | |
{{ if not (empty $cfg.SSLDHParam) }} | |
# allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam | |
ssl_dhparam {{ $cfg.SSLDHParam }}; | |
{{ end }} | |
ssl_ecdh_curve {{ $cfg.SSLECDHCurve }}; | |
# PEM sha: {{ $cfg.DefaultSSLCertificate.PemSHA }} | |
ssl_certificate {{ $cfg.DefaultSSLCertificate.PemFileName }}; | |
ssl_certificate_key {{ $cfg.DefaultSSLCertificate.PemFileName }}; | |
{{ if gt (len $cfg.CustomHTTPErrors) 0 }} | |
proxy_intercept_errors on; | |
{{ end }} | |
{{ range $errCode := $cfg.CustomHTTPErrors }} | |
error_page {{ $errCode }} = @custom_upstream-default-backend_{{ $errCode }};{{ end }} | |
proxy_ssl_session_reuse on; | |
{{ if $cfg.AllowBackendServerHeader }} | |
proxy_pass_header Server; | |
{{ end }} | |
{{ range $header := $cfg.HideHeaders }}proxy_hide_header {{ $header }}; | |
{{ end }} | |
{{ if not (empty $cfg.HTTPSnippet) }} | |
# Custom code snippet configured in the configuration configmap | |
{{ $cfg.HTTPSnippet }} | |
{{ end }} | |
upstream upstream_balancer { | |
### Attention!!! | |
# | |
# We no longer create "upstream" section for every backend. | |
# Backends are handled dynamically using Lua. If you would like to debug | |
# and see what backends ingress-nginx has in its memory you can | |
# install our kubectl plugin https://kubernetes.github.io/ingress-nginx/kubectl-plugin. | |
# Once you have the plugin you can use "kubectl ingress-nginx backends" command to | |
# inspect current backends. | |
# | |
### | |
server 0.0.0.1; # placeholder | |
balancer_by_lua_block { | |
balancer.balance() | |
} | |
{{ if (gt $cfg.UpstreamKeepaliveConnections 0) }} | |
keepalive {{ $cfg.UpstreamKeepaliveConnections }}; | |
keepalive_timeout {{ $cfg.UpstreamKeepaliveTimeout }}s; | |
keepalive_requests {{ $cfg.UpstreamKeepaliveRequests }}; | |
{{ end }} | |
} | |
{{ range $rl := (filterRateLimits $servers ) }} | |
# Ratelimit {{ $rl.Name }} | |
geo $remote_addr $whitelist_{{ $rl.ID }} { | |
default 0; | |
{{ range $ip := $rl.Whitelist }} | |
{{ $ip }} 1;{{ end }} | |
} | |
# Ratelimit {{ $rl.Name }} | |
map $whitelist_{{ $rl.ID }} $limit_{{ $rl.ID }} { | |
0 {{ $cfg.LimitConnZoneVariable }}; | |
1 ""; | |
} | |
{{ end }} | |
{{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}} | |
{{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}} | |
{{ range $zone := (buildRateLimitZones $servers) }} | |
{{ $zone }} | |
{{ end }} | |
# Cache for internal auth checks | |
proxy_cache_path /tmp/nginx-cache-auth levels=1:2 keys_zone=auth_cache:10m max_size=128m inactive=30m use_temp_path=off; | |
# Global filters | |
{{ range $ip := $cfg.BlockCIDRs }}deny {{ trimSpace $ip }}; | |
{{ end }} | |
{{ if gt (len $cfg.BlockUserAgents) 0 }} | |
map $http_user_agent $block_ua { | |
default 0; | |
{{ range $ua := $cfg.BlockUserAgents }}{{ trimSpace $ua }} 1; | |
{{ end }} | |
} | |
{{ end }} | |
{{ if gt (len $cfg.BlockReferers) 0 }} | |
map $http_referer $block_ref { | |
default 0; | |
{{ range $ref := $cfg.BlockReferers }}{{ trimSpace $ref }} 1; | |
{{ end }} | |
} | |
{{ end }} | |
{{/* Build server redirects (from/to www) */}} | |
{{ range $redirect := .RedirectServers }} | |
## start server {{ $redirect.From }} | |
server { | |
server_name {{ $redirect.From }}; | |
{{ buildHTTPListener $all $redirect.From }} | |
{{ buildHTTPSListener $all $redirect.From }} | |
ssl_certificate_by_lua_block { | |
certificate.call() | |
} | |
{{ if gt (len $cfg.BlockUserAgents) 0 }} | |
if ($block_ua) { | |
return 403; | |
} | |
{{ end }} | |
{{ if gt (len $cfg.BlockReferers) 0 }} | |
if ($block_ref) { | |
return 403; | |
} | |
{{ end }} | |
set_by_lua_block $redirect_to { | |
local request_uri = ngx.var.request_uri | |
if string.sub(request_uri, -1) == "/" then | |
request_uri = string.sub(request_uri, 1, -2) | |
end | |
{{ if ne $all.ListenPorts.HTTPS 443 }} | |
{{ $redirect_port := (printf ":%v" $all.ListenPorts.HTTPS) }} | |
return string.format("%s://%s%s%s", ngx.var.scheme, "{{ $redirect.To }}", "{{ $redirect_port }}", request_uri) | |
{{ else }} | |
return string.format("%s://%s%s", ngx.var.scheme, "{{ $redirect.To }}", request_uri) | |
{{ end }} | |
} | |
return {{ $all.Cfg.HTTPRedirectCode }} $redirect_to; | |
} | |
## end server {{ $redirect.From }} | |
{{ end }} | |
{{ range $server := $servers }} | |
## start server {{ $server.Hostname }} | |
server { | |
{{ $hostsplit := split $server.Hostname "." }} | |
{{ $olddomain := "env-hb6vmj.dw.xcu2-8y8x.dev.cldr.work" }} | |
{{ if gt (len $hostsplit) 0 }} | |
{{ if eq $server.Hostname "_" }} | |
server_name {{ $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; | |
{{ else }} | |
server_name {{ $server.Hostname }} {{ index $hostsplit 0 }}.{{ $olddomain }} {{range $server.Aliases }}{{ . }} {{ end }}; | |
{{ end }} | |
{{ else }} | |
server_name {{ $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; | |
{{ end }} | |
server_name {{ $server.Hostname }} {{range $server.Aliases }}{{ . }} {{ end }}; | |
{{ if gt (len $cfg.BlockUserAgents) 0 }} | |
if ($block_ua) { | |
return 403; | |
} | |
{{ end }} | |
{{ if gt (len $cfg.BlockReferers) 0 }} | |
if ($block_ref) { | |
return 403; | |
} | |
{{ end }} | |
{{ template "SERVER" serverConfig $all $server }} | |
{{ if not (empty $cfg.ServerSnippet) }} | |
# Custom code snippet configured in the configuration configmap | |
{{ $cfg.ServerSnippet }} | |
{{ end }} | |
{{ template "CUSTOM_ERRORS" (buildCustomErrorDeps "upstream-default-backend" $cfg.CustomHTTPErrors $all.EnableMetrics) }} | |
} | |
## end server {{ $server.Hostname }} | |
{{ end }} | |
# backend for when default-backend-service is not configured or it does not have endpoints | |
server { | |
listen {{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }}; | |
{{ if $IsIPV6Enabled }}listen [::]:{{ $all.ListenPorts.Default }} default_server {{ if $all.Cfg.ReusePort }}reuseport{{ end }} backlog={{ $all.BacklogSize }};{{ end }} | |
set $proxy_upstream_name "internal"; | |
access_log off; | |
location / { | |
return 404; | |
} | |
} | |
# default server, used for NGINX healthcheck and access to nginx stats | |
server { | |
listen 127.0.0.1:{{ .StatusPort }}; | |
set $proxy_upstream_name "internal"; | |
keepalive_timeout 0; | |
gzip off; | |
access_log off; | |
{{ if $cfg.EnableOpentracing }} | |
opentracing off; | |
{{ end }} | |
location {{ $healthzURI }} { | |
return 200; | |
} | |
location /is-dynamic-lb-initialized { | |
content_by_lua_block { | |
local configuration = require("configuration") | |
local backend_data = configuration.get_backends_data() | |
if not backend_data then | |
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) | |
return | |
end | |
ngx.say("OK") | |
ngx.exit(ngx.HTTP_OK) | |
} | |
} | |
location {{ .StatusPath }} { | |
stub_status on; | |
} | |
location /configuration { | |
client_max_body_size {{ luaConfigurationRequestBodySize $cfg }}m; | |
client_body_buffer_size {{ luaConfigurationRequestBodySize $cfg }}m; | |
proxy_buffering off; | |
content_by_lua_block { | |
configuration.call() | |
} | |
} | |
location / { | |
content_by_lua_block { | |
ngx.exit(ngx.HTTP_NOT_FOUND) | |
} | |
} | |
} | |
} | |
stream { | |
lua_package_path "/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/?.lua;;"; | |
lua_shared_dict tcp_udp_configuration_data 5M; | |
init_by_lua_block { | |
collectgarbage("collect") | |
-- init modules | |
local ok, res | |
ok, res = pcall(require, "configuration") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
configuration = res | |
end | |
ok, res = pcall(require, "tcp_udp_configuration") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
tcp_udp_configuration = res | |
end | |
ok, res = pcall(require, "tcp_udp_balancer") | |
if not ok then | |
error("require failed: " .. tostring(res)) | |
else | |
tcp_udp_balancer = res | |
end | |
} | |
init_worker_by_lua_block { | |
tcp_udp_balancer.init_worker() | |
} | |
lua_add_variable $proxy_upstream_name; | |
log_format log_stream '{{ $cfg.LogFormatStream }}'; | |
{{ if or $cfg.DisableAccessLog $cfg.DisableStreamAccessLog }} | |
access_log off; | |
{{ else }} | |
access_log {{ or $cfg.StreamAccessLogPath $cfg.AccessLogPath }} log_stream {{ $cfg.AccessLogParams }}; | |
{{ end }} | |
error_log {{ $cfg.ErrorLogPath }} {{ $cfg.ErrorLogLevel }}; | |
{{ if $cfg.EnableRealIp }} | |
{{ range $trusted_ip := $cfg.ProxyRealIPCIDR }} | |
set_real_ip_from {{ $trusted_ip }}; | |
{{ end }} | |
{{ end }} | |
upstream upstream_balancer { | |
server 0.0.0.1:1234; # placeholder | |
balancer_by_lua_block { | |
tcp_udp_balancer.balance() | |
} | |
} | |
server { | |
listen 127.0.0.1:{{ .StreamPort }}; | |
access_log off; | |
content_by_lua_block { | |
tcp_udp_configuration.call() | |
} | |
} | |
# TCP services | |
{{ range $tcpServer := .TCPBackends }} | |
server { | |
preread_by_lua_block { | |
ngx.var.proxy_upstream_name="tcp-{{ $tcpServer.Backend.Namespace }}-{{ $tcpServer.Backend.Name }}-{{ $tcpServer.Backend.Port }}"; | |
} | |
{{ range $address := $all.Cfg.BindAddressIpv4 }} | |
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; | |
{{ else }} | |
listen {{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; | |
{{ end }} | |
{{ if $IsIPV6Enabled }} | |
{{ range $address := $all.Cfg.BindAddressIpv6 }} | |
listen {{ $address }}:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; | |
{{ else }} | |
listen [::]:{{ $tcpServer.Port }}{{ if $tcpServer.Backend.ProxyProtocol.Decode }} proxy_protocol{{ end }}; | |
{{ end }} | |
{{ end }} | |
proxy_timeout {{ $cfg.ProxyStreamTimeout }}; | |
proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; | |
proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; | |
proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; | |
proxy_pass upstream_balancer; | |
{{ if $tcpServer.Backend.ProxyProtocol.Encode }} | |
proxy_protocol on; | |
{{ end }} | |
} | |
{{ end }} | |
# UDP services | |
{{ range $udpServer := .UDPBackends }} | |
server { | |
preread_by_lua_block { | |
ngx.var.proxy_upstream_name="udp-{{ $udpServer.Backend.Namespace }}-{{ $udpServer.Backend.Name }}-{{ $udpServer.Backend.Port }}"; | |
} | |
{{ range $address := $all.Cfg.BindAddressIpv4 }} | |
listen {{ $address }}:{{ $udpServer.Port }} udp; | |
{{ else }} | |
listen {{ $udpServer.Port }} udp; | |
{{ end }} | |
{{ if $IsIPV6Enabled }} | |
{{ range $address := $all.Cfg.BindAddressIpv6 }} | |
listen {{ $address }}:{{ $udpServer.Port }} udp; | |
{{ else }} | |
listen [::]:{{ $udpServer.Port }} udp; | |
{{ end }} | |
{{ end }} | |
proxy_responses {{ $cfg.ProxyStreamResponses }}; | |
proxy_timeout {{ $cfg.ProxyStreamTimeout }}; | |
proxy_next_upstream {{ if $cfg.ProxyStreamNextUpstream }}on{{ else }}off{{ end }}; | |
proxy_next_upstream_timeout {{ $cfg.ProxyStreamNextUpstreamTimeout }}; | |
proxy_next_upstream_tries {{ $cfg.ProxyStreamNextUpstreamTries }}; | |
proxy_pass upstream_balancer; | |
} | |
{{ end }} | |
} | |
{{/* definition of templates to avoid repetitions */}} | |
{{ define "CUSTOM_ERRORS" }} | |
{{ $enableMetrics := .EnableMetrics }} | |
{{ $upstreamName := .UpstreamName }} | |
{{ range $errCode := .ErrorCodes }} | |
location @custom_{{ $upstreamName }}_{{ $errCode }} { | |
internal; | |
proxy_intercept_errors off; | |
proxy_set_header X-Code {{ $errCode }}; | |
proxy_set_header X-Format $http_accept; | |
proxy_set_header X-Original-URI $request_uri; | |
proxy_set_header X-Namespace $namespace; | |
proxy_set_header X-Ingress-Name $ingress_name; | |
proxy_set_header X-Service-Name $service_name; | |
proxy_set_header X-Service-Port $service_port; | |
proxy_set_header X-Request-ID $req_id; | |
proxy_set_header Host $best_http_host; | |
set $proxy_upstream_name {{ $upstreamName | quote }}; | |
rewrite (.*) / break; | |
proxy_pass http://upstream_balancer; | |
log_by_lua_block { | |
{{ if $enableMetrics }} | |
monitor.call() | |
{{ end }} | |
} | |
} | |
{{ end }} | |
{{ end }} | |
{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}} | |
{{ define "CORS" }} | |
{{ $cors := .CorsConfig }} | |
# Cors Preflight methods needs additional options and different Return Code | |
if ($request_method = 'OPTIONS') { | |
more_set_headers 'Access-Control-Allow-Origin: {{ $cors.CorsAllowOrigin }}'; | |
{{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} | |
more_set_headers 'Access-Control-Allow-Methods: {{ $cors.CorsAllowMethods }}'; | |
more_set_headers 'Access-Control-Allow-Headers: {{ $cors.CorsAllowHeaders }}'; | |
{{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} | |
more_set_headers 'Access-Control-Max-Age: {{ $cors.CorsMaxAge }}'; | |
more_set_headers 'Content-Type: text/plain charset=UTF-8'; | |
more_set_headers 'Content-Length: 0'; | |
return 204; | |
} | |
more_set_headers 'Access-Control-Allow-Origin: {{ $cors.CorsAllowOrigin }}'; | |
{{ if $cors.CorsAllowCredentials }} more_set_headers 'Access-Control-Allow-Credentials: {{ $cors.CorsAllowCredentials }}'; {{ end }} | |
{{ if not (empty $cors.CorsExposeHeaders) }} more_set_headers 'Access-Control-Expose-Headers: {{ $cors.CorsExposeHeaders }}'; {{ end }} | |
{{ end }} | |
{{/* definition of server-template to avoid repetitions with server-alias */}} | |
{{ define "SERVER" }} | |
{{ $all := .First }} | |
{{ $server := .Second }} | |
{{ buildHTTPListener $all $server.Hostname }} | |
{{ buildHTTPSListener $all $server.Hostname }} | |
set $proxy_upstream_name "-"; | |
ssl_certificate_by_lua_block { | |
certificate.call() | |
} | |
{{ if not (empty $server.AuthTLSError) }} | |
# {{ $server.AuthTLSError }} | |
return 403; | |
{{ else }} | |
{{ if not (empty $server.CertificateAuth.CAFileName) }} | |
# PEM sha: {{ $server.CertificateAuth.CASHA }} | |
ssl_client_certificate {{ $server.CertificateAuth.CAFileName }}; | |
ssl_verify_client {{ $server.CertificateAuth.VerifyClient }}; | |
ssl_verify_depth {{ $server.CertificateAuth.ValidationDepth }}; | |
{{ if not (empty $server.CertificateAuth.CRLFileName) }} | |
# PEM sha: {{ $server.CertificateAuth.CRLSHA }} | |
ssl_crl {{ $server.CertificateAuth.CRLFileName }}; | |
{{ end }} | |
{{ if not (empty $server.CertificateAuth.ErrorPage)}} | |
error_page 495 496 = {{ $server.CertificateAuth.ErrorPage }}; | |
{{ end }} | |
{{ end }} | |
{{ if not (empty $server.ProxySSL.CAFileName) }} | |
# PEM sha: {{ $server.ProxySSL.CASHA }} | |
proxy_ssl_trusted_certificate {{ $server.ProxySSL.CAFileName }}; | |
proxy_ssl_ciphers {{ $server.ProxySSL.Ciphers }}; | |
proxy_ssl_protocols {{ $server.ProxySSL.Protocols }}; | |
proxy_ssl_verify {{ $server.ProxySSL.Verify }}; | |
proxy_ssl_verify_depth {{ $server.ProxySSL.VerifyDepth }}; | |
{{ if not (empty $server.ProxySSL.ProxySSLName) }} | |
proxy_ssl_name {{ $server.ProxySSL.ProxySSLName }}; | |
proxy_ssl_server_name {{ $server.ProxySSL.ProxySSLServerName }}; | |
{{ end }} | |
{{ end }} | |
{{ if not (empty $server.ProxySSL.PemFileName) }} | |
proxy_ssl_certificate {{ $server.ProxySSL.PemFileName }}; | |
proxy_ssl_certificate_key {{ $server.ProxySSL.PemFileName }}; | |
{{ end }} | |
{{ if not (empty $server.SSLCiphers) }} | |
ssl_ciphers {{ $server.SSLCiphers }}; | |
{{ end }} | |
{{ if not (empty $server.SSLPreferServerCiphers) }} | |
ssl_prefer_server_ciphers {{ $server.SSLPreferServerCiphers }}; | |
{{ end }} | |
{{ if not (empty $server.ServerSnippet) }} | |
# Custom code snippet configured for host {{ $server.Hostname }} | |
{{ $server.ServerSnippet }} | |
{{ end }} | |
{{ range $errorLocation := (buildCustomErrorLocationsPerServer $server) }} | |
{{ template "CUSTOM_ERRORS" (buildCustomErrorDeps $errorLocation.UpstreamName $errorLocation.Codes $all.EnableMetrics) }} | |
{{ end }} | |
{{ buildMirrorLocations $server.Locations }} | |
{{ $enforceRegex := enforceRegexModifier $server.Locations }} | |
{{ range $location := $server.Locations }} | |
{{ $path := buildLocation $location $enforceRegex }} | |
{{ $proxySetHeader := proxySetHeader $location }} | |
{{ $authPath := buildAuthLocation $location $all.Cfg.GlobalExternalAuth.URL }} | |
{{ $applyGlobalAuth := shouldApplyGlobalAuth $location $all.Cfg.GlobalExternalAuth.URL }} | |
{{ $externalAuth := $location.ExternalAuth }} | |
{{ if eq $applyGlobalAuth true }} | |
{{ $externalAuth = $all.Cfg.GlobalExternalAuth }} | |
{{ end }} | |
{{ if not (empty $location.Rewrite.AppRoot) }} | |
if ($uri = /) { | |
return 302 $scheme://$http_host{{ $location.Rewrite.AppRoot }}; | |
} | |
{{ end }} | |
{{ if $authPath }} | |
location = {{ $authPath }} { | |
internal; | |
{{ if (or $all.Cfg.EnableOpentracing $location.Opentracing.Enabled) }} | |
opentracing on; | |
opentracing_propagate_context; | |
{{ end }} | |
{{ if $externalAuth.AuthCacheKey }} | |
set $tmp_cache_key '{{ $server.Hostname }}{{ $authPath }}{{ $externalAuth.AuthCacheKey }}'; | |
set $cache_key ''; | |
rewrite_by_lua_block { | |
ngx.var.cache_key = ngx.encode_base64(ngx.sha1_bin(ngx.var.tmp_cache_key)) | |
} | |
proxy_cache auth_cache; | |
{{- range $dur := $externalAuth.AuthCacheDuration }} | |
proxy_cache_valid {{ $dur }}; | |
{{- end }} | |
proxy_cache_key "$cache_key"; | |
{{ end }} | |
# ngx_auth_request module overrides variables in the parent request, | |
# therefore we have to explicitly set this variable again so that when the parent request | |
# resumes it has the correct value set for this variable so that Lua can pick backend correctly | |
set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; | |
proxy_pass_request_body off; | |
proxy_set_header Content-Length ""; | |
proxy_set_header X-Forwarded-Proto ""; | |
proxy_set_header X-Request-ID $req_id; | |
{{ if $externalAuth.Method }} | |
proxy_method {{ $externalAuth.Method }}; | |
proxy_set_header X-Original-URI $request_uri; | |
proxy_set_header X-Scheme $pass_access_scheme; | |
{{ end }} | |
proxy_set_header Host {{ $externalAuth.Host }}; | |
proxy_set_header X-Original-URL $scheme://$http_host$request_uri; | |
proxy_set_header X-Original-Method $request_method; | |
proxy_set_header X-Sent-From "nginx-ingress-controller"; | |
proxy_set_header X-Real-IP $remote_addr; | |
{{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} | |
proxy_set_header X-Forwarded-For $full_x_forwarded_for; | |
{{ else }} | |
proxy_set_header X-Forwarded-For $remote_addr; | |
{{ end }} | |
{{ if $externalAuth.RequestRedirect }} | |
proxy_set_header X-Auth-Request-Redirect {{ $externalAuth.RequestRedirect }}; | |
{{ else }} | |
proxy_set_header X-Auth-Request-Redirect $request_uri; | |
{{ end }} | |
{{ if $externalAuth.AuthCacheKey }} | |
proxy_buffering "on"; | |
{{ else }} | |
proxy_buffering {{ $location.Proxy.ProxyBuffering }}; | |
{{ end }} | |
proxy_buffer_size {{ $location.Proxy.BufferSize }}; | |
proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; | |
proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; | |
proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; | |
proxy_ssl_server_name on; | |
proxy_pass_request_headers on; | |
{{ if isValidByteSize $location.Proxy.BodySize true }} | |
client_max_body_size {{ $location.Proxy.BodySize }}; | |
{{ end }} | |
{{ if isValidByteSize $location.ClientBodyBufferSize false }} | |
client_body_buffer_size {{ $location.ClientBodyBufferSize }}; | |
{{ end }} | |
# Pass the extracted client certificate to the auth provider | |
{{ if not (empty $server.CertificateAuth.CAFileName) }} | |
{{ if $server.CertificateAuth.PassCertToUpstream }} | |
proxy_set_header ssl-client-cert $ssl_client_escaped_cert; | |
{{ end }} | |
proxy_set_header ssl-client-verify $ssl_client_verify; | |
proxy_set_header ssl-client-subject-dn $ssl_client_s_dn; | |
proxy_set_header ssl-client-issuer-dn $ssl_client_i_dn; | |
{{ end }} | |
{{- range $line := buildAuthProxySetHeaders $externalAuth.ProxySetHeaders}} | |
{{ $line }} | |
{{- end }} | |
{{ if not (empty $externalAuth.AuthSnippet) }} | |
{{ $externalAuth.AuthSnippet }} | |
{{ end }} | |
set $target {{ $externalAuth.URL }}; | |
proxy_pass $target; | |
} | |
{{ end }} | |
{{ if isLocationAllowed $location }} | |
{{ if $externalAuth.SigninURL }} | |
location {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }} { | |
internal; | |
add_header Set-Cookie $auth_cookie; | |
return 302 {{ buildAuthSignURL $externalAuth.SigninURL $externalAuth.SigninURLRedirectParam }}; | |
} | |
{{ end }} | |
{{ end }} | |
location {{ $path }} { | |
{{ $ing := (getIngressInformation $location.Ingress $server.Hostname $location.IngressPath) }} | |
set $namespace {{ $ing.Namespace | quote}}; | |
set $ingress_name {{ $ing.Rule | quote }}; | |
set $service_name {{ $ing.Service | quote }}; | |
set $service_port {{ $ing.ServicePort | quote }}; | |
set $location_path {{ $ing.Path | escapeLiteralDollar | quote }}; | |
{{ buildOpentracingForLocation $all.Cfg.EnableOpentracing $location }} | |
{{ if $location.Mirror.Source }} | |
mirror {{ $location.Mirror.Source }}; | |
mirror_request_body {{ $location.Mirror.RequestBody }}; | |
{{ end }} | |
rewrite_by_lua_block { | |
lua_ingress.rewrite({{ locationConfigForLua $location $all }}) | |
balancer.rewrite() | |
plugins.run() | |
} | |
# be careful with `access_by_lua_block` and `satisfy any` directives as satisfy any | |
# will always succeed when there's `access_by_lua_block` that does not have any lua code doing `ngx.exit(ngx.DECLINED)` | |
# other authentication method such as basic auth or external auth useless - all requests will be allowed. | |
#access_by_lua_block { | |
#} | |
header_filter_by_lua_block { | |
lua_ingress.header() | |
plugins.run() | |
} | |
body_filter_by_lua_block { | |
} | |
log_by_lua_block { | |
balancer.log() | |
{{ if $all.EnableMetrics }} | |
monitor.call() | |
{{ end }} | |
plugins.run() | |
} | |
{{ if not $location.Logs.Access }} | |
access_log off; | |
{{ end }} | |
{{ if $location.Logs.Rewrite }} | |
rewrite_log on; | |
{{ end }} | |
{{ if $location.HTTP2PushPreload }} | |
http2_push_preload on; | |
{{ end }} | |
port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }}; | |
set $balancer_ewma_score -1; | |
set $proxy_upstream_name {{ buildUpstreamName $location | quote }}; | |
set $proxy_host $proxy_upstream_name; | |
set $pass_access_scheme $scheme; | |
{{ if $all.Cfg.UseProxyProtocol }} | |
set $pass_server_port $proxy_protocol_server_port; | |
{{ else }} | |
set $pass_server_port $server_port; | |
{{ end }} | |
set $best_http_host $http_host; | |
set $pass_port $pass_server_port; | |
set $proxy_alternative_upstream_name ""; | |
{{ buildModSecurityForLocation $all.Cfg $location }} | |
{{ if isLocationAllowed $location }} | |
{{ if gt (len $location.Whitelist.CIDR) 0 }} | |
{{ range $ip := $location.Whitelist.CIDR }} | |
allow {{ $ip }};{{ end }} | |
deny all; | |
{{ end }} | |
{{ if not (isLocationInLocationList $location $all.Cfg.NoAuthLocations) }} | |
{{ if $authPath }} | |
# this location requires authentication | |
auth_request {{ $authPath }}; | |
auth_request_set $auth_cookie $upstream_http_set_cookie; | |
add_header Set-Cookie $auth_cookie; | |
{{- range $line := buildAuthResponseHeaders $externalAuth.ResponseHeaders }} | |
{{ $line }} | |
{{- end }} | |
{{ end }} | |
{{ if $externalAuth.SigninURL }} | |
set_escape_uri $escaped_request_uri $request_uri; | |
error_page 401 = {{ buildAuthSignURLLocation $location.Path $externalAuth.SigninURL }}; | |
{{ end }} | |
{{ if $location.BasicDigestAuth.Secured }} | |
{{ if eq $location.BasicDigestAuth.Type "basic" }} | |
auth_basic {{ $location.BasicDigestAuth.Realm | quote }}; | |
auth_basic_user_file {{ $location.BasicDigestAuth.File }}; | |
{{ else }} | |
auth_digest {{ $location.BasicDigestAuth.Realm | quote }}; | |
auth_digest_user_file {{ $location.BasicDigestAuth.File }}; | |
{{ end }} | |
proxy_set_header Authorization ""; | |
{{ end }} | |
{{ end }} | |
{{/* if the location contains a rate limit annotation, create one */}} | |
{{ $limits := buildRateLimit $location }} | |
{{ range $limit := $limits }} | |
{{ $limit }}{{ end }} | |
{{ if $location.CorsConfig.CorsEnabled }} | |
{{ template "CORS" $location }} | |
{{ end }} | |
{{ buildInfluxDB $location.InfluxDB }} | |
{{ if isValidByteSize $location.Proxy.BodySize true }} | |
client_max_body_size {{ $location.Proxy.BodySize }}; | |
{{ end }} | |
{{ if isValidByteSize $location.ClientBodyBufferSize false }} | |
client_body_buffer_size {{ $location.ClientBodyBufferSize }}; | |
{{ end }} | |
{{/* By default use vhost as Host to upstream, but allow overrides */}} | |
{{ if not (eq $proxySetHeader "grpc_set_header") }} | |
{{ if not (empty $location.UpstreamVhost) }} | |
{{ $proxySetHeader }} Host {{ $location.UpstreamVhost | quote }}; | |
{{ else }} | |
{{ $proxySetHeader }} Host $best_http_host; | |
{{ end }} | |
{{ end }} | |
# Pass the extracted client certificate to the backend | |
{{ if not (empty $server.CertificateAuth.CAFileName) }} | |
{{ if $server.CertificateAuth.PassCertToUpstream }} | |
{{ $proxySetHeader }} ssl-client-cert $ssl_client_escaped_cert; | |
{{ end }} | |
{{ $proxySetHeader }} ssl-client-verify $ssl_client_verify; | |
{{ $proxySetHeader }} ssl-client-subject-dn $ssl_client_s_dn; | |
{{ $proxySetHeader }} ssl-client-issuer-dn $ssl_client_i_dn; | |
{{ end }} | |
# Allow websocket connections | |
{{ $proxySetHeader }} Upgrade $http_upgrade; | |
{{ if $location.Connection.Enabled}} | |
{{ $proxySetHeader }} Connection {{ $location.Connection.Header }}; | |
{{ else }} | |
{{ $proxySetHeader }} Connection $connection_upgrade; | |
{{ end }} | |
{{ $proxySetHeader }} X-Request-ID $req_id; | |
{{ $proxySetHeader }} X-Real-IP $remote_addr; | |
{{ if and $all.Cfg.UseForwardedHeaders $all.Cfg.ComputeFullForwardedFor }} | |
{{ $proxySetHeader }} X-Forwarded-For $full_x_forwarded_for; | |
{{ else }} | |
{{ $proxySetHeader }} X-Forwarded-For $remote_addr; | |
{{ end }} | |
{{ $proxySetHeader }} X-Forwarded-Host $best_http_host; | |
{{ $proxySetHeader }} X-Forwarded-Port $pass_port; | |
{{ $proxySetHeader }} X-Forwarded-Proto $pass_access_scheme; | |
{{ if $all.Cfg.ProxyAddOriginalURIHeader }} | |
{{ $proxySetHeader }} X-Original-URI $request_uri; | |
{{ end }} | |
{{ $proxySetHeader }} X-Scheme $pass_access_scheme; | |
# Pass the original X-Forwarded-For | |
{{ $proxySetHeader }} X-Original-Forwarded-For {{ buildForwardedFor $all.Cfg.ForwardedForHeader }}; | |
# mitigate HTTPoxy Vulnerability | |
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ | |
{{ $proxySetHeader }} Proxy ""; | |
# Custom headers to proxied server | |
{{ range $k, $v := $all.ProxySetHeaders }} | |
{{ $proxySetHeader }} {{ $k }} {{ $v | quote }}; | |
{{ end }} | |
proxy_connect_timeout {{ $location.Proxy.ConnectTimeout }}s; | |
proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; | |
proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; | |
proxy_buffering {{ $location.Proxy.ProxyBuffering }}; | |
proxy_buffer_size {{ $location.Proxy.BufferSize }}; | |
proxy_buffers {{ $location.Proxy.BuffersNumber }} {{ $location.Proxy.BufferSize }}; | |
{{ if isValidByteSize $location.Proxy.ProxyMaxTempFileSize true }} | |
proxy_max_temp_file_size {{ $location.Proxy.ProxyMaxTempFileSize }}; | |
{{ end }} | |
proxy_request_buffering {{ $location.Proxy.RequestBuffering }}; | |
proxy_http_version {{ $location.Proxy.ProxyHTTPVersion }}; | |
proxy_cookie_domain {{ $location.Proxy.CookieDomain }}; | |
proxy_cookie_path {{ $location.Proxy.CookiePath }}; | |
# In case of errors try the next upstream server before returning an error | |
proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }}; | |
proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }}; | |
proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }}; | |
{{/* Add any additional configuration defined */}} | |
{{ $location.ConfigurationSnippet }} | |
{{ if not (empty $all.Cfg.LocationSnippet) }} | |
# Custom code snippet configured in the configuration configmap | |
{{ $all.Cfg.LocationSnippet }} | |
{{ end }} | |
{{/* if we are sending the request to a custom default backend, we add the required headers */}} | |
{{ if (hasPrefix $location.Backend "custom-default-backend-") }} | |
proxy_set_header X-Code 503; | |
proxy_set_header X-Format $http_accept; | |
proxy_set_header X-Namespace $namespace; | |
proxy_set_header X-Ingress-Name $ingress_name; | |
proxy_set_header X-Service-Name $service_name; | |
proxy_set_header X-Service-Port $service_port; | |
proxy_set_header X-Request-ID $req_id; | |
{{ end }} | |
{{ if $location.Satisfy }} | |
satisfy {{ $location.Satisfy }}; | |
{{ end }} | |
{{/* if a location-specific error override is set, add the proxy_intercept here */}} | |
{{ if $location.CustomHTTPErrors }} | |
# Custom error pages per ingress | |
proxy_intercept_errors on; | |
{{ end }} | |
{{ range $errCode := $location.CustomHTTPErrors }} | |
error_page {{ $errCode }} = @custom_{{ $location.DefaultBackendUpstreamName }}_{{ $errCode }};{{ end }} | |
{{ if (eq $location.BackendProtocol "FCGI") }} | |
include /etc/nginx/fastcgi_params; | |
{{ end }} | |
{{- if $location.FastCGI.Index -}} | |
fastcgi_index {{ $location.FastCGI.Index | quote }}; | |
{{- end -}} | |
{{ range $k, $v := $location.FastCGI.Params }} | |
fastcgi_param {{ $k }} {{ $v | quote }}; | |
{{ end }} | |
{{ if not (empty $location.Redirect.URL) }} | |
return {{ $location.Redirect.Code }} {{ $location.Redirect.URL }}; | |
{{ end }} | |
{{ buildProxyPass $server.Hostname $all.Backends $location }} | |
{{ if (or (eq $location.Proxy.ProxyRedirectFrom "default") (eq $location.Proxy.ProxyRedirectFrom "off")) }} | |
proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }}; | |
{{ else if not (eq $location.Proxy.ProxyRedirectTo "off") }} | |
proxy_redirect {{ $location.Proxy.ProxyRedirectFrom }} {{ $location.Proxy.ProxyRedirectTo }}; | |
{{ end }} | |
{{ else }} | |
# Location denied. Reason: {{ $location.Denied | quote }} | |
return 503; | |
{{ end }} | |
{{ if not (empty $location.ProxySSL.CAFileName) }} | |
# PEM sha: {{ $location.ProxySSL.CASHA }} | |
proxy_ssl_trusted_certificate {{ $location.ProxySSL.CAFileName }}; | |
proxy_ssl_ciphers {{ $location.ProxySSL.Ciphers }}; | |
proxy_ssl_protocols {{ $location.ProxySSL.Protocols }}; | |
proxy_ssl_verify {{ $location.ProxySSL.Verify }}; | |
proxy_ssl_verify_depth {{ $location.ProxySSL.VerifyDepth }}; | |
{{ end }} | |
{{ if not (empty $location.ProxySSL.ProxySSLName) }} | |
proxy_ssl_name {{ $location.ProxySSL.ProxySSLName }}; | |
{{ end }} | |
{{ if not (empty $location.ProxySSL.ProxySSLServerName) }} | |
proxy_ssl_server_name {{ $location.ProxySSL.ProxySSLServerName }}; | |
{{ end }} | |
{{ if not (empty $location.ProxySSL.PemFileName) }} | |
proxy_ssl_certificate {{ $location.ProxySSL.PemFileName }}; | |
proxy_ssl_certificate_key {{ $location.ProxySSL.PemFileName }}; | |
{{ end }} | |
} | |
{{ end }} | |
{{ end }} | |
{{ if eq $server.Hostname "_" }} | |
# health checks in cloud providers require the use of port {{ $all.ListenPorts.HTTP }} | |
location {{ $all.HealthzURI }} { | |
{{ if $all.Cfg.EnableOpentracing }} | |
opentracing off; | |
{{ end }} | |
access_log off; | |
return 200; | |
} | |
# this is required to avoid error if nginx is being monitored | |
# with an external software (like sysdig) | |
location /nginx_status { | |
{{ if $all.Cfg.EnableOpentracing }} | |
opentracing off; | |
{{ end }} | |
{{ range $v := $all.NginxStatusIpv4Whitelist }} | |
allow {{ $v }}; | |
{{ end }} | |
{{ if $all.IsIPV6Enabled -}} | |
{{ range $v := $all.NginxStatusIpv6Whitelist }} | |
allow {{ $v }}; | |
{{ end }} | |
{{ end -}} | |
deny all; | |
access_log off; | |
stub_status on; | |
} | |
{{ end }} | |
{{ end }} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment