Configure apache2 + mod_mono to run ASP.Net MVC5 application on Ubuntu 14.04

Install binaries

Install mono

Please click here to install mono.

Install mod_mono

sudo apt-get install apache2
sudo apt-get install mono-complete
sudo apt-get install libapache2-mod-mono mono-apache-server4

After above installation, visit http://your-host-name, we should see below default page.

Verify mod_mono.config

cat /etc/apache2/mods-available/mod_mono.conf
AddType application/x-asp-net .aspx .ashx .asmx .ascx .asax .config .ascx
DirectoryIndex index.aspx
# Include the web application definitions generated by mono-server{2,4}-update.
# If you want to use ASP.NET 2.0 (via mono-apache-server2), use:
# Include /etc/mono-server2/mono-server2-hosts.conf
# If you want to use ASP.NET 4.0 (via mono-apache-server4), use:
# Include /etc/mono-server4/mono-server4-hosts.conf
Include /etc/mono-server4/mono-server4-hosts.conf

Prepare you webapp directory

Create folder for your webapp

mkdir /home/azureuser/webapp

Grant permission allow Apache to access your webapp folder

sudo chown -R www-data:www-data /home/azureuser/webapp

Config Apache for your webapp

Generate Apache config

Go to, in this article i will choose “Virtual Host” in “Configuration Type”, but it will be similar if you choose “Application”

Fill in require fields and click preview to generate configuration file, and modify “/usr/bin/mod-mono-server2” to “/usr/bin/mod-mono-server4”.

if you webapp require certain environment variable, you can define with “MonoSetEnv” command within the config file.

Virtual Host:

<VirtualHost *:80>
ServerAdmin webmaster@localhost
MonoAutoApplication disabled
AddHandler mono .aspx ascx .asax .ashx .config .cs .asmx .axd
MonoApplications “/:/home/azureuser/webapp”
MonoServerPath /usr/bin/mod-mono-server4
DocumentRoot /home/azureuser/webapp
<Directory />
Options FollowSymLinks
AllowOverride None
<Directory “/home/azureuser/webapp”>
Options Indexes FollowSymLinks MultiViews
AllowOverride AuthConfig FileInfo
Order allow,deny
Allow from all
SetHandler mono
DirectoryIndex index.aspx index.html Default.cshtml
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory “/usr/lib/cgi-bin”>
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
ErrorLog /var/log/apache2/kudu-error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog /var/log/apache2/kudu-access.log combined


Alias /scm “/home/azureuser/webapp”
# MonoServerPath can be changed to specify which version of ASP.NET is hosted
# mod-mono-server1 = ASP.NET 1.1 / mod-mono-server2 = ASP.NET 2.0
# For SUSE Linux Enterprise Mono Extension, uncomment the line below:
# MonoServerPath scm “/opt/novell/mono/bin/mod-mono-server2”
# For Mono on openSUSE, uncomment the line below instead:
MonoServerPath scm “/usr/bin/mod-mono-server4”
# To obtain line numbers in stack traces you need to do two things: 
# 1) Enable Debug code generation in your page by using the Debug=”true”
# page directive, or by setting <compilation debug=”true” /> in the
# application’s Web.config
# 2) Uncomment the MonoDebug true directive below to enable mod_mono debugging
MonoDebug scm true

# The MONO_IOMAP environment variable can be configured to provide platform abstraction
# for file access in Linux. Valid values for MONO_IOMAP are:
# case
# drive
# all
# Uncomment the line below to alter file access behavior for the configured application
MonoSetEnv scm MONO_IOMAP=all
# Additional environtment variables can be set for this server instance using
# the MonoSetEnv directive. MonoSetEnv takes a string of ‘name=value’ pairs
# separated by semicolons. For instance, to enable platform abstraction *and*
# use Mono’s old regular expression interpreter (which is slower, but has a
# shorter setup time), uncomment the line below instead:
# MonoSetEnv scm MONO_IOMAP=all;MONO_OLD_RX=1
MonoApplications scm “/scm:/home/azureuser/webapp”
<Location “/scm”>
Allow from all
Order allow,deny
MonoSetServerAlias scm
SetHandler mono
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI “\.(?:gif|jpe?g|png)$” no-gzip dont-vary
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript

Register config

Navigate to /etc/apache2/sites-available, copy above content and save into webapp.conf (file name doesn`t matter, but must have suffix “conf”). And register config with a2ensite, we should see below output.

sudo a2ensite webapp.conf
Enabling site webapp.
To activate the new configuration, you need to run:
service apache2 reload

A symlink will be created under /etc/apache2/sites-enabled

├── sites-available
│ ├── 000-default.conf
│ ├── default-ssl.conf
│ └── webapp.conf
└── sites-enabled
├── 000-default.conf -> ../sites-available/000-default.conf
└── webapp.conf -> ../sites-available/webapp.conf

Enable mod_mono module

Enable mod_mono module, navigate to /etc/apache2/mods-available

sudo a2enmod mod_mono

should see below output

Enabling module mod_mono.
To activate the new configuration, you need to run:
service apache2 restart

let restart Apache (which will also reload all the config)

sudo service apache2 restart

Now visit http://your-hostname/scm, (http://your-hostname if you are configuring virtual host). Ooop! 403!!!

We can also see error logs from /var/log/apache2/error.log

[Thu Mar 03 01:16:13.498564 2016] [authz_core:error] [pid 21259:tid 139811025307392] [client] AH01630: client denied by server configuration: /home/azureuser/webapp

Allow request to visit webapp folder

Turn out by default Apache not allow request access any file path other than /var/www/html. Let edit /etc/apache2/apache2.conf

We will see there is an sample code block that commented out in default

#<Directory /srv/>
# Options Indexes FollowSymLinks
# AllowOverride None
# Require all granted

Enable or copy it and update the folder path

<Directory /home/azureuser/webapp>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted

Restart Apache again then you should good to go!

sudo service apache2 restart
Like what you read? Give shrimpy a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.