2017-04-28 20:41:53 +00:00
{{ $ cfg := .Cfg }}
2017-04-09 18:03:27 +00:00
{{ $ IsIPV6Enabled := .IsIPV6Enabled }}
2017-02-26 22:01:07 +00:00
{{ $ healthzURI := .HealthzURI }}
{{ $ backends := .Backends }}
{{ $ proxyHeaders := .ProxySetHeaders }}
2016-02-22 00:13:08 +00:00
daemon off;
2016-11-16 18:24:26 +00:00
worker_processes {{ $ cfg . WorkerProcesses }};
2016-02-22 00:13:08 +00:00
pid /run/nginx.pid;
2017-01-19 02:31:33 +00:00
{{ if ne .MaxOpenFiles 0 }}
worker_rlimit_nofile {{ .MaxOpenFiles }};
{{ end}}
2016-02-22 00:13:08 +00:00
events {
2016-03-22 18:01:04 +00:00
multi_accept on;
2016-11-16 18:24:26 +00:00
worker_connections {{ $ cfg . MaxWorkerConnections }};
2017-03-03 01:44:45 +00:00
use epoll;
2016-02-22 00:13:08 +00:00
}
http {
2016-06-17 22:26:08 +00:00
{{/* we use the value of the header X-Forwarded-For to be able to use the geo_ip module */}}
2016-11-16 18:24:26 +00:00
{{ if $ cfg . UseProxyProtocol }}
2016-12-12 13:23:45 +00:00
set_real_ip_from {{ $ cfg . ProxyRealIPCIDR }};
2016-07-05 16:37:54 +00:00
real_ip_header proxy_protocol;
{{ else }}
2017-05-12 02:55:35 +00:00
set_real_ip_from {{ $ cfg . ProxyRealIPCIDR }};
2016-06-17 22:26:08 +00:00
real_ip_header X-Forwarded-For;
2016-11-10 22:56:29 +00:00
{{ end }}
2017-03-03 01:44:45 +00:00
2016-06-17 22:26:08 +00:00
real_ip_recursive on;
2016-05-30 18:44:02 +00:00
{{/* 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.dat;
geoip_city /etc/nginx/GeoLiteCity.dat;
2016-06-17 22:26:08 +00:00
geoip_proxy_recursive on;
2016-05-30 18:44:02 +00:00
2016-11-16 18:24:26 +00:00
{{ if $ cfg . EnableVtsStatus }}
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $ cfg . VtsStatusZoneSize }};
2016-05-30 18:44:02 +00:00
vhost_traffic_status_filter_by_set_key $ geoip_country_code country::*;
2016-11-10 22:56:29 +00:00
{{ end }}
2016-02-22 00:13:08 +00:00
2016-06-17 22:26:08 +00:00
# lua section to return proper error codes when custom pages are used
2017-04-11 07:43:33 +00:00
lua_package_path '.?.lua;/etc/nginx/lua/?.lua;/etc/nginx/lua/vendor/lua-resty-http/lib/?.lua;';
2016-09-29 15:02:45 +00:00
init_by_lua_block {
2016-02-22 00:13:08 +00:00
require("error_page")
}
2016-03-22 18:01:04 +00:00
sendfile on;
aio threads;
tcp_nopush on;
tcp_nodelay on;
2017-03-03 01:44:45 +00:00
2016-03-22 18:01:04 +00:00
log_subrequest on;
reset_timedout_connection on;
2016-02-22 00:13:08 +00:00
2017-05-17 06:23:18 +00:00
keepalive_timeout {{ $ cfg . KeepAlive }}s;
keepalive_requests {{ $ cfg . KeepAliveRequests }};
2016-02-22 00:13:08 +00:00
2017-01-20 22:14:59 +00:00
client_header_buffer_size {{ $ cfg . ClientHeaderBufferSize }};
large_client_header_buffers {{ $ cfg . LargeClientHeaderBuffers }};
2017-05-17 06:23:18 +00:00
client_body_buffer_size {{ $ cfg . ClientBodyBufferSize }};
2017-04-28 20:41:53 +00:00
2017-03-10 13:01:26 +00:00
http2_max_field_size {{ $ cfg . HTTP2MaxFieldSize }};
http2_max_header_size {{ $ cfg . HTTP2MaxHeaderSize }};
2017-01-20 22:14:59 +00:00
2016-11-10 22:56:29 +00:00
types_hash_max_size 2048;
2016-11-16 18:24:26 +00:00
server_names_hash_max_size {{ $ cfg . ServerNameHashMaxSize }};
server_names_hash_bucket_size {{ $ cfg . ServerNameHashBucketSize }};
map_hash_bucket_size {{ $ cfg . MapHashBucketSize }};
2016-02-22 00:13:08 +00:00
2017-05-24 04:25:42 +00:00
underscores_in_headers {{ if $ cfg . EnableUnderscoresInHeaders }}on{{ else }}off{{ end }};
ignore_invalid_headers {{ if $ cfg . IgnoreInvalidHeaders }}on{{ else }}off{{ end }};
2017-04-20 21:12:16 +00:00
2016-02-22 00:13:08 +00:00
include /etc/nginx/mime.types;
2016-04-02 20:41:41 +00:00
default_type text/html;
2016-11-16 18:24:26 +00:00
{{ if $ cfg . UseGzip }}
2016-02-22 00:13:08 +00:00
gzip on;
gzip_comp_level 5;
gzip_http_version 1.1;
gzip_min_length 256;
2017-03-03 01:44:45 +00:00
gzip_types {{ $ cfg . GzipTypes }};
2016-02-22 00:13:08 +00:00
gzip_proxied any;
2016-11-10 22:56:29 +00:00
{{ end }}
2016-02-22 00:13:08 +00:00
2017-02-27 10:00:31 +00:00
server_tokens {{ if $ cfg . ShowServerTokens }}on{{ else }}off{{ end }};
2016-02-22 00:13:08 +00:00
2017-05-11 18:04:19 +00:00
# disable warnings
uninitialized_variable_warn off;
2017-03-10 13:01:26 +00:00
log_format upstreaminfo '{{ buildLogFormatUpstream $ cfg }}';
2016-02-22 00:13:08 +00:00
2016-06-18 22:04:07 +00:00
{{/* map urls that should not appear in access.log */}}
{{/* http://nginx.org/en/docs/http/ngx_http_log_module.html #access _log * / } }
2017-02-17 21:21:46 +00:00
map $ request_uri $ loggable {
2016-11-16 18:24:26 +00:00
{{ range $ reqUri := $ cfg . SkipAccessLogURLs }}
2016-06-18 22:04:07 +00:00
{{ $ reqUri }} 0;{{ end }}
default 1;
}
2017-02-09 23:20:12 +00:00
{{ if $ cfg . DisableAccessLog }}
access_log off;
{{ else }}
2016-06-18 22:04:07 +00:00
access_log /var/log/nginx/access.log upstreaminfo if= $ loggable ;
2017-02-09 23:20:12 +00:00
{{ end }}
2016-11-16 18:24:26 +00:00
error_log /var/log/nginx/error.log {{ $ cfg . ErrorLogLevel }};
2016-02-22 00:13:08 +00:00
2016-12-22 03:00:27 +00:00
{{ buildResolvers $ cfg . Resolver }}
2016-02-22 00:13:08 +00:00
2016-09-29 21:42:46 +00:00
{{/* Whenever nginx proxies a request without a "Connection" header, the "Connection" header is set to "close" */}}
{{/* when making the target request. This means that you cannot simply use */}}
{{/* "proxy_set_header Connection $ http_connection " for WebSocket support because in this case, the */}}
{{/* "Connection" header would be set to "" whenever the original request did not have a "Connection" header, */}}
{{/* which would mean no "Connection" header would be in the target request. Since this would deviate from */}}
{{/* normal nginx behavior we have to use this approach. */}}
# Retain the default nginx handling of requests without a "Connection" header
2016-02-22 00:13:08 +00:00
map $ http_upgrade $ connection_upgrade {
2016-11-16 18:24:26 +00:00
default upgrade;
'' close;
2016-02-22 00:13:08 +00:00
}
# trust http_x_forwarded_proto headers correctly indicate ssl offloading
2016-03-26 21:25:51 +00:00
map $ http_x_forwarded_proto $ pass_access_scheme {
2016-11-16 18:24:26 +00:00
default $ http_x_forwarded_proto ;
'' $ scheme ;
2016-02-22 00:13:08 +00:00
}
2016-12-26 13:56:22 +00:00
map $ http_x_forwarded_port $ pass_server_port {
default $ http_x_forwarded_port ;
'' $ server_port ;
}
2017-05-11 18:04:19 +00:00
map $ pass_access_scheme $ the_x_forwarded_for {
default $ remote_addr ;
https $ proxy_protocol_addr ;
}
map $ pass_access_scheme $ the_real_ip {
default $ remote_addr ;
https $ proxy_protocol_addr ;
}
2016-12-26 13:56:22 +00:00
# map port 442 to 443 for header X-Forwarded-Port
map $ pass_server_port $ pass_port {
442 443;
default $ pass_server_port ;
}
2016-02-22 00:13:08 +00:00
# Map a response error watching the header Content-Type
map $ http_accept $ httpAccept {
default html;
application/json json;
application/xml xml;
text/plain text;
}
map $ httpAccept $ httpReturnType {
default text/html;
json application/json;
xml application/xml;
text text/plain;
}
2017-03-16 08:46:29 +00:00
# Obtain best http host
map $ http_host $ best_http_host {
default $ http_host ;
'' $ host ;
}
2016-02-22 00:13:08 +00:00
server_name_in_redirect off;
2016-11-16 18:24:26 +00:00
port_in_redirect off;
2016-02-22 00:13:08 +00:00
2016-11-16 18:24:26 +00:00
ssl_protocols {{ $ cfg . SSLProtocols }};
2016-02-22 00:13:08 +00:00
# turn on session caching to drastically improve performance
2016-11-16 18:24:26 +00:00
{{ if $ cfg . SSLSessionCache }}
ssl_session_cache builtin:1000 shared:SSL:{{ $ cfg . SSLSessionCacheSize }};
ssl_session_timeout {{ $ cfg . SSLSessionTimeout }};
2016-02-22 00:13:08 +00:00
{{ end }}
# allow configuring ssl session tickets
2016-11-16 18:24:26 +00:00
ssl_session_tickets {{ if $ cfg . SSLSessionTickets }}on{{ else }}off{{ end }};
2016-02-22 00:13:08 +00:00
# slightly reduce the time-to-first-byte
2016-11-16 18:24:26 +00:00
ssl_buffer_size {{ $ cfg . SSLBufferSize }};
2016-02-22 00:13:08 +00:00
2016-11-16 18:24:26 +00:00
{{ if not (empty $ cfg . SSLCiphers ) }}
2016-02-22 00:13:08 +00:00
# allow configuring custom ssl ciphers
2016-11-16 18:24:26 +00:00
ssl_ciphers '{{ $ cfg . SSLCiphers }}';
2016-02-22 00:13:08 +00:00
ssl_prefer_server_ciphers on;
{{ end }}
2016-11-16 18:24:26 +00:00
{{ if not (empty $ cfg . SSLDHParam ) }}
2016-02-22 00:13:08 +00:00
# allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html #ssl _dhparam
2016-11-16 18:24:26 +00:00
ssl_dhparam {{ $ cfg . SSLDHParam }};
2016-02-22 00:13:08 +00:00
{{ end }}
2016-11-16 18:24:26 +00:00
{{ if not $ cfg . EnableDynamicTLSRecords }}
2016-06-18 21:03:27 +00:00
ssl_dyn_rec_size_lo 0;
{{ end }}
2017-03-31 02:23:14 +00:00
ssl_ecdh_curve {{ $ cfg . SSLECDHCurve }};
2016-11-16 18:24:26 +00:00
{{ if .CustomErrors }}
2016-03-15 15:31:39 +00:00
# Custom error pages
2016-02-22 00:13:08 +00:00
proxy_intercept_errors on;
2016-06-01 14:39:12 +00:00
{{ end }}
2016-02-22 00:13:08 +00:00
2016-11-16 18:24:26 +00:00
{{ range $ errCode := $ cfg . CustomHTTPErrors }}
2016-06-01 14:39:12 +00:00
error_page {{ $ errCode }} = @custom_{{ $ errCode }};{{ end }}
2016-02-22 00:13:08 +00:00
# In case of errors try the next upstream server before returning an error
2016-11-16 18:24:26 +00:00
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504{{ if $ cfg . RetryNonIdempotent }} non_idempotent{{ end }};
2016-02-22 00:13:08 +00:00
2017-04-25 01:14:38 +00:00
proxy_ssl_session_reuse on;
2016-11-16 18:24:26 +00:00
{{range $ name , $ upstream := $ backends }}
2016-03-15 15:31:39 +00:00
upstream {{ $ upstream . Name }} {
2017-02-12 23:13:39 +00:00
{{ if eq $ upstream . SessionAffinity . AffinityType "cookie" }}
sticky hash={{ $ upstream . SessionAffinity . CookieSessionAffinity . Hash }} name={{ $ upstream . SessionAffinity . CookieSessionAffinity . Name }} httponly;
2016-11-10 22:56:29 +00:00
{{ else }}
2017-04-28 20:41:53 +00:00
# Load balance algorithm; empty for round robin, which is the default
{{ if ne $ cfg . LoadBalanceAlgorithm "round_robin" }}
{{ $ cfg . LoadBalanceAlgorithm }};
{{ end }}
2016-11-10 22:56:29 +00:00
{{ end }}
2016-11-11 23:43:35 +00:00
{{ range $ server := $ upstream . Endpoints }}server {{ $ server . Address }}:{{ $ server . Port }} max_fails={{ $ server . MaxFails }} fail_timeout={{ $ server . FailTimeout }};
2016-04-28 04:03:59 +00:00
{{ end }}
2016-03-15 15:31:39 +00:00
}
2016-05-16 20:29:33 +00:00
{{ end }}
2016-03-15 15:31:39 +00:00
2017-05-20 23:32:03 +00:00
{{/* build the maps that will be use to validate the Whitelist */}}
{{ range $ index , $ server := .Servers }}
{{ range $ location := $ server . Locations }}
{{ $ path := buildLocation $ location }}
{{ if isLocationAllowed $ location }}
{{ if gt (len $ location . Whitelist . CIDR ) 0 }}
geo $ the_real_ip $ deny_ {{ $ server . Hostname }}_{{ $ path }} {
default 1;
{{ range $ ip := $ location . Whitelist . CIDR }}
{{ $ ip }} 0;{{ end }}
}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
2016-05-27 21:03:54 +00:00
{{/* 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 */}}
2016-11-16 18:24:26 +00:00
{{ range $ zone := (buildRateLimitZones .Servers) }}
2016-05-27 21:03:54 +00:00
{{ $ zone }}
{{ end }}
2017-01-19 02:04:00 +00:00
{{ $ backlogSize := .BacklogSize }}
2016-11-28 22:26:09 +00:00
{{ range $ index , $ server := .Servers }}
2016-03-15 02:29:13 +00:00
server {
2016-11-16 18:24:26 +00:00
server_name {{ $ server . Hostname }};
2017-04-09 18:03:27 +00:00
listen 80{{ if $ cfg . UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $ server . Hostname "_"}} default_server reuseport backlog={{ $ backlogSize }}{{end}};
{{ if $ IsIPV6Enabled }}listen [::]:80{{ if $ cfg . UseProxyProtocol }} proxy_protocol{{ end }}{{ if eq $ server . Hostname "_"}} default_server reuseport backlog={{ $ backlogSize }}{{ end }};{{ end }}
2017-05-14 00:59:30 +00:00
set $ proxy_upstream_name "-";
2017-04-09 18:03:27 +00:00
2017-04-09 23:51:38 +00:00
{{/* Listen on 442 because port 443 is used in the TLS sni server */}}
2017-04-28 22:21:47 +00:00
{{/* This listener must always have proxy_protocol enabled, because the SNI listener forwards on source IP info in it. */}}
{{ if not (empty $ server . SSLCertificate ) }}listen 442 proxy_protocol{{ if eq $ server . Hostname "_"}} default_server reuseport backlog={{ $ backlogSize }}{{end}} ssl {{ if $ cfg . UseHTTP2 }}http2{{ end }};
{{ if $ IsIPV6Enabled }}{{ if not (empty $ server . SSLCertificate ) }}listen [::]:442 proxy_protocol{{ end }} {{ if eq $ server . Hostname "_"}} default_server reuseport backlog={{ $ backlogSize }}{{end}} ssl {{ if $ cfg . UseHTTP2 }}http2{{ end }};{{ end }}
2016-05-24 14:02:29 +00:00
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
2016-09-29 15:02:45 +00:00
# PEM sha: {{ $ server . SSLPemChecksum }}
2016-11-10 22:56:29 +00:00
ssl_certificate {{ $ server . SSLCertificate }};
ssl_certificate_key {{ $ server . SSLCertificate }};
{{ end }}
2016-12-22 13:03:58 +00:00
2016-11-16 18:24:26 +00:00
{{ if (and (not (empty $ server . SSLCertificate )) $ cfg . HSTS ) }}
2017-05-04 09:29:32 +00:00
more_set_headers "Strict-Transport-Security: max-age={{ $ cfg . HSTSMaxAge }}{{ if $ cfg . HSTSIncludeSubdomains }}; includeSubDomains{{ end }};{{ if $ cfg . HSTSPreload }} preload{{ end }}";
2016-11-10 22:56:29 +00:00
{{ end }}
2016-04-02 20:41:41 +00:00
2016-11-16 18:24:26 +00:00
{{ if $ cfg . EnableVtsStatus }}vhost_traffic_status_filter_by_set_key $ geoip_country_code country:: $ server_name ;{{ end }}
2016-05-30 18:44:02 +00:00
2016-11-10 22:56:29 +00:00
{{ range $ location := $ server . Locations }}
2016-06-01 14:39:12 +00:00
{{ $ path := buildLocation $ location }}
2016-08-19 14:51:40 +00:00
{{ $ authPath := buildAuthLocation $ location }}
2016-11-10 22:56:29 +00:00
2017-02-06 18:16:36 +00:00
{{ if not (empty $ location . CertificateAuth . AuthSSLCert . CAFileName ) }}
# PEM sha: {{ $ location . CertificateAuth . AuthSSLCert . PemSHA }}
ssl_client_certificate {{ $ location . CertificateAuth . AuthSSLCert . CAFileName }};
2016-11-10 22:56:29 +00:00
ssl_verify_client on;
2017-02-06 18:16:36 +00:00
ssl_verify_depth {{ $ location . CertificateAuth . ValidationDepth }};
2016-11-10 22:56:29 +00:00
{{ end }}
2017-04-28 20:41:53 +00:00
2017-03-13 15:03:47 +00:00
{{ if (or $ location . Redirect . ForceSSLRedirect (and (not (empty $ server . SSLCertificate )) $ location . Redirect . SSLRedirect )) }}
# enforce ssl on server side
if ( $ pass_access_scheme = http) {
2017-03-16 08:46:29 +00:00
return 301 https:// $ best_http_host $ request_uri ;
2017-03-13 15:03:47 +00:00
}
{{ end }}
2016-11-10 22:56:29 +00:00
2017-03-12 22:06:10 +00:00
{{ if not (empty $ location . Redirect . AppRoot )}}
2017-03-13 15:03:47 +00:00
if ( $ uri = /) {
return 302 {{ $ location . Redirect . AppRoot }};
2017-03-12 22:06:10 +00:00
}
{{ end }}
2016-11-10 22:56:29 +00:00
{{ if not (empty $ authPath ) }}
2016-08-19 14:51:40 +00:00
location = {{ $ authPath }} {
internal;
2017-03-12 15:27:05 +00:00
set $ proxy_upstream_name "internal";
2016-11-10 22:56:29 +00:00
{{ if not $ location . ExternalAuth . SendBody }}
2016-08-19 14:51:40 +00:00
proxy_pass_request_body off;
proxy_set_header Content-Length "";
2016-11-10 22:56:29 +00:00
{{ end }}
2017-03-03 01:44:45 +00:00
{{ if not (empty $ location . ExternalAuth . Method ) }}
2017-04-25 01:14:38 +00:00
proxy_method {{ $ location . ExternalAuth . Method }};
proxy_set_header X-Original-URI $ request_uri ;
proxy_set_header X-Scheme $ pass_access_scheme ;
2016-11-10 22:56:29 +00:00
{{ end }}
2016-08-19 14:51:40 +00:00
proxy_pass_request_headers on;
2017-04-25 01:14:38 +00:00
proxy_set_header Host {{ $ location . ExternalAuth . Host }};
2017-04-28 20:41:53 +00:00
proxy_ssl_server_name on;
2017-04-25 01:14:38 +00:00
2016-11-10 22:56:29 +00:00
set $ target {{ $ location . ExternalAuth . URL }};
proxy_pass $ target ;
2016-08-19 14:51:40 +00:00
}
{{ end }}
2017-03-03 01:44:45 +00:00
2016-05-27 14:58:13 +00:00
location {{ $ path }} {
2017-01-26 13:33:29 +00:00
set $ proxy_upstream_name "{{ $ location . Backend }}";
2016-12-29 20:02:06 +00:00
{{ if isLocationAllowed $ location }}
2016-11-10 22:56:29 +00:00
{{ if gt (len $ location . Whitelist . CIDR ) 0 }}
2017-05-20 23:32:03 +00:00
if ( $ deny_ {{ $ server . Hostname }}_{{ $ path }}) {
return 403;
}
2016-11-10 22:56:29 +00:00
{{ end }}
2017-03-03 01:44:45 +00:00
2017-01-20 22:37:59 +00:00
port_in_redirect {{ if $ location . UsePortInRedirects }}on{{ else }}off{{ end }};
2016-11-10 22:56:29 +00:00
{{ if not (empty $ authPath ) }}
2016-08-19 14:51:40 +00:00
# this location requires authentication
auth_request {{ $ authPath }};
2017-02-04 00:43:15 +00:00
{{- range $ idx , $ line := buildAuthResponseHeaders $ location }}
{{ $ line }}
{{- end }}
2016-11-10 22:56:29 +00:00
{{ end }}
2017-03-03 01:44:45 +00:00
2017-03-10 13:01:26 +00:00
{{ if not (empty $ location . ExternalAuth . SigninURL ) }}
error_page 401 = {{ $ location . ExternalAuth . SigninURL }};
{{ end }}
2017-03-13 15:03:47 +00:00
2016-05-30 17:39:10 +00:00
{{/* if the location contains a rate limit annotation, create one */}}
{{ $ limits := buildRateLimit $ location }}
2016-11-10 22:56:29 +00:00
{{ range $ limit := $ limits }}
2016-05-30 17:39:10 +00:00
{{ $ limit }}{{ end }}
2017-03-03 01:44:45 +00:00
2016-11-10 22:56:29 +00:00
{{ if $ location . BasicDigestAuth . Secured }}
{{ if eq $ location . BasicDigestAuth . Type "basic" }}
auth_basic "{{ $ location . BasicDigestAuth . Realm }}";
auth_basic_user_file {{ $ location . BasicDigestAuth . File }};
2016-05-31 16:22:04 +00:00
{{ else }}
2016-11-10 22:56:29 +00:00
auth_digest "{{ $ location . BasicDigestAuth . Realm }}";
auth_digest_user_file {{ $ location . BasicDigestAuth . File }};
{{ end }}
2016-07-18 02:02:02 +00:00
proxy_set_header Authorization "";
2016-11-10 22:56:29 +00:00
{{ end }}
2017-03-03 01:44:45 +00:00
2016-11-10 22:56:29 +00:00
{{ if $ location . EnableCORS }}
2016-09-22 18:00:09 +00:00
{{ template "CORS" }}
2016-11-10 22:56:29 +00:00
{{ end }}
2016-12-22 13:03:58 +00:00
2017-01-20 21:53:32 +00:00
client_max_body_size "{{ $ location . Proxy . BodySize }}";
2017-03-16 08:46:29 +00:00
proxy_set_header Host $ best_http_host ;
2016-03-22 18:01:04 +00:00
2017-02-06 18:16:36 +00:00
# Pass the extracted client certificate to the backend
{{ if not (empty $ location . CertificateAuth . AuthSSLCert . CAFileName ) }}
proxy_set_header ssl-client-cert $ ssl_client_cert ;
{{ end }}
2016-03-22 18:01:04 +00:00
# Pass Real IP
2017-05-20 23:32:03 +00:00
proxy_set_header X-Real-IP $ the_real_ip ;
2016-03-22 18:01:04 +00:00
# Allow websocket connections
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection $ connection_upgrade ;
2017-05-11 18:04:19 +00:00
proxy_set_header X-Real-IP $ the_real_ip ;
proxy_set_header X-Forwarded-For $ the_x_forwarded_for ;
2017-03-16 08:46:29 +00:00
proxy_set_header X-Forwarded-Host $ best_http_host ;
2016-12-22 13:03:58 +00:00
proxy_set_header X-Forwarded-Port $ pass_port ;
2016-03-26 21:25:51 +00:00
proxy_set_header X-Forwarded-Proto $ pass_access_scheme ;
2017-03-10 13:01:26 +00:00
proxy_set_header X-Original-URI $ request_uri ;
proxy_set_header X-Scheme $ pass_access_scheme ;
2016-03-22 18:01:04 +00:00
2016-07-20 13:55:46 +00:00
# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
2017-02-07 18:13:08 +00:00
# Custom headers
{{ range $k, $v := $ proxyHeaders }}
proxy_set_header {{ $k }} "{{ $v }}";
{{ end }}
2016-11-10 22:56:29 +00:00
proxy_connect_timeout {{ $ location . Proxy . ConnectTimeout }}s;
proxy_send_timeout {{ $ location . Proxy . SendTimeout }}s;
proxy_read_timeout {{ $ location . Proxy . ReadTimeout }}s;
2016-03-22 18:01:04 +00:00
proxy_redirect off;
proxy_buffering off;
2016-11-10 22:56:29 +00:00
proxy_buffer_size "{{ $ location . Proxy . BufferSize }}";
2017-03-10 13:01:26 +00:00
proxy_buffers 4 "{{ $ location . Proxy . BufferSize }}";
2016-03-22 18:01:04 +00:00
proxy_http_version 1.1;
2017-02-24 21:46:39 +00:00
proxy_cookie_domain {{ $ location . Proxy . CookieDomain }};
proxy_cookie_path {{ $ location . Proxy . CookiePath }};
2016-12-27 09:52:04 +00:00
2016-05-27 14:58:13 +00:00
{{/* rewrite only works if the content is not compressed */}}
2016-11-10 22:56:29 +00:00
{{ if $ location . Redirect . AddBaseURL }}
2016-05-27 14:58:13 +00:00
proxy_set_header Accept-Encoding "";
2016-11-10 22:56:29 +00:00
{{ end }}
2016-05-27 14:58:13 +00:00
2017-02-23 18:10:32 +00:00
{{/* Add any additional configuration defined */}}
{{ $ location . ConfigurationSnippet }}
2016-11-16 18:24:26 +00:00
{{ buildProxyPass $ backends $ location }}
2016-12-29 20:02:06 +00:00
{{ else }}
#{{ $ location . Denied }}
return 503;
{{ end }}
2016-03-15 15:31:39 +00:00
}
{{ end }}
2017-03-03 01:44:45 +00:00
2016-11-16 18:24:26 +00:00
{{ if eq $ server . Hostname "_" }}
2016-09-16 21:23:52 +00:00
# health checks in cloud providers require the use of port 80
2016-11-16 18:24:26 +00:00
location {{ $ healthzURI }} {
2016-09-16 21:23:52 +00:00
access_log off;
return 200;
}
2016-04-05 18:15:59 +00:00
# this is required to avoid error if nginx is being monitored
# with an external software (like sysdig)
location /nginx_status {
allow 127.0.0.1;
2017-04-09 18:03:27 +00:00
{{ if $ IsIPV6Enabled }}allow ::1;{{ end }}
2016-04-05 18:15:59 +00:00
deny all;
access_log off;
stub_status on;
}
2016-11-10 22:56:29 +00:00
{{ end }}
2016-11-16 18:24:26 +00:00
2016-03-19 20:17:58 +00:00
{{ template "CUSTOM_ERRORS" $ cfg }}
2016-03-15 15:31:39 +00:00
}
2017-03-03 01:44:45 +00:00
2016-03-15 15:31:39 +00:00
{{ end }}
2017-03-03 01:44:45 +00:00
2016-07-21 15:40:47 +00:00
# default server, used for NGINX healthcheck and access to nginx stats
2016-02-22 00:13:08 +00:00
server {
2016-07-21 15:40:47 +00:00
# Use the port 18080 (random value just to avoid known ports) as default port for nginx.
# Changing this value requires a change in:
# https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/nginx/command.go #L 104
2017-04-09 18:03:27 +00:00
listen 18080 default_server reuseport backlog={{ .BacklogSize }};
{{ if $ IsIPV6Enabled }}listen [::]:18080 default_server reuseport backlog={{ .BacklogSize }};{{ end }}
2017-05-14 00:59:30 +00:00
set $ proxy_upstream_name "-";
2016-02-22 00:13:08 +00:00
2016-11-16 18:24:26 +00:00
location {{ $ healthzURI }} {
2016-02-22 00:13:08 +00:00
access_log off;
return 200;
}
2017-03-03 01:44:45 +00:00
2016-03-26 21:25:51 +00:00
location /nginx_status {
2017-03-12 15:27:05 +00:00
set $ proxy_upstream_name "internal";
2016-11-16 18:24:26 +00:00
{{ if $ cfg . EnableVtsStatus }}
2016-03-26 21:25:51 +00:00
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
{{ else }}
2016-03-22 18:01:04 +00:00
access_log off;
2016-02-22 00:13:08 +00:00
stub_status on;
2016-11-10 22:56:29 +00:00
{{ end }}
2016-02-22 00:13:08 +00:00
}
2016-11-29 01:39:17 +00:00
# this location is used to extract nginx metrics
# using prometheus.
# TODO: enable extraction for vts module.
location /internal_nginx_status {
2017-03-12 15:27:05 +00:00
set $ proxy_upstream_name "internal";
2016-11-29 01:39:17 +00:00
allow 127.0.0.1;
2017-03-10 13:01:26 +00:00
{{ if not $ cfg . DisableIpv6 }}allow ::1;{{ end }}
2016-11-29 01:39:17 +00:00
deny all;
access_log off;
stub_status on;
}
2016-02-22 00:13:08 +00:00
location / {
2016-09-29 15:02:45 +00:00
set $ proxy_upstream_name "upstream-default-backend";
2016-03-19 20:17:58 +00:00
proxy_pass http://upstream-default-backend;
2016-02-22 00:13:08 +00:00
}
2016-11-10 22:56:29 +00:00
{{ template "CUSTOM_ERRORS" $ cfg }}
2016-02-22 00:13:08 +00:00
}
2016-03-16 14:12:45 +00:00
# default server for services without endpoints
server {
2016-03-19 23:29:29 +00:00
listen 8181;
2016-09-29 15:02:45 +00:00
set $ proxy_upstream_name "-";
2016-03-16 14:12:45 +00:00
location / {
2016-11-16 18:24:26 +00:00
{{ if .CustomErrors }}
2016-03-16 14:12:45 +00:00
content_by_lua_block {
2017-02-14 17:24:25 +00:00
openURL(ngx.req.get_headers(0), 503)
2016-03-16 14:12:45 +00:00
}
2016-05-23 23:15:13 +00:00
{{ else }}
return 503;
{{ end }}
2016-09-29 15:02:45 +00:00
}
2016-09-29 19:01:09 +00:00
}
2016-02-22 00:13:08 +00:00
}
stream {
2017-02-27 10:00:31 +00:00
log_format log_stream {{ $ cfg . LogFormatStream }};
2016-11-10 22:56:29 +00:00
2017-02-09 23:20:12 +00:00
{{ if $ cfg . DisableAccessLog }}
access_log off;
{{ else }}
2016-11-10 22:56:29 +00:00
access_log /var/log/nginx/access.log log_stream;
2017-02-09 23:20:12 +00:00
{{ end }}
2016-11-10 22:56:29 +00:00
error_log /var/log/nginx/error.log;
2017-03-03 01:44:45 +00:00
# TCP services
2017-01-09 00:31:16 +00:00
{{ range $i, $ tcpServer := .TCPBackends }}
2017-03-15 17:45:21 +00:00
upstream tcp-{{ $ tcpServer . Backend . Namespace }}-{{ $ tcpServer . Backend . Name }}-{{ $ tcpServer . Backend . Port }} {
2017-02-24 21:46:39 +00:00
{{ range $j, $ endpoint := $ tcpServer . Endpoints }}
server {{ $ endpoint . Address }}:{{ $ endpoint . Port }};
{{ end }}
}
2017-03-03 01:44:45 +00:00
2017-02-24 21:46:39 +00:00
server {
listen {{ $ tcpServer . Port }};
2017-05-26 16:19:54 +00:00
{{ if $ IsIPV6Enabled }}listen [::]:{{ $ tcpServer . Port }}{{ end }}
2017-03-15 17:45:21 +00:00
proxy_pass tcp-{{ $ tcpServer . Backend . Namespace }}-{{ $ tcpServer . Backend . Name }}-{{ $ tcpServer . Backend . Port }};
2017-02-24 21:46:39 +00:00
}
2017-01-09 00:31:16 +00:00
{{ end }}
2016-11-10 22:56:29 +00:00
2017-02-24 21:46:39 +00:00
# UDP services
{{ range $i, $ udpServer := .UDPBackends }}
2017-03-15 17:45:21 +00:00
upstream udp-{{ $ udpServer . Backend . Namespace }}-{{ $ udpServer . Backend . Name }}-{{ $ udpServer . Backend . Port }} {
2017-02-24 21:46:39 +00:00
{{ range $j, $ endpoint := $ udpServer . Endpoints }}
server {{ $ endpoint . Address }}:{{ $ endpoint . Port }};
{{ end }}
}
2017-03-03 01:44:45 +00:00
2017-02-24 21:46:39 +00:00
server {
2017-03-15 17:45:21 +00:00
listen {{ $ udpServer . Port }} udp;
2017-05-26 16:19:54 +00:00
{{ if $ IsIPV6Enabled }}listen [::]:{{ $ udpServer . Port }}{{ end }}
2017-02-24 21:46:39 +00:00
proxy_responses 1;
2017-03-15 17:45:21 +00:00
proxy_pass udp-{{ $ udpServer . Backend . Namespace }}-{{ $ udpServer . Backend . Name }}-{{ $ udpServer . Backend . Port }};
2017-02-24 21:46:39 +00:00
}
2017-01-09 00:31:16 +00:00
{{ end }}
2016-02-22 00:13:08 +00:00
}
{{/* definition of templates to avoid repetitions */}}
{{ define "CUSTOM_ERRORS" }}
2016-11-16 18:24:26 +00:00
{{ range $ errCode := .CustomHTTPErrors }}
2016-05-23 23:15:13 +00:00
location @custom_{{ $ errCode }} {
2016-03-22 18:01:04 +00:00
internal;
2016-02-22 00:13:08 +00:00
content_by_lua_block {
2017-02-14 17:24:25 +00:00
openURL(ngx.req.get_headers(0), {{ $ errCode }})
2016-02-22 00:13:08 +00:00
}
2017-03-03 01:44:45 +00:00
}
2016-05-23 23:15:13 +00:00
{{ end }}
2016-02-22 00:13:08 +00:00
{{ end }}
2016-09-22 18:00:09 +00:00
{{/* CORS support from https://michielkalkman.com/snippets/nginx-cors-open-configuration.html */}}
{{ define "CORS" }}
if ( $ request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
2017-03-23 15:07:09 +00:00
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS';
2016-09-22 18:00:09 +00:00
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
2017-03-23 15:07:51 +00:00
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
2016-09-22 18:00:09 +00:00
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
2017-03-23 15:07:09 +00:00
set $ cors_method 0;
if ( $ request_method = 'GET') {
set $ cors_method 1;
}
if ( $ request_method = 'PUT') {
set $ cors_method 1;
}
2016-09-22 18:00:09 +00:00
if ( $ request_method = 'POST') {
2017-03-23 15:07:09 +00:00
set $ cors_method 1;
2016-09-22 18:00:09 +00:00
}
2017-03-23 15:07:09 +00:00
if ( $ request_method = 'DELETE') {
set $ cors_method 1;
}
if ( $ cors_method = 1) {
add_header 'Access-Control-Allow-Origin' '*' always;
2016-09-22 18:00:09 +00:00
add_header 'Access-Control-Allow-Credentials' 'true';
2017-03-23 15:07:09 +00:00
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS';
2017-03-23 15:07:51 +00:00
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
2016-09-22 18:00:09 +00:00
}
{{ end }}