Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / Blazor

Deploying Blazor Server-side to the Linux Distro Ubuntu

3.48/5 (8 votes)
3 Jun 2020CPOL5 min read 31.6K  
Step by step process to deploy Blazor Server-side app to an existing installation of Linux Distro Ubuntu
This article is part of a series of articles. This article describes how to deploy an existing Blazor Server-side app to an existing installation of Linux Distro Ubuntu. The article presumes a basic understanding of Linux and Blazor Server-side. By the end of the article, you will know how to deploy to an existing base Linux Distro Ubuntu installation an existing Blazor Server-side App.

Introduction

This article is a step by step guide on how to get a Blazor Server-side Web App working on Ubuntu Linux.

The other article in the series that you can use depending on your needs is:

Installation Instructions (Detailed for Beginners)

For those who do not want detailed instructions, there is a summary at the end of the articles which just lists all the commands used in the article without any output.

The way the article is written is for leaving no doubt as to what commands to use in a detailed step by step fashion. The listing of output is for those who get errors and want to see what good working output, like mine, is supposed to look like.

First, have the latest version of Ubuntu installed. From your favourite Terminal Command Line, type the following commands in the listed order.

This first step is to go to check which version of Ubuntu you are on:

akshays@CodeProjectUbuntu:~$ lsb_release -a
No LSB modules are available.
Distributor ID:    Ubuntu
Description:    Ubuntu 20.04 LTS
Release:    20.04
Codename:    focal

I am on 20.04 version. So go to packages.microsoft.com/config/ubuntu. Check for a directory with your version. Then check for the file inside the directory called packages-microsoft-prod.deb. So for my version as of writing this article, run the following command:

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

Check if the file was downloaded with:

akshays@CodeProjectUbuntu:~$ ls
Desktop  Documents  Downloads  Music  packages-microsoft-prod.deb  
Pictures  Public  snap  Templates  Videos

Now install the package with:

akshays@CodeProjectUbuntu:~$ sudo dpkg -i packages-microsoft-prod.deb
Selecting previously unselected package packages-microsoft-prod.
(Reading database ... 184434 files and directories currently installed.)
Preparing to unpack packages-microsoft-prod.deb ...
Unpacking packages-microsoft-prod (1.0-ubuntu20.04.1) ...
Setting up packages-microsoft-prod (1.0-ubuntu20.04.1) ...

Next step is to update the packages:

akshays@CodeProjectUbuntu:~$ sudo apt-get update
Get:1 http://security.ubuntu.com/ubuntu focal-security InRelease [107 kB]
Hit:2 http://in.archive.ubuntu.com/ubuntu focal InRelease          
Hit:3 http://in.archive.ubuntu.com/ubuntu focal-updates InRelease                    
Hit:4 http://in.archive.ubuntu.com/ubuntu focal-backports InRelease                
Get:5 https://packages.microsoft.com/ubuntu/20.04/prod focal InRelease [10.5 kB]          
Get:6 https://packages.microsoft.com/ubuntu/20.04/prod focal/main amd64 Packages [6,506 B]
Fetched 124 kB in 2s (72.0 kB/s)    
Reading package lists... Done

If you are using SSL (Secure Sockets Layer) HTTPS, then do the following:

akshays@CodeProjectUbuntu:~$ sudo apt-get install apt-transport-https
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  apt-transport-https
0 upgraded, 1 newly installed, 0 to remove and 40 not upgraded.
Need to get 1,708 B of archives.
After this operation, 160 kB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu focal-updates/universe amd64 
apt-transport-https all 2.0.2ubuntu0.1 [1,708 B]
Fetched 1,708 B in 0s (45.9 kB/s)              
Selecting previously unselected package apt-transport-https.
(Reading database ... 184442 files and directories currently installed.)
Preparing to unpack .../apt-transport-https_2.0.2ubuntu0.1_all.deb ...
Unpacking apt-transport-https (2.0.2ubuntu0.1) ...
Setting up apt-transport-https (2.0.2ubuntu0.1) ...

Next, install the .NET Core SDK:

akshays@CodeProjectUbuntu:~$ sudo apt-get install dotnet-sdk-3.1
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  aspnetcore-runtime-3.1 aspnetcore-targeting-pack-3.1 dotnet-apphost-pack-3.1 
  dotnet-host dotnet-hostfxr-3.1 dotnet-runtime-3.1 dotnet-runtime-deps-3.1
  dotnet-targeting-pack-3.1 netstandard-targeting-pack-2.1
