Setting up a simple Express.js server to test Nginx

by Lance Gold

This short code listens in to port 3000

Return to index
From Google A.I. "debian what is best directory for node.js projects" For production deployment on a Debian server, the recommended directories following the Filesystem Hierarchy Standard (FHS) are different: /opt/: This is a good location for the application's program distribution files, which includes the application code, package.json, and node_modules. /srv/: This directory is appropriate for data that is served by the system (e.g., static files like HTML, images, and CSS). /var/opt/: Logs and other variable data should be stored here. /etc/opt/: Configuration files should be placed here x@c7:~$ ls -l / | grep opt drwxr-xr-x 2 root root 4096 Aug 19 11:03 opt x@c7:~$ from Google A.I. "debian create group" sudo addgroup groupname # or sudo groupadd groupname verify group creation tail /etc/group This will display the last few lines of the file, which should include the new group's entry Optional: Creating a group with a specific Group ID (GID) By defaul, the system assigns the next available GID. You can specify a GID using the --gid or -g option sudo addgroup groupname --gid 1005 sudo groupadd -g 1005 groupname Next steps: Adding users to the group # Debian-specific command sudo adduser username groupname # Universal Linux command (use -aG options) sudo usermod -aG groupname username the -aG options ensure the user is appended to the specified supplementary groups without removong them from other groups. x@c7:/opt$ sudo groupadd ndev [sudo] password for x: x@c7:/opt$ tail /etc/group ... jci:x:1000: x:x:1001: ndev:x:1002: x@c7:/opt$ x@c7:/opt$ sudo usermod -aG ndev x x@c7:/opt$ from Google A.I. "debian change group permissions on directory" To change ownership recursively (including all subdirectories and files) sudo chgrp -R Change the Group Permissions Next, use the chmod command to set the desired permissions for the group. You can use either symbolic (letters) or numerical (octal) notation. Using Symbolic Notation (Recommended) This method lets you specifically add or remove permissions for the group without affecting the owner or others. Pluralsight Pluralsight +1 g+rwx: Adds read, write, and execute permissions for the group. g-w: Removes write permissions for the group. g=rw: Sets the group permissions to exactly read and write (removing execute if it was present). Examples: To give the group full read, write, and execute permissions on a directory: bash chmod g+rwx /srv/shared_data To do this recursively for all files and subdirectories: bash chmod -R g+rwx /srv/shared_data Using Numerical Notation Numerical notation sets permissions for the owner, group, and others simultaneously. A common setting for shared directories is 775, which grants full permissions (read, write, execute) to the owner and the group, but only read and execute to others. Super User Super User +2 Permissions breakdown: 7 = Read (4) + Write (2) + Execute (1) 5 = Read (4) + Execute (1) Example: To set permissions to 775 (owner: full, group: full, others: read/execute) on a directory: bash chmod 775 /srv/shared_data To do this recursively: bash chmod -R 775 /srv/shared_data Verify the Changes After running the commands, verify the new ownership and permissions using the ls -ld command: bash ls -ld /srv/shared_data The output will display the permissions (e.g., drwxrwxr-x) and the owner/group (e.g., user consult), confirming your changes. from the webpage "https://blog.logrocket.com/how-to-run-node-js-server-nginx/" x@c7:~$ sudo mkdir /opt/nginx_server_project [sudo] password for x: x@c7:~$ x@c7:/opt$ cd /opt/nginx_server_project x@c7:/opt/nginx_server_project$ Make the changes to the project directory group name and permissions before: x@c7:/opt$ ls -l total 4 drwxr-xr-x 2 root root 4096 Jan 31 08:25 nginx_server_project x@c7:/opt$ after: x@c7:/opt$ sudo chgrp -R ndev /opt/nginx_server_project x@c7:/opt$ sudo chmod -R g+rwx /opt/nginx_server_project x@c7:/opt$ ls -l total 4 drwxrwxr-x 2 root ndev 4096 Jan 31 08:25 nginx_server_project x@c7:/opt$ Add user to group x@c7:~$ sudo usermod -aG ndev x Return to instructions from blog.logrocket.com: Still need to create npm with sudo. x@c7:/opt$ cd nginx_server_project x@c7:/opt/nginx_server_project$ sudo npm init -y [sudo] password for x: Wrote to /opt/nginx_server_project/package.json: { "name": "nginx_server_project", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" } x@c7:/opt/nginx_server_project$ Continue on: x@c7:/opt/nginx_server_project$ sudo touch server.js x@c7:/opt/nginx_server_project$ sudo vi server.js Now it’s time to build and start the server. Let’s define two extra subdomains as a means to test that our application is fully functional: const http = require("http"); const server = http.createServer((req, res) => { const urlPath = req.url; if (urlPath === "/overview") { res.end('Welcome to the "overview page" of the nginX project'); } else if (urlPath === "/api") { res.writeHead(200, { "Content-Type": "application/json" }); res.end( JSON.stringify({ product_id: "xyz12u3", product_name: "NginX injector", }) ); } else { res.end("Successfully started a server"); } }); server.listen(3000, "localhost", () => { console.log("Listening for request"); }); We created a server with a Node.js HTTP module that we imported using the require function in the above code. Within our server, we’ll render two different responses, depending on our current route. The two routes are /overview and /api. On the /overview subdomain, we’ll render a plain text, while on the /api, we’ll render a JSON object. The above application will be accessed on the Public IPv4 address of your virtual machine — e.g., 34.211.115.4 on port 3000. x@c7:/opt/nginx_server_project$ ls -l total 8 -rw-r--r-- 1 root root 234 Jan 31 09:34 package.json -rw-r--r-- 1 root root 542 Jan 31 09:54 server.js x@c7:/opt/nginx_server_project$ Now that the Node server application is ready, let’s install Nginx and configure it. x@c7:~$ cd /etc/nginx/sites-available x@c7:/etc/nginx/sites-available$ sudo touch myserver.config x@c7:/etc/nginx/sites-available$ sudo vi /etc/nginx/sites-available/myserver.config x@c7:/etc/nginx/sites-available$ Paste in the following configuration: #The Nginx server instance server{ listen 80; server_name wach.quest; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://127.0.0.1:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # location /overview { # proxy_pass http://127.0.0.1:3000$request_uri; # proxy_redirect off; # } } } The above configuration has Nginx listening on port 80 on your-domain.com. The / is your Uniform Resource Identifier (URI) with the following properties: • proxy_set_header: Sets the host header to be that of the Nginx server • proxy_pass HTTP: Instructs Nginx to proxy all requests matching the location pattern to an upstream (backend) server •proxy_http_version: Converts the incoming connection to HTTP 1.1 • proxy_set_header Upgrade: Converts the proxied connection to type Upgrade because WebSockets only communicate on upgraded connections •proxy_set_header Connection: Ensures the connection header value is Upgrade Save the changes and exit the file by clicking the Esc key. Then, type the command :wq and hit the Enter or Return key. Next enable the new config file in the sites-available directory with a symbolic link in the sites-enabled directory x@c7:/etc/nginx/sites-available$ sudo ln -s /etc/nginx/sites-available/myserver.config /etc/nginx/sites-enabled/ x@c7:/etc/nginx/sites-available$ x@c7:/etc/nginx/sites-available$ ls -l /etc/nginx/sites-enabled total 0 lrwxrwxrwx 1 root root 42 Jan 31 12:20 myserver.config -> /etc/nginx/sites-available/myserver.config lrwxrwxrwx 1 root root 40 Jan 27 09:17 with-ssl.conf -> /etc/nginx/sites-available/with-ssl.conf x@c7:/etc/nginx/sites-available$ Remove the symbolic link to the other configuration x@c7:/etc/nginx/sites-available$ sudo unlink /etc/nginx/sites-enabled/with-ssl.conf Change the permissions to the symbolic link x@c7:/etc/nginx/sites-available$ sudo chmod 644 /etc/nginx/sites-enabled/myserver.config x@c7:/etc/nginx/sites-available$ ls -l /etc/nginx/sites-enabled/ total 0 lrwxrwxrwx 1 root root 42 Jan 31 12:20 myserver.config -> /etc/nginx/sites-available/myserver.config x@c7:/etc/nginx/sites-available$ Test the configuration x@c7:/etc/nginx/sites-available$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful x@c7:/etc/nginx/sites-available$ Restart NginX x@c7:/etc/nginx/sites-available$ sudo systemctl restart nginx x@c7:/etc/nginx/sites-available$ Change to directory of Node.js application x@c7:/etc/nginx/sites-available$ cd /opt/nginx_server_project x@c7:/opt/nginx_server_project$ Start application x@c7:/opt/nginx_server_project$ node server.js Listening for request Open a browser and access the Node.js application using the domain http://c7.xcvvc.com: node.js server response successful Access the /overview endpoint of the application http://c7.xcvvc.com/overview. node.js overview page successful Test if the api is accessible http://c7.xcvvc.com/api. node.js api successful Adding SSL/TLS encryption Create a configuration file for port 443 traffic. x@c7:~$ ls /etc/nginx/sites-available/ default myserver.config with-ssl.conf x@c7:~$ sudo touch /etc/nginx/sites-available/nginx-443.config [sudo] password for x: x@c7:~$ sudo vi /etc/nginx/sites-available/nginx-443.config server { listen 443 ssl; server_name example.com; ssl_certificate /etc/ssl/certs/de.somewhere.com.pem # /path/to/ssl_certificate.crt; ssl_certificate_key /etc/ssl/private/c7.xcvvc.com.key # /path/to/ssl_certificate.key; # SSL settings ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; location / { proxy_pass http://127.0.0.1:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } Here is the list of configurations x@c7:~$ ls -l /etc/nginx/sites-available/ total 16 -rw-r--r-- 1 root root 2815 Jan 27 09:01 default -rw-r--r-- 1 root root 436 Jan 31 12:53 myserver.config -rw-r--r-- 1 root root 602 Jan 31 16:25 nginx-443.config -rw-r--r-- 1 root root 2817 Jan 18 22:56 with-ssl.conf x@c7:~$ Add a 2nd symbolic link for the nginx-443.config file x@c7:~$ sudo ln -s /etc/nginx/sites-available/nginx-443.config /etc/nginx/sites-enabled/ x@c7:~$ ls -l /etc/nginx/sites-enabled/ total 0 lrwxrwxrwx 1 root root 42 Jan 31 12:20 myserver.config -> /etc/nginx/sites-available/myserver.config lrwxrwxrwx 1 root root 43 Jan 31 17:12 nginx-443.config -> /etc/nginx/sites-available/nginx-443.config x@c7:~$ Check the nginx configuration x@c7:~$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful x@c7:~$ Restart NginX with the added configuration x@c7:~$ sudo systemctl restart nginx x@c7:~$ Open a browser and test the three categories using secure https:// A static server page: https://c7.xcvvc.com Successful link to a node.js static page An Overview page from node.js: https://c7.xcvvc.com/overview Link to the site's overview page A look at a node.js .api request: https://c7.xcvvvc.com/api Return data from a node.js api Load Balancing with NginX From the end of the logrocket blog: As Node.js applications develop in size to accommodate an increasing number of users, it becomes important to allocate incoming traffic among several backend servers to guarantee efficiency and dependability. Nginx provides a variety of algorithms to help with load balancing. These algorithms determine how loads are distributed among the available servers: http { upstream node_app_servers { # no load balancing method is specified for Round Robin server api1.backend.com; server api2.backend.com; } server { listen 80; server_name example.com; location / { proxy_pass http://node_app_servers; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } } The upstream directive defines a group of backend Node.js servers for load balancing Nginx distributes incoming requests among the specified servers using a default round-robin algorithm The proxy_pass directive forwards requests to the backend servers within the upstream group Another example from SSL-Dragon Here is a brief description of installing ssl onto NginX from https://www.ssldragon.com/how-to/install-ssl-certificate/nginx/: Edit the NGINX configuration file Next, edit the NGINX configuration file. Add or edit the server block for HTTPS (port 443). You will also need to include the following special properties: listen 443 ssl; (for releases after 1.15.0) ssl on; (for releases before 1.15.0) ssl_certificate – pointed to the directory of your combined SSL file ssl_certificate_key pointed to the directory of your private key file generated along with the CSR The final version of your configuration file should look like the example below: server { listen 443 ssl; #ssl on; (for releases before 1.15.0) ssl_certificate /etc/ssl/ssl-bundle.crt; ssl_certificate_key /etc/ssl/ssl-dragon.key; server_name ssl-dragon.com; access_log /var/log/nginx/nginx.vhost.access.log; error_log /var/log/nginx/nginx.vhost.error.log; location / { root /var/www/; index index.html; } }

This is from "Beginning Node.js" p. 142. Listing 7-3 "1basic.js"


var express = require('express');
var serveStatic = require('serve-static');
var app = express()
	.use(serveStatic(__dirname + '/public'))
	.listen(3000);