Skip to content

Instantly share code, notes, and snippets.

@ff55lab
Last active July 28, 2023 02:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ff55lab/6d43391b2d0f3e6950845d17ffa8cb1f to your computer and use it in GitHub Desktop.
Save ff55lab/6d43391b2d0f3e6950845d17ffa8cb1f to your computer and use it in GitHub Desktop.
Checklist on How To Deploy ASP .Net Core Web on Ubuntu (Linux) From Windows 10 Machine

Deploy ASP .Net Core Web on Ubuntu (Linux) From Windows 10 Machine

After a year of researched and tried-and-error, finally implemented .Net Core 3.1 on Ubuntu Server 20.04. DigitalOcean has been choosen to live the project.

DigitalOcean Referral Badge

Setup Ubuntu Server 20.04

Deploy Core Feature

Other features

Credits

Shared and suggested ideas on Gist and DigitalOcean.

References

This gist was migrated from this original blog post https://ff55coding.blogspot.com/2020/04/how-to-deploy-asp-net-core-web-on.html.

.Net Core Deployment

Ubuntu, Linux

.Net Core

Disclaimer

All information on this gist is used at your own risk and is not endorsed by any party.

7zip

Install the simplest compression app, 7zip, which supports both Windows and Ubuntu.

user@ubuntu:~$ sudo apt install p7zip-full

To unzip (decompress) the zipped file, run the below command.

user@ubuntu:~$ 7z x zippedfile.7z

Note: [x] argument is to command 7zip to extract all files into the absolute/exact paths as and when compressed the files and folders.

Go to top.

Apache as Reverse Proxy Server

Using existing Apache as the reverse proxy server to forward the incoming HTTP or HTTPS subdomain protocol to the respective .Net Core Runtime service (when there are two or more .Net Core Runtime running together on the same server).

  1. Assuming Apache has been installed.

  2. Create a Virtual host file for each *.conf

user@ubuntu:~$ sudo nano /etc/apache2/sites-available/app1.conf
user@ubuntu:~$ sudo nano /etc/apache2/sites-available/app2.conf

Add the following lines and save the file. Replace Server_IP with your Server IP

<VirtualHost *:80>
     ProxyPreserveHost On
     ProxyPass / http://127.0.0.1:5000/
     ProxyPassReverse / http://127.0.0.1:5000/
     ServerName `Server_IP`
     ServerAlias www.`Server_IP`
     ServerAlias sub.`Server_IP`
     ErrorLog ${APACHE_LOG_DIR}/app1-error.log
     CustomLog ${APACHE_LOG_DIR}/app1-access.log common
</VirtualHost>
  1. Verify file syntax
user@ubuntu:~$ sudo apachectl -t
  1. Enable app1 configuration file, enable proxy server
user@ubuntu:~$ sudo a2ensite app1
user@ubuntu:~$ sudo a2enmod proxy
user@ubuntu:~$ sudo a2enmod proxy_http
  1. Restart the Apache server
user@ubuntu:~$ sudo systemctl restart apache2

Go to top.

Using Certbot to Generate SSL Certificate (Apache2)

Heading to the certbot instruction page at https://certbot.eff.org/instructions

In this example, we refer to apache and DigitalOcean. So, choose the appropriate topic accordingly.

Choose the wildcard topic to implement and support multiple domain names.

Follow the instructions and your server will be implemented with SSL.

Remember to backup the below files in secure and safe place.

  • digitalocean.ini
  • fullchain.pem
  • privkey.pem

The certbot will be automatically scheduled to renew the SSL certificate before it is expired.

Alternatively, run the below command to create certificate:

user@ubuntu:~$ sudo certbot --apache

If you have multiple aliases or sub-domains point to the same host, then type the below command to create certificate:

user@ubuntu:~$ sudo certbot --apache -d main.com -d www.main.com -d sub.main.com

However, you may always test the automatic renewal by the certbot. Type the below command:

user@ubuntu:~$ sudo certbot renew --dry-run

If you accidentally create the wrong certificate, then run the below command:

user@ubuntu:~$ sudo certbot delete

Go to top.

Using Certbot to Generate SSL Certificate

Heading to the certbot instruction page at https://certbot.eff.org/instructions

In this example, we refer to nginx and DigitalOcean. So, choose the appropriate topic accordingly.

Choose the wildcard topic to implement and support multiple domain names, and it will lead us to this specific page https://certbot.eff.org/lets-encrypt/ubuntufocal-nginx

Follow the instructions and your server will be implemented with SSL.

