mod_wsgi on os x
sunday, march 1st, 2009 5:20am
[This installation was so easy it may not seem worth the notes and output below. But over the years I've found it surprisingly useful to be able to refer back to notes such as this, and helpful to read others' detailed installation reports.]
On this page...
Goal & motivation
I'll be developing more and more web-apps that call services, and unless I call them all via ajax -- which might actually be a good idea -- I'll bump into the development server's single-threaded limitation. And even if I do call the services via ajax I'll likely run into problems if I'm calling more than one service simultaneously -- although the ability of an ajax call to fail gracefully via a timeout and try its resource again would be a cool thing to learn how to implement.
Thinking about this off and on for the last few months, I recently came across a posting by the god of apache-python integration, Graham Dumpleton, about using mod_wsgi for development. This, on top of a slow solaris installation using mod_python (the slowness probably has more to do with the box than mod_python) give me the impetus to delve into this.
Finally, gsf's encouragement to check out mod_wsgi at code4lib 2009 made me bite the bullet.
Sources of info
Starting setup
python version 2.5.1, via:
birkinbox:~ birkin$ birkinbox:~ birkin$ python Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>>apache version 2.2.9, via phpinfo():
apache2handler Apache Version Apache/2.2.9 (Unix) mod_ssl/2.2.9 OpenSSL/0.9.7l DAV/2 PHP/5.2.6 Apache API Version 20051115 Server Administrator you@example.com Hostname:Port ::1:0 User/Group www(70)/70 Max Requests Per Child: 0 - Keep Alive: on - Max Per Connection: 100 Timeouts Connection: 300 - Keep-Alive: 5 Virtual Server No Server Root /usr Loaded Modules core prefork http_core mod_so mod_authn_file mod_authn_dbm mod_authn_anon mod_authn_dbd mod_authn_default mod_authz_host mod_authz_groupfile mod_authz_user mod_authz_dbm mod_authz_owner mod_authz_default mod_auth_basic mod_auth_digest mod_cache mod_disk_cache mod_mem_cache mod_dbd mod_dumpio mod_ext_filter mod_include mod_filter mod_deflate mod_log_config mod_log_forensic mod_logio mod_env mod_mime_magic mod_cern_meta mod_expires mod_headers mod_ident mod_usertrack mod_setenvif mod_version mod_proxy mod_proxy_connect mod_proxy_ftp mod_proxy_http mod_proxy_ajp mod_proxy_balancer mod_ssl mod_mime mod_dav mod_status mod_autoindex mod_asis mod_info mod_cgi mod_dav_fs mod_vhost_alias mod_negotiation mod_dir mod_imagemap mod_actions mod_speling mod_userdir mod_alias mod_rewrite mod_bonjour2 mod_php5Requirement: Docs say "The GNU C compiler from the MacOS X Developer Toolkit bundle is required." -- I should be fine; developer stuff is installed.
Plan
- Follow Quick installation guide, 'cause I've been living a good life recently.
Install
Got source code from the specified download page.
Selected single version listed (2.3)
Unstuff
birkinbox:~ birkin$ birkinbox:~ birkin$ mv /Users/birkin/Downloads/mod_wsgi-2.3.tar.gz /Developer_3rd/mod_wsgi-2.3.tar.gz birkinbox:~ birkin$ birkinbox:~ birkin$ cd /Developer_3rd/ birkinbox:Developer_3rd birkin$ birkinbox:Developer_3rd birkin$ /usr/bin/tar xvfz ./mod_wsgi-2.3.tar.gz mod_wsgi-2.3/ mod_wsgi-2.3/configure mod_wsgi-2.3/configure.ac mod_wsgi-2.3/LICENCE mod_wsgi-2.3/Makefile-1.X.in mod_wsgi-2.3/Makefile-2.X.in mod_wsgi-2.3/mod_wsgi.c mod_wsgi-2.3/README birkinbox:Developer_3rd birkin$Configure
birkinbox:Developer_3rd birkin$ birkinbox:Developer_3rd birkin$ cd ./mod_wsgi-2.3/ birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ ls -alF total 952 drwxr-xr-x@ 9 birkin admin 306 Aug 23 2008 ./ drwxr-xr-x 20 birkin admin 680 Mar 2 08:16 ../ -rw-r--r--@ 1 birkin admin 11358 Jun 23 2007 LICENCE -rw-r--r--@ 1 birkin admin 1195 Dec 13 2007 Makefile-1.X.in -rw-r--r--@ 1 birkin admin 1247 Dec 13 2007 Makefile-2.X.in -rw-r--r--@ 1 birkin admin 16440 Mar 13 2008 README -rwxr-xr-x@ 1 birkin admin 78314 Dec 21 2007 configure* -rw-r--r--@ 1 birkin admin 4151 Jan 24 2008 configure.ac -rw-r--r--@ 1 birkin admin 352904 Aug 23 2008 mod_wsgi.c birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ ./configure checking for apxs2... no checking for apxs... /usr/sbin/apxs checking Apache version... 2.2.9 checking for python... /usr/bin/python configure: creating ./config.status config.status: creating Makefile birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ ls -alF total 1032 drwxr-xr-x@ 13 birkin admin 442 Mar 2 10:38 ./ drwxr-xr-x 20 birkin admin 680 Mar 2 08:16 ../ -rw-r--r--@ 1 birkin admin 11358 Jun 23 2007 LICENCE -rw-r--r-- 1 birkin admin 1559 Mar 2 10:38 Makefile -rw-r--r--@ 1 birkin admin 1195 Dec 13 2007 Makefile-1.X.in -rw-r--r--@ 1 birkin admin 1247 Dec 13 2007 Makefile-2.X.in lrwxr-xr-x 1 birkin admin 15 Mar 2 10:38 Makefile.in@ -> Makefile-2.X.in -rw-r--r--@ 1 birkin admin 16440 Mar 13 2008 README -rw-r--r-- 1 birkin admin 4474 Mar 2 10:38 config.log -rwxr-xr-x 1 birkin admin 20621 Mar 2 10:38 config.status* -rwxr-xr-x@ 1 birkin admin 78314 Dec 21 2007 configure* -rw-r--r--@ 1 birkin admin 4151 Jan 24 2008 configure.ac -rw-r--r--@ 1 birkin admin 352904 Aug 23 2008 mod_wsgi.c birkinbox:mod_wsgi-2.3 birkin$So far so good.
Build
birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ make /usr/sbin/apxs -c -I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5 -DNDEBUG -DMACOSX -DENABLE_DTRACE -Wc,'-arch ppc7400' -Wc,'-arch ppc64' -Wc,'-arch i386' -Wc,'-arch x86_64' mod_wsgi.c -arch ppc7400 -arch ppc64 -arch i386 -arch x86_64 -Wl,-F/System/Library/Frameworks -framework Python -u _PyMac_Error -framework Python -ldl /usr/share/apr-1/build-1/libtool --silent --mode=compile gcc -DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp -I/usr/include/apache2 -I/usr/include/apr-1 -I/usr/include/apr-1 -arch ppc7400 -arch ppc64 -arch i386 -arch x86_64 -I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5 -DNDEBUG -DMACOSX -DENABLE_DTRACE -c -o mod_wsgi.lo mod_wsgi.c && touch mod_wsgi.slo /usr/share/apr-1/build-1/libtool --silent --mode=link gcc -o mod_wsgi.la -rpath /usr/libexec/apache2 -module -avoid-version mod_wsgi.lo -arch ppc7400 -arch ppc64 -arch i386 -arch x86_64 -Wl,-F/System/Library/Frameworks -framework Python -u _PyMac_Error -framework Python -ldl birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ ls -alF total 2648 drwxr-xr-x@ 18 birkin admin 612 Mar 2 11:26 ./ drwxr-xr-x 20 birkin admin 680 Mar 2 08:16 ../ drwxr-xr-x 7 birkin admin 238 Mar 2 11:26 .libs/ -rw-r--r--@ 1 birkin admin 11358 Jun 23 2007 LICENCE -rw-r--r-- 1 birkin admin 1559 Mar 2 11:26 Makefile -rw-r--r--@ 1 birkin admin 1195 Dec 13 2007 Makefile-1.X.in -rw-r--r--@ 1 birkin admin 1247 Dec 13 2007 Makefile-2.X.in lrwxr-xr-x 1 birkin admin 15 Mar 2 11:26 Makefile.in@ -> Makefile-2.X.in -rw-r--r--@ 1 birkin admin 16440 Mar 13 2008 README -rw-r--r-- 1 birkin admin 4474 Mar 2 11:26 config.log -rwxr-xr-x 1 birkin admin 20621 Mar 2 11:26 config.status* -rwxr-xr-x@ 1 birkin admin 78314 Dec 21 2007 configure* -rw-r--r--@ 1 birkin admin 4151 Jan 24 2008 configure.ac -rw-r--r--@ 1 birkin admin 352904 Aug 23 2008 mod_wsgi.c -rw-r--r-- 1 birkin admin 800 Mar 2 11:26 mod_wsgi.la -rw-r--r-- 1 birkin admin 315 Mar 2 11:26 mod_wsgi.lo -rw-r--r-- 1 birkin admin 817180 Mar 2 11:26 mod_wsgi.o -rw-r--r-- 1 birkin admin 0 Mar 2 11:26 mod_wsgi.slo birkinbox:mod_wsgi-2.3 birkin$Smooth! Confirm that mod_wsgi.so file exists (the point of the build):
birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ ls -alF ./.libs/ total 4432 drwxr-xr-x 7 birkin admin 238 Mar 2 11:26 ./ drwxr-xr-x@ 18 birkin admin 612 Mar 2 11:26 ../ -rw-r--r-- 1 birkin admin 803768 Mar 2 11:26 mod_wsgi.a lrwxr-xr-x 1 birkin admin 14 Mar 2 11:26 mod_wsgi.la@ -> ../mod_wsgi.la -rw-r--r-- 1 birkin admin 801 Mar 2 11:26 mod_wsgi.lai -rw-r--r-- 1 birkin admin 817100 Mar 2 11:26 mod_wsgi.o -rwxr-xr-x 1 birkin admin 633872 Mar 2 11:26 mod_wsgi.so* birkinbox:mod_wsgi-2.3 birkin$Looks good.
Install
birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ sudo make install Password: /usr/sbin/apxs -i -S LIBEXECDIR=/usr/libexec/apache2 -n 'mod_wsgi' mod_wsgi.la /usr/share/httpd/build/instdso.sh SH_LIBTOOL='/usr/share/apr-1/build-1/libtool' mod_wsgi.la /usr/libexec/apache2 /usr/share/apr-1/build-1/libtool --mode=install cp mod_wsgi.la /usr/libexec/apache2/ cp .libs/mod_wsgi.so /usr/libexec/apache2/mod_wsgi.so cp .libs/mod_wsgi.lai /usr/libexec/apache2/mod_wsgi.la cp .libs/mod_wsgi.a /usr/libexec/apache2/mod_wsgi.a ranlib /usr/libexec/apache2/mod_wsgi.a chmod 644 /usr/libexec/apache2/mod_wsgi.a ---------------------------------------------------------------------- Libraries have been installed in: /usr/libexec/apache2 If you ever happen to want to link against installed libraries in a given directory, LIBDIR, you must either use libtool, and specify the full pathname of the library, or use the `-LLIBDIR' flag during linking and do at least one of the following: - add LIBDIR to the `DYLD_LIBRARY_PATH' environment variable during execution See any operating system documentation about shared libraries for more information, such as the ld(1) and ld.so(8) manual pages. ---------------------------------------------------------------------- chmod 755 /usr/libexec/apache2/mod_wsgi.so birkinbox:mod_wsgi-2.3 birkin$Confirm the mod_wsgi.so file has been installed in '/usr/libexec/apache2', as specified in this line of my Makefile:
LIBEXECDIR = /usr/libexec/apache2 birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ ls -alF /usr/libexec/apache2 total 81488 drwxr-xr-x 72 root wheel 2448 Mar 2 11:35 ./ drwxr-xr-x 93 root wheel 3162 Feb 12 16:44 ../ (...) -rwxr-xr-x 1 root wheel 633872 Mar 2 11:35 mod_wsgi.so* birkinbox:mod_wsgi-2.3 birkin$Nice, there it is at the bottom.
Load module into apache
I can never remember exactly where the httpd.conf file is.
birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ locate 'httpd.conf' (...) /private/etc/apache2/httpd.conf (...) birkinbox:mod_wsgi-2.3 birkin$First a backup:
birkinbox:apache2 birkin$ sudo cp ./httpd.conf ./2009-03-02_httpd.confAdded to the LoadModule section:
# Added 2009-03-02 LoadModule wsgi_module libexec/apache2/mod_wsgi.soRestart
birkinbox:apache2 birkin$ sudo apachectl restartClean up
birkinbox:apache2 birkin$ birkinbox:apache2 birkin$ cd /Developer_3rd/mod_wsgi-2.3 birkinbox:mod_wsgi-2.3 birkin$ birkinbox:mod_wsgi-2.3 birkin$ make clean rm -rf .libs rm -f mod_wsgi.o mod_wsgi.la mod_wsgi.lo mod_wsgi.slo mod_wsgi.loT rm -f config.log config.status rm -rf autom4te.cache birkinbox:mod_wsgi-2.3 birkin$
Configure & test
Reference: 'Configuring An Application'. Docs recommend following this to verify that mod_wsgi is actually working properly.
Note: phpinfo() does indicate the module is loaded.
Note: docs state to follow these QuickConfiguration instructions before delving into the more thorough configuration docs.
Test app function & directories
Created, per instructions, test function in a file and enclosing directory:
birkinbox:repository birkin$ birkinbox:repository birkin$ cd /Users/birkin/Documents/Brown_Library/ModWsgiTest birkinbox:ModWsgiTest birkin$ birkinbox:ModWsgiTest birkin$ ls -alF total 8 drwxr-xr-x 3 birkin staff 102 Mar 2 15:54 ./ drwxr-xr-x 87 birkin staff 2958 Mar 2 15:54 ../ -rw-r--r--@ 1 birkin staff 277 Mar 2 15:43 mod_wsgi_test.wsgi birkinbox:ModWsgiTest birkin$ birkinbox:ModWsgiTest birkin$ cat ./mod_wsgi_test.wsgi def application(environ, start_response): status = '200 OK' output = 'Hello World!' response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))] start_response(status, response_headers) return [output] birkinbox:ModWsgiTest birkin$httpd.conf file changes
The docs give some sample configuration:
<VirtualHost *:80> ServerName www.example.com ServerAlias example.com ServerAdmin webmaster@example.com DocumentRoot /usr/local/www/documents <Directory /usr/local/www/documents> Order allow,deny Allow from all </Directory> WSGIScriptAlias /myapp /usr/local/www/wsgi-scripts/myapp.wsgi <Directory /usr/local/www/wsgi-scripts> Order allow,deny Allow from all </Directory> </VirtualHost>My try will be:
<VirtualHost *:80> ServerName 127.0.0.1 ServerAlias 127.0.0.1 ServerAdmin birkin_diana@brown.edu DocumentRoot /Users/birkin/Sites <Directory /Users/birkin/Sites> Order allow,deny Allow from all </Directory> WSGIScriptAlias /myapp /Users/birkin/Documents/Brown_Library/ModWsgiTest/mod_wsgi_test.wsgi <Directory /Users/birkin/Documents/Brown_Library/ModWsgiTest> Order allow,deny Allow from all </Directory> </VirtualHost>Backup
birkinbox:~ birkin$ sudo cp /private/etc/apache2/httpd.conf /private/etc/apache2/2009-03-02b_httpd.confMake change and restart
birkinbox:~ birkin$ birkinbox:~ birkin$ sudo apachectl restart Password: birkinbox:~ birkin$Well, no errors on restart.
Plain old 127.0.0.1 still yields the usual default page, which is good.
Trying 'myapp'...
birkinbox:~ birkin$ python Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> >>> import urllib >>> >>> urllib.urlopen( 'http://127.0.0.1/myapp/' ).read() '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">\n<html><head>\n<title>403 Forbidden</title>\n</head><body>\n<h1>Forbidden</h1>\n<p>You don\'t have permission to access /myapp/\non this server.</p>\n</body></html>\n' >>>Ok... no permission, but it seems to recognize it as a valid web-address at least -- that's a start!
Got it; problem is permissions on an enclosing folder...
drwx------@ 81 birkin staff 2754 Feb 4 16:03 Documents/Test app function & directories #2
Follow instructions this time and create a fully-accessible directory:
birkinbox:~ birkin$ birkinbox:~ birkin$ mv /Users/birkin/Documents/Brown_Library/ModWsgiTest /Users/birkin/ModWsgiTest birkinbox:~ birkin$ birkinbox:~ birkin$ ls -alF /Users/birkin/ total 1472 (...) drwxr-xr-x 3 birkin staff 102 Mar 2 17:03 ModWsgiTest/ (...) birkinbox:~ birkin$Backup httpd.conf:
birkinbox:~ birkin$ birkinbox:~ birkin$ ls -alF /private/etc/apache2/ total 256 (...) -rw-r--r-- 1 root wheel 17614 Mar 1 2008 2008-03-02_httpd.conf -rw-r--r-- 1 root wheel 17613 Mar 2 11:55 2009-03-02_httpd.conf -rw-r--r-- 1 root wheel 17685 Mar 2 16:59 2009-03-02b_httpd.conf (...) -rw-r--r-- 1 root wheel 18156 Mar 2 17:08 httpd.conf (...) birkinbox:~ birkin$ birkinbox:~ birkin$ sudo cp /private/etc/apache2/httpd.conf /private/etc/apache2/2009-03-02c_httpd.conf Password: birkinbox:~ birkin$ birkinbox:~ birkin$ ls -alF /private/etc/apache2/ total 296 (...) -rw-r--r-- 1 root wheel 17614 Mar 1 2008 2008-03-02_httpd.conf -rw-r--r-- 1 root wheel 17613 Mar 2 11:55 2009-03-02_httpd.conf -rw-r--r-- 1 root wheel 17685 Mar 2 16:59 2009-03-02b_httpd.conf -rw-r--r-- 1 root wheel 18156 Mar 2 18:40 2009-03-02c_httpd.conf (...) -rw-r--r-- 1 root wheel 18156 Mar 2 17:08 httpd.conf (...) birkinbox:~ birkin$Change httpd.conf; section now is:
<VirtualHost *:80> ServerName 127.0.0.1 ServerAlias 127.0.0.1 ServerAdmin birkin_diana@brown.edu DocumentRoot /Users/birkin/Sites <Directory /Users/birkin/Sites> Order allow,deny Allow from all </Directory> WSGIScriptAlias /myapp /Users/birkin/ModWsgiTest/mod_wsgi_test.wsgi <Directory /Users/birkin/ModWsgiTest> Order allow,deny Allow from all </Directory> </VirtualHost>Restart & test
birkinbox:~ birkin$ birkinbox:~ birkin$ sudo apachectl restart birkinbox:~ birkin$ birkinbox:~ birkin$ python Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> >>> import urllib >>> >>> urllib.urlopen( 'http://127.0.0.1/myapp/' ).read() 'Hello World!' >>>Success!!!