Where to get mod_spin?
======================
It is available from here:
ftp://ftp.rexursive.com/pub/mod-spin/
You can also get source and binary RPM packages, built on and for Fedora Core
Linux distribution on x86 architecture. Skeleton application (i.e. an example
application) is available from here:
ftp://ftp.rexursive.com/pub/spinapps/app/
Unless you already have your own mod_spin applications, it can be useful for
testing if the installation of mod_spin actually worked. Source and binary
RPM packages are also available.
What else is required to build
==============================
1. Apache 2.2 or better: http://httpd.apache.org/.
2. Apache Portable Runtime and Apache Portable Runtime Utilities 1.2.8
(unreleased as of this writing) or better. Version 1.3.x (unreleased as of
this writing) is highly recommended, as it contains code for correct
handling of database column names. The home page of APR project is here:
http://apr.apache.org/
IMPORTANT NOTE: You should always use the version of APR/APU that you used
to link Apache with. If you pick another version, especially with a
different major number, you may get a nasty surprise.
3. Apache Request Library, version 2 (libapreq2); the home page of this project
is here: http://httpd.apache.org/apreq/. Apache 2.2 requires version 2 of
this library/module and will not work with version 1; mod_apreq2 has to be
installed and configured for mod_spin to work.
IMPORTANT NOTE: mod_spin is known to work with libapreq2-2.07 and above
(i.e. the multi-env version of this library/module).
4. XML C parser and toolkit, libxml2. You can get if from here:
http://www.xmlsoft.org/. Most Linux distributions already include it.
Apache Portable Runtime Utilities Library includes some support for XML,
but libxml2 is a much more mature implementation.
5. A Linux (or Unix) system with Apache 2.2, APR/APR Util, libxml2 and
libapreq2 INSTALLED!
6. If you intend to rebuild scanner.c and parser.c files from scanner.l and
parser.y, respectively, you'll need Flex version 2.5.33 or better, which
comes with reentrant C scanner support. Versions below that won't work! You
can get this version of Flex from http://lex.sourceforge.net/. Also,
having Bison version 1.875 or better is recommended.
7. The build and install are tested with GNU tools on Linux (Fedora Core).
Other tools may work, but you will have to find out for yourself.
How to build and install
========================
There are three options to install mod_spin into Apache:
1. As a binary RPM
2. As Dynamic Shared Object (DSO) from source
3. By static linking into Apache from source
IMPORTANT: You have to have Apache configured, compiled and installed
BEFORE you attempt this procedure (either as an RPM or from source). You MUST
have a working apxs for options 2 and 3, otherwise nothing will work!
The various config scripts
==========================
Packages that mod_spin depends on come with their own configuration scripts.
Examples include apr-1-config, apu-1-config, apreq2-config, xml2-config etc.
The first two will normally reside in the binary path returned by apxs. Others
may be in various places on the system. If you want to use a particular one,
set the PATH variable so that it points to the version you want when you're
running the configure script.
Note on environment variables
=============================
Depending on the system you're running and the features you select, some
environment variables will have to be set, namely CFLAGS, CPPFLAGS and
LDFLAGS. Normally, they are picked up by the above configration scripts.
For instance, if you're compiling in MySQL support on Fedora Core (this
applies if you're using APR Utils 1.2.x), the libraries will not be in
/usr/lib, but in /usr/lib/mysql. Also, the headers will not be in
/usr/include, but in /usr/include/mysql. To make sure configure finds the
libraries and headers, the configure script will attempt to detect the correct
location of header files and library dependencies, by using mysql_config. If
that doesn't work, you'll have to run something like:
CPPFLAGS="$CPPFLAGS -I/usr/include/mysql \
LDFLAGS="$LDFLAGS -L/usr/lib/mysql" ./configure [other options here]
This would ensure that the compiler and linker can find the required files.
Some other systems may have those files in a different location, so you'll
have to know certain things about your system before you attempt this.
The same can be said for libxml2, which is a requirement to build mod_spin.
For instance, this library installs its header files in /usr/include/libxml2
on Fedora Core. The configure script will attempt to figure that out at the
beginning of its run by running xml2-config. Sometimes this won't work as
expected. In that case pass relevant -I option on CPPFLAGS variable and -l/-L
options in the LDFLAGS variable, similar to the MySQL example above.
The CFLAGS environment variable is used to pass optimisation and other flags
to the C compiler. For instance, you might want to see all warnings and
compile in debugging support. You would specify:
CFLAGS="-Wall -g" ./configure [other options here]
The above is relevant to systems that have GNU C Compiler (gcc). If you use
some other compiler, you should check its documentations for the options.
Installation of libraries
=========================
Default prefix is /usr/local, making the installation of libraries go into
/usr/local/lib (or /usr/local/lib64 on some 64-bit systems). If you want
rxv_spin library in the system location (i.e. /usr/lib or /usr/lib64), specify
/usr prefix during configuration. Note that this may clash with rxv_spin
library installation from the RPM, if you do have one.
WARNING: rxv_spin library (i.e. librxv_spin.* files) are ABSOLUTELY REQUIRED
to run both mod_spin and any applications that you may have. If the library
isn't installed correctly, things will break! Luckily, all three installation
options install libraries automatically and this usually isn't a problem.
Library conflicts
=================
If you have an RPM installed on the system that includes a library (including
mod_spin), the location will usually be /usr/lib or /usr/lib64. When building
from source, mod_spin will link against a specific library, possibly located
in /usr/local/lib or /usr/local/lib64, to avoid versioning conflicts and
misterious problems with your module when certain RPMs are removed. Use ldd to
verify that you finished mod_spin has correct dependencies.
Macro files for aclocal
=======================
An installable M4 macro file, mod_spin.m4, is located in the m4 subdirectory
of the distribution. It gets installed into the aclocal's ACDIR directory (to
verify what that is on your system, run 'aclocal --print-ac-dir'). This macro
file is required for all mod_spin applications that want to use some mod_spin
specific configure tests and it simplifies writing of your own configure.ac
files. All mod_spin macros start with RXV_SPIN_, to distinguish them from
other macros. You can see how they are used in various mod_spin applications,
including the skeleton application, spin_app.
On most systems there is only one installation of aclocal. Therefore, both
packaged installation (via RPM or some other mechanism) and installation from
source would attempt to install this file in the system wide location. In all
cases, package installed file will be kept, as it is always marked with a
comment 'dnl PACKAGE' in the last line of the file. If you want to overwrite
this file with the M4 file from the source build, you will have to copy it to
the system wide location manually. This discussion only applies if both
package based and source based installation are used on the same system.
IMPORTANT: If you install mod_spin using an unprivileged user account, there
is a good chance you won't be able to write to system wide aclocal location
(usually one needs to be root to do this). Therefore, mod_spin.m4 file IS NOT
GOING TO BE INSTALLED. If you still need it for your applications, either
convice your system administrator to install the file in the system wide
location, copy the file into the m4 subdirectory of your application or use a
local installation of aclocal.
Session support
===============
Session identifiers are taken from mod_unique_id and hashed using MD5. An HMAC
MD5 of the hash is appended to the hash. This then creates a method of
protection against session spoofing (not unbreakable, but enough to prevent
massive amount of sessions from being introduced). For sessions to work at
all, YOU MUST set SpinSalt parameter, which cannot be less than 30 characters
long. On purpose, there is no default for this parameter, because it is
supposed to be secret, somewhat random and unique to your server (or group of
servers).
Option 1: From binary RPM
=========================
You have to be using an RPM based distro to do this (the packages are normally
built for Fedora Core on x86). If you are, then it's really simple:
rpm -Uvh mod_spin-X.Y.Z-R.ARCH.rpm
where X.Y.Z is version of mod_spin and R is the RPM release of it. Such
installation will create a configuration file for mod_spin, located here:
/etc/httpd/conf.d/spin.conf. This is just an example file, but it should work
for the simplest of applications. You'll have to edit it (or deploy your own
files via RPM of you application) to actually deploy your own mod_spin
applications, of course. Once you do that, any further upgrades of mod_spin
shouldn't overwrite the configuration file you fiddled with, courtesy of RPM.
Or you can provide applications' own configuration files, especially if you're
deploying those as RPMs as well.
If you want to develop software for mod_spin and you have an RPM installation,
you have to install the development RPM too:
rpm -Uvh mod_spin-devel-X.Y.Z-R.ARCH.rpm
Option 2: DSO from source
=========================
From the top directory of mod_spin source do:
./configure [--prefix=/top/dir] [--with-apxs=/path/to/apxs] \
[--with-flex-reentrant=/path/to/flex/installation/directory]
make
make install
Option 3: Static linking from source
====================================
IMPORTANT: THIS OPTION HAS NOT BEEN TESTED IN A WHILE AND IT MAY NOT WORK AT
ALL. IT SURE ISN'T RECOMMENDED.
From the top directory of mod_spin source do:
./configure [--prefix=/top/dir] --with-apache=/path/to/apache2/source \
[--with-apxs=/path/to/apxs] \
[--with-flex-reentrant=/path/to/flex/installation/directory]
make
make install
From the top directory of Apache source do:
If this is the first time you are installing mod_spin into this source tree of
Apache, you will have to build appropriate files in modules/spin directory:
./buildconf
IMPORTANT: If you compiled Apache from this source tree before, you should
run:
make distclean
If you don't, compile or link may fail.
Configure Apache, either by using an existing configuration (you can also
edit config.nice and place --enable-spin there):
./config.nice --enable-spin
or by using brand new set of options:
./configure --enable-spin [your options here]
Later, if you don't want mod_spin (why would you ever want to do that ;-), then
specify --disable-spin in your configuration options. Now build Apache and
install it:
make
make install
Uninstall
=========
If you installed from RPM, just do:
rpm -e mod_spin
and:
rpm -e mod_spin-devel
if you installed the development package.
In cases 2 and 3, you can simply run from the top directory of mod_spin source:
make uninstall
If you did the install into Apache source for static linking, you should
run:
./buildconf
from the top directory of the Apache source tree. This should clean up the
configure script and remove mod_spin options from it.
How to build RPMs
=================
You can do it from the tarball by:
rpmbuild -ta mod_spin-X.Y.Z.tar.bz2
The above will build both source and binary RPMs. Or you can build a binary
RPM from the source RPM like this:
rpmbuild --rebuild mod_spin-X.Y.Z-R.src.rpm
Most systems don't come with reentrant flex (this feature is available in
version 2.5.33 and above), but unless you've changed the scanner rules,
rebuilding the RPMs shouldn't fail (i.e. generated C files are shipped with
the distribution). If scanner rules were changed, however, you will need
reentrant flex. Replacing flex with a reentrant package may have system wide
implications, especially if you compile software that produces scanners.
Therefore, mod_spin was designed to use flex-reentrant package, which can
coexist peacefully alongside flex on your RPM based system.
Although source RPMs are normally versioned according to the distribution they
have been built on (for instance, SRPM built on Fedora Core 5 will have FC5 in
its name), you can still use them on other distributions.
Doxygen documentation
=====================
References to external documentation, namely that of Apache Portable Runtime,
Apache Portable Runtime Utilities Library and Apache Request Library, are all
done to the URLs at various Apache web sites. If you're installing from
source, in order to link to local documentation instead of one on the net, use
the installdox Perl script, located in the docs/html directory (after you
performed make install). Something like this should do the trick (of course,
substitute example locations with the ones on your system):
./installdox -l apr.tag@/usr/local/doc/apr \
-l apu.tag@/usr/local/doc/apr-util \
-l apreq2.tag@/usr/local/apache2/share/libapreq2/docs/html
For the RPM installation, the RPM post install script will attempt to detect
what documentation you have locally and run installdox for you. If you install
some documentation after you put mod_spin RPM on your system, you can either
run installdox manually (like in the example above) or you can reinstall the
RPM (the --force option does wonders here), which will run the post install
script again.
For your convenience, all mod_spin packages contain mod_spin.tag file, to
allow easy referencing from your documentation.
Module loading order
====================
The Apache Request Library module must be loaded before mod_spin, or your
Apache web server won't be able to resolve some symbols. So, have them like
this in your httpd.conf file:
LoadModule apreq_module modules/mod_apreq2.so
LoadModule spin_module modules/mod_spin.so
Luckily, when deployed in a standard Red Hat manner via the RPM, where each
module gets its own configuration file in conf.d directory, apreq is
alphabetically before spin, so it loads first. Phew!
Note on cookies
===============
As of Apache 2.0.48, support for RFC2965 cookies still has problems. It is
best to stick with Netscape cookies for now. Also, Apache 2.0.48 requires you
to specify CookieName or things won't work. This has been fixed in Apache SVN
and it will appear in later Apache versions.
SELinux environments
====================
If you are running Security Enhanced Linux (for instance, Fedora Core), you
may need to do a bit of extra configuration for mod_spin to work correctly
(depending on the application/session store type you choose). For instance,
with SQLite2/3, if you place application/session database in /var/tmp/myapp.db
file, you'll have to make sure that this file belongs to the correct security
context, which is normally root:object_r:httpd_cache_t. To do that, you'd run:
chcon -u root -r object_r -t httpd_cache_t /var/tmp/myapp.db
Without this, you may have Apache running in a different security context and
being denied access to your application/session database files. Meaning, every
time mod_spin attempts to access /var/tmp/myapp.db file, although file
permissions allow it, file access would be denied by policy and the client
would get an internal server error response.
Obviously, if you're running other databases where connections are made via a
TCP or Unix domain socket, you will have to allow Apache to connect to those
sockets. On Fedora Core, this is done using SELinux booleans. You can obtain
the list of those by running sestatus -b. You can change them by running
setsebool. Check relevant manual pages for all details.
Configuration
=============
Here is an example snippet from httpd.conf (comments after configuration
parameters will cause errors - they are here only to point out the default
settings):
AddHandler spin-template .sm
AddType text/html .sm
SpinApplication /usr/local/libexec/spinapps/spinapp.so
SpinAppInit rxv_spin_init # Default
SpinAppPrepare rxv_spin_prepare # Default
SpinAppService rxv_spin_service # Default
SpinAppConfig /usr/local/etc/spinapps/spinapp.xml
SpinStore sqlite3:/var/tmp/mod_spin/store.db
SpinStoreTable spinstore # Default
SpinCookie SpinSession
SpinTimeout 0 # Default
SpinSendfile on # Default
SpinCache on # Default
SpinCacheAll off # Default
SpinCacheCount 50 # Default
SpinConnPool on # Default
SpinConnCount 5 # Default
SpinSalt # No default
SpinApplication, SpinAppInit, SpinAppPrepare, SpinAppService, SpinAppConfig,
SpinStore, SpinStoreTable, SpinCookie, SpinTimeout, SpinSendfile, SpinCache,
SpinCacheAll and SpinConnPool can be placed in the main server section,
virtual host section, directory or location section. The nearest available
will be used. SpinCacheCount, SpinConnCount and SpinSalt can only be placed
in the global configuration, as they don't make sense anywhere else.
SpinApplication is the path to the shared library that is your application.
SpinAppInit is the name of the application init function in the shared library
(rxv_spin_init() by default). This function, if exists, will be called when
the library is dynamically linked into Apache.
SpinAppPrepare is the name of the application prepare function (called in the
fixups phase of the request processing) in the shared library
(rxv_spin_prepare() by default). Function named in SpinAppPrepare will be
called after the library is dynamically linked by mod_spin.
SpinAppService is the name of the application service function (called from the
handler) in the shared library (rxv_spin_service() by default). Function named
in SpinAppService will be called after the library is dynamically linked by
mod_spin.
SpinAppConfig is the path to the application configuration file. This is a
simple XML file (so that we can use XML parsing facilities easily) which looks
like this:
]>
The value associated with spinparameter1
The value associated with spinparameter2
Given that parsing of the configuration file is a very rare event (application
parameters are kept in the database file after that), the overhead is not big.
The DTD of the document is preferably always local, simply because it is very
small and makes parsing a predictable event.
SpinStore is a location (in APR Util DBD speak) of your session and appliction
store. The store is actually a table in an SQL database (e.g. PostgreSQL,
SQLite3 etc.). This parameter obeys SpinConnPool parameter. With version 1.3.x
of APR Util DBD, supported database prefixes are pgsql, mysql, sqlite2,
sqlite3 and oracle. This obviously depends on how APR Utils was compiled and
linked and what databases really exist in your environment. If you're using
MySQL, you have to specify flags=CLIENT_FOUND_ROWS in your connect string, or
the store isn't going to work properly.
SpinStoreTable is the name of the SQL table used for the store.
SpinCookie is the name of the cookie used for session management. This
parameter is optional, that is to say, if it isn't defined, sessions will not
be supported for that particular configuration section. By convention, this is
normally called SpinSession, but it can be called anything you like. Session
cookie handling is entirely done in mod_spin. You need to define SpinSalt for
sessions to work.
SpinTimeout is session timeout in seconds. After this time, the session data
from session store will be ignored (i.e. not retrieved) and overwritten by new
data if the same session ID is used. By default, this value is set to zero,
meaning no timeout. Specifying anything but an integer greater or equal zero
will set the value to zero.
SpinSendfile enables sendfile() support for pushing the data from the template
file onto the socket. Default is on. Disable this for file systems that have
problems with sendfile().
SpinCache enables caching of templates and it is on by default. This improves
performance if the same templates are used over and over again by the same
thread, but uses more memory. By turning this off, templates will be parsed on
every new request, unless the request for the same template is within the same
connection. This reduces both performance and the memory pressure.
SpinCacheAll enables caching of all text for every template. This can improve
performance, but it'll use more memory. By default, this switch is turned off
and all file chunks 256 bytes in size and over will be put into the brigade as
FILE buckets, rather than IMMORTAL buckets.
SpinCacheCount specifies the number of templates to keep in cache. Least
Recently Used (LRU) algorithm is used to maintain up to this many templates in
cache. Specifying anything but an integer greater than zero will set the value
to the default. Default is 50.
SpinConnPool enables pooling of connections and it is turned on by default.
SpinConnCount specifies the number of connections to keep in the connection
pool. Least Recently Used (LRU) algorithm is used to maintain up to this many
connections open. Specifying anything but an integer greater than zero will
set the value to the default. Default is 5.
SpinSalt is the cryptographic salt (key) used to produce HMACs for session id
hashes. It has to be at least 30 characters long. DO NOT SET THIS TO THE SAME
VALUE ON ALL YOUR SERVERS UNLESS YOU'RE RUNNING A CLUSTER of machines that
share sessions, as it'll be easier for potential attackers to spoof your
sessions. The best thing to do is to make this a "random" string, something
that doesn't make any sense in any language.
Strangely enough, you can set SpinSalt parameter more than once and that is
not an error. This functionality exists to enable security savvy
administrators to rotate cryptographic salt, in order to make session
spoofing even more difficult.
An external program, possibly started from cron, can manipulate SpinSalt
parameters in the configuration file (or, file included from the configuration
file). The first specified SpinSalt will be considered new and the second one
will be considered old, but still valid (other instances of SpinSalt will be
ignored). After a graceful restart of Apache, mod_spin will accept sessions
encrypted with both the old and the new salt. All outgoing sessions will be
encrypted using the new salt. This enables smooth transition between different
crypto salts.