Production ready ASP.NET 5 MVC (vNext) on Linux behind nginx.

What is vNext (ASP.NET 5) (.Net Core Version 1) ?

vNext is Microsoft's new, completely rewritten and open source .NET framework. They worked with MONO and Xamarin to create a completely cross platform library that can run .NET Core Apps.

You can get Visual Studio Ultimate 2015 now in as a release candidate and try out vNext projects but if you are are seasoned dot netter there is quite a paradigm shift.

There is no official name yet but it seems like ASP.NET 5 / .NET Core Version 1 is the favourite.

What the new lingo?

I am focusing on trying to deploy MVC sites to Linux (and hopefully FreeBSD) and there are a few new tools and terms used. In Windows the same tools are used transparently in Visual Studio and there is no need to know any of the command on Windows or Mac (MonoIDE)

'K' is the codename for .NET Core Version 1, and you might see people referring to it as K10 (K 1.0) which is the new open source .NET libraries. (K, KRE, KVM, KPM, may be renamed or just referred to differently once the beta is complete.) 

K is also used whenever you want to run your apps in the command line and essential is the entry point into your application. I use apostrophes to emphasize the K more.

K'PM

KPM ('K' Package Manager) is everything to do with packages. This command is used to restore dependencies defined in your packages.json file. It is also used to create packages.

K'RE

In order to get K you need to install a KRE ('K' Runtime Engine) The KRE is what is used to bootstrap, and run your vNext projects, using the new projects.json project solution file.

To install KRE you need to have KVM .

K'VM 

KVM ('K' Version Manager) in Linux this is just a simple bash app that lets you specify the version of KRE you want to download and install. It like a runtime package manager and it also allows you have many different version installed side by side.

So lets start already!

You can use Azure with Ubuntu if you want, your own Ubuntu server, Virtual machine or you can try Digital Ocean SSD Droplets for 2 months free. Using that link you will get $10 credit with which you can create the smallest machine for two months. It is very generous offer and I like the site. Its fast to deploy Ubuntu, can be hosted in Europe or USA and a few other nice features.

Pre Install

These heading will be the order you should follow to successfully install KRE. Unfortunately the order does matter as I had some issues doing things in the incorrect order. Hopefully that will be solved once KRE matures. 
sudo apt-get update
sudo apt-get install make gyp npm
sudo apt-get install git autoconf libtool automake build-essential mono-devel gettext zip unzip
sudo apt-get install bash zsh curl

Mono

The very first thing we will need to install is the latest version of Mono. Or at least version 10.6.
You can download the source and compile yourself if you know how but you can add a reposiroty that already has the latest binaries. (These are single liners)
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
then
echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
Now we can run apt-get update to get the latest repo files list, install mono-complete and verify the version is one of the newest ones, preferably 1.12+.

sudo apt-get install mono-complete
mono --version
 To finish it off we need to manually add SSL certificates that are not shipped with Ubuntu by default. If you skip this then you wont be able to restore packages or use bower.
sudo certmgr -ssl -m https://go.microsoft.com
sudo certmgr -ssl -m https://nugetgallery.blob.core.windows.net
sudo certmgr -ssl -m https://nuget.org
sudo certmgr -ssl -m https://www.myget.org/F/aspnetvnext/

mozroots --import –sync

Libuv

This only needs to be compiled in Linux. OSX has the correct version of this library. It is required by kestrel. Libuv enforces asynchronous and event driver style of programming. I will talk about kestrel a bit later since its installed with KVM and KRE in the next steps.
wget http://dist.libuv.org/dist/v1.0.0-rc1/libuv-v1.0.0-rc1.tar.gz
tar -xvf libuv-v1.0.0-rc1.tar.gz
cd libuv-v1.0.0-rc1/
./gyp_uv.py -f make -Duv_library=shared_library
make -C out
sudo cp out/Debug/lib.target/libuv.so /usr/lib/libuv.so.1.0.0-rc1
sudo ln -s libuv.so.1.0.0-rc1 /usr/lib/libuv.so.1

KVM

KVM is installed with a one liner. It downloads the required files and puts them in the correct palces based on your OS distro. In Ubuntu you will notice a new directory ~/.kre  where every thing related to .NET Core and K will be stored and managed from. (Please note that I am using the dev branch which is bleeding edge since the Master has some issues still)
curl -sSL https://raw.githubusercontent.com/aspnet/Home/dev/kvminstall.sh | sh && source ~/.kre/kvm/kvm.sh

KRE

To install the latest KRE we just run the following command.At the time of writing this article it is beta2. You will messages about the version it is getting and installing. (All these files are stored in ~./kre)
kvm upgrade
Congratulations, you now have access to K, KPM and all the libraries included in the .NET Core.

