13 May 2020

Angular Universal: Server-Side Rendering (SSR) with cPanel WHM

As with all topics related to software development, there is always more than one solution to a problem. The following proposition is simply one possible solution and not intended to be definitive.

Summary:

  • Ensure your cPanel account has NodeJS (via Passenger) available.
  • Upload your standard Angular Universal distribution folder (dist/server, dist/browser).
  • Create an .htaccess file that redirects your standard web ports into a NodeJS service.
  • Add a 'node' command shortcut to your cPanel account .bashrc file.
  • Connect to your cPanel account using SSH and execute your NodeJS service.

Okay, let start by saying that cPanel Passenger Application Manager does not play well with Angular Universal. Running an Angular client on cPanel is trivial. Creating an Express server with cPanel and Passenger is a breeze... But making an Angular Universal app run with cPanel and Passenger seems like an insurmountable task! Never-the-less, it's possible to run your Angular SSR using the tools cPanel has provided.

Firstly, you need to be sure you have NodeJS available on your cPanel account. If you have WHM access, then you can easily use EasyApache4 to make NodeJS available. See here for an easy cPanel NodeJS installation guide.

If you don't have the luxury of full WHM access, you can check that you've been provided the basics by following this cPanel Application Manager tutorial.

Once you're sure that your cPanel server supports NodeJS, you can go-ahead and upload your standard Angular Universal build to your cPanel public_html or alternative public access web directory.

In this instance, we're not going to over-complicate it. Just take your entire Angular Universal build dist folder and upload it to the web server.

/home/{cPanel account name}/public_html/dist/server/main.js
/home/{cPanel account name}/public_html/dist/browser/{Angular client files}

IMPORTANT: In a production environment you do not want to have your server/main.js folder accessible to the public. You should have it outside the public_html directory.

While you're working with the public_html folder, create an .htaccess file and include the following redirect:

/home/{cPanel account name}/public_html/.htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
# Redirect Public ports to NodeJS port
RewriteEngine On
RewriteRule ^$ http://127.0.0.1:4000/ [P,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://127.0.0.1:4000/$1 [P,L]
</IfModule>

This little slice of sorcery will allow your web server (Apache) to continue doing its job serving content via the :80 and :443 ports, but will redirect traffic into your NodeJS service at port 4000 (provided you've stuck to Angular Universal's default).

One last piece of work while you're making edits to files on your cPanel server. Locate the .bashrc file in your cPanel account; probably somewhere here:

/home/{cPanel account name}/.bashrc

Edit that file and add the following line:

# User specific aliases and functions
export PATH=/opt/cpanel/ea-nodejs10/bin/:$PATH

This will allow you to use the 'node' command from the console once you are logged on via SSH. Otherwise, you'd have to run node using the full path to the executable on the server.

Using your favourite SSH terminal, connect to your cPanel account, navigate to your public_html directory (or where ever you placed your Angular Universal dist folder). Run this command to see that everything is in working order:

# cd /home/{cPanel account name}/public_html
# node dist/server/main.js

If all has gone to plan, you should be given the following response:

Node Express server listening on http://localhost:4000

Cross your fingers and go visit the website's public URL. Hopefully, the Angular Universal Application loads and all is well in the world! You can right-click your web page to "View page source" and confirm that you're Angular App. has indeed been rendered server-side.

 If you'd like to run your NodeJS service in the background you can append the ampersand (&)

# node dist/server/main.js &

Don't forget to take note of the ProcessID because you'll need that to terminate the background service later... However, you can recover your ProcessID and terminate the NodeJS service using the following commands:

# node dist/server/main.js &
# ps -ef | grep node
# kill {ProcessID}

 

Install Angular Universal as a background service on CentOS 7 WHM

If you have full root access to your CentOS 7 & WHM server, you can take your NodeJS Angular Universal SSR to the next level by creating an automated background service.

Log on to the server as root or an account with similar permissions, and navigate to the systemd folder.

# cd /etc/systemd/system

Create a new empty file and label it something like: my_nodejs_ngu_app.service

[Unit]
Description=Node.js Angular Universal Service

[Service]
PIDFile=/tmp/my_nodejs_ngu_app-99.pid
User={cPanel account name}
Group={cPanel account name}
Restart=always
KillSignal=SIGQUIT
WorkingDirectory=/home/{cPanel account name}/public_html/
ExecStart=/opt/cpanel/ea-nodejs10/bin/node /home/{cPanel account name}/public_html/dist/server/main.js

[Install]
WantedBy=multi-user.target

You can use the following commands to start, stop, refresh, etc.

# sudo systemctl enable my_nodejs_ngu_app.service
# sudo systemctl start my_nodejs_ngu_app.service
# sudo systemctl stop my_nodejs_ngu_app.service
# sudo systemctl daemon-reload

 

Install Angular Universal as a background service on CentOS 6 WHM

If you are still running a CentOS 6 WHM server, then you need to set-up the service using init.d.

# cd /etc/rc.d/init.d

CentOS 6 services are more complicated than CentOS 7, take a look at the following examples to help get started:

https://github.com/chovy/node-startup/blob/master/init.d/node-app https://gist.github.com/lowol/3223614

 


PurcellYoon are a team of expert Angular Developers with a passion for creating exceptional digital experiences. We are committed to delivering superior Angular Applications for all our partners and clients.

We'd love to talk with you about Angular Universal Development.
More questions? Get in touch.