Thefrank / dotnet-freebsd-crossbuild

Bash script and patches for building dotNET for FreeBSD under Linux
31 stars 3 forks source link

System.IO.IOException: Read-only file system : '/.dotnet' #5

Closed nkosi23 closed 1 year ago

nkosi23 commented 1 year ago

When trying to launch an ASP.NET Core application in a jail having the root partition mounted on a read-only file system (but whose /usr/local and /tmp partitions are writable) I receive the following exception on application startup:

System.IO.IOException: Read-only file system : '/.dotnet'
   at System.IO.FileSystem.CreateDirectory(String fullPath, UnixFileMode unixCreateMode)
   at System.IO.FileSystem.CreateDirectory(String fullPath)
   at System.IO.Directory.CreateDirectory(String path)
   at Microsoft.Extensions.EnvironmentAbstractions.DirectoryWrapper.CreateDirectory(String path)
   at Microsoft.DotNet.Configurer.FileSystemExtensions.<>c__DisplayClass0_0.<CreateIfNotExists>b__0()
   at Microsoft.DotNet.Cli.Utils.FileAccessRetrier.RetryOnIOException(Action action)
   at Microsoft.DotNet.Configurer.FileSystemExtensions.CreateIfNotExists(IFileSystem fileSystem, String filePath)
   at Microsoft.DotNet.Configurer.FileSentinel.Create()
   at Microsoft.DotNet.Configurer.DotnetFirstTimeUseConfigurer.AddPackageExecutablePath()
   at Microsoft.DotNet.Configurer.DotnetFirstTimeUseConfigurer.Configure()
   at Microsoft.DotNet.Cli.Program.ConfigureDotNetForFirstTimeUse(IFirstTimeUseNoticeSentinel firstTimeUseNoticeSentinel, IAspNetCertificateSentinel aspNetCertificateSentinel, IFileSentinel toolPathSentinel, Boolean isDotnetBeingInvokedFromNativeInstaller, DotnetFirstRunConfiguration dotnetFirstRunConfiguration, IEnvironmentProvider environmentProvider, Dictionary`2 performanceMeasurements)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)
   at Microsoft.DotNet.Cli.Program.Main(String[] args)

Is there a way to modify the default path chosen by dotnet? I am using your latest release (7.0.203)

Thefrank commented 1 year ago

Never tried running dotNET in a read-only jail but you can try and set DOTNET_RUNNING_IN_CONTAINER=true environment variable and DOTNET_ROOT=/path/to/dotnet

There are a few more here but I don't think they apply: https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables

late edit: @nkosi23 if you are trying to use it from an rc script you might want to make use of ${name}_chdir or ${name}_chroot if needed

nkosi23 commented 1 year ago

Thanks a lot! This is exactly the kind of environment variables I was thinking about and looking for, however I found that the issue was actually caused by the fact that I am using supervisord to launch the application.

This question from a fellow FreeBSD user describes my situation and gave me the solution. In a nutshell, the issue was that supervisord does not spawn a full shell environment when told to impersonate a user, therefore the HOME environment variables are not set. This must be done manually:

No shell is executed by supervisord when it runs a subprocess, so environment variables such as USER, PATH, HOME, SHELL, LOGNAME, etc. are not changed from their defaults or otherwise reassigned. This is particularly important to note when you are running a program from a supervisord run as root with a user= stanza in the configuration. Unlike cron, supervisord does not attempt to divine and override “fundamental” environment variables like USER, PATH, HOME, and LOGNAME when it performs a setuid to the user defined within the user= program config option. If you need to set environment variables for a particular program that might otherwise be set by a shell invocation for a particular user, you must do it explicitly within the environment= program config option. An example of setting these enviroment variables is as below.

[program:apache2]
command=/home/chrism/bin/httpd -c "ErrorLog /dev/stdout" -DFOREGROUND
user=chrism
environment=HOME="/home/chrism",USER="chrism"

Also in case this helps someone, I also noticed that running dotnet /path/to/cli-binary resulted in dotnet returning a file not found error:

Could not execute because the specified command or file was not found.
Possible reasons for this include:
  * You misspelled a built-in dotnet command.
  * You intended to execute a .NET program, but dotnet-cli-binary does not exist.
  * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH

But the problem is fixed by using dotnet /path/to/cli-binary.dll instead. Trying to execute the CLI file directly results in an invalid binary format error being issued from FreeBSD but this should be expected I think.