Remember to backup the below files in secure and safe place.

  • digitalocean.ini
  • fullchain.pem
  • privkey.pem

The certbot will be automatically scheduled to renew the SSL certificate before it is expired.

However, you may always test the automatic renewal by the certbot. Type the below command:

user@ubuntu:~$ sudo certbot renew --dry-run

If you accidentally create the wrong certificate, then run the below command:

user@ubuntu:~$ sudo certbot delete

Go to top.

Change the Ownership (chown) of Solution Folder in Web Root Folder

After successfully copied the web solution folder to the web root folder, we need to change the ownership of the web solution folder to current user so that we could run the .Net Core service with current user's privilege.

For example, Solution folder in web root folder: /var/www/yourcorefolder

user@ubuntu:~$ sudo chown -R $USER:$USER /var/www/yourcorefolder

Go to top.

Copy (cp) Solution Folder to Web Root Folder on Ubuntu

After successfully upload the web solution folder on the server, usually inside the user home folder, the web solution folder has to be copied to the web root folder.

For example, Solution folder: yourcorefolder

user@ubuntu:~$ sudo cp -Rv yourcorefolder/ /var/www/

Go to top.

DO (DigitalOcean) Domains and DNS

Nice ready articles by DigitalOcean to setup domains and DNS, and introduction of DNS.

DO provides free DNS management for those who own domain name from external registrars (as DO itself is not domain name registrar yet).

The basic info you may need is to provide DO's nameserver URLs for your domain name registrar so that DO will be became your preferred DNS management. The current DO nameservers URLs are as below:

ns1.digitalocean.com
ns2.digitalocean.com
ns3.digitalocean.com

After successfully setup nameserver URLs on domain name registrar. Next step is.

Manage DNS Records

Next step is to setup DNS records on DO DNS management. There are ready-nice articles to follow to setup DNS records.

Go to top.

(DotNet) .Net Core Runtime

Depending on the versions of .Net Core Runtime and Ubuntu, always check the supported version at official documentation at below links.

Upon writing this page, the .Net Core Runtime was 3.1 and was running on Ubuntu 20.04.

Add Microsoft package signing key

user@ubuntu:~$ wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb

user@ubuntu:~$ sudo dpkg -i packages-microsoft-prod.deb

Install .Net Core Runtime

user@ubuntu:~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

Go to top.

Run .Net Core Instance as Service

Assuming the .Net Core web solution folder (.dll, .config, etc...) has been uploaded to Ubuntu server, and all files have been copied to the web root directory.

For example, Solution folder: yourcorefolder Main assembly dll: yourcorefolder/yourcore.dll Admin user with sudo access: user

/var/www/yourcorefolder/

Create a new service file.

user@ubuntu:~$ sudo nano /etc/systemd/system/kestrel-yourcore.service

Write the following configuration.

[Unit]
Description=My own core service

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

[Install]
WantedBy=multi-user.target
Alias=myowncore.service

Save the configuration file.

Enable and start the newly created service.

user@ubuntu:~$ sudo systemctl enable kestrel-yourcore.service
user@ubuntu:~$ sudo systemctl start kestrel-yourcore.service

Check the service's status.

user@ubuntu:~$ sudo systemctl status kestrel-yourcore.service

Extra note: Below commands help to stop and disable the service.

user@ubuntu:~$ sudo systemctl stop kestrel-yourcore.service
user@ubuntu:~$ sudo systemctl disable kestrel-yourcore.service

Extra note: Below command change the ownership (chown) of web folder for the current user with root access.

user@ubuntu:~$ sudo chown -R $USER:$USER /var/www/yourcorefolder

Go to top.

MariaDB

There is a comprehensive explanation by DigitalOcean discussion on How To Install MariaDB on Ubuntu 20.04

It has a better 'quick' script to enhance the MariaDB security.

user@ubuntu:~$ sudo apt update
user@ubuntu:~$ sudo apt install mariadb-server
user@ubuntu:~$ sudo mysql_secure_installation

Hit Enter key without typing any password if this is newly setup.

Enter current password for root (enter for none):

Key in Y and hit Enter key to setup root password.

Set root password? [Y/n] Y

Setting up the rest of the settings such as:

  • Port number (Default port number 3306)

MariaDB - Adding New Admin Account

Connect to MariaDB service by using newly created root user.

Enter the root password when the service asks.

user@ubuntu:~$ sudo mariadb -uroot -p -P3306
Enter password:

Create new MariaDB login. Example: User id: admin Password: password

