Install .NET Core on Raspberry Pi
.NET Core 3.1 for ARM32
Installing .NET Core on Raspberry Pi 4 is a very straightforward process these days. There are plenty descriptions in the wild, so please welcome my own guide on this subject too.
Login into Raspberry Pi and upgrade all current modules to latest.
sudo apt update sudo apt upgrade
Install some dependencies, that .NET Core relies on (as described here). Potentially all of them are already on your system, but let’s be sure.
sudo apt-get install curl libunwind8 gettext apt-transport-https
Create
dotnet-core
folder in your home and navigate there. This is only place to keep things downloaded during the installation process. At the end, the whole folder can be deleted without any harm.mkdir dotnet-core cd dotnet-core
Download .NET Core SDK 3.1.403 (latest stable at the time of writing) from here.
Remember that Raspberry OS runs as 32-bit OS, even if the device itself is 64-bit SoC.
wget https://download.visualstudio.microsoft.com/download/pr/8a2da583-cac8-4490-bcca-2a3667d51142/6a0f7fb4b678904cdb79f3cd4d4767d5/dotnet-sdk-3.1.403-linux-arm.tar.gz
Extract it into
/opt
and make proper links to expose thedotnet
binary into your$PATH
.sudo mkdir /opt/dotnet-3.1.403 sudo tar zxf dotnet-sdk-3.1.403-linux-arm.tar.gz -C /opt/dotnet-3.1.403 sudo rm dotnet -f sudo ln -s /opt/dotnet-3.1.403 /opt/dotnet sudo rm /usr/local/bin/dotnet -f sudo ln -s /opt/dotnet/dotnet /usr/local/bin
Check, if everything is correctly applied by command:
dotnet --info
Expected output:
.NET Core SDK (reflecting any global.json): Version: 3.1.403 Commit: 9e895200cd Runtime Environment: OS Name: raspbian OS Version: 10 OS Platform: Linux RID: linux-arm Base Path: /opt/dotnet-3.1.403/sdk/3.1.403/ Host (useful for support): Version: 3.1.9 Commit: 774fc3d6a9 .NET Core SDKs installed: 3.1.403 [/opt/dotnet-3.1.403/sdk] .NET Core runtimes installed: Microsoft.AspNetCore.App 3.1.9 [/opt/dotnet-3.1.403/shared/Microsoft.AspNetCore.App] Microsoft.NETCore.App 3.1.9 [/opt/dotnet-3.1.403/shared/Microsoft.NETCore.App] To install additional .NET Core runtimes or SDKs: https://aka.ms/dotnet-download
From now on, it should be possible to compile any .NET Core application on this device and run any .NET Core application, even the one created elsewhere (using command: dotnet publish -r linux-arm
). Bravo!
If you need to use as less space as required, the download page contains links for runtimes-only editions, which could be installed instead. Please remember that in this scenario you would need to install ASP.NET Core separately, if required.
ASP.NET Core
Once you play a bit with console applications, you will see that true power of Raspberry Pi lies in hosting your own web-sites, Web APIs and storing data in local databases. In this second part I would like to show, how the Web App
/ Web API
created using Visual Studio 2019 or JetBrains Rider could be hosted seamlessly on the device.
Note: To improve performance all data can be stored on external SSD disk. This will also increase the live of the microSD card used by the Raspberry Pi. If you encounter any issues with moving data to dedicated volume, I already fought it a lot here. Maybe it will show itself useful. I would also recommend to install PostgreSQL or MariaDB (a.k.a MySQL) to store your data. Both can be also configured to keep the data outside of the microSD card.
Create simple Web API project using IDE mentioned above.
Deploy your application onto the device, here into
/volumes/www/home-library
and start it.cd /volumes/www/home-library dotnet MyWebServer.dll
This will case the local .NET service to start hosting the app (using .NET Kestrel server). It will have however few major issues:
* it will stop in case of any application termination exception occur and will never restart * it won't also automatically get up, when the device rebooted * additionally, it won't be inaccessible for external connections.
To overcome those limitation we need to register the application as a service inside the autostart chain, then install
nginx
(WWW server) to let the Web API be consumed by remote clients. Official Microsoft guide is located here.First things first. Creation of startup service is as easy as creation of text file in respective location:
sudo nano /etc/systemd/system/home-library-app.service
And put following content into this file:
[Unit] Description=CodeTitans HomeLibrary ASP.NET Core 3.0 App [Service] WorkingDirectory=/volumes/www/home-library ExecStart=/opt/dotnet/dotnet /volumes/www/home-library/MyWebServer.dll Restart=always # Restart service after 10 seconds if the dotnet service crashes: RestartSec=10 KillSignal=SIGINT SyslogIdentifier=dotnet-home-library User=pi Environment=ASPNETCORE_ENVIRONMENT=Production Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false [Install] WantedBy=multi-user.target
Then enable it and start:
sudo systemctl enable home-library-app.service sudo systemctl start home-library-app.service
Of course, this service can be restarted at any time using following command:
sudo systemctl restart home-library-app.service
Now, make sure nginx (WWW server) is installed and enabled.
sudo apt install nginx sudo /etc/init.d/nginx start
Optional - if you have a public domain, you can use the
Let's Encrypt
service to make the server connection more secure. Please refer to this guide for details. It explains how to usecertbot
to actually generate SSL certificate and enable it withinnginx
.Create a new site definition for
nginx
and enable it:sudo nano /etc/nginx/sites-available/home-library-site sudo ln -s /etc/nginx/sites-available/home-library-site /etc/nginx/sites-enabled
The content of
home-library-site
without any HTTPS support (without any certificated) should look like following:server { listen 80; server_name _; # don't limit to any domains 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; } }
With HTTPS enabled, there are 2 things defined inside
home-library-site
. First we declare listening on port443
instead of default80
and paths to SSL keys. Secondly here appears the permanent redirect from non-encrypted traffic, that users can accidentally request to fully encrypted location. It will automatically pass the path and other arguments.server { listen 443 ssl; server_name homelib abc.example.com; ssl_certificate /volumes/www/ssl/fullchain.pem; ssl_certificate_key /volumes/www/ssl/privkey.pem; location / { client_max_body_size 256M; proxy_pass http://localhost:5000; proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; proxy_set_header X-Real-IP $remote_addr; } } server { listen 80; server_name homelib abc.example.com; return 301 https://abc.example.com$request_uri; }
After changing any settings
Nginx
have to be restarted.Here are some few ways of doing it:
sudo nginx -t sudo nginx -s reload
or
service nginx restart
That’s actually all. From now on only your imagination and development skills are your limit!
Post scriptum - NuGet Server
There is also a great guide on how to setup own private NuGet server from Scott Hanselman. It’s a useful addon, once the .NET Core is working locally! Unfortunately this server can’t be deployed in Unix environment. The better option would be to use BaGet server instead.
Have a good day, comrade.