Why .NET together with arch linux is a top development platform
With the release of .NET 9, Microsoft’s latest iteration of their cross-platform framework has introduced several improvements, including more streamlined deployment options. If you’re working in an Arch Linux environment, creating a robust, custom systemd service using .NET can be straightforward and versatile. In this guide, we’ll set up a basic service in C# using .NET 9, cover the configuration needed for systemd, and explore options for deploying it as a native ELF binary or as a .NET runtime-dependent application.
Prerequisites
- Arch Linux environment with
systemd
. - .NET 9 SDK: You can install it by running:
sudo pacman -S dotnet-sdk
- Basic understanding of C#, .NET CLI, and systemd.
Step 1: Create Your .NET Service Application
Let’s start by creating a simple .NET console application that will act as our service. Open your terminal and follow these steps:
# Create a new directory for your service
mkdir DotnetService
cd DotnetService
# Initialize a new .NET console application
dotnet new console -o DotnetServiceApp
cd DotnetServiceApp
Replace the contents of Program.cs
with some basic functionality that simulates a service operation:
using System;
using System.Threading;
class Program
{
static void Main()
{
Console.WriteLine("Service started at: " + DateTime.Now);
while (true)
{
// Simulate some work by waiting 5 seconds in each loop
Console.WriteLine("Service running at: " + DateTime.Now);
Thread.Sleep(5000);
}
}
}
Step 2: Compile and Test the Application
Compile the application to ensure it’s working:
dotnet run
This should print messages every five seconds, showing that your service is running as intended.
Step 3: Create the Systemd Service File
To run this .NET application as a systemd service, we need to create a systemd unit file. Systemd uses these files to manage services on startup and during runtime.
Create the file /etc/systemd/system/dotnetservice.service
with the following content:
[Unit]
Description=Sample .NET Service
After=network.target
[Service]
ExecStart=/usr/bin/dotnet /path/to/DotnetService/DotnetServiceApp/bin/Debug/net9.0/DotnetServiceApp.dll
Restart=always
User=nobody
Environment=DOTNET_ENVIRONMENT=Production
[Install]
WantedBy=multi-user.target
In this setup:
ExecStart
points to thedotnet
executable followed by the path to our compiled.dll
file.Restart=always
ensures the service will restart on failure.User=nobody
restricts the service to a non-root user.Environment=DOTNET_ENVIRONMENT=Production
sets an environment variable for production.
Step 4: Run and Enable the Service
Now we can start the service and enable it to run on boot:
# Reload systemd to recognize the new service
sudo systemctl daemon-reload
# Start the service
sudo systemctl start dotnetservice
# Enable the service to run on boot
sudo systemctl enable dotnetservice
To verify the service is running:
sudo systemctl status dotnetservice
You should see the service running and periodically outputting messages.
Option 1: Running with the .NET Executable
By default, this setup requires the .NET runtime to be installed on the machine. This is a viable option for applications where updates to the .NET runtime might benefit your application or where other services also use .NET.
Advantages:
- Smaller File Size: Your deployed application is a .dll, so you’re only deploying your code and libraries.
- Runtime Benefits: Updates to .NET itself can potentially improve your service without recompilation.
- Easier Updates: You can update your application code without needing to recompile as a binary executable.
Disadvantages:
- Dependency: The .NET runtime must be present on the target machine.
- Startup Speed: Dependent applications might start slightly slower since the runtime needs to be loaded.
Option 2: Producing a Native ELF Binary with dotnet publish
.NET 9 also allows us to compile our application into a native ELF binary, which includes all necessary dependencies and runtime files. This is particularly useful for creating standalone services that don’t rely on the .NET runtime being installed on the host system.
To compile your application as a native binary, use the dotnet publish
command with the --self-contained
option:
dotnet publish -c Release -r linux-x64 --self-contained -o ./publish
This command:
- Publishes the application in release mode (
-c Release
). - Targets a Linux runtime (
-r linux-x64
). - Creates a self-contained binary with all dependencies (
--self-contained
).
The output will be located in the ./publish
directory as a single executable file.
Update the systemd Service File for Native Binary
With a self-contained binary, update the ExecStart
line in /etc/systemd/system/dotnetservice.service
:
ExecStart=/path/to/DotnetService/DotnetServiceApp/publish/DotnetServiceApp
Now, reload the systemd configuration and restart the service:
sudo systemctl daemon-reload
sudo systemctl restart dotnetservice
Advantages:
- Independent Execution: No need for the .NET runtime on the system.
- Potentially Faster Startup: No runtime loading, leading to faster startup times.
- Ease of Deployment: Single binary to manage.
Disadvantages:
- Larger File Size: The binary includes the runtime, which increases the file size.
- Fixed Runtime Version: The application will use the runtime version it was compiled with, requiring a rebuild for updates.
Summary
Running .NET 9 applications as a systemd service on Arch Linux offers flexibility in deployment. You can choose between:
- Runtime-dependent Deployment: Suitable when the .NET runtime is installed, offering easier updates and smaller application size.
- Native Binary Deployment: Provides a self-contained, standalone executable ideal for systems without the .NET runtime or where performance and independence are priorities.
This versatility enables you to select the best fit based on the requirements of your environment and application. Whether you choose runtime-dependent deployment or go with a self-contained ELF binary, .NET 9 on Linux provides a powerful and efficient way to deploy C# services on Arch Linux.
With this guide, you’re well on your way to creating robust and maintainable .NET services on Arch Linux using systemd.