Skip to content

Register the .NET install location in the Linux guide - #510

Merged
Zaldaryon merged 2 commits into
devfrom
docs/linux-dotnet-install-location
Sep 23, 2026
Merged

Zaldaryon merged 2 commits into
devfrom
docs/linux-dotnet-install-location

Conversation

@Pixnop

@Pixnop Pixnop commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor

What changes

In docs/get-started/installation/linux.md, right after the three dotnet-install.sh commands in the Debian/Ubuntu section:

  • Switches the recommended --install-dir to /usr/share/dotnet, the apphost's own compiled-in default, so there's nothing to register at all.
  • Keeps /usr/lib/dotnet as an alternative for anyone who wants the game's .NET kept separate, with a hint that registers it by writing both /etc/dotnet/install_location and /etc/dotnet/install_location_x64, since newer hosts read the architecture-specific file instead of the plain one.
  • Adds sudo ln -s .../dotnet /usr/bin/dotnet, so dotnet --list-runtimes works for checking.
  • Adds a "Check it" line: dotnet --list-runtimes should list Microsoft.NETCore.App for the major version the game needs.
  • Adds a troubleshooting hint: a "missing .NET runtime" report from the launcher, when an older copy of the game ran fine, usually means that copy shipped its own runtime, not that the system install is broken. Shows the searched-locations block from verbose.log, and mentions the per-Installation ENV variables field (Advanced section) as an alternative to the system-wide registration when the runtime lives somewhere else.

In the Arch section, adds one sentence noting that dotnet-runtime packages register the install location themselves, so that step doesn't apply there. Fedora and a separate Ubuntu apt path aren't covered by this doc, so nothing changed there.

Why

A PikaOS (Debian-based) player followed this guide, installed .NET 7/8/10 with dotnet-install.sh into /usr/lib/dotnet, and Vintage Story still could not find .NET 10 (dotnet wasn't on PATH either). A separate copy of the game that bundled its own runtime ran fine, which is what pointed at the missing system-wide registration rather than a bad download.

dotnet-install.sh only adds the install directory to the current shell's PATH for that session, and explicitly does not set DOTNET_ROOT:

By default, the script adds the install location to the $PATH for the current session. Override this default behavior by specifying the -NoPath|--no-path argument. The script doesn't set the DOTNET_ROOT environment variable.

dotnet-install scripts reference

Vintage Story starts through its own apphost, not through the shell that ran the script, so that session-only PATH change never reaches it. The apphost resolves the runtime through DOTNET_ROOT, then the registered install location, then its compiled-in default, in that order:

These environment variables are used only when running apps via generated executables (apphosts). The order in which the environment variables are considered is: 1. DOTNET_ROOT_<ARCH> [...] 3. DOTNET_ROOT.

.NET environment variables

Global installs are registered in /etc/dotnet/install_location. On some systems, architecture-specific files are also present, such as /etc/dotnet/install_location_arm64.

Troubleshoot app launch failures

/etc/dotnet/install_location is a file that contains the full path for {dotnet_root}. [...] It's not necessary to add these files when the root is /usr/share/dotnet.

.NET distribution packaging

And the compiled-in default for Linux is /usr/share/dotnet/, which is also the location the "framework not found" error reports as searched when nothing else is registered.

None of that runs for a dotnet-install.sh install, which is why the game kept failing even though dotnet-install.sh reported success. src/ipc/handlers/gameExecutionOutcome.ts recognizes the host's own wording for this failure, "You must install or update .NET to run this application.", which matches what Microsoft's docs show the host prints.

Update: a second PikaOS report came in from a player who had already applied this guide, writing /etc/dotnet/install_location, and the game still failed on .NET 10.0.2. Their verbose.log had the apphost list exactly what it searched:

Environment variable: DOTNET_ROOT_X64 = <not set>, DOTNET_ROOT = <not set>; Registered location: /etc/dotnet/install_location_x64 = <not set>; Default location: /usr/share/dotnet

It names install_location_x64, not install_location: this host only checked (and only reported on) the architecture-specific file, so the plain one this guide wrote was invisible to it. Microsoft's troubleshoot-app-launch page confirms the arch-specific file exists (quoted above) but doesn't spell out precedence between the two on Linux; this apphost's own diagnostic output is the evidence that a recent host can skip the plain file entirely. The guide now writes both files when registering a custom location, and, since installing straight into the apphost's default /usr/share/dotnet needs no registration file of either kind, leads with that instead.

Checked

On this machine (dotnet installed system-wide, not via the script):

$ dotnet --list-runtimes
Microsoft.NETCore.App 7.0.20 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.30 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.11 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

$ cat /etc/dotnet/install_location
cat: /etc/dotnet/install_location: No such file or directory

The missing file is expected here: the install root is /usr/share/dotnet, the compiled-in default, and Microsoft's own docs say the file isn't needed in that case.

Also ran npm run format:check on the branch, which passes.

@Pixnop
Pixnop requested a review from Zaldaryon September 18, 2026 17:08

@Zaldaryon Zaldaryon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified at 37b2be5 against this machine's installed tree. The apphost binary does carry /usr/share/dotnet as its compiled-in default root (strings on apphost shows the literal), so installing straight there means no registration file is needed, which is exactly the simplification the PR sells. The four search-path lines the warning hint shows match the host's own trace wording (Environment variable:, Registered location:, Default location: in the packaged singlefilehost), and the install_location_x64 note is right: hostfxr does look for the architecture-suffixed file, and dotnet-install.sh sets neither file, so both need to be written for the /usr/lib/dotnet alternative. TheArch note about pacman writing the location file itself is correct. Docs-only, one file, nothing else touched.

@Zaldaryon
Zaldaryon merged commit c07dd21 into dev Sep 23, 2026
9 checks passed
@Zaldaryon
Zaldaryon deleted the docs/linux-dotnet-install-location branch September 23, 2026 14:43
@Pixnop Pixnop mentioned this pull request Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants