Question

HTTPS with Express and NGINX

Hi! First time user of DigitalOcean, and really beginner at setting up all this server stuff. So I have a NextJS front deployed with Vercel, and it communicates with an Node.JS Express backend REST API that I have created. I’m trying to host the express server on my droplet, and I went ahead and used the NodeJS 1 Click Droplet to set up nginx and pm2. I believe those parts are working. However, I’m having issues with setting the server with HTTPS. I have bought a custom domain, set up all the necessary DNS stuff in digital ocean networking tab and in namecheap(where I got the domain). To set up certbot with my domain I used this guide from digitalocean: https://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl-certificates-on-ubuntu-22-04.

I believe it is an issue with my nodejs / nginx setup, but I’m not sure what is going on, and I’m not sure if I’m missing something. Here is where I setup the express server in nodejs:

_if_ (process.env.NODE_ENV === "production") {
  const privateKey = fs.readFileSync('/etc/letsencrypt/live/domain/privkey.pem', 'utf8');
  const certificate = fs.readFileSync('/etc/letsencrypt/live/domain/cert.pem', 'utf8');
  const ca = fs.readFileSync('/etc/letsencrypt/live/domain/chain.pem', 'utf8');
  const credentials = {
      key: privateKey,
      cert: certificate,
      ca: ca
  };
  _// create the HTTPS server on port 443_
  var https_server = https.createServer(credentials, app).listen(443, function(err){
    console.log("Node.js Express HTTPS Server Listening on Port 443");
  });
_// HTTP server on port 80 and redirect to HTTPS_
  var http_server = http.createServer(function(req,res){
    _// 301 redirect (reclassifies google listings)_
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
  }).listen(80, function(err){
    console.log("Node.js Express HTTPS Server Listening on Port 80");
  });

  _// create a_
} _else_ {
  app.listen(process.env.PORT || 3000, () => {
    console.log(`Running app backend on Port ${process.env.PORT}`);
  })
}

and here is what /etc/nginx/sites-enabled/default looks like:


# HTTP — redirect all traffic to HTTPS
server {
    listen 80;
    listen [::]:80 default_server ipv6only=on;
    return 301 https://$host$request_uri;
}



# HTTPS — proxy all requests to the Node app
server {
    # Enable HTTP/2
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name domain;


    # Use the Let’s Encrypt certificates
    ssl_certificate /etc/letsencrypt/live/domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain/privkey.pem;

    # Include the SSL configuration from cipherli.st
    include snippets/ssl-params.conf;

    location / {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3000/;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_cache_bypass $http_upgrade;
        proxy_redirect off;
    }
}

when I run the app in NODE_ENV=development it actually works fine (going to www.domain.com works and returns the right thing), however trying to run it production i get a 502 bad gateway, any ideas what I might be doing wrong in my setup?


Submit an answer


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Bobby Iliev
Site Moderator
Site Moderator badge
February 10, 2023

Hi there,

There is no need to run your Node.js app on port 443 as you can have only 1 service listening on a specific port. You would get an error saying that the port is already in use.

What you could do is just leave your Node.js app running on the standard port and do the SSL termination via Nginx as you’ve done already.

Let me know how it goes!

Best,

Bobby

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

card icon
Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Sign up
card icon
Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We’d like to help.

Learn more
card icon
Become a contributor

You get paid; we donate to tech nonprofits.

Learn more
Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow – whether you’re running one virtual machine or ten thousand.

Learn more ->
DigitalOcean Cloud Control Panel