MariaDB [(none)]> GRANT ALL ON *.* TO 'admin'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;

Refresh (flush) the latest privileges for newly created admin user.

Then type exit to quit MariaDB connection.

MariaDB [(none)]> FLUSH PRIVILEGES;

MariaDB [(none)]> exit

Go to top.

MySQL Backup and Restore SQL

MySQL comes with utilities to easily backup and restore database via sql.

  1. Using mysqldump to backup database into SQL file.
    user@ubuntu:~$ mysqldump -u [username] -p[password] [database_name] > [backup_file_name].sql
  1. Create database if it is not yet exist.
    MySQL [(none)]> CREATE DATABASE [database_name];
  1. Restore SQL file into existing database.
    user@ubuntu:~$ sudo mysql -u [username] -p[password] [database_name] < [backup_file_name].sql

Go to top.

nginx as Reverse Proxy Server

Using nginx as the reverse proxy server to forward the incoming HTTP or HTTPS subdomain protocol to the respective .Net Core Runtime service (when there are two or more .Net Core Runtime running together on the same server).

Install nginx.

user@ubuntu:~$ sudo apt install nginx

Start the nginx service.

user@ubuntu:~$ sudo service nginx start

Edit the default nginx configuration.

user@ubuntu:~$ nano /etc/nginx/sites-available/default

Assuming there are two .Net Core production instances running to accept different sub-domains.

Example server 1:

Sub-domain address: subdomain.domain.com
Accepted port number: 88888

Example server 2:

Sub-domain address: subdomain2nd.domain.com
Accepted port number: 99999

The nginx configuration will be liked as below.

server {
 listen      80;
 server_name subdomain.domain.com;
 
 location / {
  proxy_pass         http://localhost:88888; # local .Net Core production server with port number 88888
  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;
 }
}

server {
 listen      80;
 server_name subdomain2nd.domain.com;
 
 location / {
  proxy_pass         http://localhost:99999; # local .Net Core production server with port number 99999
  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;
 }
}

Save the configuration file and test the file.

user@ubuntu:~$ sudo nginx -t

If there is no error from the above testing, then reload the nginx configuration.

user@ubuntu:~$ sudo nginx -s reload

Or, restart the nginx service.

user@ubuntu:~$ sudo systemctl restart nginx

Go to top.

Remove/Delete Folder on Ubuntu

You may want to delete the existing solution folder (even when it is not empty) from your local user path.

For example, Solution folder: yourcorefolder

user@ubuntu:~$ rm -r yourcorefolder

Go to top.

Add New User into SUDO (Administrator)

To add new user, type the below command.

root@ubuntu:~$ adduser user

View newly added user with the below command.

root@ubuntu:~$ cat /etc/passwd

Switch User (su) from root to newly added user, try to update apt list.

root@ubuntu:~$ su - user
user@ubuntu:~$ sudo apt update
[sudo] password for user:
user is not in the sudoers file.  This incident will be reported.

To logout user, click [Ctrl + D] to switch back to root user.

Add newly added user into sudo group, type the below command:

root@ubuntu:~$ usermod -aG sudo user
root@ubuntu:~$ groups user
user : user sudo

Now, newly added user should have the sudo privilege. Switch to the user, type the below command:

root@ubuntu:~$ su - user
To run a command as administrator (user "root"), use "sudo ". 
See "main sudo_root" for details.

Try to update apt list again, type the below command:

user@ubuntu:~$ sudo apt update
[sudo] passowrd for user:

To logout user, click [Ctrl + D] to switch back to root user.

Go to top.

Secure Copy files (scp) From Server

Transfer a File from Server

To transfer FILE from server, reverse the source and destination.

C:\Users\user>scp user@ubuntu:/home/user/folder/test.txt .\test\test.txt
  • [/home/user/folder/test.txt] source file.
  • [.\test\test.txt] destination file (error will be displayed if test folder is not exist), is referring to [C:\Users\user\test\test.txt]

or

C:\Users\user>scp user@ubuntu:./folder/test.txt .\test\test.txt
  • [./folder/test.txt] is referring to [/home/user/folder/test.txt]
  • [.\test\test.txt] is referring to [C:\Users\user\test\test.txt]

Transfer a Folder from Server

To transfer files from a FOLDER on server, type the below command:

C:\Users\user>scp -r user@ubuntu:/home/user/folder/ .\test\
  • [.\test] folder will be automatically created if it is not exists, is referring to [C:\Users\user\test] folder.

Go to top.

Secure Copy files (scp) To Server

Transfer a File to Server

