Published in


Deploying ASP.NET & DotVVM web applications to a Linux virtual machine in Azure

Hey, there! It’s a pleasure to be able to greet you. In this new article we will learn step by step how to deploy our web applications with ASP.NET (with a DotVVM project as an example) on an Ubuntu Server 20.04 virtual machine under the concept infrastructure as a service in Microsoft Azure.

Given these considerations, here are the important points that we will review in this tutorial article:

  • Create a virtual machine with a Linux distribution in Azure.
  • Install the .NET environment and an Apache server on the virtual machine.
  • Publish the ASP.NET web application in Visual Studio 2019.
  • Host the web application on the virtual machine.
  • Plus: Attach a database to the virtual machine.

Part 1: Create a virtual machine with a Linux distribution in Azure

To start, we must have a subscription in Azure, if we do not have an account we can get a free one here:

As a first step, we need to go to the Azure portal and find the Virtual Machines resource and create a new one. In the creation process we will have several important parts for the creation of the resource. Each of these parts is detailed below.


To begin with, you need to specify the subscription and resource group, then the details of the instance to create. This is where we will define the operating system that the virtual machine will have and the size of it. For our goals, we will work with Ubuntu Server 20.04.

Then we need to define the virtual machine administrator account information through the username and password. This data is very important as it will allow us to access the virtual machine later. For this purpose we have two options, either generate an SSH public key, or set an access password. For this case, we will select the password option and we will have something like this:

Finally, in the general section we can define rules for the ports of the virtual machine. In this case we will enable port 80 for HTTP connections that will allow access to the website from the internet browser. The other port is SSH (22), which will allow us to access the virtual machine remotely.


Once you have specified the general aspects, you can perform a general review of the parameters set and create the resource. In another scenario, we can also specify in detail the disk configuration for the virtual machine, whether ssd or HDD type, network configuration and load balancing, management and extension management.

Once these configurations are complete and the creation process has begun, this operation will take a few minutes to execute.

With the resource ready, we can now go to the main section of the resource in Azure and get the public IP address assigned to our VM.

If this is the case, in the configuration of the public IP we can establish that this IP address is static, that is, that the address does not change at the time of restarting the virtual machine. On the other hand, we can also establish a DNS for this public IP address.

Part 2: Install the .NET environment and an Apache server on the virtual machine

Now that we have the virtual machine with Ubuntu Server 20.04 set in Azure, we will connect remotely via the SSH (Secure SHell) protocol through the command console.

In this case, we’ll run the following command with the username (set at the time the VM was created in Azure), followed by the IP address or DNS:

ssh azureuser@

Here we will have to enter our access credentials:

.NET Installation

All right, to get started we’ll install the .NET SDK. Installation with APT can be done with a few commands. Before installing .NET, we need to add the Microsoft package signing key to the list of trusted keys and add the package repository.

wget -O packages-microsoft-prod.debsudo dpkg -i packages-microsoft-prod.deb

When you install the .NET SDK, you do not need to install the corresponding runtime environment. To install the .NET SDK, we must run the following commands:

sudo apt-get update
sudo apt-get install -y apt-transport-https
sudo apt-get update
sudo apt-get install -y dotnet-sdk-5.0

With this process, we will already have .NET installed on our virtual machine. To perform a verification of the installed SDK, we can enter the following command:

dotnet --version

Apache Installation

To expose our application to the internet, we need IIS (Internet Information Services), Nginx, or Apache as a reverse proxy server that accepts the HTTP request and forwards it to Kestrel (a web server that is included and enabled by default in the ASP.NET project templates).

Given these considerations, we must enter the following command to install Apache:

sudo apt-get install apache2

Considering that port 80 of the virtual machine is open, now we can copy the public IP or DNS and run it in the browser, if apache is installed correctly, we can display the default apache page:

Now, we need to enable Apache’s modproxy modules so that it can function as a reverse proxy:

systemctl restart apache2
a2enmod proxy proxy_http proxy_html

Part 3: Publish the web application with ASP.NET in Visual Studio 2019

Up to this point, the machine with Ubuntu Server 20.04 on Azure is with all the required components. From this point on, we’ll start with the process of deploying a web application to the .NET virtual machine.

To exemplify this scenario, we will deploy a web application with the DotVVM framework, based on the MVVM (Model, View, ViewModel) pattern on ASP.NET 5.

The first thing we will do is go to our solution in Visual Studio 2019 to select the main project (in this case with DotVVM) in .NET, and click on the Publish button:

In the dialog box that is displayed, we will create a new publishing profile of type Folder, and specify the path where we want our files to be deployed:

Finally, we will publish our solution from the profile created:

When finished, our files will have been deployed in the previously specified folder:

We will use these files in the next step within the virtual machine.

Part 4: Host the web application on the virtual machine

Configure the Apache server

All configuration files in Apache are stored in the /etc/apache2/conf-enabled directory. Back to our virtual machine via an SSH connection, we will need to create a .conf file for our web application. We can do this by opening the nano text editor as follows:

