Running dotnet / .NET Core

Hi,
I just figured I’d post this here for anyone else interested.
I was able to get part way into running .net under shared hosting.
Although to run an actual site you would probably need passenger 6 instead of passenger 5 support (I’m pretty sure passenger 5 is in use on the shared hosting at the moment).
https://www.phusionpassenger.com/docs/advanced_guides/gls/dotnetcore.html

This still might be useful for anyone using VPS or just wants to run a dotnet script as a cronjob periodically though. It works in a similar fashion to running a custom version of python3.
That being said I wouldn’t want to go against any form of TOS or rules since Microsoft technicologies aren’t officially supported by dreamhost, so any feedback would be welcome.

.Net Core Overview

.Net Core is a different animal than the original old mono / 4.7 version of .Net
It’s a lot more self contained (similar to an install of python3) and it doesn’t require that much in the way of dependencies.
It was basically a total re-write of the framework to be Linux friendly.
Currently it’s possible to get Ruby / Python / NodeJS working via Passenger, so I was curious as to if it would be possible to get .Net core working as well.

Personally I’m using a Shared Host (not a VPS) so no sudo access.
I’ve managed to get as far as running a simple hello world program from the shell under .Net Core 6 which I’ll List below

Install

First download and extract the runtime (I’m using .Net 6 preview here)

mkdir dotnet6
cd dotnet6
wget https://download.visualstudio.microsoft.com/download/pr/898bd961-c1fe-4e22-8692-d488ee838afd/315180a646a83063ceaae7a8ab9804cf/aspnetcore-runtime-6.0.0-preview.7.21378.6-linux-x64.tar.gz
tar -xvzf aspnetcore-runtime-6.0.0-preview.7.21378.6-linux-x64.tar.gz

Next you’ll need to patch the header of the dotnet exe using paxctl
It may be possible to do this on the host, although paxctl isn’t installed there so it’s probably best to do this on a separate linux box
Then copy it across / overwrite it on the host

paxctl -c -m dotnet

Without this you will probably run into the problem of seeing a

Failed to create CoreCLR, HRESULT: 0x80004005

I suspect this might be related to grsecurity on the kernel

Running a console app

Lets setup some paths, I’m not sure these are actually needed but lets set them up anyway

mkdir /home/username/tmp
TMPDIR=/home/username/tmp
COMPlus_EnableDiagnostics=0
DOTNET_ROOT=/home/username/dotnet6

It should now be possible to run a simple program with something like

./dotnet6/dotnet Hello1.dll

If you build a self contained exe with the runtime inbuilt
then you’ll probably need to do the same paxctl patch on it as above

Dependencies

I did a quick check on the host for the needed dependencies with

/sbin/ldconfig -p | grep XXX

All of these seem installed

  • libc6
  • libstdc++6
  • libicu60 (for 18.x)
  • libssl1.1 (for 18.x, 20.x)
  • libgssapi-krb5-2
  • libgcc1

Ones that were missing were

  • zlib1g
    Used for Zips / Compression I think

  • libgdiplus (version 6.0.1 or later)
    (used for System.Drawing.Common which isn’t likley I think on a website)

For the dependencies you may be able to work around the zlib one by setting the RPATH / ORIGIN env variable, and placing the lib there locally
(if you need it) - https://github.com/dotnet/core/blob/main/Documentation/self-contained-linux-apps.md

In theory Passenger 6 would also allow support for a whole bunch of other languages such as rust, go elixir, swift, java etc
Although given the release was in 2018 I suspect we might not see it any time soon here

DreamHost run Passenger 4 (which is why users are limited to using, for example, older nodejs versions). No one at DH has ever explained why they refuse to update it, my guess is they patched a v4 years ago to work with their setup at the time and have held off on ever touching it again.

There has been an uptick on posts about nodejs over the past year and given node v12 is End-Of-Life in a few months perhaps you could get them to revisit upgrading Passenger.

The reason I mentioned version 5 above, is that if you try running

