Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run a deployed Haskell web application

Tags:

haskell

I've read every Haskell deploy thread I could find here and several on the wider web, but I still don't get one thing. If I've compiled an app for my server, and can ssh in and run it, how do I go about running the thing? Assume I'm using an HTTP interface (not FastCGI).

For example, with node.js, we use cluster to get the app started on several processor cores, then create an init.d script for centOS to get the thing to run, daemonize, have a pid file, etc.

How do I do this for a Haskell app?

like image 862
Sean Clark Hess Avatar asked Jan 11 '12 22:01

Sean Clark Hess


2 Answers

Since you don't mention which framework you're using, I'm just going to answer this question in general.

With Haskell, you don't have to start multiple instances (in a cluster) of the web application, because if the application supports concurrency, it usually uses multiple threads internally. What you instead want to do, is to make sure that the application is compiled with the -threaded and -rtsopts flags. Then, when you run the application, you pass the flags +RTS -N<number of simultaneous threads>. If you use a Snap web application running on port 1234 on a 8-core computer with Intel® Hyper-Threading, for example, you would start it with my-server -p 1234 +RTS -N16 to get it to parallellize to up to 16 OS threads.

To daemonize the web application, you use the same procedure as with node.js. You create an init script that starts the executable in various UNIX run modes, and Bob's your uncle.

As with any other web application, you might want to use a front end server that redirects traffic to your web application (which is why you might not want to use port 80 for your web applications). For details on how to do this, visit the Web/Deploy page on HaskellWiki.

like image 176
dflemstr Avatar answered Nov 08 '22 06:11

dflemstr


The big three Haskell web frameworks (Snap, Yesod, and Happstack) all have the ability to ship with a web server built in. The traditional approach to production deployment is probably to use your OS's mechanism for running a process as a daemon in an init script or similar. One lighter solution I have used is a script something like the following:

while true; do
  echo Restarting at `date` | tee -a stdout.log stderr.log > /dev/null
  ./my_app 80 >> stdout.log 2>> stderr.log
done

I run this script in the background. It's dead simple, so the shell script process itself never crashes. If the server crashes for any reason, this script automatically ensures that it immediately gets restarted. If you want to roll out a new version, just copy it over the my_app executable and send a SIGHUP to the my_app process.

Hardened sysadmins out there might shudder at something like this. I won't say this is the best way to do it, but I've been running a production app for several years with this approach and it has worked great. As others have mentioned, you can also set this up with a front-end proxy server so your app doesn't have to run as root.

like image 20
mightybyte Avatar answered Nov 08 '22 05:11

mightybyte