DotNET: Difference between revisions
create systemd service from an ASP.NET-based package |
group into sections, add intro text from wikipedia |
||
| (10 intermediate revisions by 6 users not shown) | |||
| Line 1: | Line 1: | ||
From [https://en.wikipedia.org/wiki/.NET Wikipedia] | |||
<blockquote> | |||
The .NET platform (formerly named .NET Core) is a free and open-source, managed computer software framework for Windows, Linux, and macOS operating systems. It is a cross-platform successor to the .NET Framework. The project is mainly developed by Microsoft employees by way of the .NET Foundation and is today released under an MIT License. | |||
</blockquote> | |||
== NativeAOT == | |||
This is relevant for NixOS only. | |||
[https://github.com/Mic92/nix-ld nix-ld] is needed: | |||
<syntaxHighlight lang=nix> | |||
{ | |||
programs.nix-ld.enable = true; | |||
} | |||
</syntaxHighlight> | |||
Now we will need a bunch of native dependencies. Here's an example of a shell: | |||
<syntaxHighlight lang=nix> | |||
with import <nixpkgs> {}; | |||
pkgs.mkShell rec { | |||
dotnetPkg = | |||
(with dotnetCorePackages; combinePackages [ | |||
sdk_7_0 | |||
]); | |||
deps = [ | |||
zlib | |||
zlib.dev | |||
openssl | |||
dotnetPkg | |||
]; | |||
NIX_LD_LIBRARY_PATH = lib.makeLibraryPath ([ | |||
stdenv.cc.cc | |||
] ++ deps); | |||
NIX_LD = "${pkgs.stdenv.cc.libc_bin}/bin/ld.so"; | |||
nativeBuildInputs = [ | |||
] ++ deps; | |||
shellHook = '' | |||
DOTNET_ROOT="${dotnetPkg}"; | |||
''; | |||
} | |||
</syntaxHighlight> | |||
== Global Tools == | |||
Local installation of .NET global tools is fully supported and preferred when possible - more info [https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools#install-a-local-tool in the Microsoft docs]. | |||
For globally installing .NET tools, search if they are available as Nix packages - they are packaged as any other normal | |||
.NET binary, using <code>buildDotnetModule</code>. For .NET tools with no source available, or those hard to build from source, <code>buildDotnetGlobalTool</code> is available. See [https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/dotnet.section.md#dotnet-global-tools-dotnet-global-tools dotnet nixpkgs manual] for more info. | |||
Note that Nix-packaged .NET tools use a special wrapper (toggled by <code>useDotnetFromEnv</code> option in <code>buildDotnetModule</code>) that automatically picks up .NET install from the user environment. If you want to use a | |||
different SDK version with a Nix-packaged .NET tools than the default, make sure the <code>dotnet</code> CLI of your wanted SDK version is installed and available. | |||
== Packaging == | |||
.NET packages can be built with <code>buildDotnetModule</code> | .NET packages can be built with <code>buildDotnetModule</code> | ||
| Line 4: | Line 64: | ||
Example build file: | Example build file: | ||
<syntaxhighlight lang="nix"> | <syntaxhighlight lang="nix" line="1" start="1"> | ||
{ | { | ||
, dotnetCorePackages | buildDotnetModule, | ||
, | dotnetCorePackages, | ||
}: | }: | ||
buildDotnetModule | buildDotnetModule { | ||
pname = " | pname = "hello"; | ||
version = " | version = "0.1"; | ||
src = | src = ./.; | ||
projectFile = " | 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 = ./deps. | nugetDeps = ./deps.json; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
If the <code>fetch-deps</code> script isn't working for whatever reason, you can manually run <code>nuget-to- | If the <code>fetch-deps</code> script isn't working for whatever reason, you can manually run <code>nuget-to-json</code>: | ||
<syntaxhighlight lang=" | <syntaxhighlight lang="shell-session"> | ||
dotnet restore --packages=packageDir ./SomeProject.csproj | $ dotnet restore --packages=packageDir ./SomeProject.csproj | ||
nuget-to- | $ nuget-to-json packageDir > deps.json | ||
rm -r packageDir | $ rm -r packageDir | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Remember to build and run the <code>fetch-deps</code> script after NuGet packages are updated, or building the derivation will fail. | 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 == | === 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. | 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. | ||
| Line 52: | Line 101: | ||
Just remember to add `mono` to `buildInputs` and generate a wrapper script in `postInstall`. | Just remember to add `mono` to `buildInputs` and generate a wrapper script in `postInstall`. | ||
== Packaging ASP.NET projects == | === 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 | 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. | ||
> Request finished HTTP/2 GET https://my.app/css/site.css - 404 0 | <blockquote> | ||
Request finished HTTP/2 GET https://my.app/css/site.css - 404 0 | |||
</blockquote> | |||
The situation can be fixed by setting | The situation can be fixed by setting <code>WEBROOT</code> environment variable to the package path. | ||
An example of systemd + ASP.NET 8 service: | An example of systemd + ASP.NET 8 service: | ||
<syntaxhighlight lang="nix"> | |||
# myapp package needs to be imported; and added to `environment.systemPackages` | # myapp package needs to be imported; and added to `environment.systemPackages` | ||
# | # the variable myapp is used below | ||
systemd.services.my-app = { | systemd.services.my-app = { | ||
| Line 73: | Line 124: | ||
wants = [ "network-online.target" ]; | wants = [ "network-online.target" ]; | ||
serviceConfig = { | 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"; }; | User = "myapp"; # must be created using users.users.myapp = { isSystemUser = true; group = "myapp"; }; | ||
Group = "myapp"; # must be created using users.groups.myapp = {}; | Group = "myapp"; # must be created using users.groups.myapp = {}; | ||
| Line 110: | Line 162: | ||
}; | }; | ||
</syntaxhighlight> | |||
See also: setting up SSL certificates using [[ACME]] | |||
== Examples == | |||
== | === Running Rider with dotnet & PowerShell === | ||
Rider has better compatibility when run in FHS mode | |||
< | Rider package<syntaxhighlight lang="nix"> | ||
pkgs.jetbrains.rider | |||
</syntaxhighlight>rider-fhs.nix<syntaxhighlight lang="nix"> | |||
{ pkgs ? import <nixpkgs> {} }: | |||
(pkgs.buildFHSEnv { | |||
name = "rider-env"; | |||
targetPkgs = pkgs: (with pkgs; [ | |||
dotnetCorePackages.dotnet_8.sdk | |||
dotnetCorePackages.dotnet_8.aspnetcore | |||
powershell | |||
]); | |||
multiPkgs = pkgs: (with pkgs; [ | |||
]); | |||
runScript = "nohup rider &"; | |||
}).env | |||
</syntaxhighlight> | |||
</ | <syntaxhighlight lang="nix"> | ||
nix-shell ./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. | |||
= | <syntaxhighlight> | ||
run-rider = "nix-shell ~/nix/rider-fhs.nix"; | |||
</syntaxhighlight> | |||
=== Multi-SDK installation with local workload installation enabled === | |||
By default, workload installation will fail on NixOS, as dotnet will attempt to save it to $DOTNET_ROOT, which is inside the read-only Nix store. | |||
Please visit the [https://discourse.nixos.org/t/dotnet-maui-workload/20370/10 forum] for an example of a multi-SDK installation with workload changed to install to home directory. | |||
with | |||
== Troubleshooting == | |||
=== .NET location: Not found === | |||
== | If running a .NET-build executable you get the above error, make sure the DOTNET_ROOT environment variable is set: | ||
<syntaxhighlight lang="nix"> | |||
environment.sessionVariables = { | |||
DOTNET_ROOT = "${pkgs.dotnet-sdk}/share/dotnet/"; | |||
}; | |||
</syntaxhighlight> | |||
See : https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#net-sdk-and-cli-environment-variables | |||
=== TargetFramework value was not recognized === | |||
<blockquote> | |||
error NETSDK1013: The TargetFramework value 'net6.0-windows' was not recognized. It may be misspelled. If not, then the TargetFrameworkIdentifier and/or TargetFrameworkVersion properties must be specified explicitly. | |||
</blockquote> | |||
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 | |||
with | |||
</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. | |||
== See also == | == See also == | ||
| Line 238: | Line 265: | ||
* https://learn.microsoft.com/en-us/dotnet/core/introduction | * https://learn.microsoft.com/en-us/dotnet/core/introduction | ||
[[Category: | |||
[[Category:Languages]] | |||