DotNET: Difference between revisions

Lostmsu (talk | contribs)
No edit summary
m Use the correct command name.
 
(14 intermediate revisions by 6 users not shown)
Line 4: Line 4:
Example build file:
Example build file:


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix" line="1" start="1">
{ fetchFromGitHub
{
, dotnetCorePackages
  buildDotnetModule,
, buildDotnetModule
  dotnetCorePackages,
}:
}:


buildDotnetModule rec {
buildDotnetModule {
   pname = "some_program";
   pname = "hello";
   version = "some_version";
   version = "0.1";


   src = fetchFromGitHub {
   src = ./.;
    owner = "some_owner";
    repo = pname;
    rev = "v${version}";
    sha256 = ""; # can be figured out from the first build attempt
  };


   projectFile = "SomeProject/SomeProject.csproj";
   projectFile = "Hello/Hello.csproj";
   dotnet-sdk = dotnetCorePackages.sdk_8_0;
   dotnet-sdk = dotnetCorePackages.sdk_8_0;
   dotnet-runtime = dotnetCorePackages.runtime_8_0;
   dotnet-runtime = dotnetCorePackages.runtime_8_0;
   nugetDeps = ./nuget-deps.nix; # only if there are NuGet dependencies, real file will be genned later
   nugetDeps = ./deps.json;
}
 
</syntaxhighlight>
 
If the <code>fetch-deps</code> script isn't working for whatever reason, you can manually run <code>nuget-to-json</code>:
<syntaxhighlight lang="shell-session">
$ dotnet restore --packages=packageDir ./SomeProject.csproj
$ nuget-to-json packageDir > deps.json
$ rm -r packageDir
</syntaxhighlight>
 
Remember to build and run the <code>fetch-deps</code> script after NuGet packages are updated, or building the derivation will fail.
 
== Building non-.NET Core packages ==
 
Keep in mind that building projects which don't use the .NET SDK (formerly the .NET Core SDK) and its <code>dotnet</code> CLI tool isn't supported.
For those projects, you'll have to heavily customise the <code>buildDotnetModule</code> build steps, or write a custom derivation.
 
Projects which target .NET Standard or .NET Framework (incl. Mono), but still use the new project structure and SDK, work as expected.
Just remember to add `mono` to `buildInputs` and generate a wrapper script in `postInstall`.
 
== Packaging ASP.NET projects ==
 
Currently building ASP.NET project as Nix package produces a website that does not work correctly out of the box because the executable can not find <code>wwwroot</code>, so all the static assets won't load with 404.
 
<blockquote>
Request finished HTTP/2 GET https://my.app/css/site.css - 404 0
</blockquote>
 
The situation can be fixed by setting <code>WEBROOT</code> environment variable to the package path.
 
An example of systemd + ASP.NET 8 service:
 
<syntaxhighlight lang="nix">
# myapp package needs to be imported; and added to `environment.systemPackages`
# the variable myapp is used below


   meta = with lib; {
systemd.services.my-app = {
     homepage = "some_homepage";
   enable = true;
     description = "some_description";
  description = "Runs my.app";
     license = licenses.mit;
  wantedBy = [ "multi-user.target" ];
  after = [ "network-online.target" ];
  wants = [ "network-online.target" ];
  serviceConfig = {
     # allow binding to privileged ports - when you want to expose Kestrel directly without reverse proxy
    AmbientCapabilities = "CAP_NET_BIND_SERVICE";
     User = "myapp"; # must be created using users.users.myapp = { isSystemUser = true; group = "myapp"; };
     Group = "myapp"; # must be created using users.groups.myapp = {};
    Restart = "always";
    ExecStart = "${myapp}/bin/myapp";
    StateDirectory = "myapp";
    StateDirectoryMode = "0750";
    WorkingDirectory = "/var/lib/myapp";
    # EnvironmentFile = "/var/lib/myapp/env";
   };
   };
}
  environment = {
    WEBROOT = "${myapp}/lib/myapp/wwwroot"; # IMPORTANT, required to pick up static assets
 
    DOTNET_ENVIRONMENT = "Production";


</syntaxhighlight>
    # the following are examples
    ConnectionStrings__DefaultConnection = "Host=/var/run/postgresql;Database=myapp";


To generate <code>nuget-deps.nix</code> file you can run
    # Kestrel + HTTPS; must setup https://wiki.nixos.org/wiki/ACME
    Kestrel__Endpoints__Https__Url = "https://my.app";
    Kestrel__Endpoints__Https__Certificate__Path = "/var/lib/acme/my.app/cert.pem";
    Kestrel__Endpoints__Https__Certificate__KeyPath = "/var/lib/acme/my.app/key.pem";


<code>dotnet restore --packages=packageDir SomeProject.csproj && nuget-to-nix packageDir >nuget-deps.nix; rm -rf packageDir</code>
    Logging__LogLevel__Default = "Information";
    Logging__LogLevel__Microsoft__AspNetCore = "Warning"; # this does not actually work, not sure how to fix


After that the package will build normally. Remember to re-run nuget-to-nix every time the package is updated.
    Authentication__Google__ClientId = "xxxyyyzzz.apps.googleusercontent.com";
    Authentication__Microsoft__ClientId = "aaaaaa-0000-aaaa-0000-aaaaaaaaaa";
    # secrets must be placed in /var/lib/myapp/appsettings.json


== Building non-.NET Core packages ==
    # TODO email


Keep in mind that building non-.NET Core projects (ie. projects that don't build using the <code>dotnet</code> CLI tool) is not well supported. For those projects, you have to work on a custom derivation or override the <code>buildDotnetModule</code> build steps.
    # TODO Stripe
    Stripe__Currency = "USD";
  };
};


== Building ASP.NET packages ==
</syntaxhighlight>


Currently building ASP.NET packages produces website that does not work correctly out of the box because the executable can not find ContentRoot and wwwroot, so all the static assets won't load.
See also: setting up SSL certificates using [[ACME]]


== .NET location: Not found ==
== .NET location: Not found ==


If running a .NET-build executable you get the above error, make sure the DOTNET_ROOT environment variable is set:
If running a .NET-build executable you get the above error, make sure the DOTNET_ROOT environment variable is set:
<syntaxHighlight lang=nix>
<syntaxhighlight lang="nix">
environment.sessionVariables = {
environment.sessionVariables = {
   DOTNET_ROOT = "${pkgs.dotnet-sdk}";
   DOTNET_ROOT = "${pkgs.dotnet-sdk}/share/dotnet/";
};
};
</syntaxHighlight>
</syntaxhighlight>


See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables
See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables
Line 69: Line 126:


Wontfix: The project will build only on Windows.
Wontfix: The project will build only on Windows.
== Unable to find package ==
<blockquote>
error NU1101: Unable to find package runtime.any.System.Collections. No packages exist with this id in source(s): nugetSource
</blockquote>
Unsure what specific situations cause this, probably has something to do with .NET Standard libraries.
The workaround is modifying the bits that generate nuget-deps.nix:
<syntaxhighlight lang="sh">
dotnet restore --packages=packageDir --use-current-runtime ./SomeProject.csproj
nuget-to-nix packageDir >deps.nix
rm -r packageDir
</syntaxhighlight>
The new parameter <code>--use-current-runtime</code> requires .NET SDK 8+. I believe what it does is explicitly adding packages missing in this runtime vs .NET Standard to packageDir.
If this still does not work, it might indicate a good time to update target frameworks and dependencies.


== NativeAOT ==
== NativeAOT ==
Line 123: Line 202:


== Example: Running Rider with dotnet & PowerShell ==
== Example: Running Rider with dotnet & PowerShell ==
Rider has better compatibility when run in FHS mode


Rider package
Rider package<syntaxhighlight lang="nix">
 
<syntaxHighlight lang=nix>
pkgs.jetbrains.rider
pkgs.jetbrains.rider
</syntaxHighlight>
</syntaxhighlight>rider-fhs.nix<syntaxhighlight lang="nix">
{ pkgs ? import <nixpkgs> {} }:


dotnet.nix
(pkgs.buildFHSEnv {
 
   name = "rider-env";
<syntaxHighlight lang=nix>
   targetPkgs = pkgs: (with pkgs; [
with import <nixpkgs> {};
    dotnetCorePackages.dotnet_8.sdk
 
     dotnetCorePackages.dotnet_8.aspnetcore
mkShell {
   name = "dotnet-env";
   packages = [
    (with dotnetCorePackages; combinePackages [
      sdk_6_0
      sdk_7_0
      sdk_8_0
     ])
     powershell
     powershell
   ];
   ]);
}
  multiPkgs = pkgs: (with pkgs; [
</syntaxHighlight>
  ]);
 
  runScript = "nohup rider &";
To execute Rider
}).env
 
</syntaxhighlight><syntaxhighlight lang="nix">
<syntaxHighlight lang=bash>
nix-shell ./rider-fhs.nix
nix-shell ./dotnet.nix --run 'nohup rider &'
</syntaxhighlight>This can be added as an alias to your shell if you update the reference to an absolute address, such as location within your home directory. <syntaxhighlight>
</syntaxHighlight>
run-rider = "nix-shell ~/nix/rider-fhs.nix";
 
</syntaxhighlight>
This can be added as an alias to your shell if you update the reference to an absolute address, such as location within your home directory. e.g. `~/nix/dotnet.nix`


== Example: multi-SDK installation with local workload installation enabled ==
== Example: multi-SDK installation with local workload installation enabled ==
Line 167: Line 237:
* [https://nixos.org/manual/nixpkgs/unstable/#dotnet dotnet in the nixpkgs manual]
* [https://nixos.org/manual/nixpkgs/unstable/#dotnet dotnet in the nixpkgs manual]
* [https://github.com/search?q=repo%3ANixOS%2Fnixpkgs%20buildDotnetModule&type=code buildDotnetModule references in nixpkgs]
* [https://github.com/search?q=repo%3ANixOS%2Fnixpkgs%20buildDotnetModule&type=code buildDotnetModule references in nixpkgs]
* [https://www.reddit.com/r/NixOS_dotnet NixOS.NET community on Reddit]
* [https://discord.gg/pTpq7Qfs NixOS.NET community on Discord]
* [https://sgt.hootr.club/molten-matter/dotnet-on-nix/ The journey of packaging a .NET app on Nix]
* [https://sgt.hootr.club/molten-matter/dotnet-on-nix/ The journey of packaging a .NET app on Nix]
* https://en.wikipedia.org/wiki/.NET_Framework - The old, windows-only version of .NET. Newer versions (ie. .NET Core) are multiplatform.
* https://en.wikipedia.org/wiki/.NET_Framework - The old, windows-only version of .NET. Newer versions (ie. .NET Core) are multiplatform.
** https://en.wikipedia.org/wiki/Mono_(software) is the deprecated open source implementation of the DotNET compiler and runtime. It has transformed into .NET Core.
** https://en.wikipedia.org/wiki/Mono_(software) is the open source reimplementation of .NET Framework. Its runtime/JIT has been merged into .NET Core, and now it only receives bugfixes.
* https://learn.microsoft.com/en-us/dotnet/core/introduction
* https://learn.microsoft.com/en-us/dotnet/core/introduction


[[Category: Development]]
 
[[Category:Languages]]