I have a new blogpost on auto deployment an ASP.NET 6.0 application from GitHub to an Digital Ocean App.

You can find the post here

In this tutorial we will deploy and host a simple ASP.NET Core 3.1 demo app on Ubuntu 18.04 droplet in Digital Ocean.

You can download or clone the demo app from my GitHub, or you can deploy your own ASP.NET Core 3.1 application. Just keep in my mind that this demo app doesn't make use of a database. So in this tutorial we don't setup a database. Maybe I'll write another tutorial about implementing an MySql server.

We will break this up in different steps:

1. Create Digital Ocean Ubuntu droplet

2. Create a new user in Ubuntu

3. Install .NET SDK in Ubuntu

4. Deploy our ASP.NET Core 3.1 app to Ubuntu

5. Install and configure NGINX in Ubuntu

Create Digital Ocean Ubuntu droplet

Create Digital Ocean account

First of all, you'll need a Digital Ocean account. If you haven't an DO account than you can create an account with this referral link and you'll get $100 credits to spend in the next 60 days.

Create Digital Ocean project

Once you're logged in, create a new project by clicking on the + New Project link:

digital-ocean-create-project 01

In the next screen you'll need to enter an name, description and tell DO what want to do with the project.

digital ocean create project 02

When you're done, click on the Create Project button.

digital ocean create project 03

On the next screen click on the Skip for now link below.

Now it's time to create our droplet.

digital ocean create project 04

Click on the Get Started with a Droplet button

Create Digital Ocean droplet

Now it's time to create a droplet! First we have to choose an image distribution, in our case we choose Ubuntu 18.04.3 (LTS) x64:

digital ocean create droplet 01

We choose the Basic plan for $5/mo (scroll to the left):

digital ocean create droplet 02 digital ocean create droplet 03

We don't need block storage, so we'll skip that.

Choose a data center region close to your hometown, in my case I'll choose Amsterdam:

digital ocean create droplet 04

For the authentication, choose SSH Keys and click on the New SSH Key button:

digital ocean create droplet 05

Then follow the steps described on the right:

digital ocean create droplet 06

Now it's time to finalize and create our droplet. In my case I added backups, but for this demo purposes you don't have to.

digital ocean create droplet 07

Now click on the Create Droplet button.

Now DO will create this droplet (give it some seconds). When everything is done you'll see the droplet and it's IP address. Something like this example:

digital ocean create droplet 07

If you enter the IP address in your browser you'll get an error. This is normal, because we only have a droplet with Ubuntu. But we have to configure our Linux VPS. Let's do this next.

Create a new user in Ubuntu

We need to login into our server. We'll do this through SSH. You can download PUTTY or download PowerShell (Scroll down to assets to download). In my case I'll use PowerShell.

Connect with SSH to the server

Open PowerShell and SSH into your droplet through this command to log in to your server as the root user:

ssh root@

The IP address from my droplet is 167.172.37.58. Change the IP address by your droplets IP address

ssh [email protected]

Type yes if you get this message:

The authenticity of host '167.172.37.58 (167.172.37.58)' can't be established.
ECDSA key fingerprint is SHA256:VodrbvWvtonPzxiFpRiuoq0tTrgZjow+YIGUOXukx7w.
Are you sure you want to continue connecting (yes/no)?

By typing yes the connection closes, so I'll need to login again:

ssh [email protected]

Now you're asked to enter your passphrase. Enter your passphrase (or paste it with the right mouse button) and hit enter:

Enter passphrase for key 'C:\Users\dries.deboosere/.ssh/id_rsa':

Now we're logged in to the server as the root user:

Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-66-generic x86_64)Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-66-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Sun Aug  9 15:24:27 UTC 2020

  System load:  0.0               Processes:           81
  Usage of /:   4.0% of 24.06GB   Users logged in:     0
  Memory usage: 11%               IP address for eth0: 167.172.37.58
  Swap usage:   0%

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

root@ubuntu-s-1vcpu-1gb-ams3-01:~#

Create new user

First we'll create a new user on the server:

adduser USERNAME

A little explanation about these commands:

adduser: create a new user with the name of USERNAME

USERNAME: the username for the new user. In my case I'll use dries as the username

Now enter following commands in PowerShell with your username:

adduser dries

The user dries is now created:

root@ubuntu-s-1vcpu-1gb-ams3-01:~# adduser dries
Adding user `dries' ...
Adding new group `dries' (1000) ...
Adding new user `dries' (1000) with group `dries' ...
Creating home directory `/home/dries' ...
Copying files from `/etc/skel' ...