The following NEW packages will be installed:
  aspnetcore-runtime-3.1 aspnetcore-targeting-pack-3.1 dotnet-apphost-pack-3.1 
  dotnet-host dotnet-hostfxr-3.1 dotnet-runtime-3.1 dotnet-runtime-deps-3.1
  dotnet-sdk-3.1 dotnet-targeting-pack-3.1 netstandard-targeting-pack-2.1
0 upgraded, 10 newly installed, 0 to remove and 40 not upgraded.
Need to get 78.7 MB of archives.
After this operation, 337 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 dotnet-host amd64 3.1.4-1 [32.9 kB]
Get:2 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 dotnet-hostfxr-3.1 amd64 3.1.4-1 [121 kB]
Get:3 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 dotnet-runtime-deps-3.1 amd64 3.1.4-1 [2,668 B]
Get:4 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 dotnet-runtime-3.1 amd64 3.1.4-1 [21.8 MB]
Get:5 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 aspnetcore-runtime-3.1 amd64 3.1.4-1 [5,762 kB]
Get:6 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 dotnet-targeting-pack-3.1 amd64 3.1.0-1 [1,988 kB]
Get:7 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 aspnetcore-targeting-pack-3.1 amd64 3.1.3-1 [949 kB]
Get:8 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 dotnet-apphost-pack-3.1 amd64 3.1.4-1 [42.5 kB]
Get:9 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
      amd64 netstandard-targeting-pack-2.1 amd64 2.1.0-1 [1,474 kB]
Get:10 https://packages.microsoft.com/ubuntu/20.04/prod focal/main 
       amd64 dotnet-sdk-3.1 amd64 3.1.300-1 [46.5 MB]
Fetched 78.7 MB in 16s (5,012 kB/s)
Selecting previously unselected package dotnet-host.
(Reading database ... 184446 files and directories currently installed.)
Preparing to unpack .../0-dotnet-host_3.1.4-1_amd64.deb ...
Unpacking dotnet-host (3.1.4-1) ...
Selecting previously unselected package dotnet-hostfxr-3.1.
Preparing to unpack .../1-dotnet-hostfxr-3.1_3.1.4-1_amd64.deb ...
Unpacking dotnet-hostfxr-3.1 (3.1.4-1) ...
Selecting previously unselected package dotnet-runtime-deps-3.1.
Preparing to unpack .../2-dotnet-runtime-deps-3.1_3.1.4-1_amd64.deb ...
Unpacking dotnet-runtime-deps-3.1 (3.1.4-1) ...
Selecting previously unselected package dotnet-runtime-3.1.
Preparing to unpack .../3-dotnet-runtime-3.1_3.1.4-1_amd64.deb ...
Unpacking dotnet-runtime-3.1 (3.1.4-1) ...
Selecting previously unselected package aspnetcore-runtime-3.1.
Preparing to unpack .../4-aspnetcore-runtime-3.1_3.1.4-1_amd64.deb ...
Unpacking aspnetcore-runtime-3.1 (3.1.4-1) ...
Selecting previously unselected package dotnet-targeting-pack-3.1.
Preparing to unpack .../5-dotnet-targeting-pack-3.1_3.1.0-1_amd64.deb ...
Unpacking dotnet-targeting-pack-3.1 (3.1.0-1) ...
Selecting previously unselected package aspnetcore-targeting-pack-3.1.
Preparing to unpack .../6-aspnetcore-targeting-pack-3.1_3.1.3-1_amd64.deb ...
Unpacking aspnetcore-targeting-pack-3.1 (3.1.3-1) ...
Selecting previously unselected package dotnet-apphost-pack-3.1.
Preparing to unpack .../7-dotnet-apphost-pack-3.1_3.1.4-1_amd64.deb ...
Unpacking dotnet-apphost-pack-3.1 (3.1.4-1) ...
Selecting previously unselected package netstandard-targeting-pack-2.1.
Preparing to unpack .../8-netstandard-targeting-pack-2.1_2.1.0-1_amd64.deb ...
Unpacking netstandard-targeting-pack-2.1 (2.1.0-1) ...
Selecting previously unselected package dotnet-sdk-3.1.
Preparing to unpack .../9-dotnet-sdk-3.1_3.1.300-1_amd64.deb ...
Unpacking dotnet-sdk-3.1 (3.1.300-1) ...
Setting up dotnet-host (3.1.4-1) ...
Setting up dotnet-apphost-pack-3.1 (3.1.4-1) ...
Setting up netstandard-targeting-pack-2.1 (2.1.0-1) ...
Setting up dotnet-targeting-pack-3.1 (3.1.0-1) ...
Setting up aspnetcore-targeting-pack-3.1 (3.1.3-1) ...
Setting up dotnet-runtime-deps-3.1 (3.1.4-1) ...
Setting up dotnet-hostfxr-3.1 (3.1.4-1) ...
Setting up dotnet-runtime-3.1 (3.1.4-1) ...
Setting up aspnetcore-runtime-3.1 (3.1.4-1) ...
Setting up dotnet-sdk-3.1 (3.1.300-1) ...
This software may collect information about you and your use of the software, 
and send that to Microsoft.
Please visit http://aka.ms/dotnet-cli-eula for more information.
Welcome to .NET Core!
---------------------
Learn more about .NET Core: https://aka.ms/dotnet-docs
Use 'dotnet --help' to see available commands or visit: https://aka.ms/dotnet-cli-docs

