For admins, by admins.
  
 
  1. Antiweb is very different from other webservers. Are you guys crazy?
  2. What platforms does Antiweb run on?
  3. Where can I ask questions, report bugs, etc?
  4. What license does Antiweb use?
  5. Why am I getting errors from gcc when compiling Antiweb?
  6. How do I find out ...?
  7. How can I change Antiweb build/install options?
  8. What is the cache directory for?
  9. Do I need to restart a worker process to reload a worker conf file?
  10. Do I need to restart the hub to add new listeners?
  11. Can I attach to a running process and give it lisp commands?
  12. How can I get the hub to reopen its log files?
  13. Was Antiweb inspired by Erlang?
  14. What are rollbacks?
  15. Can I use multiple lisp environments at the same time?
  16. Why does it take a few seconds to start a worker?
  17. Can a compromised worker wait until I -reload to steal vhosts?
  18. Will Antiweb automatically restart a crashed worker/hub?
  19. Does Antiweb use continuations?
  20. Why does Antiweb linger on HTTP sockets?
  21. What is timeout clustering?
  22. Does AW support SSL and/or reverse proxying?
  23. Are there any known limitations with CMUCL?
  24. Are there any known limitations with CLISP?
  25. Is SBCL supported?
  26. Can you teach me l33t k0ding skillz?

Antiweb is very different from other webservers. Are you guys crazy?

No. Well, maybe a little, but we aren't letting that stop us from building the best webserver ever. Before Antiweb4, we recommended the following servers:

These servers are good, but they don't take advantage of lisp, the greatest programming language in the world.

What platforms does Antiweb run on?

Tested platforms:

  • CMUCL/Linux 2.6/x86
  • CLISP/OpenBSD 4.3/x86
  • CLISP/Linux 2.6/x86
  • CMUCL/FreeBSD 7.0/x86
  • ClozureCL/Linux 2.6/x86-64

Please do not port Antiweb to proprietary unix or lisp environments.

Where can I ask questions, report bugs, etc?

Please use the Antiweb Google Group for discussions about Antiweb. Acceptable topics include but are not limited to:

  • Questions about installation/setup
  • Bug reports
  • Feature requests

Security issues or other sensitive communications can be sent directly to Doug Hoyte.

What license does Antiweb use?

Your rights to use and distribute Antiweb are protected under the terms and conditions of the GNU GPL version 3.

  • The manual.awp file is also covered by the GPL.
  • Before accepting patches, the Antiweb project requires copyright assignment that allows us to relicense your modifications. You still keep full rights to your modifications and Antiweb will always be available under the GPL.

Why am I getting errors from gcc when compiling Antiweb?

Most likely you don't have all the header files installed. Some systems package header files separately from the libraries themselves. For example, on an Ubuntu machine you will need at least the following extra packages:

$ sudo apt-get install libc6-dev zlib1g-dev

How do I find out ...?

If a process terminates unexpectedly, the first thing you should check is the syslog file:

# tail /var/aw/aw_log/syslog

The fastest and most reliable way to get info about what an Antiweb process is currently doing or how it is configured is to use the launch script's -stats command. For example, to get the stats of a running hub, run this command (as root):

# antiweb -stats /var/aw

Similarly, to get the stats of a worker process:

# antiweb -stats /var/aw/worker.conf

  • When attached to a process you can also get this info by evaluating (stats).

For info on the memory consumption of an Antiweb process, use the -room command. This will give you information about the lisp managed heap, as well as Antiweb's special conn and ioblock data-structures:

# antiweb -room /var/aw/worker.conf

How can I change Antiweb build/install options?

As mentioned in the installation instructions, there are several variables that can be changed at the top of build.lisp that will change how Antiweb is built and installed. Although you can change the build options directly in this file, the recommended way is to create a local.lisp file in the Antiweb tarball directory. This way, when you upgrade Antiweb you can simply copy your existing local.lisp file into the new Antiweb directory.

