Mono on Shared Hosting at DreamHost through FastCGI

Mono @ DreamHostIt is technically possible to run a website on Mono (the open-source .NET development framework) using the Shared Hosting servers at DreamHost. The technique makes use of the pre-installed FastCGI module that is available on DreamHost’s Apache web servers, which is then configured to dynamically start the Mono FastCGI Backend. Just like for any other dynamic FastCGI server (such as for PHP FastCGI), the FastCGI module of Apache would monitor and manage the Mono FastCGI persistent processes and start/stop them as needed, in line with DreamHost’s configured FastCGI policy. The Mono FastCGI Backend is distributed as part of Mono’s XSP package, which needs to be built and installed along with all the other supporting Mono binaries. This procedure is detailed below, and an example Apache configuration is also provided for a basic Mono web-application that contains some standard ASP.NET pages (.aspx files) and a Web Service (.asmx file). With that in place, you can explore the rest of what Mono has to offer on a shared web server.

Compile and Install Mono

The most difficult and time-consuming part of getting the Mono website up and running may be to compile and install the Mono binaries. However, you just need to follow the steps in the shell script shown below to accomplish this. To make sure that everything goes according to plan and to have the opportunity to intervene if something does go wrong, you might want to run this script manually and copy-and-paste it step-by-step into your shell/console (simply check for error message that would be shown above the prompt after each step completes execution). Alternatively, if you insist on running this as an automated script, I would recommend that you insert programmatic error-checks: for example, after each wget, tar, make and configure step, you can insert the line “if [ $? -ne 0 ]; then exit 1; fi”, which would abort the script if something goes wrong. (Either way, there are about 84 places where you should check for successful progress along the way.) Also, note that not all the packages are essential to get Mono running: for example, libxml2 and libxslt are only included so that the xsltproc utility becomes available (which is needed if you want to run some of Mono’s unit-tests after the build). Similarly, if you do not intend to use the Visual Basic .NET (VB.NET) language, the mono-basic package is not needed. Furthermore, if no graphics-related functionality is required by your .NET applications (that is, GDI+ or the System.Drawing namespace), then neither Mono’s libgdiplus package nor its dependencies are needed (such as zlib, libpng, libjpeg/jpegsrc, libexif, libtiff/tiff and giflib). But if you want it all, the complete build-and-install script is as follows (download the script):

# ===================================================================
# Download, build and install the Mono .NET-compatible Framework...
# ===================================================================
# ===================================================================
# Setup and initialization
# -------------------------------------------------------------------
# Define some common variables
# TODO: Remember to use your own domain name (DreamHost directory name)
export DOMAIN=""
# Create a few directories (maybe not needed, but it shouldn't hurt)
mkdir -p "${mono_dir}"
mkdir -p "${mono_dir}/etc"
mkdir -p "${mono_src}"
# Setup the source environment variables to ensure that any custom 
# pkg-config libraries can be located and progressive compilations 
# can use the C# compiler and other Mono tools
export DYLD_LIBRARY_PATH="${mono_dir}/lib:${DYLD_LIBRARY_PATH}"
export LD_LIBRARY_PATH="${mono_dir}/lib:${LD_LIBRARY_PATH}"
export LIBRARY_PATH="${mono_dir}/lib:${LIBRARY_PATH}"
export C_INCLUDE_PATH="${mono_dir}/include"
export CPLUS_INCLUDE_PATH="${mono_dir}/include"
export ACLOCAL_PATH="${mono_dir}/share/aclocal"
export PKG_CONFIG_PATH="${mono_dir}/lib/pkgconfig:${PKG_CONFIG_PATH}"
export PATH="${mono_dir}/bin:${PATH}"
# ===================================================================
# Get and extract Mono and related packages/extensions
# -------------------------------------------------------------------
cd "${mono_src}"
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
wget -c ""
nice -n 19 tar -xzf "libiconv-1.13.1.tar.gz"
nice -n 19 tar -xzf "gettext-0.17.tar.gz"
nice -n 19 tar -xjf "libexif-0.6.18.tar.bz2"
nice -n 19 tar -xzf "zlib-1.2.3.tar.gz"
nice -n 19 tar -xzf "libpng-1.2.40.tar.gz"
nice -n 19 tar -xzf "jpegsrc.v7.tar.gz"
nice -n 19 tar -xzf "tiff-3.9.1.tar.gz"
nice -n 19 tar -xjf "giflib-4.1.6.tar.bz2"
nice -n 19 tar -xjf "bison-2.4.1.tar.bz2"
nice -n 19 tar -xzf "libxml2-2.7.6.tar.gz"
nice -n 19 tar -xzf "libxslt-1.1.26.tar.gz"
nice -n 19 tar -xjf "glib-2.22.2.tar.bz2"
nice -n 19 tar -xjf "libgdiplus-2.4.2.tar.bz2"
nice -n 19 tar -xjf "mono-"
nice -n 19 tar -xjf "xsp-2.4.2.tar.bz2"
nice -n 19 tar -xjf "mono-basic-2.4.2.tar.bz2"
# ===================================================================
# Build packages
# -------------------------------------------------------------------
# libiconv
cd "${mono_src}/libiconv-1.13.1"
./configure --enable-extra-encodings "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# gettext
cd "${mono_src}/gettext-0.17"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# Rebuild libiconv, again after gettext; recommended 
# on the GNU page
cd "${mono_src}/libiconv-1.13.1"
nice -n 19 make distclean
./configure --enable-extra-encodings "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# libexif
cd "${mono_src}/libexif-0.6.18"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# zlib
cd "${mono_src}/zlib-1.2.3"
./configure "--shared" "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# libpng
cd "${mono_src}/libpng-1.2.40"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# jpegsrc
cd "${mono_src}/jpeg-7"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# libtiff
cd "${mono_src}/tiff-3.9.1"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# giflib
cd "${mono_src}/giflib-4.1.6"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# bison
cd "${mono_src}/bison-2.4.1"
./configure --without-libintl-prefix "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# libxml2
cd "${mono_src}/libxml2-2.7.6"
./configure "--with-iconv=${mono_dir}" \
    "--with-zlib=${mono_dir}" "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# libxslt
cd "${mono_src}/libxslt-1.1.26"
./configure "--prefix=${mono_dir}" "--with-iconv=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# glib
cd "${mono_src}/glib-2.22.2"
./configure --with-libiconv=gnu "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# libgdiplus
cd "${mono_src}/libgdiplus-2.4.2"
./configure --with-libexif --with-libjpeg \
    --with-libtiff --with-libgif "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# ===================================================================
# Build Mono core and extensions
# -------------------------------------------------------------------
# Mono
cd "${mono_src}/mono-"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# XSP, including Mono's FastCGI support
cd "${mono_src}/xsp-2.4.2"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# Basic (alternative Mono language, similar to .NET's Visual Basic)
cd "${mono_src}/mono-basic-2.4.2"
./configure "--prefix=${mono_dir}"
nice -n 19 make
nice -n 19 make install
# ===================================================================
# Cleanup and wrap-up
# -------------------------------------------------------------------
# Remove intermediate source code, since it is no longer needed
cd ~
rm -rf "${mono_src}"
# Create a directory for the web-app launcher script
mkdir -p "${HOME}/${DOMAIN}/cgi-bin"
chmod 751 "${HOME}/${DOMAIN}/cgi-bin"
echo "             *************** INSTALL COMPLETE! ***************"
# ===================================================================

When you build your Mono environment, you may run into an error message similar to the following:

Yikes! One of your processes (xxx, pid 12345) was just killed because your
processes are, as a whole, consuming too much memory. If you believe you've
received this message in error, please contact Support.

If this happens, contact DreamHost Support and kindly request that they temporarily increase your memory allowance; DreamHost Support was very helpful with this and promptly relaxed the constraint (within 5 minutes!). Interestingly though, having analyzed some of the itemized resources logs afterwards for the build period, the maximum amounts of memory used by Mono processes were only about 40% of the maxima used by Java processes.

Once you have successfully completed the installation of Mono, you can add Mono’s executable path to your environment variables by inserting the following line into your ~/.bash_profile file. This way, you would have easy access to the Mono Framework whenever you log into the interactive shell:


You should now be able to type something like “mono --version” at the command prompt and get back a message starting with “Mono JIT compiler version”.  The next steps are to create and configure your Mono website, and to get the basics up and running should take much less effort than the preceding setup.

Configure Apache and the .NET Website

The entire directory structure of the example Mono website is as follows (in an edited and abbreviated format similar to what you’d get from a Unix “ls -alR” command):

drwxr-xr-x username groupname .
drwxr-x--x username groupname cgi-bin
drwxr-x--x username groupname mono-web
-rw-r--r-- username groupname .htaccess
-rw-r--r-- username groupname index.html

-rwxr-x--x username groupname mono-web-launcher.fcgi

