This guide is a catch-all for configuration, performance, and enterprise integration issues which are not a routine part of an initial installation, but likely concerns for any institution working toward production.
Running Tomcat as non-root user
*nix systems can use some iptables magic to allow Tomcat to run as a non-root user. The iptables must first pre-route to redirect ports 80, 443 and 25 to 8080, 8443 and 8025
:PREROUTING ACCEPT [510:80231]
:POSTROUTING ACCEPT [12:2548]
:OUTPUT ACCEPT [12:2548]
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
-A PREROUTING -i eth0 -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8443
-A PREROUTING -i eth0 -p tcp -m tcp --dport 25 -j REDIRECT --to-ports 8025
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8443 -j ACCEPT
-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8025 -j ACCEPT
Then run everything under a user with /sbin/nologin as the shell (you will need to "su -s /bin/bash - sakai" from root to get in as this user, when necessary).
In environments where local network policy or firewalls require use of an upstream http proxy / cache, Sakai needs to be configured to use this. Otherwise, components or services which use http requests, such as BasicNewsService for RSS feeds in the News tool, cannot retrieve data from the target URLs. RSS feeds then do not display in the news tool, and it is not possible to add new news channels.
This can be fixed by adding these lines to the Sakai local startup script (e.g. /etc/rc.d/sakai), or to a Sakai startup script such as startup.sh or catalina.sh:
JAVA_OPTS="-DproxySet=true -DproxyHost=cache.some.domain -DproxyPort=8080"
File-based Content Hosting
By default Sakai stores all its files - including uploaded binaries - in the database. If you wish to use file based content hosting instead, you must:
This latter conversion is needed even for a brand new database, since there are some resources shipped with the starting Sakai DB.
Configuring for File-based storage:First, include the following lines in the sakai.properties file:
# the file system root for content hosting's external stored files (default is null, i.e. store them in the db)
Edit the above line to point at the chosen location for the root folder for the files to be stored. Then enable the line below, and set an appropriate list of "volumes" for storage.
# when storing content hosting's body bits in files, an optional set of folders just within the content.filesystem.root
# to act as volumes to distribute the files among a comma-separated list of folders. If left out, no volumes will be used.
You can specify one or more (comma-separated) volume names on this line, but provide at least one. These volumes will be folders under the file system root, and files will be distributed among these volumes. If you are going to use multiple volume devices you need to map them to these volume names that live "under" the root. If you are not using separate devices then you can use any folder names for the volumes.
*CAUTION: Adding volumes once content is stored directly under the file system root is untested and its effects unknown. It is strongly recommended that you provide initially at least one volume name if you expect future expansion or large amounts of content to be stored on the file system.
Files will be stored under each volume in a way such that there are not too many in any one folder. The folder structure we use is:
YYYY/DDD/HH/id, where YYYY=year, DDD=day of year, HH=hour of day, and the numerical file name is based on its id. For example, using the above root and volumes, it might be:
Note that the resource name and type is not encoded here. The date/time used to form the file name is the date/time of file creation. This effectively means that the file system can be put to no practical use apart from the database (i.e. you cannot browse the directory structure to find resources by identifiable names). A further consequence is that individual files cannot be restored without first restoring the database.
Converting DB files to File-based storage:
Once you have your database set up (see below), your file values configured, and the file system read/write accessible to your application server, you then need to configure your Sakai to run and convert - in other words, to spit its current files out of the database and into your file system. Do this once, then shutdown after the conversion is complete, and finally re-configure Sakai to no longer do the conversion. At that point you could remove the table CONTENT_RESOURCE_BODY_BINARY from the database.
To convert, add this line to your sakai.properties:
As soon as Sakai starts up it will create a file system file for any content hosting resource that has a null "FILE_PATH" field. This could take a long time if you have many resources. If the process dies mid way, you can restart it, and it will pick up about where it left off (since it does not update the "FILE_PATH" until it has written out the file).
Apache with Sakai
For many reasons, production systems will likely have an Apache web server on the front end to handle HTTP and HTTPS request to Sakai. Apache is generally more trusted to run on the protected ports (80, 443) than Tomcat. It also is more efficient in processing the SSL part of the requests.
When Apache is handling the requests, it must send them to Tomcat for Sakai processing. This is done by using an Apache - Tomcat connector. This has to be properly configured on the Apache side and the Tomcat side. The necessary Apache configuration is outside the scope of this document (see the Apache-Tomcat connector documentation from apache.org for details), but we can say something about the Tomcat side of the configuration. It involves turning off the http connector and turning on the ajp connector. Simply comment out the parts of the configuration file ($CATALINA_HOME/conf/server.xml) that you don't want, and remove the comments from those that you do. Also make sure the port number set in Tomcat and Apache match, and add the URIEncoding option for proper character handling in Sakai, as in:
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" URIEncoding="UTF-8" />
Sakai and SSL
Most Sakai installations will want to run under HTTP for the SSL secure connections between the browser and the server. This is good to protect the user passwords as well as the data that goes in and out of Sakai.
We do not recommend using Tomcat SSL support. This SSL is implemented in Java, and is much slower than a native SSL like that found in an Apache module for SSL. Even better, put a hardware SSL handler / load balancer in front of your app servers to take care of the SSL processing.
See the Apache documentation for information on how to install an SSL plugin to Apache.
Providers are the means by which Sakai can poll external sources for its data. Sakai has basically 3 such providers:
Providers are found by the Sakai components that use them by looking for provider components registered under the names:
org.sakaiproject.service.legacy.user.UserDirectoryProvider (the user directory provider)
org.sakaiproject.service.legacy.realm.RealmProvider (the realm provider)
org.sakaiproject.service.legacy.coursemanagement.CourseManagementProvider (the course management provider)
The trick is to make sure that one component gets registered in your Sakai setup with each of these names, no more.
If you do not want a provider, set things up so that there is no component registered with the provider name. The provider client code will properly handle not having one defined.
One way to change the provider is to modify the sakai source code file that controls the provider registration in the Provider module. The file, a Spring bean definition file, is found here:
See this file for more details - examples of an LDAP and Kerberos providers are included in comments. Edit this file to pick which Provider module provider you want to use, and re-deploy Sakai.
Replacing the Provider Module
The other way to change the provider configuration is to completely remove the Provider module from your local sakai-src folder. Then you need to create a new module / project with the providers you write to satisfy the three provider APIs. You register your new components with the proper provider names, and include your module in the Sakai build and deploy.
At runtime, the Sakai provider module will be missing, your new module will be present, and when the provider client components get started up they will be wired to your new provider components.
If you integrate Sakai in some sort of single sign-on environment you will need to also make your provider for users work with the same environment. Most requests come in from browsers and will trigger the single sign-on for authentication. But our WebDAV support relies on the internal authentication system in Sakai, and the WebDAV protocol itself cannot handle the re-directs that single sign-on systems often require, so your provider must manage this burden.
Sakai also has a direct login path (/portal/xlogin) to bypass the single sign-on and invoke internal authentication directly.
This can be done in one of two ways: by either an Apache module or a servlet filter.
Edit Tomcat's server.xml
Disable Tomcat's container authentication by adding the following parameter to the JK2 connector configuration:
When you're done, the connector declaration should look something like this:
enableLookups="false" redirectPort="8443" debug="0"
Edit sakai.properties with:
top.login = false
container.auth = true
Configure sakai-login's web.xml ($TOMCAT/webapps/sakai-login/WEB-INF/web.xml):
First, add your filter configuration, usually after any others:
<!-- begin servlet filter -->
<!-- end servlet filter -->
next, add another filter to force requests for /container through Sakai's RequestFilter. This filter must be placed close to the top of web.xml near:
<!-- Force request for /container through the request filter -->
If your tests (see
below) fail, try substituting "
You may need to run multiple Sakai application servers in a cluster to support your user load. At this time, we don't have a good feel for how many users each application server can support, but it's likely that an application server class machine should be able to handle a load of 100 concurrent users or more. You must experiment with loads and your environment to see what you will need.
*Note: load testing of Sakai is schedule to occur around the release time - look for information about load testing and results on Sakai Collab in the Sakai Development site).
Configuring your Cluster
Sakai clusters by running a number of application servers with the same version of Sakai on each. The only difference between them is the configuration value "serverId", usually set in a file in sakai.home called "local.properties". This is an extension to sakai.properties that is optional. If present, it will be used. The advantage of using this file is that it is the only file that needs to be different between the clustered app servers - sakai.properties and the rest of Sakai are the same.
You need a front end "sprayer" or load balancer to take requests and distribute them among the machines in the cluster. This must preserve "Session Stickiness". This means that once a user establishes a Sakai session, they remain on the same app server until they logout. Sakai does not support session sharing or serialization.
The machines in the cluster must also share the same back end database. MySQL or Oracle are acceptable for this.
Simply start and stop each app server in the normal way. It registers with the cluster on startup, and unregisters on shutdown. If an app server ends without proper shutdown, the other app servers will notice this and do some cleanup of sessions left open by the missing server.
The Admin's OnLine tool shows who's on and what app server they are connected to. This is one way to see that your cluster is working. Note that if an app server is running but has no active sessions, it will not show up in the list.
You can add machines to the cluster, and remove machines from the cluster, without bringing your entire service down. This is useful if you have a load increase and want to bring more machines on-line temporarily to handle it. It can also be used to rotate machines out for maintenance, and back in, without service interruption.
When removing a machine from the cluster, first configure your front end load balancer to stop sending new requests to that app server. Then watch for users to drain off of the app server. The Admin's OnLine tool, or the access logs can be monitored to see that everyone's off the machine. At that point it's safe to shut it down.