Skip to content

Setup Nginx as a Reverse Proxy

Video Lecture

Setup Nginx as a Reverse Proxy Setup Nginx as a Reverse Proxy Setup Nginx as a Reverse Proxy

Description

While it is possible to host your applications on a production server using a Nodejs and Express server directly, it is also beneficial to host them behind a reverse proxy, for example an Nginx configuration.

Using Nginx for the reverse proxy will also allow us to easily bind the domain name, SSL certificate and later have further options for modifying compression, load balancing, passing request headers and more in case you need and independently of your applications project code.

We will setup the Socket.IO example from the previous lesson, Socket.IO with Node.js, Express and Webpack, on the same production server that we created in the lesson Host using an Nginx Server

Build the Production version

Build the production version of bundle.js by using the Webpack production configuration.

npm run build

Compile the ./src/server/server.ts file into javascript using TSC. This is only necessary if you made any changes from the last lesson. The ./dist/server/server.js will most likely already exist.

tsc -p ./src/server

Test the production version fully works. The start script will run our ./dist/server/server.js script using Node.js which includes all of the instructions to serve the static content and start the Socket.io Server using Express.

npm start

Visit http://127.0.0.1:3000 using several web browsers to also test that the socket communications is working.

Copy the files to the production server

Open WinSCP or other preferred tool and add a new relevantly named director for your Socket.IO application, for example socketio.your-domain.tld in the /var/www/ directory.

Copy the ./package.json and the contents of ./dist/ and all of its sub folders to the new folder you just created.

Start the Nginx and Express server on the production server

Connect to your server using an SSH client, such as Putty, and change directory to the /var/www/socketio.your-domain.tld/ folder.

cd /var/www/socketio.your-domain.tld/

Check if you have npm installed

npm -v

If not, then install it using

sudo apt install npm

Now we need to install the production dependencies which will be the Express and Socket.IO libraries.

npm install --only=prod

I have added the --only=prod flag since I don't need to also install all of the devDependencies such as TypeScript, Webpack, the type definitions, nodemon, concurrently, etc.

Now we can start the project using

npm start

Now open a browser and visit your ipdress at port 3000. E.g, http://###.###.###.###:3000, and try out a few things to verify that it works as expected.

Note that depending on which cloud provider you use, port 3000 may be blocked by a security rule or firewall setting. If so, then no problem, you can either open the port and test your application works, or continue to leave the port closed and move onto the Screen command. We will close the port 3000 anyway near the end of this lesson.

Go back into SSH and press Ctrl-C to stop the server.

We will now start the application in a separate Screen session so that the Node.js server continues to run in the background in case we close our main SSH session.

screen

Press enter to bypass the Screen introduction page.

Navigate to the /var/www/socketio.your-domain.tld/ folder again while in the new screen session.

cd /var/www/socketio.your-domain.tld/

And start the node js server

npm start

Press CTRL-A and CTRL-D to detach from the screen session.

The Node.js server is still running in the background and will still continue to run if we close our main SSH session.

To go back into an existing screen session, type

screen -r

If you want to end and exit a Screen session fully so that it no longer is running in the background. Then, while in the screen session, type exit. The screen session will now end and you will not be able to reconnect or reattach to the old session, since it no longer exists, until you create a new session.

Remember, Screen is useful when you want your process to continue after you close your main ssh client, putty in our case.

Configure the Domain Name

Decide on which domain name you want to use and configure the A name record in your domain name providers user interface to point to the IP address of your production server.

E.g. socketio.your-domain.tld will point to an IP address 1.2.3.4

Configure Nginx to act as a Reverse Proxy

Create a new file called /etc/nginx/sites-enabled/socketio.your-domain.tld.conf

Add this script

1
2
3
4
5
6
7
8
9
server {
    listen 80;
    listen [::]:80;
    server_name socketio.your-domain.tld;

    location / {
        proxy_pass http://127.0.0.1:3000/;
    }
}

Test it by visiting again http://socketio.your-domain.tld

Note that since this project I am setting up, includes Socket.IO, there will be errors in the console about how it is polling, and not creating a proper socket. This addition below is only applicable if you see this error in the developer tools, and are also serving Socket.IO from your Node.js server as I am.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
server {
    listen 80;
    listen [::]:80;
    server_name socketio.your-domain.tld;

    location /socket.io/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_pass "http://localhost:3000/socket.io/";
    }

    location / {
        proxy_pass http://127.0.0.1:3000/;
    }
}

Test the Nginx configuration is ok,

nginx -t

restart and check status

sudo service nginx restart
sudo service nginx status

And visit again http://socketio.your-domain.tld

It should be perfect without any errors.

Depending on which cloud provider you got your server from, as an extra measure, to ensure that the application can only be played via the Nginx proxy, we can also block access to port 3000 from the internet but not locally on the server.

iptables -A INPUT -p tcp -s localhost --dport 3000 -j ACCEPT
iptables -A INPUT -p tcp --dport 3000 -j DROP
iptables -L

Bind the SSL certificate

Now we can run CertBot again and follow the prompts and select the socketio.your-domain.tld option this time.

sudo certbot --nginx

After completion, visit the https version of your url.

https://socketio.your-domain.tld

You can also visit the example that was created in the video.

https://socketio.sbcode.net