Telemetry
---------
The .NET Core tools collect usage data in order to help us improve your experience. 
The data is anonymous and doesn't include command-line arguments. 
The data is collected by Microsoft and shared with the community. 
You can opt-out of telemetry by setting the DOTNET_CLI_TELEMETRY_OPTOUT 
environment variable to '1' or 'true' using your favorite shell.

Read more about .NET Core CLI Tools telemetry: https://aka.ms/dotnet-cli-telemetry

Configuring...
--------------
A command is running to populate your local package cache to improve 
restore speed and enable offline access. This command takes up to one minute 
to complete and only runs once.
Processing triggers for man-db (2.9.1-1) ...

Then update the packages just in case:

akshays@CodeProjectUbuntu:~$ sudo apt-get update
Hit:1 http://in.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 http://in.archive.ubuntu.com/ubuntu focal-updates InRelease            
Hit:3 http://in.archive.ubuntu.com/ubuntu focal-backports InRelease          
Get:4 http://security.ubuntu.com/ubuntu focal-security InRelease [107 kB]
Hit:5 https://packages.microsoft.com/ubuntu/20.04/prod focal InRelease         
Fetched 107 kB in 2s (63.1 kB/s)                         
Reading package lists... Done

If you do not want the .NET Core SDK but only want the runtime, then check for the latest version of the .NET Core runtime, in my case, it is 3.1, and run the following command:

akshays@CodeProjectUbuntu:~$ sudo apt-get install aspnetcore-runtime-3.1

Check your version of .NET Core with:

akshays@CodeProjectUbuntu:~$ dotnet --version
3.1.300

Go to the following URL and check to see if you got the latest .NET Core version including security updates:

Now install Nginx, web server, to serve up your Blazor Server-side Web App:

akshays@CodeProjectUbuntu:~$ sudo apt-get install nginx
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter 
  libnginx-mod-mail libnginx-mod-stream nginx-common nginx-core
Suggested packages:
  fcgiwrap nginx-doc
The following NEW packages will be installed:
  libnginx-mod-http-image-filter libnginx-mod-http-xslt-filter 
  libnginx-mod-mail libnginx-mod-stream nginx nginx-common nginx-core
