It’s been a really long time since I wrote the last time and now here I am. I hope you missed me :).
In recent weeks I have been busy developing a WhatsApp client that interfaces with the WhatsApp Business API. This application consists of a web client developed in Javascript / VueJs 3 and a backend web API developed in ASP.NET Core 7. The web API must be run in a Linux CentOS 7 with Apache installed.
Why run .NET in a Linux environment? As a constraint, I had to use a Linux CentOS 7 server, so I could have developed the entire backend part in (for example) PHP, so that I could run it more easily on Linux, but I preferred to adopt the .NET platform, as it is an environment in which I am more comfortable. And given the “cross platform” capabilities of .NET, it is now possible to run a .NET web API on Linux with relative ease.
A small note: in this post we will not use Docker-type virtualization platforms, but we will perform a native installation of the .NET runtime on Linux.
I assume that you already have a working .NET web API and a valid URL that can be used to point to this web API (in this post we will use api.myapi.local).
Let’s start… follow me in this new adventure!
Installing .NET 7 runtime
We’ll start by installing the .NET 7 runtime in CentOS. You can find detailed information about .NET installation on the Microsoft website at this address:
https://learn.microsoft.com/en-us/dotnet/core/install/linux-centos
Below I report the main steps necessary for installation.
From the Linux command line run the following command to make Microsoft’s packages available on your server:
sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm
And then run the following:
sudo yum install aspnetcore-runtime-7.0
During the installation you may be asked for various types of confirmations. Of course you will have to type “y” to continue. Once the installation is complete you should see something like this:
We are ready for the next step…
Running the web API as service
After completing the web API build, the next thing to do is upload the files produced by the build step to the web server. I’m using a CentOS 7 installation running in a VirtualBox virtual machine, so I can use a shared folder to transfer the files from the host OS to the guest OS. Once this was done, we can test the web API by running this command:
/usr/bin/dotnet /vboxshared/myapi/api.myapi.local/bin/myapi.dll
You should see something similar:
As you can see, the web API is running. Of course, we don’t want to manually run this command at every server restart, so we need a way to make this happen automatically. We con do this be configuring the web API to run as a service. Let’s see how…
First, I will create a link from the Apache “www” directory to the directory where I uploaded the files:
cd /var/www
sudo ln -s /vboxshared/myapi/api.myapi.local api.myapi.local
In your command prompt, go to the folder “/etc/systemd/system” and create the file “api.myapi.local.service”. I will use Nano as text editor:
cd /etc/systemd/system
sudo nano api.myapi.local.service
In the file api.myapi.local.service insert the following content:
[Unit]
Description=api.myapi.local Service
[Service]
WorkingDirectory=/var/www/api.myapi.local/bin
ExecStart=/usr/bin/dotnet /var/www/api.myapi.local/bin/myapi.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=api-myapi-local-service
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
Pay attention to the paths you indicate: they must correspond to the location where you copied the files.
Now execute the following commands:
sudo systemctl daemon-reload
sudo systemctl enable api.myapi.local.service
sudo systemctl start api.myapi.local.service
sudo systemctl status api.myapi.local.service
If everything went well, after executing the last command, you should see something similar:
Now, if your reboot the server and run again the command:
sudo systemctl status api.myapi.local.service
You will see that your web API is has been automatically started.
Configuring Apache
Our web API is now running and listening on TCP port 5000, so you should already be able to use it. But now we want to go one step further: run our web API through Apache configured as reverse proxy.
In your command prompt, go to the directory “/etc/httpd/conf” and edit the file “httpd.conf”:
sudo nano httpd.conf
and add the following configuration block:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}s
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ServerName api.myapi.local
ErrorLog /var/log/httpd/api.myapi.local-error.log
CustomLog /var/log/httpd/api.myapi.local.log common
</VirtualHost>
After that, go the folder “/etc/httpd/conf.d” and edit the file “ssl.conf”:
sudo nano ssl.conf
and add the following configuration block:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}s
</VirtualHost>
<VirtualHost *:443>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
ErrorLog /var/log/httpd/api.myapi.local_ssl-error.log
CustomLog /var/log/httpd/api.myapi.local_ssl.log common
ServerName api.myapi.local
SSLEngine on
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder off
SSLCompression off
SSLSessionTickets on
SSLUseStapling off
SSLCertificateFile /etc/ssl/certs/wildcard.myapi.local.crt
SSLCertificateKeyFile /etc/ssl/certs/wildcard.myapi.local_nopassword.key
</VirtualHost>
As you may have noticed, this configuration block refers to an SSL certificate. Make sure you have one to use for your web API. There are many ways through which you can get an SSL certificate, and I have covered one here.
Additionally, also note that the setup above is for a test / development environment. Check for security risks before using it in a production environment.
Now run this command to check your configuration:
sudo apachectl configtest
If there are no problems, restart Apache to load the new configuration:
sudo systemctl restart httpd
Let’s make a call to test our web API using Insomnia rest client:
As you can see in the screenshot above, I made a call to the login method and the web API correctly responded.
That’s it for now!