How do I setup a SSL certificate for an express.js server?
Asked Answered
G

4

170

Before, in an older version of express, I could do this:

express.createServer({key:'keyFile', cert:'certFile'});

However, in newer versions of express this no longer works:

var app = express();

Should I call app.use() to set the certs? If so how?

Geisha answered 3/8, 2012 at 22:38 Comment(0)
H
206

See the Express docs as well as the Node docs for https.createServer (which is what express recommends to use):

var privateKey = fs.readFileSync( 'privatekey.pem' );
var certificate = fs.readFileSync( 'certificate.pem' );

https.createServer({
    key: privateKey,
    cert: certificate
}, app).listen(port);

Other options for createServer are at: http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener

Hegelian answered 4/8, 2012 at 4:31 Comment(9)
Hmmm from node: https.createServer(options, [requestListener]) so passing app is ok? isn't that app is an 'object'...Geisha
what is the function signature for 'app'? i try to look up on github for express but i don't see that it takes (req, res)Geisha
Take a look at the definition of createServer in connect.js (express just inherits this from connect). You'll see that it returns a function with the correct signature. connect() is simply an alias for connect.createServer() and therefore so is express() (which probably does some extra initialization, but the result is still a function appropriate for use as a request handler).Hegelian
-1, what library? Explanation as to what app is? Pasting a single line of code isn't concise or clear.Gamaliel
@Qix - in the OPs example, app is defined. This answer is satisfactory.Incurve
I've added some useful links to official docs for the answer, for my own reference as well as yours.Brunner
app is what is return by this in Node.js - require('express')()Prepotent
is there any outline how to obtain the .pem files? I have two .crt files from my cert provider.Puett
I was successful using key and crt files (instead of pem). I got them via the process described here: alexanderzeitler.com/articles/… , but I had to s/-config <( cat server.csr.cnf )/-config server.csr.cnf/ and then bumble about a while to figure out how to add my root certificate (which was a PEM file) to my list of trusted providers. Of course, if you are using a signed certificate from a common authority, you won't need to do any of this. Main point is that the server works with key/crt files as well as pem.Fiume
O
129

I was able to get SSL working with the following boilerplate code:

var fs = require('fs'),
    http = require('http'),
    https = require('https'),
    express = require('express');

var port = 8000;

var options = {
    key: fs.readFileSync('./ssl/privatekey.pem'),
    cert: fs.readFileSync('./ssl/certificate.pem'),
};

var app = express();

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

app.get('/', function (req, res) {
    res.writeHead(200);
    res.end("hello world\n");
});
Oldcastle answered 22/8, 2012 at 17:35 Comment(4)
How do you actually see the hello world on the browser? 127.0.0.1:8000 gives me a Error 107 (net::ERR_SSL_PROTOCOL_ERROR): SSL protocol error.Morrissette
upvoted too soon. I get -- Error: addListener only takes instances of FunctionDrat
keep in mind that was written quite a while ago. It is possible this no longer works in newer versions of Express or Node.jsOldcastle
This is years too late, but the SSL_PROTOCOL_ERROR can be caused by the fact that you're using http://<ssl_enabled_endpoint>. It should be https://<ssl_enabled_endpoint>Vintager
S
13

This is my working code for express 4.0.

express 4.0 is very different from 3.0 and others.

4.0 you have /bin/www file, which you are going to add https here.

"npm start" is standard way you start express 4.0 server.

readFileSync() function should use __dirname get current directory

while require() use ./ refer to current directory.

First you put private.key and public.cert file under /bin folder, It is same folder as WWW file.

no such directory found error:

  key: fs.readFileSync('../private.key'),

  cert: fs.readFileSync('../public.cert')

error, no such directory found

  key: fs.readFileSync('./private.key'),

  cert: fs.readFileSync('./public.cert')

Working code should be

key: fs.readFileSync(__dirname + '/private.key', 'utf8'),

cert: fs.readFileSync(__dirname + '/public.cert', 'utf8')

Complete https code is:

const https = require('https');
const fs = require('fs');

// readFileSync function must use __dirname get current directory
// require use ./ refer to current directory.

const options = {
   key: fs.readFileSync(__dirname + '/private.key', 'utf8'),
  cert: fs.readFileSync(__dirname + '/public.cert', 'utf8')
};


 // Create HTTPs server.

 var server = https.createServer(options, app);
Swithbert answered 20/8, 2018 at 20:18 Comment(4)
How would this work with a web-server-1 and web-server-2 with 1 load balancer? The SSL cert is stored on the load balaner, which means the path to the certs does not work?Decimal
If you have a load balancer, then it should terminate the TLS (as it holds the certificates). At that point, you just need to serve yo a normal http app, with no concerns of SSL @iiiml0sto1Membranous
There is no express = require('express') anywhere here - so how is it working?Coolant
unfortunately this answer is very out of date. it's now trivial to do this.Gravois
G
2

2024, it's now incredibly simple to get a LetsCreate cert:

  1. Stop your webserver for a minute.

  2. type

% certbot certonly --standalone

It will ask your email and the domain name. It will spit out the file locations

const cts = {
    cert: fs.readFileSync("/etc/letsencrypt/-blah-/fullchain.pem"),
    key: fs.readFileSync("/etc/letsencrypt/-blah-/privkey.pem")
}

Launch https server:

app = express()
app.use .. etc etc
app.get .. etc etc
https.createServer(cts, app).listen(443)

That's the whole thing.

HUGE tip for ssl socket servers:

All non-trivial sites will have a few socket servers on different ports, as well as the web servers.

The secret is you simply add (ie, one line of code) a https server specifically for each wss server. (Full example.)

// create https SPECIFICALLY FOR wss 7788
let for_7788 = https.createServer(options).listen(7788)
let wss = new WSServer({ server: for_7788 })
wss.on( etc etc )
Gravois answered 27/2 at 17:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.