DEV Community 👩‍💻👨‍💻

Erik Vullings
Erik Vullings

Posted on

Publishing a Web site using node, pm2 and nginx

During development of a website, I often have the need to share the intermediate results with my clients using basic authentication. On one of my servers, I perform the following steps to get it up and running.

Publish the site

Assuming you have already created the website, build and deploy it to a folder that can be served by node.js. In my case, I often use parcel to build the client side, using something along the following lines as part of the package.json. As I don't want to hard-code the backend server's location in my client code, it is written in an .env file, e.g.

cat packages/gui/.env
SERVER="http://xxx.xxx.xxx.xxx/bob"
Enter fullscreen mode Exit fullscreen mode

And in my GUI code, I reference process.env.SERVER, which Parcel will replace with the value found in the .env file.

If you use TypeScript, you also need to add a declaration file for this to work, e.g. env.d.ts

declare const process: { env: { SERVER: string } };
Enter fullscreen mode Exit fullscreen mode

To actually do the build process, I have something like this in my package.json (and rimraf and parcel-bundler are part of my devDependencies), so I can use npm run build:domain to deploy the site:

  "scripts": {
    "start": "parcel index.html",
    "clean": "rimraf ./public ./.cache ./dist",
    "build": "parcel build index.html --out-dir ../server/public --public-url ./",
    "build:domain": "npm run clean && npm run build"
  },
Enter fullscreen mode Exit fullscreen mode

The most important script is the build script: it tells parcel to bundle all my stuff, put it in the out-dir folder, and use the public-url to make all file references relative to the final location where it will be running. If you do not include the latter, all file references will be hard-coded e.g. /app.123ved.css instead of app.123ved.css. See also the description here.

Deploying the service

Since my backend is on Node, I normally use a simple pm2 service to run it, e.g.

sudo pm2 start PATH/TO/SERVER.js --name APP_NAME
sudo pm2 ls # to see if it is running
Enter fullscreen mode Exit fullscreen mode

For more information about pm2, see here.

Other useful commands are sudo pm2 stop APP_NAME_OR_APP_ID and sudo pm2 start APP_NAME_OR_APP_ID.

As the server is used for many sites, the application needs to run on a dedicated port, preferably one behind a firewall, so it is not reachable from the outside. We use Nginx for that.

Configuring Nginx

Assuming you have Nginx up-and-running, add a new entry for your server in /etc/nginx/sites-available and create a symbolic link to the /etc/nginx/sites-enabled folder, e.g.

sudo vi bob
ln -s bob ../sites-enabled
Enter fullscreen mode Exit fullscreen mode

Where the content of the file is something like the following:

upstream demoserver {
   # port 55555 not reachable from Internet (firewall) 
   server 127.0.0.1:55555;
}

server {
    location = /bob {
        return 302 /bob/;
    }

    location /bob/ {
        auth_basic "Demonstration area";
        auth_basic_user_file /etc/apache2/.htpasswd;

        allow 127.0.0.1;

        # NOTE: The final / is important, as it will strip the prefix 'bob' from all URLs
        proxy_pass http://demoserver/;
    }
}
Enter fullscreen mode Exit fullscreen mode

That means that our service is running on port 55555, and will be reachable via HOST_IP/bob. Assuming, of course, that you have setup a password file. Read on...

Creating a Password File

Source

To create username-password pairs, use a password file creation utility, for example, apache2-utils or httpd-tools.

Create a password file and a first user. Run the htpasswd utility with the -c flag (to create a new file), the file pathname as the first argument, and the username as the second argument:

$ sudo htpasswd -c /etc/apache2/.htpasswd user1
Enter fullscreen mode Exit fullscreen mode

Press Enter and type the password for user1 at the prompts.

Create additional user-password pairs. Omit the -c flag because the file already exists:

$ sudo htpasswd /etc/apache2/.htpasswd user2
Enter fullscreen mode Exit fullscreen mode

You can confirm that the file contains paired usernames and encrypted passwords:

$ cat /etc/apache2/.htpasswd
user1:$apr1$/woC1jnP$KAh0SsVn5qeSMjTtn0E9Q0
user2:$apr1$QdR8fNLT$vbCEEzDj7LyqCMyNpSoBh/
user3:$apr1$Mr5A0e.U$0j39Hp5FfxRkneklXaMrr/
Enter fullscreen mode Exit fullscreen mode

Restarting Nginx

Test your configuration first using

sudo service nginx configtest
Enter fullscreen mode Exit fullscreen mode

And if that returns OK, restart Nginx using

sudo service nginx restart
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Build Anything...


Use any Linode offering to create something for the DEV x Linode Hackathon 2022. A variety of prizes are up for grabs, inculding $1,000 USD. 👀

Join the Hackathon <-