If it exists, local.lisp will be loaded before Antiweb is built. Antiweb build options can thus be changed by using the Common Lisp setq form.

Here are some examples of local.lisp files:

  • Install Antiweb into the /usr/local/ prefix instead of /usr/:
    (setq aw-bin-dir "/usr/local/bin")
    (setq aw-lib-dir "/usr/local/lib")
  • Compile Antiweb with your system's default BerkeleyDB (requires version 4.6+):
    (setq aw-use-bdb t)
  • On a 64 bit machine, compile a 32 bit version of Antiweb when compiling with CMUCL, but a 64 bit version when compiling with any other lisp:
    #+cmu (setq aw-extra-cflags "-m32")
    Note: Make sure you have 32 bit libc and zlib libraries available. On a Debian x86-64 machine try this command:
    # apt-get install ia32-libs libc6-dev-i386 lib32z1-dev
  • On a 64 bit machine, compile a 32 bit version of Antiweb using a specific 32-bit BerkeleyDB install:
    (setq aw-use-bdb t)
    (setq aw-extra-cflags
      "-m32 -L/usr/local/BerkeleyDB.4.7/lib/ -I/usr/local/BerkeleyDB.4.7/include/")

What is the cache directory for?

Workers can optionally have a cache directory. The worker conf has a cache xconf you need to enable if you want to use certain features:

  • When gzip compression is enabled, files of the appropriate extension and size are gzip compressed and stored to the cache the first time they are read, and again if their modification times change. HTTP clients that indicate they can handle gzip encoding are served the compressed data as regular static files.
  • Every Anti Webpage gets its own directory in the cache. After the page is compiled, it is stored and served out of the cache (along with a gzipped copy) until the modification time on the .awp file changes. The Anti Webpage will then be recompiled into the cache.
  • For Anti Webpages that contain code in the form of AJAX callbacks, a lisp file is stored into the cache and compiled into a "fast load" file (.x86f or .fasl or .fas or .lib or .lx64fsl or ...). This file is loaded on the first request for the Anti Webpage, and is compiled and loaded again when the .awp file's modification time changes.
  • When javascript minification and/or CSS minification is enabled, javascript and/or CSS files will be minified, gzip compressed, and stored in the cache directory.

Do I need to restart a worker process to reload a worker conf file?

No. Antiweb is designed so that you never need to restart any of its processes. To reload a worker conf file, even if the worker is chroot()ed and can no longer access the file, run this command (as root):

antiweb -reload /var/aw/worker.conf

  • The worker will not reset itself in any way during a reload. Even connections currently being sent files and keepalive connections will not be closed.
  • If an error is detected while installing the new conf file, the worker will not install it and will continue with the old configuration.
  • If an error is encountered in an HTTP dispatch with the new conf file, it will revert to the old conf file and close the connection that caused the error. This is called a rollback.

Do I need to restart the hub to add new listeners?

No. You can start listening on a port in a supervisor process with root privileges and then transfer the listening socket into a running hub. To see the interfaces/ports currently being listened on, use the -stats command:

# antiweb -stats /var/aw
...
Listening on:
  0.0.0.0 80
  :: 80
...

The above stats output means the hub is listening on all IPv4 and IPv6 interfaces for connections to port 80. This command adds a new listener:

# antiweb -add-listener /var/aw 0.0.0.0 8080

OK

And this closes a listener:

# antiweb -close-listener /var/aw 0.0.0.0 8080

OK

Can I attach to a running process and give it lisp commands?

Yes, as long as you have root privileges you can attach to or supervise any Antiweb process through the hub's unix socket. Note that root privileges are dropped once you have attached to the target process. For example, to attach to the hub process, run this command (as root):

# antiweb -attach /var/aw

Similarly, to supervise a worker process, run this command (as root):

# antiweb -attach /var/aw/worker.conf

