By Arnab Choudhuri, Alibaba Cloud Community Blog author
This article is meant for individual developers or startups with developers who are not very familiar with deployments and are currently using PaaS solutions for the same. In this article, we look at the steps one has to do to deploy multiple web applications on a single server using Alibaba Cloud's Simple Application Server.
In most cases a single server has enough resources and can run multiple web applications. A user might have, say, two web applications/websites connecting two domains abc.com and xyz.com or even abc.com and a subdomain api.abc.com. In such circumstances both, or all three of the applications, can be run from the same server using the technique shown in this article. Also, it is considered best practice to secure sites with SSL certificates. We will secure our applications and their respective domains with free valid Let's Encrypt SSL certificates.
This is a continuation from my previous articles Developing ASP.NET Core App in Visual Studio and Deploying on Simple Application Server and Developing Node.js App in Visual Studio and Deploying on Simple Application Server.
Develop two Node.js applications named NodejsApp1 and NodejsApp2.
Most information is available in the article Developing Node.js App in Visual Studio and Deploying on Simple Application Server.
Please ensure that both the applications work at different ports.
To ensure the same go to app.js in one application you have..
app.set('port', process.env.PORT || 3000);
And in the other application you have..
app.set('port', process.env.PORT || 3010);
Develop an asp.net core application and publish the same as a self-contained application.
Most information is available in the article Developing ASP.NET Core App in Visual Studio and Deploying on Simple Application Server.
While using Kestrel, which is the web server that's included by default in ASP.NET Core project templates, port 5000 is used on default behavior.
It is a good practice to explicitly state the host address and port the webhost will listen on or use a wildcard instead resulting in the web host binding to all IPv4 and IPv6 IPs addresses on specified port via the UseUrls(...) extension method that's available on the IWebHostBuilder interface.
In the Program.cs file, edit the CreateWebHostBuilder method to add UseUrls extension as shown below.
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000")
.UseStartup<Startup>();
If you are deploying more than one asp.net core applications, do use two different ports say 6000 and 6010.
Follow my previous articles to do this step.
Open a terminal window using putty and login as root to server.
Create a new user account using the adduser command (I here choose name mysudouser which you are free to replace with the user name that you want to create).
adduser mysudouser
Use the passwd command to set a password for the new user
passwd mysudouser
You will be prompted to confirm the password. Ensure you use a strong password.
Add the new user to the wheel group.
usermod -aG wheel mysudouser
Note: By default, on CentOS, members of the wheel group have sudo privileges.
Switch to the newly created user
su – mysudouser
Note: The first time you use sudo from this account, you will be prompted to enter the password for this user account.
Complete the following steps to install prerequisites for node.js applications. Please go through the node.js article to understand more on the commands.
yum -y update
sudo yum install curl
sudo yum install epel-release
curl --silent --location https://rpm.nodesource.com/setup_8.x | sudo bash -
sudo yum -y install nodejs
sudo yum install gcc-c++ make
node -v
The last command verifies the installation of node.js and provides its version as output.
The asp.net core article explains how to publish your application as self-contained and as such does not require any prerequisites or framework installation.
Our three applications are running on ports 3000, 3010 and 5000. To open these ports on the server..
Go back to the Server management screen on AlibabaCloud Console and select the option Firewall under Security.
Click on button Add Rules and add a firewall rule as shown in image below.
There are multiple ways of moving published application files to the server including the usage of FTP Client. We will use Filezilla. To install Filezilla for free visit https://filezilla-project.org/
In Filezilla, Select File > SiteManager
Select sFTP as Protocol
Add server ip address as Host, 22 as Port and Normal as Logon Type
Add root as User , Password as the one you set earlier and select Connect
Once logged in, create three directories (we named dotnetapp, expressapp1 and expressapp2) and drag and drop publish folder in case of asp.net core app and the two node.js app in the same.
In the putty terminal screen, move inside the folder where the published files are uploaded (in our case dotnetapp/publish)
Run our application now with the following commands:
chmod +x alibabadotnetcore
./alibabadotnetcore
Now, you should see an output showing the application is running properly. If you check on your browser with server_ip_address:port_number (port number=5000), you should see the application running.
Now without closing this terminal screen, open a new putty terminal screen and log in.
Move inside the folder, where first Node.js application code is uploaded (in our case /expressapp1).
Run our application now with the following commands:
npm install
npm start
Now, you should see output to show the application is running properly. If you check on browser with server_ip_address:port_number (port number=3000), you should see the application running.
Again, without closing this terminal screen, open a new putty terminal screen (this will be the third terminal) and log in.
Move inside the folder, where second Node.js application code is uploaded (in our case /expressapp2).
Run our application now with the following commands:
npm install
npm start
Now, you should see output to show the application is running properly. If you check on browser with server_ip_address:port_number (port number=3010), you should see the application running.
In case one has bought a domain name from Alibaba Cloud, the linking is very simple.
Go back to the Server management screen on the Alibaba Cloud Console and select the option Domains under Website.
Select Add Domain Name
Now resolve your domain name with this Simple Application Server
Now you should see your three applications by accessing domain_name:port_number in the browser (eg. abc.com:3000 should show the first node.js application if you own abc.com domain name).
In case one owns a domain name via a 3rd party provider, one would need to change the A Record in DNS configuration in Domain provider's console and link it to the public IP Address of Simple Application Server. Please connect with the help line of your domain name provider if you need hand holding in such cases.
Once all the domain names are connected to the simple application server, you should be able to view any of the three applications from all the three domains.
Our next task is to ensure that we do not view all the applications from all the domains but one application under each domain. We would achieve this using Nginx.
Nginx is a web server which can act as a reverse proxy. A reverse proxy server can offload work such as serving static content, caching requests, compressing requests, and SSL termination from the HTTP server.
But we already have three terminals open and we would have to open another terminal to install and configure Nginx.
Or we need to ensure our applications run without the necessity of keeping the terminals open. This is what we would do next using Supervisor.
Close the second and third terminals running node.js applications and in the first terminal shut down the asp.net core application by pressing Ctrl +C
GNU nano is a small and friendly text editor useful for editing configuration files.
sudo yum update
sudo yum install nano
When it asks if this is OK[y/d/N]: y
Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems.
sudo yum update
sudo yum install supervisor
When it asks if this is OK[y/d/N]: y
Copy all application files from home folder to /var folder
cd /
cp -r dotnetapp /var
cp -r expressapp1 /var
cp -r expressapp2 /var
To the supervisor configuration file we add the following settings info
Add a program name using [program:nodejsapp1]
Set a working directory using directory=/var/expressapp1/ExpressApp1
Add the command to run using command=npm start --production
Enable autostarting using autostart=true
Enable autorestart using autorestart=true
Add an error log file using stderr_logfile=/var/expressapp1/nodejsapp1.err.log
Add a normal log file using stdout_logfile=/var/expressapp1/nodejsapp1.out.log
Now we edit the supervisor configuration file
nano /etc/supervisord.conf
And add at the end of the file the following lines
[program:nodejsapp1]
directory=/var/expressapp1/ExpressApp1
command=npm start --production
autostart=true
autorestart=true
stderr_logfile=/var/expressapp1/nodejsapp1.err.log
stdout_logfile=/var/expressapp1/nodejsapp1.out.log
[program:nodejsapp2]
directory=/var/expressapp2/ExpressApp2
command=npm start --production
autostart=true
autorestart=true
stderr_logfile=/var/expressapp2/nodejsapp2.err.log
stdout_logfile=/var/expressapp2/nodejsapp2.out.log
Please go through the previous asp.net core article for this. It has a detailed writeup explaining the whole concept including creation of startup scripts.
Save and run supervisor by following command
sudo supervisord -c /etc/supervisord.conf
Now again you should be able to view any of the three applications from all the three domains by accessing domain_name:port_number in the browser (eg. abc.com:3000 should show the first node.js application if you own abc.com domain name).
sudo yum install nginx
When it asks if this is OK[y/d/N]: y
Start the Nginx service using the below command
sudo service nginx start
Check to ensure Nginx was setup properly.
systemctl status nginx
Now, hitting Nginx from the public IP assigned to your server or any of your domain names should show the welcome screen.
The configuration file for nginx exists at /etc/nginx/nginx.conf
We could change this file as we have done in the previous asp.net core article.
But it is better to create three separate files for three separate domains and applications with the name formatted as abc.com.conf. Later sites which are to be disabled can be named abc.com.conf.disabled.
We would do this at location /etc/nginx/conf.d/
This is because nginx.conf contains the following line which looks for configuration files at the above location.
include /etc/nginx/conf.d/*.conf;
Create three configuration files in the below format (if domain abc.com and configuration file abc.com.conf)
server {
listen 80;
listen [::]:80;
server_name abc.com www.abc.com;
location /
{
proxy_pass http://127.0.0.1:3000;
}
}
Do note to change the domain name and port number.
Note: Do study configuration examples of Nginx at https://www.nginx.com/resources/wiki/start/topics/examples/full/
Specially the proxy.conf section and server_names_hash_bucket_size under http block. Depending on the complexities in your application, you may need to add them.
Once done, Ensure your Nginx configuration changes checkout as valid syntax.
sudo nginx –t
Reload Nginx
sudo nginx -s reload
Now the applications can be accessed from the respective domains without the port number.
Note: What happens if you link a domain name to the server but do not add it to the server block in the configuration files? Nginx configuration file has a default route which takes that domain and shows it the Nginx home page on the server.
Let's Encrypt is the Certificate Authority (CA) which provides free SSL certificate.
Let's Encrypt uses the ACME protocol to verify that you control a given domain name and to issue you a certificate. To get a Let's Encrypt certificate, you'll need to choose a piece of ACME client software to use, amongst which CERTBOT is recommended.
To obtain an SSL certificate, install the certbot software on your server. The best way to install this is through the EPEL repository which we have already installed.
Obtain the certbot package
sudo yum install certbot
Test whether the client is working correctly.
certbot –help
It throws an error ImportError: No module named 'requests.packages.urllib3'
Note: In case later you do not find any error, please skip the next section and jump to configure section.
Remove the package and reinstall.
sudo rm -rf /usr/lib/python2.7/site-packages/urllib3
sudo yum install python-urllib3
sudo yum update
sudo yum clean all
sudo rm -r /var/cache/yum
sudo yum update
Test whether the client is working correctly.
certbot –help
Now, the problem is sorted.
Even though CERTBOT enables auto installation and configuration of nginx, I suggest you take the following path which will help you to know what is happening in your production servers and enable you to change, upgrade your configurations if you need.
Create the webroot folder.
sudo mkdir -p /var/www/letsencrypt/.well-known
sudo chgrp nginx /var/www/letsencrypt
sudo chmod g+s /var/www/letsencrypt
Create an nginx configuration file
sudo mkdir /etc/nginx/letsencrypt/
sudo nano -w /etc/nginx/letsencrypt/webroot.conf
Include the webroot path
location ^~ /.well-known/acme-challenge/ {
allow all;
root /var/www/letsencrypt/;
default_type "text/plain";
try_files $uri =404;
}
Create a file
sudo nano -w /etc/nginx/letsencrypt/ssl.conf
And add some ssl configuration
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";
Note: Ensure that the text after ssl_ciphers is in a single line in ssl.conf file.
Note: Follow the below instructions for all the three domains and their corresponding applications one after the other to secure all of them.
Add the webroot.conf to your nginx domain configuration file eg. abc.com.conf
sudo nano /etc/nginx/conf.d/abc.com.conf
server {
listen 80;
listen [::]:80;
server_name abc.com www.abc.com;
include letsencrypt/webroot.conf;
location /
{
proxy_pass http://127.0.0.1:3000;
}
}
Restart nginx
sudo systemctl restart nginx
Request the certificate from Let's Encrypt with certbot with a valid email id.
sudo certbot certonly --verbose --email admin@abc.com --agree-tos --webroot -w /var/www/letsencrypt/ -d abc.com -d www.abc.com
/etc/letsencrypt/live/abc.com/ folder gets created and certificate as well as chain file gets generated and placed in the folder.
Now go back to the nginx configuration file abc.com.conf and do the following
sudo nano /etc/nginx/conf.d/abc.com.conf
server {
listen 80;
listen [::]:80;
server_name abc.com www.abc.com;
include letsencrypt/webroot.conf;
return 301 https://$host$request_uri;
location /
{
proxy_pass http://127.0.0.1:3000;
}
}
server {
listen 443 ssl;
server_name abc.com;
ssl_certificate /etc/letsencrypt/live/abc.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/abc.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/abc.com/chain.pem;
include letsencrypt/ssl.conf;
include letsencrypt/webroot.conf;
location /
{
proxy_pass http://127.0.0.1:3000;
}
}
server {
listen 443 ssl;
server_name www.abc.com;
ssl_certificate /etc/letsencrypt/live/abc.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/abc.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/abc.com/chain.pem;
include letsencrypt/ssl.conf;
include letsencrypt/webroot.conf;
return 301 https://abc.com$request_uri;
location /
{
proxy_pass http://127.0.0.1:3000;
}
}
Restart nginx
sudo systemctl restart nginx
Test using the Qualys SSL Labs Report to see how your server configuration scores https://www.ssllabs.com/ssltest/analyze.html
Now, access abc.com or www.abc.com and reach http://abc.com
Note: There are a few other things which you might wish to do such as to increase security, generate a strong Diffie-Hellman group and auto renew the certificates which lapse after 90 days. There are sufficient articles available in the web to help you with them.
These are the basic steps one has to do to deploy multiple diverse applications and secure them on Alibaba Cloud Simple Application Server with CentOS.
Developing Node.js Apps Using Visual Studio Code with Docker on Simple Application Server
2,599 posts | 762 followers
FollowAlibaba Clouder - April 10, 2019
Alibaba Clouder - January 22, 2018
liptanbiswas - July 15, 2018
Alibaba Clouder - July 12, 2018
Alibaba Clouder - July 19, 2019
Alibaba Clouder - May 29, 2019
2,599 posts | 762 followers
FollowCloud-based and lightweight servers that are easy to set up and manage
Learn MoreElastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn MoreYou can use Certificate Management Service to issue, deploy, and manage public and private SSL/TLS certificates.
Learn MoreMore Posts by Alibaba Clouder