Setup Nginx as a Reverse Proxy
Video Lecture
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 set up 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 the instructions to serve the static content and start the SocketIO 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 directory 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 the devDependencies
such as TypeScript, Webpack, the type declarations, nodemon, concurrently, etc.
Now we can start the project using
npm start
Now open a browser and visit your IP address 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 |
|
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 |
|
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.