DotNET: Difference between revisions

m ryantm link -> canonical Nixpkgs manual link
m Use the correct command name.
 
(20 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
{
, buildDotnetModule
  buildDotnetModule,
  dotnetCorePackages,
}:
}:


buildDotnetModule rec {
buildDotnetModule {
   pname = "some_program";
   pname = "hello";
   version = "some_version";
   version = "0.1";
 
  src = ./.;
 
  projectFile = "Hello/Hello.csproj";
  dotnet-sdk = dotnetCorePackages.sdk_8_0;
  dotnet-runtime = dotnetCorePackages.runtime_8_0;
  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>


   src = fetchFromGitHub {
Remember to build and run the <code>fetch-deps</code> script after NuGet packages are updated, or building the derivation will fail.
     owner = "some_owner";
 
     repo = pname;
== Building non-.NET Core packages ==
     rev = "v${version}";
 
     sha256 = "";
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
 
systemd.services.my-app = {
   enable = true;
  description = "Runs my.app";
  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";
    # the following are examples
    ConnectionStrings__DefaultConnection = "Host=/var/run/postgresql;Database=myapp";


  projectFile = "SomeProject/SomeProject.csproj";
    # 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";


  meta = with lib; {
     Logging__LogLevel__Default = "Information";
     homepage = "some_homepage";
     Logging__LogLevel__Microsoft__AspNetCore = "Warning"; # this does not actually work, not sure how to fix
     description = "some_description";
    license = licenses.mit;
  };
}


</syntaxHighlight>
    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


Note that the above package will not build the first time. After adding the above definition to `all-packages.nix`, you
    # TODO email
can run the package-specific `fetch-deps` script, which will generate a file containing all the nuget dependencies of the
package. Build the script with <code>nix-build -A some-package.fetch-deps</code>, copy that generated file (the location will be printed by the script) and set the <code>nugetDeps</code> attribute in <code>buildDotnetModule</code> to point to that generated file (ie. <code>nugetDeps = ./deps.nix</code>).


After that the package will build normally. Remember to re-run <code>fetch-deps</code> every time the package is updated.
    # TODO Stripe
    Stripe__Currency = "USD";
  };
};


== Building non-.NET Core packages ==
</syntaxhighlight>


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.
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 61: 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 115: 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 159: 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]]