Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to run Snap haskell webapp in production?

I've installed Snap/Haskell on my production Ubuntu server (on EC2), and checked-out my project - but how do I run it?

I mean, locally, I run it from command line:

project-name -p 8000

Does snap come with it's own web-server (it looks like it), and if so how do I go about configuring it to run as a daemon of some sort?

Any tips?

Edit 2:

On the wiki they say:

snap-server is an HTTP server library that supports the interface defined in snap-core.

While here, the haskell wiki about "Deployment/Backend options for your haskell web code" says that Snap:

includes its own server. see Web/Frameworks

But HOW? How would I run it's own server? Why must I know about deployment of the damn thing if I am just interested in programming...

Edit: related question: Deploy Haskell code that uses the Snap Framework

like image 914
Andriy Drozdyuk Avatar asked Jun 26 '12 18:06

Andriy Drozdyuk


3 Answers

Ok, so after some digging and asking, here is what I came up with.

Big idea

Compile your Snap application into a binary and then run it as a service with the help of upstart.

Step by Step

  1. Compile your webapp. For the sake of this example, we'll assume the webapp is at /home/john/webapps/mysite:

    $ cd /home/john/webapps/mysite
    $ cabal install
    ...
    Preprocessing executable 'mysite` for 'mysite-0.1'...
    Installing executable(s) in /home/john/.cabal/bin
    

    As we can see the, the binary is placed in /home/john/.cabal/bin. You may move it to any place you like, but we'll leave it there.

  2. Create a log in your application folder, otherwise snap will complain:

    $ mkdir /home/john/webapps/mysite/log
    
  3. Now we will create a service that will run our webapp. To do so we will use Ubuntu's service facility called upstart.

    a) We name our service simply by creating a conf file with the desired name in the /etc/init/ directory. Let's call it mysite:

    $ sudo vi /etc/init/mysite.conf
    

    b) Now let's add the description of what our service is:

    start on startup
    chdir /home/john/webapps/mysite
    exec /home/john/.cabal/bin/mysite -p 80
    

    First, we say that the service should run on startup (or on bootup) of the system.

    Second, since snap needs it's snaplets and other static resources (like the log directory we created earlier) - we tell the service to run inside our project's directory.

    Lastly, we specify the binary that actually will run as a service: /home/john/.cabal/bin/mysite. We pass the -p 80 parameter to the snap webserver to make it run on port 80. (Note: you have to disable all apache and nginx servers, so that they don't take up that port any more)

  4. Done. You can check if it is running and start it manually if you need to:

    initctl list | grep mysite
    initctl start mysite
    
like image 101
Andriy Drozdyuk Avatar answered Nov 03 '22 16:11

Andriy Drozdyuk


Yes, snap-server is its own server, which means compilation of your Haskell/Snap app leaves you with an executable that you can literally run from the command line to host your site. That's it, there's no external server like apache or nginx to tie into. You can setup reverse proxies if needed, but that's up to you.

Here's what I do with most of my serious deployments:

  • Compile on the same linux box or a compatible machine - I almost always use cabal-dev for sandboxing
  • Command line arguments: cabal-dev/bin/myapp -p 8010 -e prod +RTS -A4M -qg1
  • I run on an unprivileged, non-default port (8010 above) so that I can use a load balancer to forward requests to it. This also allows me to run multiple snap apps per linux box if needed.
  • Then I use a simple process monitoring application to make sure it stays up. You can use:
    • god: http://godrb.com/
    • angel: https://github.com/jamwt/Angel
    • supervisor: http://supervisord.org/
  • One the monitor is set up, you can just send a HUP signal to your application whenever you want to restart and the monitoring app will just bring it back up.
  • I'm a big fan of Fabric for deployment automation. You can handle remote synching, restart, etc. all using fabric.

Hope this helps.

like image 42
ozataman Avatar answered Nov 03 '22 16:11

ozataman


Since it's Ubuntu, you're almost always better off using upstart to manage it.

man 5 init

Among other things, it lets you set dependency hierarchies for your services. "snapapp depends on mongodb so don't start snapapp until mongodb is running" - that sort of thing.

Yes, snap is a web server, but we almost always put nginx in front of them with the snap apps only listening on localhost, and a proxy_path pointing to the server or a group of them.

Funny enough, we've almost completely switched to Common Lisp for new development at $work and the setup is exactly the same.

like image 5
clintm Avatar answered Nov 03 '22 16:11

clintm