Linux VPS hosting with deployment pipeline

Linux VPS is a complicated method to get a live website, but it is also extremely effective and is one of cheapest method. In this tutorial, you will discover:

  • Required tools.
  • Publishing a Blazor WebAssembly website.
  • Set up the Linux VPS.
  • Speed up Blazor WebAssembly website.
  • Setup GitHub action.
  • Common mistakes.

Thanks to Discord user Grimston#0001 at NPipes for sponsoring a VPS machine that used to make this tutorial. You can contribute to the community too.

Deploying the website API is not included in this tutorial. However, you can use the same VPS to host the website API.


Require tools

To manage the Linux VPS, you need a tool to execute commands and a tool to transfer file between your computer and the VPS machine. Bitvise SSH Client is a recommended tool.


Publishing a Blazor WebAssembly website

Before deploying your website to a Linux VPS, you need to publish your website to a folder first. Then we will make the website working and then set up a GitHub action for automated deployment later. To publishing your website to a folder:

  1. Right-click your Blazor WebAssembly project and select Publish…

publishing-blazor-webassembly-1.png

  1. Select Folder in the next step.

publishing-blazor-webassembly-2.png

  1. Select the folder location.

publishing-blazor-webassembly-3.png

  1. Click Publish to start publishing your website to a folder.

publishing-blazor-webassembly-4.png


Set up the Linux VPS

When you bought a Linux VPS service, you will receive an IP, the username, and password to access the VPS. Use these information in Bitvise SSH Client to connect to the VPS machine.

  1. Run Bitvise SSH Client and connect to the VPS machine.

set-up-linux-vps-1.png

  1. Click New terminal console to open a terminal console.

set-up-linux-vps-2.png

  1. Install the .NET runtime. In the terminal console, run sudo apt-get update && sudo apt-get install -y aspnetcore-runtime-6.0:

set-up-linux-vps-3.png

  1. Back to the Bitvise SSH Client and click New SFTP window.

set-up-linux-vps-4.png

  1. Copy the wwwroot folder from the published folder to the VPS machine. Recommended path in the VPS machine: /home/<your_website>.

set-up-linux-vps-5.png

  1. Install NGINX. Back to the terminal console and run sudo apt install nginx.

set-up-linux-vps-6.png

  1. Make NGINX autostart. Run command sudo systemctl enable nginx.

set-up-linux-vps-7.png

  1. Back to the SFTP window. Rename the /etc/nginx/sites-enabled/default file. Update the file content:
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name <your_domain>;
	ssl_certificate '<your_path_to_pem_file>';
        ssl_certificate_key '<your_path_to_pem_file>';
	
	root "<path_to_wwwroot_folder>";
	
	location / {
             try_files $uri $uri/ /index.html;
	}
}

server {
	listen 80;
	listen [::]:80;
	server_name <your_domain>;
	
	return 301 https://$host$request_uri;
}

For ssl_certificate and ssl_certificate_key you can get from an SSL certificate provider service. The same with server_name, you can get from a domain provider service.

The first server block is to serve the website with the HTTPS protocol. The second server block redirects all HTTP request to HTTPS request.

  1. If your website has dynamic file data. For example, user avatar, user uploaded files, etc. You should not put the dynamic file data into the folder of the website. Instead, put the dynamic file data into another location and then redirect them in the config file as follows:
location /images/ 
{
    root "<path_to_images_folder>"; 
}
See the sample file in GitHub
  1. Whenever you change the setting, you need to reload NGINX to take effect. Back to the terminal console and run sudo systemctl reload nginx.

set-up-linux-vps-8.png


Speed up Blazor WebAssembly website

The following actions can help you to speed up the website you are hosting:

  • Redirect HTTP to HTTPS. Make sure you also have an SSL certificate up and running.
  • Check if MIME type is handled correctly.
  • Enable gzip.

Redirect HTTP to HTTPS

If you follow the tutorial, you need not worry about this. The second block of server in the example redirects all HTTP to HTTPS protocol.

Check if MIME type is handled correctly

Handle MIME type is just about telling which file extension belongs to which group. For example, any file that ends with .css should be treated as text/css. There are many MIME type out there, and they need to be recognized differently. You can see the full list of MIME type in IANA Media Types.

To check if all of your file is handled correctly, open the /etc/nginx/mime.types file in the VPS server. If the MIME type you are using is not there, you need to add it and reload the NGINX server.

Enable gzip

Enabling gzip will help your website loads faster. Your website loads faster when it is lighter. When you are enabling gzip, NGINX will use some CPU to compress your website, then send it over to the browser. The browser then uncompress your website and display it accordingly. Because the process of compressing and uncompressing are cheaper than the transportation cost, so it will increase the website loading speed.