-rw-r--r-- username groupname .htaccess
-rw-r----- username groupname Default.aspx
-rw-r----- username groupname Default.aspx.cs
-rw-r----- username groupname Test.aspx
-rw-r----- username groupname WebService.asmx
-rw-r----- username groupname web.config

The contents of the essential configuration files are displayed below, but all the files of the example website can also be downloaded from this archive. If you are going to unzip the archive and use the contained files directly on a Unix box, ensure that the file access permissions are setup the same way as shown above (using the chmod command).

Let us start with the .htaccess file in the website domain directory, which simply contains some Apache configuration settings that will allow the static index.html page (or a dynamic index.php page) to be returned when visiting the “” home URL (there’s nothing fancy about this file):

# Don't show directory listings for URLs which map to a directory
Options -Indexes
# Follow symbolic links in directories
Options +FollowSymLinks
# Specify the default page names
DirectoryIndex index.php index.html

The mono-web-launcher.fcgi file (located in the cgi-bin directory) is where most of the configuration action happens; it is based on Mono’s default “~/mono-” FastCGI Backend script and has been customized for our specific Mono web-application. The added .fcgi filename extension clearly marks the file as a FastCGI script for Apache (more about this later).  In combination with the monoWrapper handler, which is defined later in the “mono-web/.htaccess” file, this script will launch Mono’s FastCGI Backend for the ASP.NET web-application when one of its pages is accessed. Be sure to change the values of HOME and DOMAIN at the top of the launcher script to match the names of your user’s home and website’s domain directories, respectively:

# Specify the home directory, Mono directory, and the 
# domain name (that is, your DreamHost subdirectory name)
# Define a temporary directory for dynamic compilation 
# using a private directory for added security; also, 
# prevent sporadic run-time errors such as the following:
#   Single file build failed / cannot find metadata file.
# Remember to create this directory and sometimes clear 
# it under controlled conditions as part of maintenance
export TEMP=${HOME}/mono-temp_do-not-delete
# Include the Mono binaries in the path variable, since 
# the shell PATH is not used within the FastCGI context
export PATH=${MONO_DIR}/bin:$PATH
# Use case-insensitive file-system compatibility mode; 
# don't use this option unless you have to (it is slower)
export MONO_IOMAP=all
# Start the dynamic persistent FastCGI server of Mono 
# and register the web-application with its paths; the 
# FastCGI manager will stop this process when needed 
# according to policy (e.g., after some idle time)
exec mono $MONO_OPTIONS \
  ${MONO_DIR}/lib/mono/2.0/fastcgi-mono-server2.exe \
  /logfile=${HOME}/fastcgi-mono-web.log \
  /loglevels=Warning,Error \
  /applications=/mono-web/:${HOME}/${DOMAIN}/mono-web/ \

When you are initially trying to get the website installed and configured, you might also want to set the loglevels value to All, or Standard, and then monitor the configured Mono Backend log file to see what is happening (for example, located at “~/fastcgi-mono-web.log”). Of course, you can also look at the Apache log files for additional information. Be sure to familiarize you with the command-line options and environment variables that are available on the FastCGI Backend, especially the format of the applications value; for example, read the help info returned by:

mono ~/mono- /help

Next up, we have the Apache configuration file that is located in the Mono web-application’s subdirectory (the “mono-web/.htaccess” file):

# Specify default page names, including typical ASP.NET names
DirectoryIndex Default.aspx default.aspx Index.aspx index.aspx \
    Default.htm default.htm Default.html default.html \
    Index.htm index.htm Index.html index.html
# Define the FastCGI Mono launcher as an Apache handler and let
# it manage this web-application (its files and subdirectories)
SetHandler monoWrapper
Action monoWrapper /cgi-bin/mono-web-launcher.fcgi virtual

In addition to the default page names specified in the earlier .htaccess file, this file lists some typical ASP.NET filenames for default pages, such that the ASP.NET page called Default.aspx would be used when visiting the “” URL. More importantly, it gives the Mono Backend full responsibility for all file content in this directory (and its subdirectories) by registering our customized launcher script as the Apache FastCGI handler for this web-app root folder. Using SetHandler (instead of AddHandler) has the added benefit that we don’t need to explicitly tell Apache which file extensions may be served (such as .aspx and .asmx) and which ones not (such as .cs and .dll), since the Mono Backend will also take care of that.

