gdritter repos melvil / master README.md
master

Tree @master (Download .tar.gz)

README.md @masterview rendered · raw · history · blame

# melvil

**EARLY AND EXPERIMENTAL**

Melvil is the HTTP server interface I think I'd want to use.
It's very slow at present, and still quite early, but it's at
least a proof-of-concept of something I think should exist.

## Basic Use

The Melvil server does nothing but pass HTTP requests and
responses between other servers: it is, in effect, a mechanism
for establishing reverse proxies.

The server is invoked with a single optional argument, and it
continues running in the foreground until it is killed with
standard Unix signals. The argument is a directory, and if that
directory exists, it switches to that directory before
continuing. It then reads configuration from that directory and
will continuously forward requests based on that configuration.

The configuration directory contains zero or more
subdirectories, each of which describes a given request filter
and forwarding mechanism. The subdirectory may contain several
specifically named files, whose contents specify a forwarding
system:

~~~
path:    which request paths to match; defaults to "*"
domain:  which request subdomains to match; defaults to "*"
mode:    how to forward the request; defaults to "http"
host:    which host to forward to; defaults to "localhost"
port:    which port to forward to; defaults to "80"
conf:    which path to forward to; defaults to "/dev/null"
resp:    which HTTP response to issue; defaults to 303
~~~

These are interpreted as follows:

- The `path` and `domain` fields tell us which requests to forward:
both of them default to accepting anything, and both of them
allow their values to have the wildcard character `*`.

- The `mode` field tells us _how_ to forward requests. There are
three possible forwarding modes:
    - If the mode is `http`, then Melvil will forward the HTTP
      request to the server listening on the host `host` and the
      port `port`.
    - If the mode is `melvil`, then Melvil will recursively check
      the configuration directory at `conf`.
    - If the mode is `redir`, then Melvil will respond with an
      HTTP response code as indicated in `resp` and redirect to
      the host as indicated in `host`.

In the future, there might be more modes, such as a `fastcgi` mode
which points to a Unix socket or a `static` mode which serves
static files, but this is enough to test the idea.

## Example Setups

A simple-but-interesting configuration, which forwards requests
for `example.com` to `localhost:5001`, redirects `www.example.com` to
`example.com`, forwards requests for `blog.example.com` to
`example.tumblr.com`, and redirects everything else to `localhost:5000`.

~~~
$ # create the example.com config, which forwards to a
$ # local HTTP server listening on port 5001
$ mkdir 00-base
$ echo example.com         >00-base/domain
$ echo 5001                >00-base/port
$
$ # redirect www.example.com to example.com
$ mkdir 00-www
$ echo www.example.com     >00-www/domain
$ echo redir               >00-www/mode
$ echo example.com         >00-www/host
$
$ # create the configuration for the blog subdomain
$ mkdir 00-blog
$ echo blog.example.com    >00-blog/domain
$ echo example.tumblr.com  >00-blog/host
$
$ # and now create the fallthrough case
$ mkdir 99-default
$ echo mode                >99-default
$ echo 5000                >99-default/port
~~~

Notice that we only need to specify a few pieces of information for
each case, because we can often use the defaults for various fields,
so each "configuration" is usually a directory with two or maybe
three files.

Because configuration is specified as a directory, rather than as
a single file, we can use properties of the Unix file system as a
simple ACL-like mechanism. For example, a system administrator
can set up a user-owned configuration directory for each user,
and then use a global configuration directory to forward requests
to that user on a per-subdomain basis:

~~~
$ mkdir -p /etc/melvil
$ for U in $USERS; do
>     # find the user's home directory
>     HOMEDIR=`cat /etc/passwd | grep ${U} | cut -d ':' -f 6`
>
>     # add a configuration directory to each user
>     mkdir -p ${HOMEDIR}/melvil
>     chown ${U} ${HOMEDIR}/melvil
>
>     # add a new forwarding rule for each user
>     mkdir -p /etc/melvil/${U}-local
>
>     # make ${U}.example.com forward to the user's melvil configuration
>     echo "${U}.example.com"   >/melvil/user-${U}/domain
>     echo "melvil"             >/melvil/user-${U}/mode
>     echo "${HOMEDIR}/melvil"  >/melvil/user-${U}/conf
> done
$ melvil /etc/melvil
~~~

Now, if a given user wants to set up a local HTTP server that
produces dynamic content, they can add the appropriate forwarding
configuration to their own directory, but they cannot modify
other users' configurations or the global configuration.

Even if you're running a single server, but want to have multiple
services on it, this can be a convenient way to set up reverse
proxy servers without needing root access.