In both cases, you will be shown the output of the stats command run on that process, and then will be given a * prompt:

[Antiweb: Attached to HUB] *
[Antiweb: Attached to worker HOYTECH] *
This is similar to a lisp REPL. The *, **, ***, +, ++, and +++ special variables are stored in the process you attached to and are unique per REPL session. The expressions are evaluated by the process being supervised. Although all Antiweb processes only have a single thread of execution, a supervised process will continue to function normally while being supervised.

How can I get the hub to reopen its log files?

First of all, never send an Antiweb process a HUP signal. All communication with Antiweb is done via the hub.socket unix socket.

To reopen the hub's log files, attach to the hub process and evaluate (reopen-log-files).

For example, mv the log files to a new destination:

# mv /var/aw/aw_log/* /storage/dir/

Attach to the hub:

# antiweb -attach /var/aw

Then evaluate the (reopen-log-files) form at the Antiweb prompt:

[Antiweb: Attached to HUB] *
(reopen-log-files)

T

When finished, press control-d or use the (quit) command:

[Antiweb: Attached to HUB] *
(quit)

# 

Note that this does not quit the process you are attached to. To do that, either use the -kill command or evaluate (progn (quit)) when attached.

Alternatively, especially when doing all this from a script, you might choose to use the -reopen-log-files command:

# antiweb -reopen-log-files /var/aw

Was Antiweb inspired by Erlang?

Not directly, no. Hoytech engineers have never looked at any Erlang implementations and have never programmed in Erlang. But we like what we hear. Antiweb's philosophy is similar to Erlang's in several respects:

  • If an unexpected condition is encountered, die as quickly and loudly as possible. Never try to clean-up or recover. A process cannot do that because it has failed. Some other process that hasn't failed will clean-up after it.
  • Threads are bad engineering. Sharing state between processes is bad engineering. All inter-process communication is done by explicit message passing.

What are rollbacks?

Antiweb is an interactive webserver. It is designed so that it can be reconfigured and developed without any interruption of service.

Normally, in the event of an unexpected condition, Antiweb will die as quickly as possible. After an error, a process cannot continue functioning because it has failed. Rollbacks provide a way to stop the worker process from committing suicide if an error occurs in the HTTP dispatch function portion of the code.

When a worker starts, it reads its conf file and compiles an HTTP dispatch function. If there is an error compiling the dispatch function, the worker simply will not start (see the syslog file for the reason).

Once the worker does start, no rollbacks are installed so any errors encountered in the HTTP dispatch function are treated like normal errors: they will terminate the worker process and log the reason to syslog. If you -reload a worker conf (and the new HTTP dispatch compiles OK), it will push a rollback onto the rollback stack if and only if there are no existing rollbacks. If there is later an error encountered inside the newly installed HTTP dispatch function, Antiweb will close the HTTP connection that caused the error (using a 500 Internal Server Error) and then will rollback to the old conf file instead of dying. This is a safety feature and how or if you use it is a policy decision.

If all you ever do is -reload worker confs, only the original (oldest) conf file is available as a rollback. However, when you are attached to a worker you can add or remove rollbacks manually with the following commands:

  • (push-rollback) - Copies your current conf file and adds it as a rollback. You might want to add a comment to this rollback:
    (push-rollback "adding the host rewrite rule")
  • (rollback) - Installs the most recent rollback, overwriting the current HTTP dispatch function and conf file.
  • (pop-rollback) - Removes the most recent rollback without installing it. Returns the rollback struct so you can save it somewhere if you want.
  • (pop-all-rollbacks) - Removes all rollbacks. Returns a list of all rollback structs which you can save somewhere if you want.

You can always get a list of the rollbacks available to a worker with the -stats command:

# antiweb -stats /var/aw/worker.conf
...
Rollbacks:
  Rollback [changing rewrite rule] pushed 0d 1h 0m 4s ago
  Rollback [adding new rewrite rule] pushed 0d 1h 1m 53s ago
  Rollback [original] pushed 0d 2h 10m 25s ago
