nginx/SSL/Express

I'm trying to enable https for a Node app I'm running that uses Express. It used to run fine on plain http, so I don't think there are too many places where things could be going wrong. I've gotten some certificates with letsencrypt, enabled ssl in nginx, added a redirect to direct all http traffic to https for this app, pointed the express server at the certificates (I can run fine locally, and I get a response when I `curl -k https://localhost:3002/`). When I try to go to the website now, I get a `502 Bad Gateway` and in the nginx access/error logs I see this:

access log

108.30.214.151 - - [18/Feb/2017:03:19:40 -0500] "GET / HTTP/1.1" 502 584 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
108.30.214.151 - - [18/Feb/2017:03:19:40 -0500] "GET /favicon.ico HTTP/1.1" 502 584 "https://yattwo.me/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"

error log

2017/02/18 03:19:59 [error] 14843#14843: *38 upstream prematurely closed connection while reading response header from upstream, client: 108.30.214.151, server: yattwo.me, request: "GET / HTTP/1.1", upstream: "http://127.0.0.1:3002/", host: "yattwo.me"
2017/02/18 03:19:59 [error] 14843#14843: *38 upstream prematurely closed connection while reading response header from upstream, client: 108.30.214.151, server: yattwo.me, request: "GET /favicon.ico HTTP/1.1", upstream: "http://127.0.0.1:3002/favicon.ico", host: "yattwo.me", referrer: "https://yattwo.me/"

The strange thing is that I don't see anything in the node logs, which means that it should be some nginx issue? But from looking online it seems like getting the "upstream prematurely closed connection while reading response header from upstream" suggests that it's some error with the express webserver. Also `sudo nginx -t` returns

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

so at least the configuration isn't flat out wrong...

Any help would be appreciated!

---

These are my setup files

/etc/nginx/sites-available/yattwo (has some random things found online)

upstream yattwo {
server 127.0.0.1:3002;
keepalive 8;
}

server {
listen 0.0.0.0:80;
server_name yattwo.me yattwo;
access_log /var/log/nginx/yattwo.log;
error_log /var/log/nginx/yattwo_error.log;

# Always redirect to HTTPS
server_tokens off;
return 301 https://$host$request_uri;
}

server {
listen 0.0.0.0:443 ssl;
ssl_certificate /etc/letsencrypt/live/yattwo.me/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yattwo.me/privkey.pem;

server_name yattwo.me yattwo;
access_log /var/log/nginx/yattwo-https.log;
error_log /var/log/nginx/yattwo-https_error.log;

large_client_header_buffers 8 32k;

# pass the request to the node.js server with the correct headers
# and much more can be added, see nginx config options
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;

proxy_set_header X-Ssl on;

proxy_buffers 8 32k;
proxy_buffer_size 64k;

proxy_pass http://yattwo;
proxy_redirect off;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

/etc/nginx/sites-available/default

server {
listen [::]:80 default_server;

# SSL configuration

listen 443 ssl default_server;
listen [::]:443 ssl default_server;

root /var/www/html;

# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;

server_name _;

location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
}

relevant excerpts from [server.js](https://github.com/colblitz/yatto2/blob/master/server.js)

var fs = require('fs');
var http = require('http');
var https = require('https');
var config = require('./config');

var options = {
key : fs.readFileSync(config.keyPath),
cert : fs.readFileSync(config.certPath)
};

...

var app = express();

app.set('port', process.env.PORT || 3002);

https.createServer(options, app).listen(app.get('port'), function() {
console.log('Express server listening on https port ' + app.get('port'));
});

config is just a js file with

var config = {
keyPath: "/etc/letsencrypt/live/yattwo.me/privkey.pem",
certPath: "/etc/letsencrypt/live/yattwo.me/cert.pem",
};

module.exports = config;

2 thoughts on “nginx/SSL/Express”

  1. If I understand correctly, your configuration files were fine when using http. I assume the only thing you changed was the nginx configuration. Could you post what your configuration files looked like in the working scenario when on http?

    Usually 502 means the resource is unavailable. Nginx can’t find the express server, or the express service is unresponsive.

    Reply
  2. 1) I’d recommend not to use ssl in express configuration. You run your backend only on 127.0.0.1, so there is no need to make this connection secure actually. So, try to remove these lines

    var config = require(‘./config’);

    var options = {
    key : fs.readFileSync(config.keyPath),
    cert : fs.readFileSync(config.certPath)
    };

    2) Even if you wanna use ssl backend, you should use proper proxy_pass value. Right now you use it insecure

    proxy_pass http://yattwo;

    3) You use the same name for upstream and for server_name.

    upstream yattwo {
    ……
    server_name yattwo.me yattwo;

    It’s better to rename one of these (or just remove yattwo from server_name line).

    4) Actually you don’t need `location`, `index` and `root` parts in `default` unless it’s gonna be served for some unknown reason (which is, actually, bad practice). You also could disable ssl ports for `default`, without certificate it could break things.

    5) Do you use websockets in your application? If no, feel free to remove following lines:

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection “upgrade”;

    Reply

Leave a Comment