A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://www.yesodweb.com/blog/2012/05/keter-its-alive below:

Keter: It's Alive!

Keter: It's Alive! May 17, 2012 By Michael Snoyman

View source on Github

Take a good look at this site. Do you see something different? Well, to quote Captain Jack Sparrow, it's something not there to be noticed.

This site is now being deployed via Keter. In other words, it's alive!!! Keter is monitoring the yesodweb.com application process, handling logs and log rotation, configuring Nginx as necessary, and automatically deploying code updates. (If yesodweb.com used a database, Keter would handle that too.)

I've always believed heavily in dogfooding, which is why I'm rolling out Keter now. However, this should still be considered alpha quality code. I'll be keeping a close watch on the server to make sure nothing funny goes on. However, I think the code base is at the point where it makes sense to start some more serious testing.

I'm going to avoid going into the implementation details in this blog post, and instead focus on the end user. If people are interested in a post on the technical aspects of Keter itself, let me know and I'll try to write one.

Prepare the Server

You'll need to install two things on the server: Nginx and PostgreSQL. To do so on a Debian based system, just run:

sudo apt-get install nginx postgresql
Build the Executable

Since Keter is just another package on Hackage, you can build it with a simple cabal install keter. However, doing so on your server would entail installing an entire Haskell toolchain, which is not something we generally encourage. So for now, the recommended approach would be to do the cabal install on a local system with the same architecture and distribution as your web server, and then copy the executable to the server. If you happen to be running Ubuntu 12.04 64-bit, I've made a copy of my executable available online.

Now, a few caveats:

Once you have the executable, place it in /usr/bin on your server. (Of course, you can choose a different location, just keep in mind your changes as you continue.)

Run on Startup

Next you'll want to make sure that keter is run on startup. This will depend again on your distribution. I'm going to assume using Ubuntu and Upstart. The following script works for me:

# /etc/init/keter.conf
start on (net-device-up and local-filesystems and runlevel [2345])
stop on runlevel [016]
respawn

console none

exec /usr/bin/keter /opt/keter

Notice that keter takes a single argument: the folder to use as its base of operations. You can use whatever folder you want, but /opt/keter seems like a good choice to me.

You can start running Keter immediately with sudo start keter.

Bundle Your App

An application is sent to Keter as a keter bundle. This is a single GZIPed tarball with a .keter filename extension, and it contains your executable, resources, and your keter config file. This last file must be placed at config/keter.yaml. Let's set up a simple example. Suppose you have the following inanely boring web application:

-- hello.hs
{-# LANGUAGE OverloadedStrings #-}
import System.Environment (getEnv)
import Network.Wai
import Network.Wai.Handler.Warp
import Network.HTTP.Types
import Control.Monad.IO.Class
import System.IO (hFlush, stdout)

main :: IO ()
main = do
    putStrLn "Application is starting"
    liftIO $ hFlush stdout
    portS <- getEnv "PORT"
    let port = read portS
    run port $ \req -> do
        liftIO $ putStrLn $ "Received a request at: " ++ show (pathInfo req)
        liftIO $ hFlush stdout
        return $ responseLBS status200 [("content-type", "text/plain")] "Hello World!"

There's one Keter-specific aspect to this code to mention: reading the PORT environment variable. This is how an app is told where to listen for requests. Nginx will work as a front proxy and receive all requests from clients, and then pass them off to the appropriate web app based on hostname. This is the only change necessary to get an app to work with Keter. All Yesod scaffolded sites support this functionality already, and it should be trivial to add to Snap and Happstack applications too.

OK, now that we have our app, let's look at our keter.yaml file:

# config/keter.yaml
exec: ../hello
host: www.example.com

This is pretty simple. exec says where to find the executable. This will be relative to the keter.yaml file, which is inside the config folder, so we use ../hello. The host setting says which hostname to listen on. As a side note, the hostname will also be provided to your app via the APPROOT environment variable, which is how Yesod apps generate absolute URLs. This can be safely ignored: Yesod handles this automatically, and the data likely isn't necessary for other frameworks.

There are two other options you can specify in your keter.yaml file:

So a basic config file for a Yesod site called myawesomeapp running on www.myawesomeapp.com and using PostgreSQL would be:

exec: ../dist/build/myawesomeapp/myawesomeapp
args:
    - production
host: www.myawesomeapp.com
postgres: true

Coming back to our simple hello world app, here's a shell script that can bundle up your executable and config file:

#!/bin/bash -ex
ghc --make -threaded hello.hs
strip hello
rm -f hello.keter
tar czfv hello.keter hello config/keter.yaml

This will produce a hello.keter bundle which is all ready to be deployed.

Deploying

This is the (relatively) easy part. Copy your bundle to /opt/keter/incoming. That should be all there is to it. Now the caveats:

Oh, and obviously you'll need to set up your DNS to point to your server. Maybe we'll provide some ability to automate this via Amazon Route 53 in the future.

Logs

Keter keeps fairly detailed logs of its own activities, plus logs all stdout and stderr output from each application. Logs each go into their own folder, and are automatically rotated. To see what's been happening with Keter, look in /opt/keter/log/keter/current.log. For example, the log on yesodweb.com contains:

2012-05-17 11:16:35.08: Unpacking bundle '/opt/keter/incoming/yesodweb.keter' into folder: /opt/keter/temp/yesodweb-0
2012-05-17 11:16:35.29: Created process: config/../dist/build/yesodweb/yesodweb

Each app log gets placed in /opt/keter/log/app-<appname>, with error output going in the err subfolder. Keter does nothing to modify the contents of these files, it simply pipes directly from the app to the file.

What's Next?

The main thing now is testing: making sure it's working correctly under all circumstances. Keter will give fairly detailed diagnositcs about itself, and logs every single exception that gets thrown. This should make it easier to track down any problems. I've run a fair amount of testing myself, and everything seems to be in order, but obviously we won't know that for certain until more reports come in.

There are also some features I'd like to add:

comments powered by

Archives

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4