<p>I have an Nginx ingress controller set up on my kubernetes cluster, which by default does an https redirect for any requests that it receives, so <code>http://example.com</code> is automatically forwarded on to <code>https://example.com</code>.</p>

<p>I now have a host that I need to serve over http and not https, essentially excluding it from the ssl redirect. What I have found is that I can disable the ssl redirect across the whole ingress, but not for a specific host. </p>

<p>My Ingress yaml:</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
   name: ingress
annotations:
    kubernetes.io/ingress.class: nginx
spec:
  tls:
  - hosts:
    - mysslsite.co.uk
secretName: tls-secret

rules:
 - host: my-ssl-site.co.uk
   http:
    paths:
    - path: /
      backend:
        serviceName: my-service
        servicePort: 80
 - host: my-non-ssl-site.co.uk
   http:
      paths:
      - path: /
        backend:
          serviceName: my-other-service
          servicePort: 80
</code></pre>

<p>My Config Map:</p>

<pre><code>apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    app: nginx-ingress
    chart: nginx-ingress-0.28.3
    component: controller
    heritage: Tiller
    release: nginx-ingress
  name: undercooked-moth-nginx-ingress-controller
  namespace: default
data:
  proxy-buffer-size: "512k"
  client-header-buffer-size: "512k"
  proxy-body-size: "100m"
  large-client-header-buffers: "4 512k"
  http2-max-field-size: "512k"
  http2-max-header-size: "512k"
  fastcgi_buffers: "16 16k" 
  fastcgi_buffer_size: "32k"
</code></pre>

<p>What I have tried:</p>

<ol>
<li><p>Attempt to turn off ssl redirect across the board and set a rule to redirect to the site requiring ssl to https by setting the annotation <code>nginx.ingress.kubernetes.io/ssl-redirect: "false"</code> and adding the following config snippet:</p>

<pre><code>nginx.ingress.kubernetes.io/configuration-snippet: |
      if ($host = 'my-ssl-site.co.uk' ) {
        rewrite ^ https://my-ssl-site.co.uk$request_uri permanent;
      }
</code></pre>

<p>This does remove the https redirect but results in a <code>too many redirects</code> error for the site requiring ssl.</p></li>
<li><p>Attempted to add rules in the ConfigMap as per <a href="https://stackoverflow.com/a/49857465/1005609">this answer</a> to turn off ssl redirect and handle the conditional redirect in a server config snippet but this still resulted in an ssl redirect.</p></li>
<li><p>Tried to add a second ingress controller so that one could have ssl redirect enabled and the other one could have it turned off. I created the controller but I think I also need to create a second nginx ingress and configure and label the apps that will be returned to each? This seems like overkill when all I want to do is exclude one service on the cluster from the ssl redirect.</p></li>
</ol>

<p>Is there anything obvious I am missing? It feels as though it shouldn't be this hard to add a simple rule to exclude one host from the ssl-redirect.</p>

<p>You can create two Ingress objects, one for each site in the same namespace.</p>

<p>Use annotation <code>nginx.ingress.kubernetes.io/ssl-redirect: "true"</code> for SSL site</p>

<p>Use annotation <code>nginx.ingress.kubernetes.io/ssl-redirect: "false"</code> for Non-SSL site</p>

<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
   name: cmac-ingress
   namespace: ns1
   annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  tls:
  - hosts:
    - my-ssl-site.co.uk
    secretName: testsecret-tls
  rules:
  - host: my-ssl-site.co.uk
    http:
      paths:
      - path: /
        backend: 
          serviceName: my-service
          servicePort: 80
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
   name: cmac-ingress1
   namespace: ns1
   annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  tls:
  - hosts:
    - my-site.co.uk
    secretName: testsecret-tls
  rules:
  - host: my-site.co.uk
    http:
      paths:
      - path: /
        backend: 
          serviceName: my-service
          servicePort: 80
</code></pre>

<p>Here is the result from ingress-controller <code>nginx.conf</code> file:</p>

<pre><code>    ## start server my-site.co.uk
    server {
            server_name my-site.co.uk ;

            listen 80;

            set $proxy_upstream_name "-";

            listen 443  ssl http2;

            # PEM sha: ffa288482443e529d72a0984724f79d5267a2a22
            ssl_certificate                         /etc/ingress-controller/ssl/default-fake-certificate.pem;
            ssl_certificate_key                     /etc/ingress-controller/ssl/default-fake-certificate.pem;

            location / {

                    &lt;some lines skipped&gt;

                    if ($scheme = https) {
                            more_set_headers                        "Strict-Transport-Security: max-age=15724800; includeSubDomains";
                    }

                    &lt;some lines skipped&gt;

            }

    }       
    ## end server my-site.co.uk

    ## start server my-ssl-site.co.uk
    server {
            server_name my-ssl-site.co.uk ;

            listen 80;

            set $proxy_upstream_name "-";

            listen 443  ssl http2;

            # PEM sha: ffa288482443e529d72a0984724f79d5267a2a22
            ssl_certificate                         /etc/ingress-controller/ssl/default-fake-certificate.pem;
            ssl_certificate_key                     /etc/ingress-controller/ssl/default-fake-certificate.pem;

            location / {


                    &lt;some lines skipped&gt;

                    if ($scheme = https) {
                            more_set_headers                        "Strict-Transport-Security: max-age=15724800; includeSubDomains";
                    }

                    # enforce ssl on server side
                    if ($redirect_to_https) {

                            return 308 https://$best_http_host$request_uri;

                    }

                    &lt;some lines skipped&gt;

            }

    }    
    ## end server my-ssl-site.co.uk
</code></pre>

<p>You can find additional redirection section in the SSL-enforced site definition:</p>

<pre><code># enforce ssl on server side
if ($redirect_to_https) {

        return 308 https://$best_http_host$request_uri;

}
</code></pre>