Gzip is also a razor blade, you can hurt yourself if you don't know what you are doing. To effectively gzip your website, you need to monitor and determine when to compress and when is not to. Gzip is enabled by default NGINX settings, you can find the setting in /etc/nginxnginx.conf. Look for the # Gzip Settings. To turn on advanced settings, you need to uncomment all other settings. Your Gzip settings should look like:

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types
    text/plain
    text/css
    application/json
    application/javascript
    text/xml
    application/xml
    application/xml+rss
    text/javascript;

The gzip_types is the list of MIME types which will be compressed to smaller size, you can add some more to this list.

The gzip_comp_level is the level of compressing, ranging from 1 to 9 which 1 is least compressed and 9 is the most compressed. Higher compressing level compensate your CPU usage, and sometimes it becomes bigger than the original.

Some files, as mentioned above, after being compressed it becomes bigger. You need to add gzip_min_length X to tell NGINX not to compress if the size is less than X. There is no ideal number for this setting, you must monitor your website and give the decision.

To see the effectiveness and ineffectiveness of the gzip, open your website, turn on the Web Developer Tools by pressing F12. Open the Network tab, check the Disable Cache option and reload the website:

speed-up-blazor-webassembly-1.png

If the size before compressing is larger than the size after compressed, then you should compress the file. Otherwise, don't compress (either remove the gzip_types or increase the gzip_min_length X).


Setup GitHub action

Up until this point, you have a healthy website up and running. The next step is to set up a deployment pipeline, so you don't have to manually deploy whenever the website updates. GitHub is a good way to set up the deployment pipeline.

  1. In the GitHub repository, navigate to Settings > Secrets > Actions. Click the New repository secret.

set-up-github-action-1.png

  1. Create 3 secret keys for Host address, username, and password to logging your VPS machine.

set-up-github-action-2.png

  1. Switch to Action tab, and click on the New workflow button.

set-up-github-action-3.png

  1. Search for ASP.NET workflow and select .NET by GitHub Actions.

set-up-github-action-4.png

  1. Update the yml file. This is an example file:
name: Deploy to VPS
on:
  push:
    branches:
    - master
env:
  CONFIGURATION: Release
  DOTNET_CORE_VERSION: 6.x.x
  GITHUB_OUTPUT_DIRECTORY: blazorschool.<your_website>
  VPS_WEB_DIRECTORY: /home/blazor school.<your_website>
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: ${{ env.DOTNET_CORE_VERSION }}
    - name: Restore web
      run: dotnet restore
    - name: Build web
      run: dotnet build --configuration ${{ env.CONFIGURATION }} --no-restore
    - name: Test web
      run: dotnet test --no-build
    - name: Publish web
      run: dotnet publish --configuration ${{ env.CONFIGURATION }} --output "${{ env.GITHUB_OUTPUT_DIRECTORY }}"

    - name: Copy web via ssh
      uses: garygrossgarten/github-action-scp@master
      with:
        local: ${{ env.GITHUB_OUTPUT_DIRECTORY }}
        remote: ${{ env.VPS_WEB_DIRECTORY }}
        host: ${{ secrets.HOST }}
        username: ${{ secrets.USERNAME }}
        password: ${{ secrets.PASSWORD }}

From the example, you need to change GITHUB_OUTPUT_DIRECTORY, VPS_WEB_DIRECTORY to your folder. The GITHUB_OUTPUT_DIRECTORY can be anything, but the VPS_WEB_DIRECTORY needs to be existed before running this workflow.

The on key: decide when to deploy the website. In this example, it is deployed whenever a push on master branch.

You need to update the secret keys in the Copy web via ssh job as well.


Common mistakes

In this section, we have collected some common mistakes from the Blazor School Discord Community.

Mistake #1: Let NGINX handles errors like 404, etc.

You should let Blazor handles all the errors. Otherwise, you will have an unprofessional error page, not to mention that your code to handle errors will never show up. This is an example of letting NGINX handles errors:

// DON'T DO THIS
location / 
{ 
    try_files $uri $uri/ /index.html =404; 
}

Mistake #2: Not serving index.html as backup

If you make this mistake, your website is not accessible through sub URL and can only access by homepage. For example, when you access your website via https://208.115.245.90/product-list you will get an 404 error. This is an example of not serving index.html as backup.

// DON'T DO THIS
location / 
{ 
    try_files /index.html; 
}

Mistake #3: Files are case-sensitive

By default, NGINX searches the files with case-sensitive enabled. For example, you are trying to access a picture from your website, the picture file name is wwwroot/Logo.png, and you type <your_website>.com/logo.png; You will get an 404 error because there is not a file name wwwroot/logo.png.

Mistake #4: Putting dynamic files (user avatar, user uploaded files) inside the wwwroot folder

The wwwroot folder should contain static files only. It will make it easy when you want to deploy more website server. The backup process will be easier to maintain.

BLAZOR SCHOOL
Designed and built with care by our dedicated team, with contributions from a supportive community. We strive to provide the best learning experience for our users.
Docs licensed CC-BY-SA-4.0
Copyright © 2021-2025 Blazor School
An unhandled error has occurred. Reload 🗙