Lastly, as far as the website configuration is concerned, we provide a bare-basics web.config configuration file:

    <!-- TODO: Enable custom errors once things work -->
    <customErrors mode="Off"/>

Setting the customErrors mode-attribute to Off would help you to get your website going, since it would display detailed error messages when things go wrong. You don’t need any extra settings in the web.config configuration file just to run the example web service and pages, but expand on this as you develop your own ASP.NET website. Also, for security reasons, remember to define your own custom error-pages or at least disable the default remote-debugging error-pages before going live on the Internet.

Add Content to the Website

You can now add ASP.NET web pages, similar to Test.aspx and Default.aspx (with its associated Default.aspx.cs code file), web services and more to your Mono website. The example web service, called WebService.asmx, has been defined like this:

<%@ WebService Language="C#" Class="WebService" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
[WebService(Namespace = "")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService  : System.Web.Services.WebService 
    public string HelloWorld()
        return "Hello World";
    public string GetUniqueIdentifier()
        return Guid.NewGuid().ToString("N");

Navigating to its Service Description (WSDL) page at “” would produce something similar to the following:

Example Mono Web Service Description Page

Final Thoughts

The shared hosting server that I tested on used the “mod_fastcgi” Apache module as its FastCGI manager. However, even if the newer “mod_fcgid” Apache module would be used (which I think is the case for DreamHost Private Servers and possibly some DreamHost Shared Servers), the example configuration should still work. The only requirement is that the Apache server knows that is must execute *.fcgi files using its FastCGI module, and the Apache server seems to know this already (no “AddHandler fastcgi-script .fcgi” or “Options +ExecCGI” statements were needed in any .htaccess file). Perhaps just make sure that FastCGI (the recommended PHP mode) is turned on for your website in the DreamHost panel (under Manage Domains). Also, for future reference, the test server had the following software pre-installed: pkg-config 0.21 (not the latest, but it worked) and gcc 4.1.2 20061115 for Linux 2.6.29, Debian 4.1.1-21.

I suspect that one may still need to tweak the example .htaccess files to improve security. For one thing, it is perhaps not a good idea to be able to execute the FastCGI launcher by itself directly through an exposed URL (such as “”). At the very least one might want to include some random alpha-numeric characters in the launcher filename in an attempt to make it a bit more secure (if that would make much of a difference).

It is great to be able to run Mono on a shared server after having gone through all the trouble of setting it up yourself, but it would be much nicer if DreamHost could also provide a default pre-compiled and installed version of Mono FastCGI, just like they do for PHP FastCGI. Anyway, having Mono makes the development of web applications and web services much nicer than with PHP, in my opinion, and you get to use .NET-based technologies, such as C#, on Unix-based machines. Now that’s what I call... Cool!




Excellent post.
I too had problems building mono getting my processes killed all the time, but I had less luck getting Dreamhost temporarily extending my memory allowance. The only suggestion they had was for me to get their VPS service.

My solution was to install a VMware image (64-bit one to match the Dreamhost target platform) where I could build mono. No problems so far, except that the mono installer script for some reason hard-coded my VMware username in quite some of the scripts in the mono-2xx/bin directory.
Everything else worked out of the box.

By the way, I added set -e in the beginning of the build script just to make sure it stops if any errors occurred.

Neat error-checking

It is good to know that there is also an alternative workaround for the memory-constraint issue. And the “set -e” tip would really come in handy next time – UNIX does have many hidden “Easter eggs”.

DH helpdesk issue

Hi, I asked DH helpdesk, but also refused. Is it possible to share your complied binary?

Mono On Dreamhost

Thanks for this great tutorial...can't wait to try it. FYI, I've linked to it from the dreamhost support wiki topic for Mono, so that others may benefit from your work! I know I've spent countless hours trying to get it to work and eventually just gave up...


I just got the latest stable sources, used ./configure --prefix=/home/arienh4/mono and make, make installed it. Thanks for the fastcgi part of the guide though, that really did help.

It gets easier

The simple build procedure that you describe never worked previously. So, it is great news if that indeed now works at last! I suppose that DreamHost may have finally updated some of the core dependencies to newer versions that are compatible with Mono. However, if you only built the mono and xsp packages, and skipped ones such as libgdiplus and libxml2/libxslt, you probably still won’t have all the features. At least it sounds like the core functionality can now be attained more easily than before.

VPS or Shared Hosting

Are you on a VPS or is it shared hosting? If shared, this is great news...

Shared Hosting (not Virtual Private Servers)

This is shared. However, while Mono itself worked (I managed to run .NET assemblies) I never quite got ASP.NET to run.

ASP.NET and even MVC is possible

Following the complete procedure from the main post, one does get standard ASP.NET functionality. And ever since Mono 2.6, the ASP.NET MVC functionality also works through FastCGI. So it seems that, although the simpler build procedure might build okay, one might still need the full procedure for all of the functionality.


Great instruction! Thanks, works like a charm!

Root directory

Hello, is it possible to change the root virtual directory to the $HOME/$DOMAIN?


I was wondering about that myself. I think it should be possible with all the magic of the .htaccess file, but I haven't yet figured out how — let me know if you get it working.

Latest working packages

The original script won't work because zlib is now at 1.2.5 and libpng is 1.2.44. Here's a script (with some error checks) that seems to work for the latest stable version of Mono 2.6.7 with current updates (minor, not major version) for all packages. I was able to get this to work, but had to have DreamHost tech support compile it since they couldn't turn off the "Yikes!" memory killer.

Re: Latest working packages

Thanks for the update, Dave. I slightly edited the Mono 2.6.7 build script included in your comment to use the “set -e” option recommended by Rene, instead of the many explicit error checks. I am glad you got Mono compiled and find it encouraging that DreamHost tech support was willing to build the script for you.

Premature end of script headers

Any idea on what might cause "Premature end of script headers: mono-web-launcher.fcgi" error message in error.log? Thanks.

Re: Premature end of script headers

Initially I also got those errors while setting up Mono, but the documented procedure resolved them. Double-check your file permissions and the directory structure. You could also try to set loglevels to All and check whether fastcgi-mono-web.log gets created; if not, the problem is likely with the early boot-strapping of FastCGI involving Apache, otherwise the Mono log may contain additional info.

Re: Premature end of script headers

The issue ended up being execute permissions on the mono-web-launcher.fcgi script.

Now, I'm onto getting BlogEngine.NET to work.

Same problem

I am getting the same premature end of script error regardless of what I set my permissions on the fast cgi. I turned on all logging but there isn't anything telling in either the fastcgi or apache logs that I can find. Any ideas?

Re: Same problem

If you are sure all your file and directory access-rights are configured correctly, you should also carefully check the contents of your mono-web-launcher.fcgi script. A simple typo in that file could also easily cause the mentioned error. It can be a bit frustrating to get beyond this point, since the log files are not really helpful until after this step in the procedure.

You could try executing ~/ manually from the command shell. If your script is setup correctly, you should probably get a message similar to “Error: Pipe socket is not bound”. However, if your script has some other problem, you may get a different error message hinting at the real problem (for example, with a line number).

Realtime debug log file

If you want to debug the script in realtime, try redirecting the output at the end of the exec call to a temp log file. I had environment issues to debug and could only find the error by doing this and then hitting the web site to get the error:

&> ${HOME}/temp/${DOMAIN}/fcgi.log

Alternate Sub Issue

I'm also getting the "Premature end of script headers: mono-web-launcher.fcgi", and when I run the fcgi directly from shell I get an interesting message. Anyone seen this before?

Inconsistency detected by dl-version.c: 230: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!

Any help is greatly appreciated!

Re: Alternate Sub Issue

I haven't seen that message before, sorry. I'm also no longer using this Mono built, so I'm not sure if it can still be done on Dreamhost. If you do get it working, please let me know.

Mostly works, problems with Web.config

Following everything in your 2.6.7 script (with numerous restarts of the main mono make), I managed to get something going - but it consistently hits a "Server Error in '/mono-web' Application". The error message talks about setting up the Web.config - but I have, and it doesn't seem to honor it.

Have you seen anything like this before?

Re: Mostly works, problems with Web.config

This sounds like a similar problem I had that was solved by using case-insensitive file-system compatibility mode ("export MONO_IOMAP=all" in the mono-web-launcher.fcgi file). Perhaps try renaming "Web.config" to "web.config", or something like that, and double-check your launcher script.

Dreamhost Shared + Mono

Is Dreamhost still an option? I have compiled and installed it but not able to run.
Cannot open assembly '/home/myusername/mono-2.6.7/bin/fastcgi-mono-server2': File does not contain a valid CIL image.


Re: Dreamhost Shared + Mono

Yes, it still works for me, but I suspect you're trying to do something weird. It looks as if you're attempting to execute the fastcgi-mono-server2 file in the CLI runtime, as if it were a CIL assembly, which it is not. Instead, it is a shell script.