Now your asked to choose a password. Enter the password and confirm your password:

Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

Now your asked about some information. You can fill this in or press ENTER for the default values. In my case I press ENTER and at the end I choose yes by typing y:

Changing the user information for dries
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] y

Give administrator/sudo privileges to our new user

Now our new user needs to get administrator/sudo privileges. So let set this up. To do this we'll need following commands:

usermod -a -G sudo USERNAME

A little explanation about these commands:

usermod: calls the program

-a: to add the user to a group

-G: to specify the group

sudo: stands for 'super user do'. This will execute root commands as an non-root user.

Now enter following commands in PowerShell with your username:

usermod -a -G sudo dries

Now I want the same ssh key for the root user and for the new created user (dries). We can copy this key by following commands (change dries by your username):

cp -r ~/.ssh /home/dries/
sudo chown -R dries:dries /home/dries/.ssh

Now restart the SSH service by following command:

sudo service ssh restart

Now exit the server by typing the exit command:

exit

Now it's time to login as the new created user:

ssh [email protected]

You'll be asked for the passphrase. Because we copied over the ssh key from root user to dries we can now use the same passphrase from the root user. Enter the passphrase:

Enter passphrase for key 'C:\Users\dries.deboosere/.ssh/id_rsa':

Now you should see this in PowerShell:

dries@ubuntu-s-1vcpu-1gb-ams3-01:~$

This means we're now logged in as user dries in the server.

Install .NET SDK in Ubuntu

Now it's time to install .NET on Ubuntu. We can go to the Microsoft documentation website to see which commands we need to install this on our Ubuntu 18.04 server.

First we install the Microsoft package sources:

wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb

Then we install the .NET 3.1 SDK:

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

Next we check if it's installed by running following command:

dotnet --info

You should see something similar like this:

.NET Core SDK (reflecting any global.json):
 Version:   3.1.302
 Commit:    41faccf259

Runtime Environment:
 OS Name:     ubuntu
 OS Version:  18.04
 OS Platform: Linux
 RID:         ubuntu.18.04-x64
 Base Path:   /usr/share/dotnet/sdk/3.1.302/

Host (useful for support):
  Version: 3.1.6
  Commit:  3acd9b0cd1