0 upgraded, 7 newly installed, 0 to remove and 40 not upgraded.
Need to get 602 kB of archives.
After this operation, 2,134 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
nginx-common all 1.17.10-0ubuntu1 [37.3 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
libnginx-mod-http-image-filter amd64 1.17.10-0ubuntu1 [14.3 kB]
Get:3 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
libnginx-mod-http-xslt-filter amd64 1.17.10-0ubuntu1 [12.5 kB]
Get:4 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
libnginx-mod-mail amd64 1.17.10-0ubuntu1 [42.3 kB]
Get:5 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
libnginx-mod-stream amd64 1.17.10-0ubuntu1 [66.9 kB]
Get:6 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
nginx-core amd64 1.17.10-0ubuntu1 [425 kB]
Get:7 http://in.archive.ubuntu.com/ubuntu focal/main amd64 
nginx all 1.17.10-0ubuntu1 [3,616 B]
Fetched 602 kB in 0s (1,662 kB/s)
Preconfiguring packages ...
Selecting previously unselected package nginx-common.
(Reading database ... 187228 files and directories currently installed.)
Preparing to unpack .../0-nginx-common_1.17.10-0ubuntu1_all.deb ...
Unpacking nginx-common (1.17.10-0ubuntu1) ...
Selecting previously unselected package libnginx-mod-http-image-filter.
Preparing to unpack .../1-libnginx-mod-http-image-filter_1.17.10-0ubuntu1_amd64.deb ...
Unpacking libnginx-mod-http-image-filter (1.17.10-0ubuntu1) ...
Selecting previously unselected package libnginx-mod-http-xslt-filter.
Preparing to unpack .../2-libnginx-mod-http-xslt-filter_1.17.10-0ubuntu1_amd64.deb ...
Unpacking libnginx-mod-http-xslt-filter (1.17.10-0ubuntu1) ...
Selecting previously unselected package libnginx-mod-mail.
Preparing to unpack .../3-libnginx-mod-mail_1.17.10-0ubuntu1_amd64.deb ...
Unpacking libnginx-mod-mail (1.17.10-0ubuntu1) ...
Selecting previously unselected package libnginx-mod-stream.
Preparing to unpack .../4-libnginx-mod-stream_1.17.10-0ubuntu1_amd64.deb ...
Unpacking libnginx-mod-stream (1.17.10-0ubuntu1) ...
Selecting previously unselected package nginx-core.
Preparing to unpack .../5-nginx-core_1.17.10-0ubuntu1_amd64.deb ...
Unpacking nginx-core (1.17.10-0ubuntu1) ...
Selecting previously unselected package nginx.
Preparing to unpack .../6-nginx_1.17.10-0ubuntu1_all.deb ...
Unpacking nginx (1.17.10-0ubuntu1) ...
Setting up nginx-common (1.17.10-0ubuntu1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → 
/lib/systemd/system/nginx.service.
Setting up libnginx-mod-http-xslt-filter (1.17.10-0ubuntu1) ...
Setting up libnginx-mod-mail (1.17.10-0ubuntu1) ...
Setting up libnginx-mod-http-image-filter (1.17.10-0ubuntu1) ...
Setting up libnginx-mod-stream (1.17.10-0ubuntu1) ...
Setting up nginx-core (1.17.10-0ubuntu1) ...
Setting up nginx (1.17.10-0ubuntu1) ...
Processing triggers for systemd (245.4-4ubuntu3.1) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for ufw (0.36-6) ...

Now to start the Nginx webserver service:

akshays@CodeProjectUbuntu:~$ sudo service nginx start

Now we will test if the Nginx web server is working by displaying its default installation web page by going to the following URL in the web browser of your choice:

http://codeprojectubuntu/index.nginx-debian.html

Or:

localhost/index.nginx-debian.html

You should see the Nginx welcome web page displayed in your web browser. Now we have Nginx installed properly and confirmed to be working, let us configure Nginx Proxy. The first step is to go to the configuration file directory which is in etc. Then list the files in the direction and you will find a default configuration file:

akshays@CodeProjectUbuntu:~$ cd /etc/nginx/sites-available/
akshays@CodeProjectUbuntu:/etc/nginx/sites-available$ ls
default

Now edit the default configuration file to set it up with the Proxy for your .NET Core Blazor Server-side Web App in the location element as follows:

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;
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
}

I use the joe terminal text editor from 1990ish on UNIX. It is libcurses based from those days so it is much easier to use than vi, etc. I have made some small video games with it for fun back then. It is not installed by default on Ubuntu so you need to run the following command to install it:

akshays@CodeProjectUbuntu:/etc/nginx/sites-available$ sudo apt install joe

Now move back to your home directory or wherever you want to install your Blazor Server-side Web App at and copy all its files there.

For example purposes, I am going to use my Github public repository and Blazor Server-side app which is part of this series on HowTo do Blazor Server-side in as much detail as I learn along the way. Remember Blazor is a new technology under constant change. So I will now execute the following commands:

akshays@CodeProjectUbuntu:/etc/nginx/sites-available$ cd ~
akshays@CodeProjectUbuntu:~$ mkdir BlazorCanvasApp
akshays@CodeProjectUbuntu:~$ cd BlazorCanvasApp/
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ 
wget https://github.com/akshays2112/BlazorCanvasApp/zipball/master/ -O BlazorCanvasApp.zip
--2020-06-03 16:55:39--  https://github.com/akshays2112/BlazorCanvasApp/zipball/master/
Resolving github.com (github.com)... 13.234.176.102
Connecting to github.com (github.com)|13.234.176.102|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/akshays2112/BlazorCanvasApp/legacy.zip/master [following]
--2020-06-03 16:55:39--  
https://codeload.github.com/akshays2112/BlazorCanvasApp/legacy.zip/master
Resolving codeload.github.com (codeload.github.com)... 13.127.152.42
Connecting to codeload.github.com (codeload.github.com)|13.127.152.42|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/zip]
Saving to: ‘BlazorCanvasApp.zip’