To transfer FILE into server, type the below command:

C:\Users\user>scp -P 22 .\test\test.txt user@ubuntu:/home/user/folder/ 
  • [-P] is the port number.
  • [.\test\test.txt] source file, is referring to [C:\Users\user\test\test.txt]
  • [/home/user/folder/] destination file.

or

C:\Users\user>scp .\test\test.txt user@ubuntu:/home/user/folder/
  • Without [-P], port 22 will be defaulted.
  • [.\test\test.txt] is referring to [C:\Users\user\test\test.txt]

or

C:\Users\user>scp .\test\test.txt user@ubuntu:
  • Without [/home/user/folder/] , [/home/user/] will be defaulted.

Transfer a Folder to Server

To transfer files a local FOLDER into server, type the below command:

C:\Users\user>scp -r .\folder\ user@ubuntu:/home/user/
  • [-r] is recursive command.
  • [.\folder] source folder.
  • [/home/user/] destination folder.

Go to top.

Connect to Server

To connect to server, type below command

C:\Users\user>ssh -p 22 user@ubuntu

[-p] is the port number

or

C:\Users\user>ssh user@ubuntu

Without [-p], port 22 is defaulted.

Go to top.

Create Private Key and Public Key via [ssh-keygen] and login with SSH

Open Windows Command Prompt, type the below command

C:\Users\user>ssh-keygen

Type-in file whatever name [example: .ssh/id_ubuntu] then press [Enter] Empty passphrase then press [Enter] Empty same passphrase then press [Enter]

C:\Users\user>ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\user/.ssh/id_rsa): .ssh/id_ubuntu
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_ubuntu.
Your public key has been saved in id_ubuntu.pub.
The key fingerprint is:
SHA256:u3ZN7**************9yoPKGTO61************ user@machineName
The key's randomart image is:
+---[RSA 2048]----+
..
*****
o=o E
+ ..+****
o * **** .
o + ..= + .
|o + .****=.+
* =o * .***** .
|. =.******+o o.
+----[SHA256]-----+

Two files will be generated:

  1. [C:\Users\user.ssh\id_ubuntu] Private key - Safely keep into machine.
  2. [C:\Users\user.ssh\id_ubuntu.pub] Public key - Later copy this public key into Ubuntu server.

Go to top.

Copy Public Key into Server

Open two Windows Command Prompts.

1. Command Prompt to copy Public Key content

Type the below command:

C:\Users\user>more .ssh\id_ubuntu.pub
ssh-rsa 4T0Cz5j0evdkeWED7+3vdlWIyqvsuKcnaGvK/ejyx6A7v2P5l5dN7iBcnaqUSq6vMO7dCu2mzH2Q3nWCNYmlxjuB3NzaC1yc2EAAAADKnlSPtgZVOPUVUJUA0NnKfIxAWJ3EbmhVPIkPWuVASfaob8htB6YbQ2mIF5B+tQB1d3H+VoGute91VFoIcURXpsrhA3SysmYVxPaeTjAQABCCABAQD2tcGYd2oh3vRAp38UBXt09CrT8ecdr66zTdCpoL+AOv4ybHlgQ6cGw4X1IOsDvxp1o2NUGKCZXLWiOuyC/5Sl93y7IvJkkFF5FN5Re+f+y0Vc6qCh8rtbC0SpHowOjkbg+mhhAAA user@machineName

Copy [Ctrl + C] the above Public Key into memory.

2. Create SSH folder [~/.ssh] into newly created user Home folder

Provided that you have already switch into new user login from root user.

user@ubuntu:~$ mkdir -p ~/.ssh
user@ubuntu:~$ nano ~/.ssh/authorized_keys
user@ubuntu:~$ chmod -R go= ~/.ssh
user@ubuntu:~$ chown -R $USER:$USER ~/.ssh

Similar guideline can be found at DigitalOcean.

How to Upload an SSH Public Key to an Existing Droplet

3. Command Prompt to copy Public Key into Server

user@ubuntu:~$ sudo nano .ssh/authorized_keys

In the nano editor, paste the Public Key into authorized_keys file as one line. Save the file.

Restart the ssh service, type the below command:

user@ubuntu:~$ sudo systemctl restart ssh

Go back to Command Prompt 1, type in below command to login into server:

C:\Users\user>ssh -i .ssh\id_ubuntu user@ubuntu
  • [-i .ssh\file_name] is to specific the actual location of your private key.
  • Ubuntu server, by default, will read [.ssh\id_rsa] file as default private key.

or