passenger-config about version

From a shell on the host (this is a shared host) you get the result

Phusion Passenger 5.0.30

I didn’t want to mess with that command too much since I think it might impact other users on the same host.

For the actual box running uname -a shows

Linux granite 4.14.117-grsec-grsec+ #1 SMP Fri May 10 17:15:47 PDT 2019 x86_64 x86_64 x86_64 GNU/Linux

So this is on the host box called granite

Interesting. Can you fire up node >12 on that box?

I’ve not tested nodejs yet but I did discover that instead of the paxctl command you can use setfattr instead which is easier since it’s already on the system and doesn’t need to be downloaded.

So to patch the dotnet binary

setfattr -n user.pax.flags -v "mr" dotnet

Results of experimenting with nodejs

Based on these links

Initial setup

Install latest version of nvm

cd ~
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
source ~/.bashrc
setfattr -n user.pax.flags -v "mr" $NVM_DIR/nvm.sh

Add the following to ~/.bash_profile

source ~/.bashrc

Lets try the current LTS release

nvm ls-remote | grep v14
nvm install v14.17.6
nvm use v14.17.6
nvm alias default v14.17.6

This is needed to fix pax security related errors

setfattr -n user.pax.flags -v "mr" $(find $NVM_DIR -type f -iname "node" -o -iname "npm" -o -iname "npx")

Setup Dummy Site

Next within the site directory

app.js

var http = require("http");

http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.write("Hello World. This page is running Node.js version: ");
  response.write(process.version);
  response.end();
}).listen(80);

.htaccess

PassengerNodejs /home/dh_7wrp5c/.nvm/versions/node/v14.17.6/bin/node

Restart Passenger

mkdir -p tmp && touch tmp/restart.txt

Results

I ran into this issue regards the GLOBAL

The error was

App 24365 stderr: /usr/share/passenger/helper-scripts/node-loader.js:41
App 24365 stderr: GLOBAL.PhusionPassenger = exports.PhusionPassenger = new EventEmitter();

Looks like the GLOBAL thing wasn’t fixed until version 5.1 of passenger

I had a quick go with v13.14.0 and v12.22.6 and they seem to work

I did a bit more digging
Based on what I’ve seen so far if you wanted official support for nodejs > 13, then you’d need Passenger 5.1 at a minimum
For other languages such as dotnet or others you’d need Passenger 6.x at a minimum

One possible workaround although I’ve not experimented with this (since I’d do that on my own local VM first, not dreamhost’s)
Would be to try setting PassengerPython or PassengerNodejs in .htaccess to a bash script or exe wrapper
The idea being to ignore the path to the wrapper script that’s probably being passed in as a command line argument and use a custom one instead.

Generally the way the wrapper scripts work from what I can tell is that they create a unix socket
Setup handlers against that unix socket to capture when Passenger will send data down them and pass that onto the python / node webservice
Then send text / api messages to Passenger over stdout to let it know which unix socket to use / that everything is ok for sending.
In the case of the python one for example the wrapper script basically wrappers the inbound message into a wsgi message before passing it on

The downside with trying to use a custom wrapper script (assuming you could) would be if Passenger was ever updated in the future by DH.
Since that might change the passenger wrapper script api.
Realistically it might be an option to get NodeJS > 13 working since that might just be a minor tweak to the script that’s needed to remove GLOBAL
For dotnet you’d need to write a custom handler to setup the unix socket etc and would probably be a lot of work.

Personally I’m just planning on using dotnet webassembly anyway so I only need static files for that and python as a backend is good enough for me
I might revisit the nodejs approach later on since that might be useful for a lot of folks and might be a quick fix
But I’d need to setup a local VM with the same version of Passenger first to experiment with

1 Like

If you can cobble together a fix to get node >12 running on DreamHost then I’m sure there will be users here who will be very appreciative of your effort.

Here you go
Hope this works for you

I no longer host here, but users searching for a solution will be thrilled.