I wanted to make sure my Pi was completely updated with all the latest software so I ran two commands to ake sure.
sudo apt update
sudo apt full-upgrade
None of that is strictly necessary but I like to be up to date before installing stuff.
Now I can install .NET 8.
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-8.0
sudo apt-get update && \
sudo apt-get install -y aspnetcore-runtime-8.0
sudo apt-get install -y dotnet-runtime-8.0
And that should be it for .NET! Next we will install a database server for the Forum, I chose to use MariaDB.
Let’s make our new server more usable by installing MariaDB:
sudo apt install mariadb-server
It can't get easier than that! A SQL client is included with the server installation, so you can connect to the database and check that it is working:
sudo mariadb
Before we leave the client, create a new database (more on this later) and a user for it. It’s a good practice to not use the root
user when consuming the database from your applications. Here’s what you need to execute:
CREATE DATABASE snitzforums;
CREATE USER 'admin'@'%' IDENTIFIED BY 'Password123!';
GRANT ALL PRIVILEGES ON snitzforums.* TO 'admin'@'%';
Now you can leave the SQL client:
quit
We’ll connect remotely to the database using the above user later.
You can use the database in its current state, but it’s always a good idea to secure the server. MariaDB includes a tool that easies this process:
sudo mariadb-secure-installation
You’ll be prompted with the root password which by default is empty, so just press enter. The tool asks you questions as you go. Feel free to configure your database server as you wish. For reference, here’s how I answered the questions:
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.
Enter current password for root (enter for none):
OK, successfully used password, moving on...
Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.
You already have your root account protected, so you can safely answer 'n'.
Switch to unix_socket authentication [Y/n] n
... skipping.
You already have your root account protected, so you can safely answer 'n'.
Change the root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
... Success!
By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] Y
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] Y
... Success!
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] Y
- Dropping test database...
... Success!
- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] Y
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
To test this all out, I move back to my local Windows machine where I have set up a test forum. If I go into that website I can publish it with the command
dotnet publish -c Release -o .\release
This publishes the website with the Release configuration and in a directory called "release" in the current directory. Navigate into the release directory through Windows Explorer and make a single zip file of everything in there. This is to help with copying everything over. I tried copying all the individual files over and it takes forever with all the thousands of little files Umbraco has. Copying a single zip is, well, pretty zippy.
Now I can copy the zip over to the Pi. In order to do so I switch back to my ssh session on the Pi and make a new directory in my home directory called "snitz". Then I can do the copy from Windows using scp:
scp release.zip huw@deskpi.local:/home/huw/snitz/release.zip
On the Pi, I need to do a one-time install of a package called unzip, you can guess what that's for .
sudo apt-get install unzip
After that is done we can go to the folder on the Pi where we copied release.zip, extract all the files and delete the zip file:
unzip release.zip
rm release.zip
Before we run the site we need to edit the appsettings.json to configure a few things first. Open the file using your prefered editor. The contents of the file are below with details of what you need to chage.
{
"ConnectionStrings": {
"SnitzConnection": "Server=192.168.0.118;Database=snitzforum;Uid=admin;Pwd=Password123!;Pooling=True;Connection Timeout=30",
"HangfireConnection": "Server=192.168.0.118;Database=snitzforum;User=admin;Password=Password123!;Pooling=True;Connection Timeout=30",
"DBProvider": "mysql"
},
"SnitzForums": {
"forumTablePrefix": "FORUM_",
"memberTablePrefix": "FORUM_",
"strVersion": "7.0.0",
"LanguageConnectionString": "SnitzConnection",
"strForumUrl": "https://localhost:5001/",
"strForumDescription": "Development site for .NET Core port of Snitz™ Forums 2000",
"strForumTitle": "MediaWizards Forums",
"strCopyright": "{0} H Reddick",
"strUniqueId": "SnitzCore00",
"excludeBots": "googlebot,bing,duckduck,yahoo,spider,bot,facebook,netEstate,Not-A.Brand,barkrowler",
"SupportedLanguages": [ "en", "no", "fa" ]
},
"MailSettings": {
"From": "huw@reddick.co.uk",
"UserName": "",
"Password": "",
"RequireLogin": false,
"SmtpServer": "localhost",
"Port": 25,
"SecureSocketOptions": "StartTls"
},
"IdentityOptions": {
"Password": {
"RequiredLength": 8,
"RequireDigit": true,
"RequiredUniqueChars": 4,
"RequireLowercase": true,
"RequireNonAlphanumeric": false,
"RequireUppercase": true
}
},
.... other sections removed for clarity
"AllowedHosts": "*"
}
I made sure to test that the site runs. My project was called "SnitzForum" so in the release folder there's a SnitzForum.dll, which is the main entry point for the app. In order to run the site, run the following command:
dotnet SnitzForum.dll
This will give absolutely no output on the command line (unless any errors occur), so open a second ssh session into the Pi and try to make sure something was running. By default, the site runs on port 5000 so I can see if there's a response using curl:
curl http://localhost:5000
This resulted in a bunch of HTML flashing on the screen. So far so good .
Now that we've confirmed the site can run, tap CTRL+C on the first ssh session to stop it from running. I want to make sure the site starts every time the Pi reboots, so I followed the guide by Niels Swimberghe to do so. Create a new text file called SnitzForum.service using nano
or vi
:
nano SnitzForum.service
The content of the file is as follows, I'll explain below what you would want to change:
[Unit]
Description=ASP.NET Core web template
[Service]
# will set the Current Working Directory (CWD)
WorkingDirectory=/home/sebastiaan/testlive
# systemd will run this executable to start the service
# if /usr/bin/dotnet doesn't work, use `which dotnet` to find correct dotnet executable path
ExecStart=/usr/bin/dotnet /home/huw/snitz/SnitzForum.dll --urls "http://*:5001"
# to query logs using journalctl, set a logical name here
SyslogIdentifier=SnitzForum
# Use your username to keep things simple, for production scenario's I recommend a dedicated user/group.
# If you pick a different user, make sure dotnet and all permissions are set correctly to run the app.
# To update permissions, use 'chown yourusername -R /srv/AspNetSite' to take ownership of the folder and files,
# Use 'chmod +x /srv/AspNetSite/AspNetSite' to allow execution of the executable file.
User=huw
# ensure the service restarts after crashing
Restart=always
# amount of time to wait before restarting the service
RestartSec=5
# copied from dotnet documentation at
# https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-nginx
KillSignal=SIGINT
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false
[Install]
WantedBy=multi-user.target
I changed the WorkingDirectory to the folder where my published site is located, then the arguments on ExecStart specify that location again plus the name of my dll. You'll note that I added a --urls option, this is to change the default port number from 5000 to 5001. Knowing that this works, I can run multiple sites on this Pi.
Finally, I changed the SyslogIdentifier and the User to be my username.
Now I can copy this service definition to where the Pi expects it, start my service and enable it to auto run:
sudo cp SnitzForum.service /etc/systemd/system/SnitzForum.service
sudo systemctl daemon-reload && sudo systemctl start SnitzForum
sudo systemctl enable SnitzForum
I figured I should probably do another "curl" command to see if it works, and if it doesn't then I can look at journalctl to figure out with what's being logged as going wrong. In my case everything was good.
Okay, the last piece of the puzzle! I already have a Pangolin server setup to access my internal systems, but you could also use CloudFlare tunnels for this.
On my Pangolin server, I simply added a new resource called snitz using my domain 'themediawizards.co.uk', Pangolin takes care of creating SSL certificates etc. I just had to point it at my local server address where the forum is running, in this case http://192.168.0.19:5001
I can now access the forum using https://snitz.themediawizards.co.uk