How to host an Asp.NET core 3.1 application on Linux Ubuntu 20.04 with Apache as reverse proxy

Host an Asp.Net Core Website in Linux without Docker

Preliminary steps: Update the machine

In this step, I just update the machine to have the last packages and updates

Every command it’s executed with sudo for not having problems so I suppose you have root access to launch commands, scripts, and so on.

sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
sudo reboot

Installing the necessary components

After updating and rebooting the machine we will install all the necessary components to run our application including the Asp.NET core framework (3.1), Apache, and the extensions needed to use it as a reverse proxy

Reverse proxy schema
sudo wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y apt-transport-https
sudo apt-get update
sudo apt-get install -y aspnetcore-runtime-3.1
sudo apt-get install -y apache2
sudo apt-get install -y nano
sudo a2enmod ssl headers rewrite proxy proxy_http proxy_html

Opening the ports

Ubuntu comes with an esoteric “Uncomplicated Firewall” app that should help you to configure the firewall easily. Let me say that for not Linux-friendly users like me this is not easy at all, and made mi struggle a lot, so I found that the easiest solution is editing the iptables directly and restart the machine.

sudo nano /etc/iptables/rules.v4
sudo reboot

Publishing the app

If you arrived here this is the easy part: now we need to publish our .net Core Web App. For doing it so we need to publish it Framework Dependent and Portable (or Linux it works anyway)

Publishing the web app
sudo mkdir /var/www/mywebsite
sudo chown -R ubuntu:www-data /var/www/mywebsite
sudo chmod --verbose -R 750 /var/www/mywebsite

Adding Kestrel service to run our application

I’m not explaining what is Kestrel in this article, I just say it’s the default .NET Core Web Server, it’s not production-ready and that’s why we use Apache as reverse proxy on top of it. Kestrel’s launched with the dotnet command and in my case, I’m changing the default port (5000) so you can add more websites with the same system, changing the port obviously for each website.

sudo nano /etc/systemd/system/kestrel-mywebsite.service
[Unit]
Description=My Web App
[Service]
WorkingDirectory=/var/www/mywebsite
ExecStart=/usr/bin/dotnet /var/www/mywebsite/The.App.Entrypoint.dll --urls "http://localhost:5100"
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=mywebsite
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
sudo systemctl enable kestrel-mywebsite.service
sudo systemctl start kestrel-mywebsite.service
sudo systemctl status kestrel-mywebsite.service
sudo journalctl -fu kestrel-mywebsite.service #Checks the events of your servicesudo systemctl stop kestrel-mywebsite.service #Stop the service
sudo systemctl disable kestrel-mywebsite.service #Disable it
# You can even launch the website manually to see if it works with the same command that the service is launching and see if you had runtime errors#Go to your website folder
cd /var/www/mywebsite
#Launch the website as the service does with the dotnet command
/usr/bin/dotnet /var/www/mywebsite/The.App.Entrypoint.dll --urls "http://localhost:5100"

Configure Apache to call Kestrel when a request is done

For this step, I suppose you have a domain name that you want to use with your website so we need to create an Apache website which basically is a .conf file in a specific folder and we copy the content of this file. It’s very important we don’t get wrong with the folder because Apache has sites-available and sites-enabled: we use sites-available and after we enable the website in the proper way

sudo nano /etc/apache2/sites-available/mywebsite.conf
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:5100/
ProxyPassReverse / http://127.0.0.1:5100/
ServerName test.ollie10.it
ServerAlias *.ollie10.it
ErrorLog ${APACHE_LOG_DIR}mywebsite-error.log
CustomLog ${APACHE_LOG_DIR}mywebsite-access.log common
</VirtualHost>
sudo apachectl configtest
sudo a2ensite mywebsite.conf #enable the website
sudo systemctl reload apache2
sudo systemctl restart apache2
The website Working!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Vincenzo Pucarelli

Project Manager and former Architect & Developer specialized in Microsoft technologies since 2004. Living in Madrid, Spain. Techie photographer, travels, wines.