= OSL Migration = The Open Source Lab environment is drastically different from our solution with Central Web Services. The largest problem we ran into was bugs that used a managed postgres cluster as oppose to running the server locally. It took a lot of time to understand which permissions were needed, since we normally use superuser access on the current local server. The OSL also uses WSGI instead of mod_python for Apache. This required us to change our configurations around for the vhosts, but wasn't too big of a deal. Because of the managed environment, we had to change our file structure as well as change where '''things''' are located. These have been solved with symlinks for the most part, but a few paths are still a bit different. == OSL Environment == * Managed Gentoo * Cfengine * Managed Postgres cluster * WSGI This guide details the steps taken to get all of Beaversource up and running in the new OSL environment === DB Info === * Postgres 8.2 * Host: dogwood.osuosl.org * [http://admin.osuosl.org/phppgadmin/ Phppgadmin] * Four users. One admin user and one for each database. * bsc_admin (Admin) * bsc_projects (Trac) * bsc_project_meta (Django) * bsc_elgg (Elgg) * Auth info located in /data === File ACL === For finer permission controls, we use file acls. The current ACL in use has been included below. {{{ # file: data # owner: root # group: beaversource user::rwx group::r-x group:beaversource:rwx mask::rwx other::r-x default:user::rwx default:group::r-x default:group:beaversource:rwx default:mask::rwx default:other::r-x }}} === Apache === For our Apache setup, we have two separate vhosts. These are for beaversource.oregonstate.edu and code.oregonstate.edu. The first vhost(beaversource) handles all of the web front-end including Elgg, Trac, and Django. The second vhost(code) is specifically for handling the SVN repositories. The working vhosts are included below. beaversource.oregonstate.edu vhost: {{{ ServerAdmin code-admins@lists.oregonstate.edu ServerName beaversource.oregonstate.edu ServerAlias www.beaversource.oregonstate.edu beaversource.osuosl.org RewriteEngine On #RewriteCond %{HTTP_HOST} !^beaversource\.oregonstate\.edu$ [NC] #RewriteRule ^(.*)$ http://beaversource.oregonstate.edu$1 [R=301,L] DocumentRoot /var/www/beaversource.oregonstate.edu BrowserMatch .*Googlebot.* gb Alias /social /var/www/beaversource.oregonstate.edu Options SymLinksIfOwnerMatch AllowOverride All Order allow,deny deny from env=gb allow from all RedirectMatch ^/$ /social # Trac Configuration WSGIDaemonProcess trac processes=5 threads=20 maximum-requests=1500 WSGIScriptAlias /projects /var/lib/trac/apache/trac.wsgi #This will redirect people to the elgg project listing instead of one created by trac RedirectMatch ^/projects/?$ /social/mod/browser/index.php?display=projects WSGIProcessGroup trac WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all #Django(bettse) based version of the metaproject Alias /media /var/lib/django/webmanagement/media WSGIDaemonProcess django processes=5 threads=20 WSGIProcessGroup django WSGIScriptAlias /request /var/lib/django/webmanagement/apache/django.wsgi Order deny,allow Allow from all Order deny,allow Allow from all LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{Cookie}i\"" beaversource CustomLog "|/usr/sbin/cronolog /var/log/apache2/beaversource.oregonstate.edu/transfer/%Y%m%d.log" beaversource ErrorLog "|/usr/sbin/cronolog /var/log/apache2/beaversource.oregonstate.edu/error/%Y%m%d.log" }}} code.oregonstate.edu vhost: {{{ ServerName code.oregonstate.edu ServerAdmin code-admins@lists.oregonstate.edu SSLEngine on BrowserMatch .*Googlebot.* gb DocumentRoot /var/www/code.oregonstate.edu/ Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny deny from env=gb allow from all # This directive allows us to have apache2's default start page RedirectMatch ^/$ /svn/ AuthBasicAuthoritative off AuthLDAPBindDN "uid=bsc_auth,ou=specials,o=orst.edu" AuthLDAPBindPassword AuthLDAPURL "ldap://ldap.onid.orst.edu:389/o=orst.edu?uid?sub?(objectClass=*)" STARTTLS AuthzLDAPAuthoritative off DAV svn SVNParentPath /var/lib/svn SVNListParentPath on AuthType basic AuthBasicProvider ldap AuthName "ONID login to SVN Repositories" AuthUserFile /dev/null Require valid-user Include /etc/apache2/vhosts.d/policies/bs_projects CustomLog "|/usr/sbin/cronolog /var/log/apache2/code.oregonstate.edu/transfer/%Y%m%d.log" combined ErrorLog "|/usr/sbin/cronolog /var/log/apache2/code.oregonstate.edu/error/%Y%m%d.log" ServerName code.oregonstate.edu RewriteEngine on RewriteRule /(.*) https://code.oregonstate.edu/$1 [R=permanent] }}} === Subversion === We implement hooks in each project repository in order to manage the size limits of commits, enforce permissions, and let Trac interact with commits. With hardened Gentoo, we ran into issues with grsec that wouln't let us execute the chain of scripts for each hook because the absolute path to the interpreter wasn't included in the hook script(thusly relying on 'shebangs' to identify interpreters). In order to solve this problem, we first needed to ensure that the chain of hook scripts were all in a single language (purely for simplicity), and then had to append the path to that interpreter. Since the majority of our scripts were Python (all but one), we rewrote '''the one''' script in Python, and appended the path to the Python interpreter in each hook (/usr/bin/python in our case). This was done for all existing repositories with the following script, which was run from /data/svn with root privileges. {{{ #!/bin/bash for repo in * do if [ -d $repo ]; then sed -i -e 's/\/data/\/usr\/bin\/python \/data/' $repo/hooks/start-commit sed -i -e 's/\/data/\/usr\/bin\/python \/data/' $repo/hooks/pre-commit sed -i -e 's/\/data/\/usr\/bin\/python \/data/' $repo/hooks/post-commit fi done }}} We also needed to ensure that all new projects have their hooks created properly, so we edited beaversource.py to append the path when hooks were later created. === Elgg === Elgg didn't change much with the migration; the Elgg setup was pretty straightforward. First thing we needed to do was checkout the latest Elgg tag from the admin projects source repository into the right directory: {{{ $ cd /var/www/beaversource.oregonstate.edu $ svn co https://code.oregonstate.edu/svn/admin/elgg/tags/20090531/ . }}} With Elgg checked out, we could then create the settings file. We did this by copying the example file into place. {{{ $ cp config-dist.php config.php }}} The configuration file Beaversource uses is significantly different than the standard file that ships with Elgg. An example has been included below. Elgg Configuration: {{{ wwwroot = "http://beaversource.oregonstate.edu/social/"; // **MUST** have a final slash at the end // Database configuration $CFG->dbtype = "postgres7"; $CFG->dbhost = "dogwood.osuosl.org"; $CFG->dbuser = "bsc_elgg"; $CFG->dbpass = ""; $CFG->dbname = "bsc_elgg"; $CFG->prefix = "elgg_"; $CFG->sysadminemail = "code-admin@lists.oregonstate.edu"; // Settings for initial administrator, only used at installation time $CFG->newsinitialusername = "news"; $CFG->newsinitialpassword = ""; $CFG->auth = 'sso'; $CFG->sso_user_create = true; $CFG->disable_passwordchanging = true; $CFG->mp_connectionstring = "host=dogwood.osuosl.org dbname=bsc_project_meta user=bsc_project_meta password="; ?> }}} A few notes on the Beaversource Elgg configuration: * We are using Postgres8, but the config still requires that we put 'postgres7' * The added config options are for both SSO and connecting to the project meta data(Django). These are '''VERY IMPORTANT'''. Apache Vhost: {{{ Alias /social /var/www/beaversource.oregonstate.edu Options SymLinksIfOwnerMatch AllowOverride All Order allow,deny deny from env=gb allow from all RedirectMatch ^/$ /social }}} === Trac === WSGI Script: {{{ import sys sys.stdout = sys.stderr import os os.environ['TRAC_ENV_PARENT_DIR'] = '/var/lib/trac/sites' os.environ['PYTHON_EGG_CACHE'] = '/var/lib/trac/egg-cache' import trac.web.main application = trac.web.main.dispatch_request import trac.db.postgres_backend trac.db.postgres_backend.PostgreSQLConnection.poolable = False }}} Apache Vhost: {{{ WSGIDaemonProcess trac processes=5 threads=20 maximum-requests=1500 WSGIScriptAlias /projects /var/lib/trac/apache/trac.wsgi #This will redirect people to the elgg project listing instead of one created by trac RedirectMatch ^/projects/?$ /social/mod/browser/index.php?display=projects WSGIProcessGroup trac WSGIApplicationGroup %{GLOBAL} Order deny,allow Allow from all }}} === Django === * Django sites are stored in /var/lib/django/ * This makes webmanagement stored at /var/lib/django/webmanagement * A symlink has been made from /data/django -> /var/lib/django * Django 1.0 is installed and managed by the OSL. With Django installed, we needed to checkout the webmanagement project from subversion. {{{ $ cd /data/django/webmanagement $ svn co https://code.oregonstate.edu/svn/admin/webmanagement/ . }}} With the project in place, it was important to put the settings file in place. {{{ $ cp settings.py.dist settings.py }}} You can edit this file with a text editor. Open settings.py and edit the pertinent information (Email addresses, DB info, file paths). I've included an example settings file that works below. One of the few differences that using WSGI causes effects the urls file. Since WSGI interprets the url we want to use(/request in this case) as the root mountpoint(/), its important to remove the 'request' from our urlconf. You can see this in the following diff: URL Diff: {{{ # Uncomment this for admin: - (r'^request/admin/(.*)', admin.site.root), - (r'request/', include('webmanagement.project_request.urls')), + (r'^admin/', admin.site.root), + (r'^', include('webmanagement.project_request.urls')), }}} SSO is the last component to check that will verify that the webmanagement Django project is working properly. When you checked out webmanagement from svn, you also pulled in the SSO middleware that was written to handle OregonState SSO auth. This should all work out of the box once you place trac.ini into /data/management. This should be completed when you get the Trac environment up and running. I've included the sections of the Apache config and the WSGI script we use for Django. Apache Vhost: {{{ Alias /media /var/lib/django/webmanagement/media WSGIDaemonProcess django processes=5 threads=20 WSGIProcessGroup django WSGIScriptAlias /request /var/lib/django/webmanagement/apache/django.wsgi Order deny,allow Allow from all Order deny,allow Allow from all }}} WSGI Script: {{{ import os, sys sys.path.append('/var/lib/django') os.environ['DJANGO_SETTINGS_MODULE'] = 'webmanagement.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler() #from webmanagement.settings import URL_PREFIX }}} Settings: {{{ # Django settings for webmanagement project. DEBUG = True TEMPLATE_DEBUG = DEBUG ADMINS = ( ('Code Admins', 'code-admins@lists.oregonstate.edu'), ) REQUEST_EMAIL = 'request@beaversource.oregonstate.edu' MANAGERS = ADMINS DATABASE_ENGINE = 'postgresql_psycopg2' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. DATABASE_NAME = 'bsc_project_meta' # Or path to database file if using sqlite3. DATABASE_USER = 'bsc_project_meta' # Not used with sqlite3. DATABASE_PASSWORD = '' # Not used with sqlite3. DATABASE_HOST = 'dogwood.osuosl.org' # Set to empty string for localhost. Not used with sqlite3. DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. # Local time zone for this installation. Choices can be found here: # http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE # although not all variations may be possible on all operating systems. # If running in a Windows environment this must be set to the same as your # system time zone. TIME_ZONE = 'America/Los_Angeles' # Language code for this installation. All choices can be found here: # http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes # http://blogs.law.harvard.edu/tech/stories/storyReader$15 LANGUAGE_CODE = 'en-us' SITE_ID = 1 # If you set this to False, Django will make some optimizations so as not # to load the internationalization machinery. USE_I18N = True # Absolute path to the directory that holds media. # Example: "/home/media/media.lawrence.com/" MEDIA_ROOT = '' # URL that handles the media served from MEDIA_ROOT. # Example: "http://media.lawrence.com" MEDIA_URL = '' # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". ADMIN_MEDIA_PREFIX = '/media/' # Make this unique, and don't share it with anybody. SECRET_KEY = '2m&0fn1qkswiukfya3mfdas34*1c*5r0-av&g1p+(ct+zfadsfdaslfihw9k!^fqke' # List of callables that know how to import templates from various sources. TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', # 'django.template.loaders.eggs.load_template_source', ) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.middleware.doc.XViewMiddleware', ) ROOT_URLCONF = 'webmanagement.urls' TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. '/data/django/webmanagement/templates' ) INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'webmanagement.project_request', 'django.contrib.admin' ) EMAIL_HOST = 'localhost' AUTHENTICATION_BACKENDS = ( 'webmanagement.SSOBackend.SSOBackend', # 'django.contrib.auth.backends.ModelBackend', ) LOGIN_URL = '/request/sso/login' SESSION_EXPIRE_AT_BROWSER_CLOSE = True SESSION_COOKIE_AGE = 3600 }}}