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 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 or better. Version 1.3.x 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). 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, 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. 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 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. 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 build 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 or rebuild the binary RPM and install it 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! SELinux environments ==================== If you are running Security Enhanced Linux (for instance, Fedora), 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. To make labeling of files correct, use semanage command, to set you local file contexts to the correct value. For instance: semanage fcontext -a -t http_cache_t '/var/tmp/modspin(/.*)?' 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, 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 # AddOutputFilter 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 file:/var/tmp/mod_spin # SpinStore sqlite3:/var/tmp/mod_spin/store.db # SpinStore mysql:dbname=spintest,flags=CLIENT_FOUND_ROWS # SpinStore pgsql:dbname=spintest SpinStoreTable spinstore # Default SpinCookie SpinSession SpinCookiePath / # Default SpinCookieDomain .example.com SpinTimeout 0 # Default SpinConnPool on # Default SpinConnCount 5 # Default SpinSalt # No default SpinApplication, SpinAppInit, SpinAppPrepare, SpinAppService, SpinAppConfig, SpinStore, SpinStoreTable, SpinCookie, SpinCookiePath, SpinCookieDomain, SpinTimeout and SpinConnPool can be placed in the main server section, virtual host section, directory or location section. The nearest available will be used. 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 The DTD of the document is local in the above example, but you don't need to specify it in your file. You can even omit the XML declaration. 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 (this won't work, as this driver doesn't support prepared statements), 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. You can also specify a special driver, file:, followed by the directory where the store will be located. In this case, application and session data is kept in XML files. This store backend features best performance. See the above example snippet from the httpd.conf file for more details. SpinStoreTable is the name of the SQL table used for the store. This parameter has no effect when file based store is in use. 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. SpinCookiePath is the path of the cookie used for session management. It is set to "/" by default. SpinCookieDomain is the domain of the cookie used for session management. It is not set by default. 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. An external program, possibly started from cron, can reap session data that timed out, whether in a database or file based store. 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. Note that any connection that has not been used for more than a minute will be closed and removed from the connection pool. 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.