...

  • Rollbacks only apply to errors encountered in the HTTP dispatch function. Errors elsewhere in Antiweb will immediately terminate the worker, regardless of rollbacks.
  • ...except that errors resulting from compiling Anti Webpages will never terminate the worker. Instead, the Anti Webpage is unavailable to clients until the .awp file is fixed (clients are sent a 500 Internal Server Error). See the syslog file for details why an Anti Webpage didn't compile.

Can I use multiple lisp environments at the same time?

Antiweb Tip
Caution: CLISP's readline can interfere with pasting in lisp forms. You can disable readline with the -noreadline option (must appear before the real command you are running). See CLISP Limitations.
Yes. Antiweb's "wire protocol" is independent of the lisp environment in use.

  • The -stats command lets you see the Common Lisp environment and version of any Antiweb process.
  • You can attach to a CLISP process with CMUCL and vice-versa (except be careful of cross-platform problems like backquote expansions).
  • If you have a 64 bit machine, you can run some Antiweb processes in 64 bit mode and others in 32 bit mode. See the local.lisp FAQ entry for configuration examples.

To install different lisp environments, simply follow the installation instructions for each of the desired lisp implementations. The antiweb launch script will default to using the most recently installed lisp environment. However, you can force a particular lisp environment with the -cmu, -clisp, or -ccl switches. For example:

antiweb -cmu -hub /var/aw

or

antiweb -clisp -worker /var/aw/worker.conf

Or if you want a REPL on a ClozureCL with all the Antiweb functions loaded:

antiweb -ccl -repl

Why does it take a few seconds to start a worker?

Antiweb compiles parts of the system only once the worker's conf is loaded. This adds a small compilation delay when starting worker processes. There are many advantages to having the compiler available at run-time, including more efficient HTTP dispatches that omit unused features and the ability to add new modules to workers (or shadow existing modules) without restarting them.

Can a compromised worker wait until I -reload to steal vhosts?

