<p>I'm trying to get <code>https</code> working on express.js for node inside K8s deployment, but I can't figure out how.</p>
<p>The express app should work like this:</p>
<ol>
<li>When you access the <code>/healthz</code> endpoint, return <code>200</code> (both <code>http</code> &amp; <code>https</code> requests)</li>
<li>Redirect any other <code>http</code> trafic to <code>https</code></li>
</ol>
<p>The problem I'm facing is that the app is then listening on two different ports (<code>8080</code> and <code>8443</code>), but the K8s Ingress points to only single port - I was thinking about maybe solving this problem with Nginx as a reverse proxy, but than, how would I &quot;link&quot; the two containers together?</p>
<p>This is my <code>app.ts</code>:</p>
<pre class="lang-js prettyprint-override"><code>import express from &quot;express&quot;
import { createServer as httpServer } from &quot;http&quot;
import { createServer as httpsServer } from &quot;https&quot;
import { readFileSync } from &quot;fs&quot;

const app = express()

const options = {
  key: readFileSync(`${__dirname}/cert/[company].key`),
  cert: readFileSync(`${__dirname}/cert/[company].crt`),
}

app.use(&quot;/healthz&quot;, (req, res) =&gt; {
  res.status(200).send(&quot;healthy&quot;)
})
app.use(&quot;*&quot;, (req, res) =&gt; {
  if (!req.secure) {
    return res.redirect([&quot;https://&quot;, req.get(&quot;Host&quot;), req.baseUrl].join(&quot;&quot;));
  }
})
app.get(&quot;/&quot;, (req, res) =&gt; {
  res.status(200).send(&quot;Hello from Express!&quot;)
})

httpServer(app).listen(8080)
httpsServer(options, app).listen(8443)
</code></pre>
<p>Here's the <code>Dockerfile</code>:</p>
<pre class="lang-sh prettyprint-override"><code>FROM node:14.4.0-alpine
...
EXPOSE 8080 8443
CMD [ &quot;yarn&quot;, &quot;start&quot; ]
</code></pre>
<p>Here's the <code>Ingress.yaml</code>:</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: networking.k8s.io/v1beta1
kind: Ingress
...
spec:
  tls:
    - secretName: [secret-name]
  rules:
    - host: [company]
      http:
        paths:
          - backend:
              serviceName: [service-name]
              servicePort: 8080
</code></pre>
<p>Could you please point me the right direction, how to approach/solve this problem?</p>

<h2>Answer</h2>
<p>On Kubernetes, your Node.js server does not need to handle TLS. The canonical approach is to use Ingress for <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/#tls" rel="nofollow noreferrer">TLS termination</a>. This is because your Node.js server can sit behind a ClusterIP Service and only be accessible from outside of the cluster through the Ingress Controller Service.</p>
<p>Assuming your TLS secret is valid, and your Ingress Controller is set up correctly (e.g. nginx), the YAML you have linked should work.</p>
<p>Make sure that the Service defined in the Ingress backend is of type ClusterIP, because it need only be accessed by the Ingress Controller Pod(s).</p>
<p>You would need to update your Node.js server to serve HTTP on a single port (e.g. 8080) for all of your endpoints.</p>
<p>If you wish <code>/healthz</code> to allow HTTP traffic, then you will need to create a second Ingress resource without TLS:</p>
<pre><code>apiVersion: networking.k8s.io/v1beta1
kind: Ingress
...
spec:
  rules:
  - http:
      paths:
      - path: /healthz
        pathType: Prefix
        backend:
          serviceName: [service]
          servicePort: 8080
</code></pre>
<h2>More Info</h2>
<p>Regarding your question about &quot;linking&quot; the nginx Ingress Controller with your Node.js app - the Ingress Controller would point to the ClusterIP Service specified in the Ingress resources' <code>backend</code> fields.</p>
<p>Remember to deploy your Ingress resources in the same Namespaces as the Services they point to for simplicity. Otherwise, you would have to make a Service of type ExternalName in the Ingress resource's Namespace which points to the Service in the other Namespace. See <a href="https://stackoverflow.com/questions/59844622/ingress-configuration-for-k8s-in-different-namespaces">here</a>.</p>
<p>Your Ingress Controller can be in any Namespace, assuming it is configured to watch all Namespaces for Ingress resources.</p>
