Hosting on a Linux virtual machine is a complicated method, yet it also allows you to control everything and is one of the cheapest method. In this tutorial, you will discover:
Thanks to Discord user Grimston#0001 at NPipes for sponsoring a VPS machine that used to make this tutorial. You can contribute to Blazor School to get more tutorials like this.
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 does both and is recommended.
Before deploying your website to a Linux VPS, you need to publish your website to a folder first.
There are 2 deployment modes for Blazor Server. Besides, there are several publish options. We take the OnlineShop project for all measurements in this section. The following table is measured by just select the deployment mode without any publish options.
Framework-dependent | Self-contained | |
Has portable option? (Build one time, run on any OS) | Yes | No |
Size (Affect deployment speed, does not affect the website loading speed) | 1.43 MB (1,506,207 bytes) | 181 MB (189,836,613 bytes) |
Build time | 00:03.154 | 00:03.337 |
The following table is a comparison between publish options to without any publish options.
Self-contained | Ready to Run | Trim unused code | Produce single file |
Size | 181 MB (189,888,325 bytes) | Size: 134 MB (140,789,437 bytes) | 183 MB (191,978,532 bytes) |
Build time | 00:03.098 | 00:37.697 | 00:03.008 |
Framework-dependent | Ready to Run (not available for Portable build) | Trim unused code | Produce single file (not available for Portable build) |
Size | 1.48 MB (1,557,919 bytes) | Not available | 1.43 MB (1,510,017 bytes) |
Build time | 00:02.115 | Not available | 00:01.782 |
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.
sudo apt-get update && sudo apt-get install -y aspnetcore-runtime-6.0
:[Unit] Description=Online Shop [Service] Type=simple User=root WorkingDirectory=/home/OnlineShop ExecStart=/usr/bin/dotnet OnlineShop.dll --urls=http://localhost:2023/ Restart=always SyslogIdentifier=Online Shop KillMode=process StandardOutput=file:/home/log/log.log StandardError=file:/home/log/error.log [Install] WantedBy=multi-user.target
WorkingDirectory
is the folder location of your website (refer step 5).
StandardOutput
and StandardError
is the location of your log files on the VPS. Whenever your website encounters any error, the log will be stored there.
You will need to remember the --urls
at the end of ExecStart
to setup the NGINX later.
sudo systemctl enable YOUR_SERVICE
to make the service starts automatically.sudo systemctl start YOUR_SERVICE
.sudo apt install nginx
.sudo systemctl enable nginx
to start NGINX automatically.map $http_upgrade $connection_upgrade { default upgrade; '' close; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name _; ssl_certificate <your_path_to_pem_file>; ssl_certificate_key <your_path_to_pem_file>; location / { proxy_pass http://localhost:2023; proxy_redirect off; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } } server { listen 80; listen [::]:80; server_name _; return 301 https://$host$request_uri; }
server_name
is your domain, separate by comma (,). For example: blazorschool.com, mywebsite.blazorschool.com.
For ssl_certificate
and ssl_certificate_key
you can get from an SSL certificate provider service like NPipes.
sudo systemctl reload nginx
for the new settings to take effect.After that, you can access your website with your domain (if you had your domain point to your VPS).
The following actions can help you to speed up the website you are hosting:
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.
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.
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:
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
).
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.
name: Deploy to VPS on: push: branches: - master env: CONFIGURATION: Release DOTNET_CORE_VERSION: 6.x.x WORKING_DIRECTORY: <your_project_name> WORKING_OUTPUT_DIRECTORY: deploy VPS_WEB_DIRECTORY: <your_folder_location_in_vps> 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 "${{ env.WORKING_DIRECTORY }}" - name: Build web run: dotnet build "${{ env.WORKING_DIRECTORY }}" --configuration ${{ env.CONFIGURATION }} --no-restore - name: Test web run: dotnet test "${{ env.WORKING_DIRECTORY }}" --no-build - name: Publish web run: dotnet publish "${{ env.WORKING_DIRECTORY }}" --configuration ${{ env.CONFIGURATION }} --no-build --output "${{ env.WORKING_OUTPUT_DIRECTORY }}" - name: Copy web via ssh uses: garygrossgarten/github-action-scp@master with: local: ${{ env.WORKING_OUTPUT_DIRECTORY }} remote: ${{ env.VPS_WEB_DIRECTORY }} host: ${{ secrets.HOST }} username: ${{ secrets.USERNAME }} password: ${{ secrets.PASSWORD }} - name: Restart <your_service> service uses: garygrossgarten/github-action-ssh@master with: host: ${{ secrets.HOST }} command: | systemctl daemon-reload systemctl restart <your_service> 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.
In this section, we have collected some common mistakes from the Blazor School Discord Community.
When publishing your project, you will see there are 2 folders: bin\Release\net6.0\ and bin\Release\net6.0\publish\.
However, you should never use bin\Release\net6.0\ to deploy. Instead, you should use bin\Release\net6.0\publish\.
Some files will not be serve because there is no wwwroot folder in that folder.
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.