We have an API that was originally written using the ASP.NET MVC framework and hosted on Windows Server. We have now ported it to an ASP.NET Core 8 Web API, and want to host on Linux (Oracle Linux 9). Pretty much got it working - I could run it manually - but when I try to run as a systemd
service it fails because it can't access the user's home directory.
I have followed the same pattern for my other Linux services, namely
- Create a user to run the service as. This is a system user so has no home directory and cannot be logged in as
- Create a folder, owned by that user, containing the API
- Create a run script, also owned by that user and in that directory, to start the service
- Create a
systemd
service definition, using the run script asExecStart
My Systemd
service definition looks like this:
[Unit]
Description=My API
[Service]
Type=forking
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_NOLOGO=true
ExecStart="/opt/myapi/run.sh"
User=myapiuser
WorkingDirectory=/opt/myapi
Restart=always
RestartSec=3
TimeoutStopSec=30
KillSignal=SIGINT
SyslogIdentifier=myapi
[Install]
WantedBy=multi-user.target
The /opt/myapi/run.sh
looks like this:
#!/bin/bash
dotnet MyApi--url=http://localhost:8080 >> /var/log/myapi/myapi.log 2>&1 &
Now systemctl status myapi
reports it's running. But if I look at the log file it's clearly crashing and restarting all the time with
2025-02-18 23:03:05.330709268+02:00 Starting: dotnet MyApi --url=http://localhost:8080
System.UnauthorizedAccessException: Access to the path '/home/myapiuser' is denied.
---> System.IO.IOException: Permission denied
--- End of inner exception stack trace ---
at System.IO.FileSystem.CreateParentsAndDirectory(String fullPath, UnixFileMode unixCreateMode)
at System.IO.FileSystem.CreateDirectory(String fullPath, UnixFileMode unixCreateMode)
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.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)
Thing is, I had run it as sudo -u myapiuser dotnet MyApi.dll
and it had run. Now I get that same error there.
Anyway, my question is the same: why does it need (or think it needs) access to the user's home directory? I want to run it as a service user, without a home directory.
We have an API that was originally written using the ASP.NET MVC framework and hosted on Windows Server. We have now ported it to an ASP.NET Core 8 Web API, and want to host on Linux (Oracle Linux 9). Pretty much got it working - I could run it manually - but when I try to run as a systemd
service it fails because it can't access the user's home directory.
I have followed the same pattern for my other Linux services, namely
- Create a user to run the service as. This is a system user so has no home directory and cannot be logged in as
- Create a folder, owned by that user, containing the API
- Create a run script, also owned by that user and in that directory, to start the service
- Create a
systemd
service definition, using the run script asExecStart
My Systemd
service definition looks like this:
[Unit]
Description=My API
[Service]
Type=forking
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_NOLOGO=true
ExecStart="/opt/myapi/run.sh"
User=myapiuser
WorkingDirectory=/opt/myapi
Restart=always
RestartSec=3
TimeoutStopSec=30
KillSignal=SIGINT
SyslogIdentifier=myapi
[Install]
WantedBy=multi-user.target
The /opt/myapi/run.sh
looks like this:
#!/bin/bash
dotnet MyApi--url=http://localhost:8080 >> /var/log/myapi/myapi.log 2>&1 &
Now systemctl status myapi
reports it's running. But if I look at the log file it's clearly crashing and restarting all the time with
2025-02-18 23:03:05.330709268+02:00 Starting: dotnet MyApi --url=http://localhost:8080
System.UnauthorizedAccessException: Access to the path '/home/myapiuser' is denied.
---> System.IO.IOException: Permission denied
--- End of inner exception stack trace ---
at System.IO.FileSystem.CreateParentsAndDirectory(String fullPath, UnixFileMode unixCreateMode)
at System.IO.FileSystem.CreateDirectory(String fullPath, UnixFileMode unixCreateMode)
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.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)
Thing is, I had run it as sudo -u myapiuser dotnet MyApi.dll
and it had run. Now I get that same error there.
Anyway, my question is the same: why does it need (or think it needs) access to the user's home directory? I want to run it as a service user, without a home directory.
Share Improve this question edited yesterday marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked yesterday AdamAdam 6,7634 gold badges44 silver badges69 bronze badges 4 |1 Answer
Reset to default 0I'm still not sure exactly why, but this has fixed itself. I'm pretty sure I was running the exact same command, with the exact same .dll when it didn't work as when it earlier did, but other changes seem to have resolved it.
/home/myapiuser
to myapiuser first, then check if the application is running or not. – Jason Pan Commented yesterday/home/myapiuser
exist or not. It looks like environment variable issue, by the way, please share the docker file with us, many thanks~ – Jason Pan Commented yesterday