BlazorCanvasApp.zip
[ <=>
] 229.32K  --.-KB/s    in 0.05s   

2020-06-03 16:55:40 (4.61 MB/s) - ‘BlazorCanvasApp.zip’ saved [234826]

akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ unzip BlazorCanvasApp.zip 
Archive:  BlazorCanvasApp.zip
fafb1f5a683a19d34ffbe01ec8b075fe7c7fe5d1
   creating: akshays2112-BlazorCanvasApp-fafb1f5/
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/.gitattributes  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/.gitignore  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp.sln  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/App.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/BlazorCanvasApp.csproj  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Data/
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Data/WeatherForecast.cs  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Data/WeatherForecastService.cs  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/CanvasDrawing.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/Counter.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/Error.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/FetchData.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/Index.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Pages/_Host.cshtml  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Program.cs  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Properties/
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Properties/launchSettings.json  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Shared/
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Shared/MainLayout.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Shared/NavMenu.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Shared/SurveyPrompt.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/Startup.cs  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/_Imports.razor  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/appsettings.Development.json  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/appsettings.json  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/css/
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/css/bootstrap/
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/bootstrap/bootstrap.min.css  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/bootstrap/bootstrap.min.css.map  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/FONT-LICENSE  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/ICON-LICENSE  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/README.md  
   creating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/
   creating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/css/
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/css/open-iconic-bootstrap.min.css  
   creating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/fonts/
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/fonts/open-iconic.eot  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/fonts/open-iconic.otf  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/fonts/open-iconic.svg  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf  
  inflating: akshays2112-BlazorCanvasApp-
  fafb1f5/BlazorCanvasApp/wwwroot/css/open-iconic/font/fonts/open-iconic.woff  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/css/site.css  
  inflating: akshays2112-BlazorCanvasApp-fafb1f5/BlazorCanvasApp/wwwroot/favicon.ico  
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ mv akshays2112-BlazorCanvasApp-fafb1f5/* ./
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ rm -rf akshays2112-BlazorCanvasApp-fafb1f5/
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ rm BlazorCanvasApp.zip 
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ ls
BlazorCanvasApp  BlazorCanvasApp.sln

Next step is to compile the BlazorCanvasApp.sln with the following command:

akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ dotnet build BlazorCanvasApp.sln -o ./release
Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
CSC : warning CS8034: Unable to load Analyzer assembly 
      /home/akshays/.nuget/packages/microsoft.aspnetcore.components.analyzers/
      3.0.0/analyzers/dotnet/cs/Microsoft.AspNetCore.Components.Analyzers.dll : 
      Assembly with same name is already loaded 
      [/home/akshays/BlazorCanvasApp/BlazorCanvasApp/BlazorCanvasApp.csproj]
CSC : warning CS8034: Unable to load Analyzer assembly 
      /home/akshays/.nuget/packages/microsoft.aspnetcore.components.analyzers/
      3.0.0/analyzers/dotnet/cs/Microsoft.AspNetCore.Components.Analyzers.dll : 
      Assembly with same name is already loaded [/home/akshays/BlazorCanvasApp/
      BlazorCanvasApp/BlazorCanvasApp.csproj]
  BlazorCanvasApp -> /home/akshays/BlazorCanvasApp/release/BlazorCanvasApp.dll
  BlazorCanvasApp -> /home/akshays/BlazorCanvasApp/release/BlazorCanvasApp.Views.dll

Build succeeded.

CSC : warning CS8034: Unable to load Analyzer assembly 
      /home/akshays/.nuget/packages/microsoft.aspnetcore.components.analyzers/
      3.0.0/analyzers/dotnet/cs/Microsoft.AspNetCore.Components.Analyzers.dll : 
      Assembly with same name is already loaded [/home/akshays/BlazorCanvasApp/
      BlazorCanvasApp/BlazorCanvasApp.csproj]
CSC : warning CS8034: Unable to load Analyzer assembly 
      /home/akshays/.nuget/packages/microsoft.aspnetcore.components.analyzers/
      3.0.0/analyzers/dotnet/cs/Microsoft.AspNetCore.Components.Analyzers.dll : 
      Assembly with same name is already loaded [/home/akshays/BlazorCanvasApp/
      BlazorCanvasApp/BlazorCanvasApp.csproj]
    2 Warning(s)
    0 Error(s)

Time Elapsed 00:00:06.32

I got some warnings but they are harmless. All it says in my case is that the DLL is already loaded so I could ignore it.

Now go into the release directory and you should see all your Blazor Server-side app files that are the compiler's output. Now we will test if the Blazor Server-side app works by running the dotnet command:

akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ cd release/
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ ls
appsettings.Development.json  BlazorCanvasApp.deps.json  
   BlazorCanvasApp.runtimeconfig.dev.json  BlazorCanvasApp.Views.dll     
   Blazor.Extensions.Canvas.JS.dll
appsettings.json              BlazorCanvasApp.dll        
   BlazorCanvasApp.runtimeconfig.json      BlazorCanvasApp.Views.pdb     
   Newtonsoft.Json.dll
BlazorCanvasApp               BlazorCanvasApp.pdb        
   BlazorCanvasApp.StaticWebAssets.xml     Blazor.Extensions.Canvas.dll  Properties
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ dotnet BlazorCanvasApp.dll 
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {3b7a72a3-b5a0-4154-a804-573c1f365e97} 
      may be persisted to storage in unencrypted form.
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /home/akshays/BlazorCanvasApp/release

So now that the Blazor Server-side Web App is running, open your favourite web browser and go to the following URL:

http://localhost:5000

You will see the formatting is gone because the www folder is missing. However, the Blazor Server-side app is rendering and working. You can copy the www folder over from your development machine and it will have all the JavaScript and CSS files and then it will look properly formatted as per usual.

You will see though that http://localhost:5000/CanvasDrawing will throw errors. This is because the JavaScript files are missing for the NuGet packages that support Canvas element drawing in C#. But for the purposes of this article which is just to demonstrate the steps to get Blazor Server-side working on Ubuntu, this is not required to get my example working fully.

Now for the final step of making Nginx, web server, manage the Kestrel Blazor Server-side Web App. The first thing to do is change directory to etc path as described below and create a new service configuration file for systemd. Before that, just to be sure to find out the path to dotnet executable:

akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ pwd
/home/akshays/BlazorCanvasApp/release
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ which dotnet
/usr/bin/dotnet
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ cd /etc/systemd/system/
akshays@CodeProjectUbuntu:/etc/systemd/system$ sudo joe kestrel-BlazorCanvasApp.service

Paste the following into the kestrel-BlazorCanvasApp.service file:

[Unit]
Description=Blazor Server-side Canvas Drawing Demo
[Service]
WorkingDirectory=/home/akshays/BlazorCanvasApp/release
ExecStart=/usr/bin/dotnet /home/akshays/BlazorCanvasApp/release/BlazorCanvasApp.dll
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=BlazorCanvasApp
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
[Install]
WantedBy=multi-user.target

Now register the new service with systemd by typing the following command:

akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ 
sudo systemctl enable kestrel-BlazorCanvasApp.service 
[sudo] password for akshays: 
Created symlink /etc/systemd/system/multi-user.target.wants/
kestrel-BlazorCanvasApp.service → /etc/systemd/system/kestrel-BlazorCanvasApp.service.

Now start up the kestrel-BlazorCanvasApp service and check its status to be sure it is running:

akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ 
sudo systemctl start kestrel-BlazorCanvasApp.service 
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ 
sudo systemctl status kestrel-BlazorCanvasApp.service 
● kestrel-BlazorCanvasApp.service - Blazor Server-side Canvas Drawing Demo
     Loaded: loaded (/etc/systemd/system/kestrel-BlazorCanvasApp.service; 
     enabled; vendor preset: enabled)
     Active: active (running) since Wed 2020-06-03 18:19:45 IST; 43s ago
   Main PID: 12990 (dotnet)
      Tasks: 19 (limit: 9488)
     Memory: 26.5M
     CGroup: /system.slice/kestrel-BlazorCanvasApp.service
             └─12990 /usr/bin/dotnet /home/akshays/BlazorCanvasApp/release/BlazorCanvasApp.dll

Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]: 
       warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]:       
       No XML encryptor configured. 
       Key {4875ffce-1bb9-40a6-a090-41dd899afa42} may be persisted to storage>
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]: info: Microsoft.Hosting.Lifetime[0]
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]:       
                Now listening on: http://localhost:5000
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]: info: Microsoft.Hosting.Lifetime[0]
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]:       
                Application started. Press Ctrl+C to shut down.
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]: info: Microsoft.Hosting.Lifetime[0]
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]:       
                Hosting environment: Production
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]: info: Microsoft.Hosting.Lifetime[0]
Jun 03 18:19:45 CodeProjectUbuntu BlazorCanvasApp[12990]:       
                Content root path: /home/akshays/BlazorCanvasApp/release

Now open multiple web browsers and go to the following URL. You can check on the /counter page that it is multi-user truly and when you click on the Click Me button, the counters are incremented differently in the different web pages on the different copies of your browser:

http://localhost:5000/counter

That is the entire step by step process. You can deploy now as many Blazor Server-side apps as you want to Ubuntu now.

Summary of All the Commands

The following is all the commands in order that need to be run without any output. This is meant for those who already know all the Ubuntu/Linux commands and just want to use them quickly.

akshays@CodeProjectUbuntu:~$ wget 
-q https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb 
-O packages-microsoft-prod.deb
akshays@CodeProjectUbuntu:~$ sudo dpkg -i packages-microsoft-prod.deb
akshays@CodeProjectUbuntu:~$ sudo apt-get update
akshays@CodeProjectUbuntu:~$ sudo apt-get install apt-transport-https

------------------ Choice Here -----------------------------------
akshays@CodeProjectUbuntu:~$ sudo apt-get install dotnet-sdk-3.1
--OR--------------------------------------------------------------
akshays@CodeProjectUbuntu:~$ sudo apt-get install aspnetcore-runtime-3.1\
------------------- End Choice -----------------------------------

akshays@CodeProjectUbuntu:~$ sudo apt-get update
akshays@CodeProjectUbuntu:~$ sudo apt-get install nginx
akshays@CodeProjectUbuntu:~$ sudo service nginx start

-------------------- Edit /etc/nginx/sites-available/default with this text -------
        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;
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
------------------------------- End Text -------------------------------------------

akshays@CodeProjectUbuntu:/etc/nginx/sites-available$ cd ~
akshays@CodeProjectUbuntu:~$ mkdir BlazorCanvasApp
akshays@CodeProjectUbuntu:~$ cd BlazorCanvasApp/
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ 
wget https://github.com/akshays2112/BlazorCanvasApp/zipball/master/ -O BlazorCanvasApp.zip
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ unzip BlazorCanvasApp.zip 
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ mv akshays2112-BlazorCanvasApp-fafb1f5/* ./
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ rm -rf akshays2112-BlazorCanvasApp-fafb1f5/
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ rm BlazorCanvasApp.zip 
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ dotnet build BlazorCanvasApp.sln -o ./release
akshays@CodeProjectUbuntu:~/BlazorCanvasApp$ cd release/
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ dotnet BlazorCanvasApp.dll 

--------------------- New file /etc/systemd/system/kestrel-BlazorCanvasApp.service 
with following text -----
[Unit]
Description=Blazor Server-side Canvas Drawing Demo
[Service]
WorkingDirectory=/home/akshays/BlazorCanvasApp/release
ExecStart=/usr/bin/dotnet /home/akshays/BlazorCanvasApp/release/BlazorCanvasApp.dll
Restart=always
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=BlazorCanvasApp
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
[Install]
WantedBy=multi-user.target
---------------------- End Text ---------------------------------------------------------------

akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ 
sudo systemctl enable kestrel-BlazorCanvasApp.service 
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ 
sudo systemctl start kestrel-BlazorCanvasApp.service 
akshays@CodeProjectUbuntu:~/BlazorCanvasApp/release$ 
sudo systemctl status kestrel-BlazorCanvasApp.service 

History

  • 3rd June, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)