The following two commands that are going to burnt into your braincells for life ... So Remember. 

K 'argument' - Is the entry point of execution and takes an argument, which is defined in project.json. Usually web for Windows/OSX and Kestrel for Linux.
KPM - Will restore packages from "myget" which are defined in the packages.json

We will be running these commands in the directories that contain these json files. 

Kestrel

Kestrel is the new, cross platform, independent development web server based on libuv. Kestrel is installed with KRE in the next step. Kestrel is marked as development because it doesnt support SSL and modules, like IIS. The .NET team said its a long term (ie 5 years) time kestrel might be production ready.

In the mean time I will be looking for ways to maybe use nginx as the production front and somehow integrate kestrel into a fastcgi or something. nginx is blazingly quick and if kestrel stays lightweight, we might have a winning pair here.

Show me the MVC!

OK all that just to get the system ready. Its not too bad I suppose but the proof is in the pudding, can we get our beloved MVC site running on Linux???

To get us off the ground quick I will use the vNext GIT example repository. Make sure you are in your home directory, or create a new directory somewhere for all your projects. 
We will first clone the git repo and then go into the MVC sample directory. KPM will restore the packages (and while its doing that create a local cache) This might take some time since there allot of packages required. It gets faster the more you use it because of the cache. And the final command will be 'k' executing the kestrel command defined in project.json
https://github.com/aspnet/Home.git
cd Home/samples/HelloMvc
kpm restore
k kestrel
You should now be able to navigate to the IP address with the samples defined port of :5004
You can change the port in the projects.json If you getting errors, at this point similar looking to YSOD but in Black and badly aligned, try and search the web for them. You will most likely find answers in the GIT bug tracker for vNext

Going Production

Kestrel is NOT production ready. That means that you cant bind SSL certificates, do IP filtering, virtual hosts, url rewrites, etc. - and all the nice things nginx or IIS can do. My idea is to use nginx as the front end and reverse proxy to kestrel. 

Thanks to this we get the a super efficient web server that IS production ready while using ASP.NET 5 MVC  :)

nginx

Nginx is in the main repo of all the Linux and BSD distributions and only the versions might vary slightly. There is no critical version number for this to work as long as its the version that supports reverse proxy.
sudo apt-get install nginx
Now you can navigate to your IP address or domain name and you should see "Welcome to nginx!" message. That is great but we want MVC to show up there. So we need to tweak some configuration.

I start a screen (apt-get install screen) which allows me to do things in another virtual screen. If your session gets disconnected the screen will carry on working. This is very handy tool and if you are not familiar with it, you should, and it comes highly recommended. 

In the screen I will start the SampleMVC that we cloned from the ASP.NET GIT. Navigate into the directory and type "k kestrel" and the sample site will be running at http://127.0.0.1:5004 or your public IP if you are not behind NAT. To detach from the screen press CTRL + A then D.

We change a few lines in the default nginx configuration found at /etc/nginx/sites-available/default - Essentially for now we only want this in the configuration.

server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;
  server_name localhost;
  location /
  {
    proxy_pass http://127.0.0.1:5004;
  }
}
Save the config file and then restart nginx.

service nginx restart
We just navigated to your public IP:80 default website with nginx on it. Go back to the browser and do a full refresh. CTRL + F5 in Chrome/FF/IE. 

et viola! ASP.MVC running on nginx

Security

If you are behind a NAT at home, then forwarding port 80 to your machine is pretty good enough security to let nginx do its thing. Forwarding SSH is your own choice.

If you went with Azure or Digital Ocean then you really need to look into a firewall solution, as all the ports that are bound to your IP, are accessible by the public. That means, if kestrel has a security flaw in it ans somebody works out they can access kestral virtual hosts between ports 5000 and 5050 they can easily bypass nginx.

I need some suggestions here since I am not a seasoned Linux user, just an emerging one :P

Conclusion

This might seem like a bumpy start but compared to this time last year, its is MUCH easier now. I tried to deploy a simple MVC site like this on Mono last year and pretty much failed at any angle I tried. Console applications ran fine in the most part but that was about it. That is why I am extremly happy that Microsoft are working together with Mono to make the entire process allot easier.

There are ways to deploy sites to docker directly if you want to explore that option but I hope more and more hosting sites will start to offer Mono or vNext or whatever they going to call it on their services at the same prices like Word Press :]

I am not sure when the full release date will be but I suspect that most of these quirks will be worked out on the official release of version 1.


References
* http://weblogs.asp.net/imranbaloch/k-kvm-kpm-klr-kre-in-asp-net-vnext
* http://www.mono-project.com/docs/getting-started/install/linux/
* http://www.ganshani.com/blog/2014/12/shell-script-to-setup-net-on-linux/
* http://wiki.nginx.org/GettingStarted

Comments