WSGI Anwendungen¶
Es wird eine Konfiguration eingerichtet, über welche es möglich ist WSGI (Python) Anwendungen zu betreiben. Eine kleines HelloWorld Beispiel wird ebenfalls mit installiert.
Installation¶
$ ${SCRIPT_FOLDER}/apache_setup.sh installWSGI
Mit dem Kommando installWSGI
werden die folgenden Schritte ausgeführt.
Es wird Apache mod_wsgi installiert (mod_wsgi RTD)
Es wird der Ordner
/var/www/pyApps
eingerichtet, in dem Python WSGI Anwendungen abgelegt werden können.
$ apt-get install libapache2-mod-wsgi-py3 python-imaging virtualenv
$ cd /etc/apache2/mods-available/
$ sudo -H mv wsgi.conf wsgi.conf-disabled
$ sudo -H mkdir /var/www/pyApps
Es wird eine virtuelle Python Umgebung (
pyenv
) in dem Ordner/var/www/pyApps
eingerichtet.In die virtuelle Python Umgebung werden (via pip) verschiedene Python Module vorinstalliert (sollte nicht ohne weiteres ins Internet gestellt werden).
$ cd /var/www/pyApps
$ sudo -H virtualenv "pyenv" --prompt="pyenv"
$ cd /var/www/pyApps/pyenv
$ source bin/activate
$ pip completion --bash | sudo -H tee /etc/bash_completion.d/pip > /dev/null
$ pip install docutils Jinja2 Pygments Sphinx Flask Werkzeug pylint \
pyratemp pyudev psutil sqlalchemy babel simplejson
$ sudo -H a2ensite py-apps
$ sudo -H service apache2 reload
Es wird eine Test-Seite ( https://localhost/hello.py ) eingrichtet.
$ sudo -H ap2ensite hello_py
$ sudo -H service apache2 reload
De-Installation¶
$ ${SCRIPT_FOLDER}/apache_setup.sh deinstallWSGI
Anmerkungen¶
Das WSGI-Modul war mal ein Projekt auf google-code, ein paar Sachen kann man immernoch dort nachlesen z.B.
Simplified GIL State: https://code.google.com/p/modwsgi/wiki/ApplicationIssues#Python_Simplified_GIL_State_API
Inzwischen wird das WSGI-Modul auf github gehostet und weiterentwickelt. In dem Github Projekt wird auch vieles aufgeräumt:
Eine aktuelle Doku gibt es bei Read The Docs mod_wsgi RTD
Das Reposetory bei github ist Apache mod_wsgi
Hardening Aspekte ????
py-apps.conf¶
Die folgende py-apps.conf
Site, richtet eine Umgebung ein, in der
WSGI-Anwendungen betrieben werden können. Die Python-Prozesse laufen in einer
virtuellen-Python Umgebung, die über die Direktive WSGIPythonHome
gesetzt
wird. Es wird mit der Direktive WSGIDaemonProcess
die Prozessgruppe
pyApps
eingerichtet. Die WSGI....
Direktieven sind in der mod_wsgi RTD
Konfiguration beschrieben.
<IfModule mod_wsgi.c>
# Die Prozesse laufen in einer VirtualEnv Umgebung
WSGIPythonHome /var/www/pyApps/pyenv
# Die Prozessgruppe pyApps für diese Python-Anwendungen
WSGIDaemonProcess pyApps \
user=www-data group=nogroup \
processes=2 threads=5 maximum-requests=5
...
In der Konfiguration wird eine Prozessgruppe pyApps
eingerichtet, deren
Prozesse unter dem Apache-Account www-data
(und nogroup
) laufen. Diese
Prozessgruppe pyApps
wird nun in der Resource /var/www/pyApps
genutzt.
...
<Directory /var/www/pyApps>
WSGIProcessGroup pyApps
WSGIApplicationGroup %{GLOBAL}
</Directory>
</IfModule>
Zu tun
Da ich nicht davon ausgehen kann, dass alle Python Module die eine WSGI
Anwendungen nutzt auch Thread-safty sind setze ich meine WSGI Anwendungen
immer in die WSGIApplicationGroup %{GLOBAL}
. Nähers zu dem Thema gibt
der Beitrag Python Simplified GIL State API. Ich bin allerdings auch
immer etwas verunsichert, weil mir nicht ganz klar ist, wie die Anordnung der
Prozesse und Threads bei %{GLOBAL}
nun genau ist (hängt vermutlich auch
von anderen Faktoren ab?) und ob es Sinn macht bei %{GLOBAL}
mehr als
einen Thread zu definieren.
WSGI-Test Anwendung¶
Die Test-Site sollte nur in einer Entwickler-Umgebung installiert werden. Sie
besteht aus nur einer Datei /var/www/pyApps/helloWorld/index.wsgi
.
import os, sys, urlparse, traceback, pprint, urlparse, pwd
def application(environ, start_response):
status = '200 OK'
o = 'WSGI: It works! :-)'
try:
o += '\nprocess id: ' + str(os.getpid())
o += '\nparent process: ' + str(os.getppid())
o += '\nuser/group: ' + "%s/%s (%s/%s)" % (os.getuid(), os.getgid(), os.geteuid(), os.getegid())
o += '\npwd user: ' + pprint.pformat(pwd.getpwuid(os.getuid()))
...o += '\nWSGI environment:\n' + pprint.pformat(environ, indent=4)
o += '\nQuery String:\n' + pprint.pformat(urlparse.parse_qs(environ['QUERY_STRING']), indent=4)
...o += '\nPython version: ' + pprint.pformat(sys.version)
...
except:
o += "\n\n" + traceback.format_exc()
response_headers = [
( 'Content-type', 'text/plain')
, ( 'Content-Length', str(len(o)))
]
start_response(status, response_headers)
return [o]
Die Installation erfolgte in den /var/www/pyApps
Ordner. Für den bereits
oben in der py-apps.conf
die virtuelle Python Umgebung WSGIPythonHome
/var/www/pyApps/pyenv
und die WSGIDaemonProcess pyApps
definiert
wurden. Die hello_py
Site definiert nur noch den Alias, damit die Site unter
der URL https://localhost/hello.py angeboten wird.
<IfModule mod_wsgi.c>
WSGIScriptAlias /hello.py /var/www/pyApps/helloWorld/index.wsgi
</IfModule>