# required to run in a container
daemon off;

user www-data;
worker_processes {{ or (.deis_router_workerProcesses) "auto" }};
pid /run/nginx.pid;

events {
    worker_connections {{ or (.deis_router_maxWorkerConnections) "768" }};
    # multi_accept on;
}

http {
    # basic settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    # The Timeout value must be greater than the front facing load balancers timeout value.
    # Default is the deis recommended timeout value for ELB - 1200 seconds + 100s extra.
    {{ $defaultTimeout := or (.deis_router_defaultTimeout) "1300" }}
    keepalive_timeout {{ $defaultTimeout }};

    types_hash_max_size 2048;
    server_names_hash_max_size {{ or (.deis_router_serverNameHashMaxSize) "512" }};
    server_names_hash_bucket_size {{ or (.deis_router_serverNameHashBucketSize) "64" }};

    include /opt/nginx/conf/mime.types;
    default_type application/octet-stream;
    {{ if .deis_router_gzip }}
    gzip {{ .deis_router_gzip }};
    gzip_comp_level {{ or .deis_router_gzipCompLevel "5" }};
    gzip_disable {{ or .deis_router_gzipDisable "\"msie6\"" }};
    gzip_http_version {{ or .deis_router_gzipHttpVersion "1.1" }};
    gzip_min_length {{ or .deis_router_gzipMinLength "256" }};
    gzip_types {{ or .deis_router_gzipTypes "application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component" }};
    gzip_proxied {{ or .deis_router_gzipProxied "any" }};
    gzip_vary {{ or .deis_router_gzipVary "on" }};
    {{ end }}

    {{ $useFirewall := or .deis_router_firewall_enabled "false" }}{{ if eq $useFirewall "true" }}# include naxsi rules
    include     /opt/nginx/firewall/naxsi_core.rules;
    include     /opt/nginx/firewall/web_apps.rules;
    include     /opt/nginx/firewall/scanner.rules;
    include     /opt/nginx/firewall/web_server.rules;{{ end }}
    {{ $firewallErrorCode := or (.deis_router_firewall_errorCode) "400" }}

    client_max_body_size {{ or (.deis_router_bodySize) "1m" }};

    log_format upstreaminfo '[$time_local] - $remote_addr - $remote_user - $status - "$request" - $bytes_sent - "$http_referer" - "$http_user_agent" - "$server_name" - $upstream_addr - $http_host - $upstream_response_time - $request_time';

    # send logs to STDOUT so they can be seen using 'docker logs'
    access_log /opt/nginx/logs/access.log upstreaminfo;
    error_log  /opt/nginx/logs/error.log {{ or (.deis_router_errorLogLevel) "error" }};

    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    # trust http_x_forwarded_proto headers correctly indicate ssl offloading
    map $http_x_forwarded_proto $access_scheme {
      default $http_x_forwarded_proto;
      ''      $scheme;
    }

    {{ $enforceHTTPS := or .deis_router_enforceHTTPS "false" }}

    ## start deis-controller
    {{ if .deis_controller_host }}
    upstream deis-controller {
        server {{ .deis_controller_host }}:{{ .deis_controller_port }};
    }
    {{ end }}

    server {
        server_name ~^deis\.(?<domain>.+)$;
        include deis.conf;

        {{ if .deis_controller_host }}
        location / {
            {{ if eq $useFirewall "true" }}include                     /opt/nginx/firewall/active-mode.rules;{{ end }}
            proxy_buffering             off;
            proxy_set_header            Host $host;
            proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect              off;
            proxy_connect_timeout       {{ or (.deis_router_controller_timeout_connect) "10s" }};
            proxy_send_timeout          {{ or (.deis_router_controller_timeout_send) "20m" }};
            proxy_read_timeout          {{ or (.deis_router_controller_timeout_read) "20m" }};

            proxy_pass                  http://deis-controller;
        }
        {{ else }}
        location / {
            return 503;
        }
        {{ end }}

        {{ if eq $useFirewall "true" }}location /RequestDenied {
            return {{ $firewallErrorCode }};
        }{{ end }}

        {{ if eq $enforceHTTPS "true" }}
        if ($access_scheme != "https") {
          return 301 https://$host$request_uri;
        }
        {{ end }}
    }
    ## end deis-controller

    ## start deis-store-gateway
    {{ if .deis_store_gateway_host }}
    upstream deis-store-gateway {
        server {{ .deis_store_gateway_host }}:{{ .deis_store_gateway_port }};
    }
    {{ end }}

    server {
        server_name ~^deis-store\.(?<domain>.+)$;
        include deis.conf;

        client_max_body_size            0;

        {{ if .deis_store_gateway_host }}
        location / {
            {{ if eq $useFirewall "true" }}include                     /opt/nginx/firewall/active-mode.rules;{{ end }}
            proxy_buffering             off;
            proxy_set_header            Host $host;
            proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_redirect              off;
            proxy_connect_timeout       10s;
            proxy_send_timeout          {{ $defaultTimeout }}s;
            proxy_read_timeout          {{ $defaultTimeout }}s;

            proxy_pass                  http://deis-store-gateway;
        }
        {{ else }}
        location / {
            return 503;
        }
        {{ end }}
    }
    ## end deis-store-gateway

    ## start service definitions for each application
    {{ $affinityArg := .deis_router_affinityArg }}
    {{ $certs := .deis_certs }}
    {{ $domains := .deis_domains }}
    {{ $root := . }}
    {{ range $service := .deis_services }}{{ if $service.Nodes }}
    upstream {{ Base $service.Key }} {
        {{ if $affinityArg }}hash $arg_{{ $affinityArg }} consistent;
        {{ end }}
        {{ range $upstream := $service.Nodes }}server {{ $upstream.Value }};
        {{ end }}
    }
    {{ end }}

    ## server entries for custom domains
    {{ range $domain := $domains }}{{ if eq (Base $service.Key) $domain.Value }}
    server {
        server_name {{ Base $domain.Key }};
        {{/* if a SSL certificate is installed for this domain, use SSL */}}
        {{/* NOTE (bacongobbler): domains are separate from the default platform domain, */}}
        {{/* so we can't rely on deis.conf as each domain is an island */}}
        {{/* FIXME (bacongobbler): confd turns hyphens to dashes, so we need to account */}}
        {{/* for that in domains */}}
        {{ if index $root (printf "deis_certs_%s_cert" (Replace (Base $domain.Key) "-" "_" -1)) }}
        server_name_in_redirect off;
        port_in_redirect off;
        listen 80;
        listen 443 ssl spdy;
        ssl_certificate /etc/ssl/deis/certs/{{ Base $domain.Key }}.cert;
        ssl_certificate_key /etc/ssl/deis/keys/{{ Base $domain.Key }}.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        {{/* if there's no app SSL cert but we have a router SSL cert, enable that instead */}}
        {{/* TODO (bacongobbler): wait for https://github.com/kelseyhightower/confd/issues/270 */}}
        {{/* so we can apply this config to just subdomains of the platform domain. */}}
        {{/* ref: https://github.com/deis/deis/pull/3519 */}}
        {{ else }}
        include deis.conf;
        {{ end }}

        {{ if $service.Nodes }}
        location / {
            {{ if eq $useFirewall "true" }}include                     /opt/nginx/firewall/active-mode.rules;{{ end }}
            proxy_buffering             off;
            proxy_set_header            Host $host;
            set $access_ssl 'off';
            set $access_port '80';
            if ($access_scheme ~ https) {
                set $access_ssl 'on';
                set $access_port '443';
            }
            proxy_set_header            X-Forwarded-Port  $access_port;
            proxy_set_header            X-Forwarded-Proto $access_scheme;
            proxy_set_header            X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header            X-Forwarded-Ssl   $access_ssl;
            proxy_redirect              off;
            proxy_connect_timeout       30s;
            proxy_send_timeout          {{ $defaultTimeout }}s;
            proxy_read_timeout          {{ $defaultTimeout }}s;
            proxy_http_version          1.1;
            proxy_set_header            Upgrade           $http_upgrade;
            proxy_set_header            Connection        $connection_upgrade;

            proxy_next_upstream         error timeout http_502 http_503 http_504;

            {{ if eq $enforceHTTPS "true" }}
            if ($access_scheme != "https") {
              return 301 https://$host$request_uri;
            }
            {{ end }}

            proxy_pass                  http://{{ Base $service.Key }};
        }
        {{ else }}
        location / {
            return 503;
        }
        {{ end }}

        {{ if eq $useFirewall "true" }}location /RequestDenied {
            return {{ $firewallErrorCode }};
        }{{ end }}
    }
    {{ end }}{{ end }}
    ## end entries for custom domains

    server {
        server_name ~^{{ Base $service.Key }}\.(?<domain>.+)$;
        include deis.conf;

        {{ if $service.Nodes }}
        location / {
            {{ if eq $useFirewall "true" }}include                     /opt/nginx/firewall/active-mode.rules;{{ end }}
            proxy_buffering             off;
            proxy_set_header            Host $host;
            set $access_ssl 'off';
            set $access_port '80';
            if ($access_scheme ~ https) {
                set $access_ssl 'on';
                set $access_port '443';
            }
            proxy_set_header            X-Forwarded-Port  $access_port;
            proxy_set_header            X-Forwarded-Proto $access_scheme;
            proxy_set_header            X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header            X-Forwarded-Ssl   $access_ssl;
            proxy_redirect              off;
            proxy_connect_timeout       30s;
            proxy_send_timeout          {{ $defaultTimeout }}s;
            proxy_read_timeout          {{ $defaultTimeout }}s;
            proxy_http_version          1.1;
            proxy_set_header            Upgrade           $http_upgrade;
            proxy_set_header            Connection        $connection_upgrade;

            proxy_next_upstream         error timeout http_502 http_503 http_504;

            {{ if eq $enforceHTTPS "true" }}
            if ($access_scheme != "https") {
              return 301 https://$host$request_uri;
            }
            {{ end }}

            proxy_pass                  http://{{ Base $service.Key }};
        }
        {{ else }}
        location / {
            return 503;
        }
        {{ end }}
        {{ if eq $useFirewall "true" }}location /RequestDenied {
            return {{ $firewallErrorCode }};
        }{{ end }}
    }
    {{ end }}
    ## end service definitions for each application

    # healthcheck
    server {
        listen 80 default_server;
        location /health-check {
            default_type 'text/plain';
            access_log off;
            return 200;
        }
        location /router-nginx-status {
            stub_status on;
        }
    }
}

## start builder
{{ if .deis_builder_host }}
tcp {
    access_log /opt/nginx/logs/git.log;
    tcp_nodelay on;
    timeout {{ or (.deis_router_builder_timeout_tcp) "1200000" }};

    # same directive names, but these are in miliseconds...
    proxy_connect_timeout       {{ or (.deis_router_builder_timeout_connect) "10000" }};
    proxy_send_timeout          {{ or (.deis_router_builder_timeout_send) "1200000" }};
    proxy_read_timeout          {{ or (.deis_router_builder_timeout_read) "1200000" }};

    upstream builder {
        server {{ .deis_builder_host }}:{{ .deis_builder_port }};
    }

    server {
        listen 2222;
        proxy_pass builder;
    }
}{{ end }}
## end builder
