In this article we're going to explain how to set up a Node.js app with nginx and Let's Encrypt on Ubuntu Server 16.04.
First, we need to create the web space for the app and the associated user account:
sudo -i # Get root privileges
adduser myapp
su - myapp
mkdir app www
exit
After getting root privileges, we can create a new set of nginx's rules (sudo -i
and then nano /etc/nginx/sites-available/myapp
):
upstream myapp {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name myapp.com;
root /home/myapp/www;
index index.html;
client_max_body_size 8m;
location / {
try_files $uri @myapp;
}
location @myapp {
proxy_pass https://myapp;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Now we can enable the new rules:
ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
Then we need to add the official repository used by the Let's Encrypt command line tool:
add-apt-repository ppa:certbot/certbot
Just refresh now the package list:
apt-get update
Now let's install Certbot:
apt-get install python-certbot-nginx
Let's get an SSL certificate for our app:
certbot --nginx -d myapp.com
After obtaining the certificate, we can choose Option #2 to allow Certbot to add the SSL rules to our nginx's configuration file.
Now let's copy the certificate files to our app directory:
cp /etc/letsencrypt/live/myapp.com/fullchain.pem > /home/myapp/app/fullchain.pem && chown myapp:myapp /home/myapp/app/fullchain.pem
cp /etc/letsencrypt/live/myapp.com/privkey.pem > /home/myapp/app/privkey.pem && chown myapp:myapp /home/myapp/app/privkey.pem
The code seen above can also be used to create a cronjob in order to renew the certificate before it expires:
export VISUAL=nano; crontab -e
x x x x x /usr/bin/certbot renew --quiet x x x x x cp /etc/letsencrypt/live/myapp.com/fullchain.pem > /home/myapp/app/fullchain.pem && chown myapp:myapp /home/myapp/app/fullchain.pem x x x x x cp /etc/letsencrypt/live/myapp.com/privkey.pem > /home/myapp/app/privkey.pem && chown myapp:myapp /home/myapp/app/privkey.pem
systemctl restart cron
Replace the
x
characters with the appropriate cron's time values.
We need to create a systemd service by typing nano /etc/systemd/system/myapp.service
and inserting the following contents:
[Service]
WorkingDirectory=/home/myapp/app
ExecStart=/usr/local/bin/node app.js
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=myapp
User=myapp
Group=myapp
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
Enable the service:
systemctl enable myapp
Let's start the service:
systemctl start myapp
We need to test the nginx configuration before restarting it:
nginx -t
If everything is correct, we can restart it:
systemctl restart nginx
The basic structure of our Node.js app (/home/myapp/app/app.js) will be as follows:
'use strict';
const express = require('express');
const fs = require('fs');
const https = require('https');
const port = process.env.PORT || 3000;
const app = express();
const sslOptions = {
key: fs.readFileSync('privkey.pem'),
cert: fs.readFileSync('fullchain.pem')
};
app.disable('x-powered-by');
// Routes will be inserted here
https.createServer(sslOptions, app).listen(port);