.NET Core SDKs installed:
  3.1.302 [/usr/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.App 3.1.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.6 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

Deploy our ASP.NET Core 3.1 app to Ubuntu

Now it's finally time to publish our ASP.NET Core app to the server. But first we need to make some arrangements. We'll going to be using the instructions from the Microsoft documentation to host our ASP.NET Core app on Linux to deploy our app.

For this tutorial I'll use a simple demo ASP.NET Core 3.1 web application. You can use your own application or else you can clone/download my demo application from my GitHub repository.

There are many ways to deploy the files to a server. In this case we will deploy our files through an FTP connection to our server. We can do this through the build in FTP client in Visual Studio or with an FTP client of choice (FileZilla, ...)

Create application folder on our server

We'll deploy our app to the /var/www/ directory from our server. But this doesn't exist yet, so we have to create this folder. We also need to give access to our user we've created and to the www-data user. This www-data user will be used to run the app.

Type in following commands in PowerShell and replace with the name u want to use for your app.

sudo mkdir /var/www/
sudo mkdir /var/www/
sudo chown -R dries:www-data /var/www/

Install an FTP server on Ubuntu

We will install an FTP (File Transfer Protocol) server on Ubuntu so we can transfer our files to Ubuntu.

Make sure that our system packages are up to date by running following command:

sudo apt-get update

Now it's time to install an FTP server. We will using the common open-source FTP utility vsftpd. To install vsftpd enter the following command:

sudo apt install vsftpd

Enter Y to continue

Now start vsftpd by entering following command:

sudo systemctl start vsftpd

To make sure that vsftpd is launched and enabled at startup entering following command:

sudo systemctl enable vsftpd

Open your FTP client of choice (for me this is FileZilla) and make a connection by entering the IP address from your server and your credentials (in my case user dries). Now check if you have access to the following path: /var/www/.

Now we need to config vsftpd so we can upload files. At this moment we can only read files from the server but not upload any file. Open the vsftpd configuration file through PowerShell:

sudo nano /etc/vsftpd.conf

Find the entry write_enable=YES and uncomment this line. Don't forget to save this configuration.

Now restart the vsftpd service:

sudo systemctl restart vsftpd.service

Publish our web application

Now open a new PowerShell window and navigate to your solution folder:

Type in the following command:

dotnet publish

You should see something similar like this:

Now open your Windows Explorer and navigate to the following folder: \bin\Debug\netcoreapp3.1\publish. You'll see that this folder contains several files.

These files and folders need to be uploaded to our server. Select all the files and folders and move/drag them to the /var/www/ folder on the server through an FTP-client.

If everything worked correctly, our app is now ready to run. But if you enter the IP address of your server in a web browser, you will see that this is not working (yet!).

We are almost there! We just need to install a web server on Ubuntu. Let's do that next.

Install and configure NGINX in Ubuntu

Now it's time to install a NGINX webserver and setup a reverse proxy. A reverse proxy will forward requests made to our server to our app. As a webserver we will use NGINX and for the configuration of our reverse proxy server we will follow the Microsoft documentation.

Install NGINX

We follow the NGINX documentation to install NGINX on our Ubuntu release.

We first need to add the repository to our source.list file:

sudo nano /etc/apt/sources.list

At the bottom of the file add following lines:

deb http://nginx.org/packages/ubuntu/ xenial nginx
deb-src http://nginx.org/packages/ubuntu/ xenial nginx

Exit and save the file. Then enter following commands:

sudo apt-get update
sudo apt-get install nginx

Run NGINX though following command:

sudo service nginx start

Enter the IP address from your server in your browser. You should see the default NGINX welcome page:

Add an SSL certificate with Certbot (if you have a domain name!)

When you have a domain name that you can redirect to your IP address then you can secure your website with an SSL certificate from Let's Encrypt by using Certbot.

If you haven't a domain name, then skip this step.

Add the Certbot PPA and install with following commands:

sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx 

Next run the following command and enter your e-mail address when asked. Agree with the Terms of Service by typing A and add your domain name.

sudo certbot --nginx

Forward requests to our app

Now it's time to forward the requests to our app instead of the NGINX welcome page.

Enter following command to configure this:

sudo nano /etc/nginx/sites-available/default

Replace the content of that file with following text:

server {
    listen        80;
    server_name   ;
    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

Now we need to enable the site by linking it to /etc/nginx/sites-enabled/default with following command:

sudo ln -sf /etc/nginx/sites-available/default /etc/nginx/sites-enabled/

We now need to ensure that the default site is included in the http section of the NGINX config file. Edit the file with the following command:

sudo nano /etc/nginx/nginx.conf

And below, where you'll find

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

Add the following line below:

http{
    ...
    include /etc/nginx/sites-available/default;
}

Now restart NGINX:

sudo service nginx restart

Now start the app by the following command:

dotnet //.dll

In my case this command will be:

dotnet /var/www/driesdeboosere-dev-demo-web/DriesDeboosere.Dev.Demo.Web.dll

Type in your browser your IP address now and you should see your website:

Create service

The next task is to set up our web application to run as a service, so you don't have to be logged in to your server for your application to run. Ubuntu uses systemd by default for managing services. So first we need to create a service file (remember the name of the file as this is what you will reference to control it) by entering following commands:

sudo nano /etc/systemd/system/.service

In my case:

sudo nano /etc/systemd/system/driesdeboosere-dev-demo-web.service

Enter the service information:

[Unit]
Description=My application service

[Service]
WorkingDirectory=/var/www/
ExecStart=/usr/bin/dotnet /var/www//.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

In my case:

[Unit]
Description=My application service

[Service]
WorkingDirectory=/var/www/driesdeboosere-dev-demo-web
ExecStart=/usr/bin/dotnet /var/www/driesdeboosere-dev-demo-web/DriesDeboosere.Dev.Demo.Web.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=driesdeboosere-dev-demo-web
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

Give read, write and execute rights to the folder:

sudo chown -R : /var/www/
sudo setfacl -R -d -m u::rwx,g::rwx,o::r /var/www/

In my case:

sudo chown -R dries:dries /var/www/
sudo setfacl -R -d -m u:dries:rwx,g:dries:rwx,o::r /var/www/

Then start the service with following command:

sudo service  start

Or in my case:

sudo service driesdeboosere-dev-demo-web start

Check if it's running:

sudo systemctl | grep 

Or in my case:

sudo systemctl | grep driesdeboosere-dev-demo-web

That's it! Now your web server will keep running your ASP.NET Core app, even if you exit the server.