sudo nano /etc/apache2/conf-enabled/DotNetApp.conf

Note: the name of the file may be what we want to specify.

In DotNetApp.conf, we will insert the following content:

<VirtualHost *:80>  
ProxyPreserveHost On
ProxyPass /
ProxyPassReverse /
ErrorLog /var/log/apache2/DotNetApp-error.log
CustomLog /var/log/apache2/DotNetApp-access.log common

In .NET, web applications by the command console run by default on port 5000, in case we wanted our application to run on another port, we can specify the execution port in the webBuilder within the Program.cs class of our project as follows:


Also, in the configuration file DotNetApp.conf we are indicating that our application can be accessed from port 80. If this is the case, we could change the port, however, it is important to remember to enable the port in question from the virtual machine settings in Azure.

Copy the application files to the virtual machine

What we have to do now is configure our web application so that it can be accessed from port 80. In this sense, what we will do at this time is to copy the files previously deployed in Visual Studio 2019 to the virtual machine. We will do this from the /var/ directory:

cd /var/
sudo mkdir DotNetApp

Now, we will have to perform the file transfer. From Windows, we can use the WinSCP program to connect to the virtual machine and perform this process.

WinSCP Installer:

Once WinSCP is installed and initialized, we will create a new session with the credentials of our Azure virtual machine:

With this connection, in the user by default we can create a new folder, for example, App, and in it copy the files of our application:

Now all the files have been uploaded to the VM, in the next step we need to move the files from the /home/azureuser/App directory to the /var/DotNetApp directory:

cd /home/azureuser/App
sudo cp -R * /var/DotNetApp/

With this process, our web application is already hosted on the virtual machine as such:

Create a service to start and monitor the web application.

To create this service file that will allow us to launch our web application, we will open the nano editor:

sudo nano /etc/systemd/system/kestrel-DotNetApp.service

In this file we will add the following content to provide the working directory and which file must be run to get the web application up and running.

Description=Aspnet 5 Web App running on Ubuntu
ExecStart=/usr/bin/dotnet /var/DotNetApp/UserDashboard.dll

Now, we’ll enable and start the created service:

sudo systemctl enable kestrel-DotNetApp.service  
sudo systemctl start kestrel-DotNetApp.service

With the status attribute we can check the status of the service:

Finally we can restart the Apache server and see that our application is running from port 80 as well:

systemctl restart apache2 
sudo service apache2 restart

Now that the hosting and all the corresponding settings have been made, we can now access the browser using the assigned public IP, or dns name, and see our web application ASP.NET with DotVVM running correctly on top of the Linux VM on Azure.

Plus: Add a database to the virtual machine

Up to this point we have already deployed our application, however, most (if not all) web projects are associated with a database. In this case, let’s look at an example on how to install a PostgreSQL database inside the virtual machine, and associate it with our project with DotVVM in ASP.NET 5.

To install PostgreSQL we will type the following command:

sudo apt install postgresql postgresql-contrib

Then, it is necessary within the configuration of the virtual machine in Azure to enable port 5432 to access PostgreSQL remotely.

Now, in Ubuntu Server we must modify the file pg_hba.conf to allow connections to PostgreSQL remotely:

sudo nano /etc/postgresql/12/main/pg_hba.conf

Inside the pg_hba.conf file, in the IPv4 local connections section we will leave the corresponding statement as follows:

# IPv4 local connections:
host all all all md5

The last file that we will have to modify is called: postgresql.conf. This configuration will be used to set the IP addresses that can be connected to PostgreSQL remotely:

sudo nano /etc/postgresql/12/main/postgresql.conf

In the section Connections and Authentication we’ll remove the # symbol and we’ll be left with the following statement:

listen_addresses = '*'

Finally we must restart the database service:

sudo service postgresql restart

With these settings we can already set a user to access the database, this could be an example:

sudo -u postgres psqlCREATE USER admin PASSWORD 'Abc#1234'

Then, we only have to make the corresponding configurations in our database. To do this we can connect remotely with the user we just created:

Finally, according to our example, in the web application we should establish this new connection to the database.


To reflect these changes in production, we need to replace the files or file with the new configuration in /var/DotNetApp, and restart the associated services (Kestrel and Apache).

What’s next?

With this article we have everything step by step how to deploy a web application with ASP.NET 5 and DotVVM from Visual Studio 2019 to a virtual machine with Ubuntu Server 20.04 on Azure. Here are additional resources so you can continue to learn about developing apps with .NET and azure:

Thanks for reading

Thank you very much for reading, I hope you found this article interesting and may be useful in the future. If you have any questions or ideas that you need to discuss, it will be a pleasure to be able to collaborate and exchange knowledge together.

See you on Twitter! Or if you like you can also write to me on Instagram or on Telegram. :=)



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
Daniel Gomez Jaramillo

Daniel Gomez Jaramillo

Microsoft MVP (Most Valuable Professional)