In theory it it possible for a compromised worker to "lie and wait" for you to -reload (which unlocks the worker process's connection to the hub) and then feed in extra unwanted vhosts for it to listen on. You should always check the hub status with the -stats command after a -reload to make sure this hasn't happened (make sure the worker has the right vhosts and is locked). The effectiveness of this attack is diminished by the following two points:

  • A worker cannot do this to steal vhosts being listened on by other workers. If a worker tries this, the hub will instantly cut it off (and log what happened).
  • In no situations does this attack allow log messages to be intercepted.

Will Antiweb automatically restart a crashed worker/hub?

No. Whether to do this or not is a policy decision, not a technical one.

  • A simple way to ensure that a worker is running is to try starting it with the -check-worker switch:
    antiweb -check-worker /var/aw/worker.conf
    The worker will only be started if it currently isn't running. -check-worker is identical to -worker except it will not add a log message in syslog if the worker was already running. For example, adding this line to your crontab will check that a particular worker is running every 15 minutes:
    0,15,30,45 * * * *   /usr/bin/antiweb -check-worker /var/aw/worker.conf
  • Once correctly configured, an Antiweb process should never crash. If it does, check the syslog file and please let us know in as much detail as possible what happened. You may have discovered a serious bug in Antiweb.

Does Antiweb use continuations?

No. Hoytech's R&D team has never read any convincing arguments that continuations are useful for web development. Instead, continuations pose a number of determinism/reliability issues that Antiweb avoids by not using them. Thankfully, Common Lisp does not force the burden of continuations upon application developers seeking to build reliable systems. This is a valuable feature of Common Lisp.

Why does Antiweb linger on HTTP sockets?

When terminating an HTTP connection with a "Connection: close" HTTP header, Antiweb will shutdown() the write direction of the socket and continue to read and discard data from the socket for up to 2 seconds. This is required for HTTP/1.1 persistent connections. See here for more details.

Note that Antiweb's maximum linger period (2 seconds) is much shorter than Apache's 30 seconds. Also, we don't use a SIGALRM. Instead, lingering sockets are tracked with Antiweb's regular connection state machine. We believe this is correctly implemented but please let us know if you encounter problems.

What is timeout clustering?

This is an experimental optimisation in Antiweb4 that so far we have had good results with. The idea is that for many types of timeouts, including timing out keepalive connections, it doesn't really matter if they occur plus or minus a second or so. Antiweb takes advantage of this by scheduling the timeouts on a second boundary. So instead of the following sequence of syscalls:

kevent(200ms)
close(socket)
kevent(200ms)
close(socket)
kevent(200ms)
close(socket)
kevent(200ms)
close(socket)
kevent(200ms)
close(socket)
kevent()

Antiweb does:

kevent(1000ms)
close(socket)
close(socket)
close(socket)
close(socket)
close(socket)
kevent()

Notice how there are four fewer calls to kevent() with clustering. In addition to making fewer system calls, we also suspect this is better for power consumption.

Does AW support SSL and/or reverse proxying?

Not yet. Currently we recommend reverse proxying SSL connections to Antiweb with nginx. Eventually Antiweb will be both SSL capable and able to reverse proxy SSL.

Are there any known limitations with CMUCL?

  • CMUCL currently needs to see the libantiweb32.so file in a system library directory when it saves the image. This means that on new systems where Antiweb has never been installed before, Antiweb/CMUCL needs to be built and installed twice. The installation instructions have details on how to do this. We are looking into a workaround for this.
  • CMUCL will always load the libantiweb32.so library from a system library directory, even if Antiweb tells it to load a freshly compiled version from the bin/ directory. If you add a new function to libantiweb.c, you will need to delete the library from its system location prior to recompiling Antiweb. This is only a problem during development and when upgrading Antiweb. We are looking into a workaround for this.
  • CMUCL mmap()s a large amount of address space which can stop it from running on certain VPS systems. Note that most of this address space doesn't map to real memory. The -dynamic-space-size doesn't seem to reduce the size of the mmap() unfortunately. SBCL does this, probably CMUCL can too.

Are there any known limitations with CLISP?

  • CLISP's readline support can interfere with pasting in lisp forms (S-expressions). When attaching to a process, you may want to turn it off:
    # antiweb -noreadline -attach /var/aw/worker.conf
    If you leave readline on, be aware that symbol completion will only find symbols in the supervisor process, not the process you have attached to.
  • The filenames of conf files (like .awp files) can only contain a subset of UTF-8. They can't include the * or ? code points because there seems to be no way to open or read such files in CLISP. This doesn't affect static files or CGI scripts because Antiweb uses its own filesystem interface for those.
  • On older versions of CLISP, certain HTTP headers will be terminated with only a newline, not a carriage-return + newline. Use CLISP 2.42 or newer.
  • Some versions of CLISP seem to ignore the -repl switch so Antiweb's -repl command won't work with them. 2.42 seems to work but 2.44 doesn't.
  • If you use -nodaemon and press control-c to interrupt an Antiweb process, you get a functioning debugger REPL (just like CMUCL) but resuming the process when you are done debugging is problematic (unlike CMUCL, where it works perfectly). We are still tracking this issue down.
  • (lisp-implementation-version) returns different information depending on whether it is a worker process or the hub process (you can observe this with -stats). We have no idea why this happens.

Is SBCL supported?

Currently no. SBCL is an experimental fork of CMUCL. We have had problems with several versions of SBCL in the past, but eventually Antiweb will probably run on SBCL. If you port Antiweb to SBCL, we recommend building a single-threaded lisp image.

Can you teach me l33t k0ding skillz?

Yes, yes we can. Please refer to Doug Hoyte's book Let Over Lambda for details on many of the coding techniques used in Antiweb4.