C:\Users\user>ssh user@ubuntu

At this point, the login screeen will not ask to enter password anymore instead login automatically.

Go to top.

Install OpenSSH Client on Windows 10

OpenSSH client is installable features of Windows 10 1809.

To install OpenSSH, open the Settings then go to Apps > Apps and Features > Manage Optional Features.

Scan the list to see if OpenSSH client is already installed. If not, then at the top of the page select "Add a feature", then:

To install the OpenSSH client, locate "OpenSSH Client", then click "Install".

Once the installation is completed, return to the Apps > Apps and Features > Manage Optional Features and you should able to see the OpenSSH component(s) is being listed.

Guide from https://docs.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse

Go to top.

Allow Specific Users

Edit ssh configuration file, type the below command:

user@ubuntu:~$ sudo nano /etc/ssh/sshd_config

Add in the below [AllowUsers] command to limit the specific user to login, and then save the file.

AllowUsers user

Restart ssh service to apply the new rule, type the below command:

user@ubuntu:~$ sudo systemctl restart ssh

Now, the only user is allowed to login into server.

Go to top.

Change Port Number Other Than 22

Edit ssh configuration file, type the below command:

user@ubuntu:~$ sudo nano /etc/ssh/sshd_config

Change the [Port] number to the desired number then save the file.

Port 1234

Install netstat manually if netstat is not found.

user@ubuntu:~$ sudo apt install net-tools

Guideline on How to Install netstat Command in Linux.

Check ssh listening ports, type the below command:

user@ubuntu:~$ sudo netstat -tulpn |grep ssh
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      865/sshd: /usr/sbin 
tcp6       0      0 :::22                   :::*                    LISTEN      865/sshd: /usr/sbin

Restart ssh service to listen to new port, type the below command:

user@ubuntu:~$ sudo systemctl restart ssh
user@ubuntu:~$ sudo netstat -tulpn |grep ssh
tcp        0      0 0.0.0.0:1234            0.0.0.0:*               LISTEN      1865/sshd: /usr/sbin
tcp6       0      0 :::1234                 :::*                    LISTEN      1865/sshd: /usr/sbin

To ssh login on the new port, need to specify port number.

C:\Users\user>ssh -p 1234 user@ubuntu
  • Same goes to scp, need to specify the port number if it is other than the default port number 22.

Go to top.

Disable Password Authentication

To disable password authentication login, type the below command:

root@ubuntu:~$ sudo nano /etc/ssh/sshd_config

Type / Find the below [PasswordAuthentication] command within the nano editor, and set to no value

PasswordAuthentication no

Restart ssh server, type the below command:

root@ubuntu:~$ sudo systemctl restart ssh

Go to top.

Disable ROOT user

To disable root login, type the below command:

root@ubuntu:~$ sudo nano /etc/ssh/sshd_config

Type / Find the below [PermitRootLogin] parameter in the nano editor, and set to no value.

PermitRootLogin no

Restart ssh server, type the below command:

root@ubuntu:~$ sudo systemctl restart ssh

Go to top.

Mount File System via SSHFS

At this point of time, there is no official tool to do this on Windows.

Go to top.

Choose Time Zone

If your system is not built for UTC Time Zone, then you may need to set specific Time Zone.

List all available time zones, type the below command:

user@ubuntu:~$ timedatectl list-timezones

From the above listed time zones, choose the one your system is built for. Type the below command to set:

user@ubuntu:~$ sudo timedatectl set-timezone Asia/Kuala_Lumpur

You may check again the set time zone, type the below command:

user@ubuntu:~$ timedatectl status | grep "Time zone"

Go to top.

Uncomplicated Firewall (ufw) Secures Ports

For a web server, the usual default Port Numbers are 80 (http), 443 (https / SSL), and 22 (ssh).

We can use (ufw) to allow only these 3 port numbers as incoming ports.

Assumption: You have setup a different port number for ssh (example: 1234), then you can allow it via ufw.

However, important, this should be the LAST step before enable (ufw) as this tool could locks the whole operating system until you restore the last OS's image or re-create new OS's image.

user@ubuntu:~$ sudo ufw default deny incoming
user@ubuntu:~$ sudo ufw default allow outgoing
user@ubuntu:~$ sudo ufw allow 80
user@ubuntu:~$ sudo ufw allow 443
user@ubuntu:~$ sudo ufw allow 1234
user@ubuntu:~$ sudo ufw enable

You may refer to this article to set up Firewall: How To Set Up a Firewall with UFW on Ubuntu 20.04.

Go to top.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment