single-file distributable web server

redbean makes it possible to share web applications that run offline as a single-file αcτµαlly pδrταblε εxεcµταblε zip archive which contains your assets. All you need to do is download the program below, change the filename to .zip, add your content in a zip tool like InfoZIP, and change the extension back to .com.

redbean can serve 1 million+ gzip encoded responses per second on a cheap personal computer. That performance is thanks to zip and gzip using the same compression format, which enables kernelspace copies. Another reason redbean goes fast is that it's a tiny static binary, which makes fork memory paging nearly free.

redbean is also easy to modify to suit your own needs. The program itself is written as a single .c file.




curl >
curl >
chmod +x
bash -c './ -vv'


echo '<b>hello</b>' >index.html
zip index.html
./ -vv
curl -v

source build

git clone && cd cosmopolitan
make -j8 MODE=dbg o/dbg/tool/net/
o/dbg/tool/net/ -vv


Assets can be listed by running the following command:

unzip -vl        # lists files

Assets can be added to the zip archive as follows:

zip index.html   # adds file

By default, anything you add to the archive gets compressed. Sometimes you don't want that to happen. A good example is video files. The web browser will want to send HTTP range requests to seek in the video, in which case redbean requires that the asset be uncompressed.

zip -0 video.mp4  # adds file without compression

Each connection uses a point in time snapshot of your ZIP file. If your ZIP is deleted then serving continues. If it's replaced then issuing SIGUSR1 (or SIGHUP if daemon) will reindex the zip for subsequent connections without interrupting active ones. If SIGINT or SIGTERM is issued then a graceful shutdown is started but if it's issued a second time, active connections are reset.

You can run redbean in the background as a daemon as follows: -vv -d -L redbean.log -P
kill -HUP $(cat
kill -TERM $(cat


-h help
-v verbosity
-d daemonize
-u uniprocess
-m log messages
-c INT cache seconds
-r /X=/Y redirect X to Y
-l ADDR listen ip [default]
-p PORT listen port [default 8080]
-L PATH log file location
-P PATH pid file location
-U INT daemon set user id
-G INT daemon set group id
-B STR changes server header


$ wrk -H 'Accept-Encoding: gzip' -t 12 -c 120 \
Running 10s test @
  12 threads and 120 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    18.27ms  131.81ms   1.71s    97.60%
    Req/Sec    85.17k    10.73k  144.05k    82.75%
  10221627 requests in 10.10s, 7.53GB read
  Socket errors: connect 0, read 0, write 0, timeout 13
Requests/sec: 1012088.67
Transfer/sec:    763.48MB

see also

justine's web page
αcτµαlly pδrταblε εxεcµταblε