Version 1 (modified by pjkersha, 9 years ago) (diff)


Security / ndg_security / Apache2? / SUSE

Example Apache Configuration with SUSE

This page gives details for Apache configuration for NDG Security with SUSE and the standard SUSE Apache2 distribution. Details are given for 11.2 The standard SUSE Apache2 package can be used. There is no need to build from source. Directory structure and file names don't need to be followed explicitly. They are included for guidelines only.

Virtual Host

  1. Create directories for the virtual host. (<fqdn> = fully qualified domain name. Replace with appropriate name).
    $ mkdir /srv/www/vhosts/
    $ mkdir /srv/www/vhosts/<fqdn>/
    $ mkdir /srv/www/vhosts/<fqdn>/htdocs
    $ mkdir /srv/www/vhosts/<fqdn>/wsgi-scripts
    $ mkdir /srv/www/vhosts/<fqdn>/cgi-bin
  2. Set-up virtual host files in /etc/apache2/vhosts.d
    $ cp vhost.template ip-based_vhosts.conf      
    (ip-based_vhosts.conf actually generated from yast2).
    VirtualHost <fqdn>:80>                                                                                                         
     ServerAdmin <admin e-mail address>                                                                                              
     ServerName <fqdn>                                                                                                              
        # DocumentRoot: The directory out of which you will serve your
        # documents. By default, all requests are taken from this directory, but
        # symbolic links and aliases may be used to point to other locations.   
     DocumentRoot /srv/www/vhosts/<fqdn>/htdocs                             
        # if not specified, the global error log is used
     ErrorLog /var/log/apache2/<fqdn>-error_log     
     CustomLog /var/log/apache2/<fqdn>-access_log combined
        # don't loose time with IP address lookups
     HostnameLookups Off                          
        # needed for named virtual hosts
     UseCanonicalName Off               
        # configures the footer on server-generated documents
     ServerSignature On                                      
        # Optionally, include *.conf files from /etc/apache2/conf.d/
        # For example, to allow execution of PHP scripts:           
        # Include /etc/apache2/conf.d/php5.conf                     
        # or, to include all configuration snippets added by packages:
        # Include /etc/apache2/conf.d/*.conf                          
        # ScriptAlias: This controls which directories contain server scripts.
        # ScriptAliases are essentially the same as Aliases, except that      
        # documents in the realname directory are treated as applications and 
        # run by the server when requested rather than as documents sent to the client.
        # The same rules about trailing "/" apply to ScriptAlias directives as to      
        # Alias.                                                                       
     ScriptAlias /cgi-bin/ "/srv/www/vhosts/<fqdn>/cgi-bin/"                       
        # "/srv/www/cgi-bin" should be changed to whatever your ScriptAliased
        # CGI directory exists, if you have one, and where ScriptAlias points to.
     <Directory "/srv/www/vhosts/<fqdn>/cgi-bin">
      AllowOverride None                             
      Options +ExecCGI -Includes                     
      Order allow,deny                               
      Allow from all                                 
        # UserDir: The name of the directory that is appended onto a user's home
        # directory if a ~user request is received.                             
        # To disable it, simply remove userdir from the list of modules in APACHE_MODULES
        # in /etc/sysconfig/apache2.                                                     
     <IfModule mod_userdir.c>
            # Note that the name of the user directory ("public_html") cannot simply be
            # changed here, since it is a compile time setting. The apache package     
            # would have to be rebuilt. You could work around by deleting              
            # /usr/sbin/suexec, but then all scripts from the directories would be     
            # executed with the UID of the webserver.                                  
    UserDir public_html                                                                
            # The actual configuration of the directory is in                          
            # /etc/apache2/mod_userdir.conf.                                           
    Include /etc/apache2/mod_userdir.conf                                              
        # Applications running under mod_wsgi - these are to be protected by NDG Security filters
     <Directory /srv/www/vhosts/<fqdn>/wsgi-scripts>
     Order allow,deny                                   
     Allow from all                                     
    Include /etc/apache2/services/services.conf
        # This should be changed to whatever you set DocumentRoot to.
     <Directory "/srv/www/vhosts/<fqdn>/htdocs">
            # Possible values for the Options directive are "None", "All",
            # or any combination of:                                      
            #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
            # Note that "MultiViews" must be named *explicitly* --- "Options All"
            # doesn't give it to you.
            # The Options directive is both complicated and important.  Please see
            # for more information.
    Options Indexes FollowSymLinks
            # AllowOverride controls what directives may be placed in .htaccess files.
            # It can be "All", "None", or any combination of the keywords:
            #   Options FileInfo AuthConfig Limit
    AllowOverride None
            # Controls who can get stuff from this server.
    Order allow,deny
      Allow from all
    • A virtual host has been set up for <fqdn>.
    • The virtual host has its own directory structure for scripts and static content /srv/www/vhosts/<fqdn>
    • A Directory directive has been set up for WSGI scripts.
    • WSGI scripts themselves are declared in the file /etc/apache2/services/services.conf included within the virtual host.
  3. Create the services file:
    $ cat > /etc/apache2/services/services.conf
    # WSGI services
    WSGIDaemonProcess my-services processes=2 threads=15 display-name=%{GROUP}
    WSGIProcessGroup my-services
    WSGIScriptAlias /myapp1 "/srv/www/vhosts/<fqdn>/wsgi-scripts/myapp1.wsgi"
    WSGIProcessGroup my-services
    WSGIScriptAlias /myapp2 "/srv/www/vhosts/<fqdn>/wsgi-scripts/myapp2.wsgi"


  1. Enable SSL (Ref:
    $ a2enmod ssl
    $ a2enflag SSL
  2. Copy the SSL certificate and key into the correct locations. (The default is: /etc/apache2/ssl.crt and /etc/apache2/ssl.key directories for the certificate and private key files respectively). Set 600 permissions on the private key. Avoid keeping duplicate copies of the key on the file system.
  1. Copy from the template:
    $ cp vhost-ssl.template vhost-ssl.conf
    This can be done from yast2 but it will remove any existing conf files you have placed there(!).
  2. Set the virtual host IP, DocumentRoot, ServerName, ServerAdmin, log paths:
            #  General setup for the virtual host
            DocumentRoot "/srv/www/vhosts/<fqdn>/htdocs"
            ServerName <fqdn>:443
            ServerAdmin <admin e-mail address>
            ErrorLog /var/log/apache2/<fqdn>-ssl_error_log
            TransferLog /var/log/apache2/<fqdn>-ssl_access_log
  3. Make a Directory directive for the WSGI scripts for this virtual host:
            # SSL Services including NDG Security
            <Directory /srv/www/vhosts/<fqdn>/wsgi-scripts>
                # Special settings enable NDG Security middleware to apply client
                # authentication where necessary
                SSLVerifyClient optional_no_ca
                SSLVerifyDepth  10
                SSLOptions +StdEnvVars +ExportCertData
                Order allow,deny
                Allow from all
            Include /etc/apache2/services/ssl_services.conf
  4. Ensure the SSLCertificateFile and SSLCertificateKeyFile directives are set correctly for the respective certificate and private key file paths.
  5. Create the SSL services file:
    $ cat > /etc/apache2/services/ssl_services.conf
    # Configuration of SSL Services
    # NDG Security Applications
    WSGIDaemonProcess ndg-security processes=2 threads=15 display-name=%{GROUP}
    WSGIProcessGroup ndg-security
    WSGIScriptAlias / "/srv/www/vhosts/<fqdn>/wsgi-scripts/ndgsecurity.wsgi"

Troubleshooting SSL

  1. Start up fails with:
    $ /etc/init.d/apache2 start
    Starting httpd2 (prefork) (98)Address already in use: make_sock: could not bind to address [::]:443
    Check for duplicate Listen 443 directives in /etc/apache2/listen.conf and/or other conf files. Remove duplicates and retry. To check to see if there really is another service using that port:
    $ netstat -pan |grep ":443"
  2. yast2 has an interface to make Apache settings including virtual hosts and SSL but this can delete existing custom config files created.


  1. Shared library not found:
    $ /usr/local/bin/python
    /usr/local/bin/python: error while loading shared libraries: cannot open shared object file: No such file or directory
  2. Run ldconfig to update the shared library paths:
    $ ldconfig
    Rerun Python to make sure the changes have taken effect.

Module build and installation

  1. Download and unpack the latest (verison 3.1 as of 01/03/2010) source:
    $ wget
    $ tar zxvf mod_wsgi-3.1.tar.gz
  2. Configure and build making sure to link against the Apache installation just completed. If building against Apache built from source use, /usr/local/apache2/bin/apxs (SUSE 10.3), if using Apache SUSE built package (SUSE 11.2) use, /usr/sbin/apxs-prefork:
    $ cd mod_wsgi-3.1
    $ ./configure --with-apxs=/usr/local/apache2/bin/apxs
    $ make
    $ sudo make install
    $ make clean
    Note the configure call defaults to the current python executable in the PATH. In this case /usr/bin/python:
    $ /usr/bin/python -V
    Python 2.5.1


  1. mpm.h not found with SUSE build:
    /usr/include/apache2/mpm_common.h:46:17: error: mpm.h: No such file or directory 
    Make sure to use apxs-prefork or apxs-worker:
    $ ./configure --with-apxs=/usr/sbin/apxs2-prefork --with-python=/usr/local/bin/python
  2. Apache can't find 64 bit Python shared object. make fails with this or something similar:
    /usr/lib64/apr-1/build/libtool --silent --mode=link gcc -o  -rpath /usr/lib64/apache2-prefork -module -avoid-version    mod_wsgi.lo -L/usr/local/lib -L/usr/local/lib/python2.5/config -lpython2.5 -lpthread -ldl -lutil -lm                                       
    /usr/lib64/gcc/x86_64-suse-linux/4.4/../../../../x86_64-suse-linux/bin/ld: /usr/local/lib/python2.5/config/libpython2.5.a(abstract.o): relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC                       
    /usr/local/lib/python2.5/config/libpython2.5.a: could not read symbols: Bad value
    Rebuild Python with shared object option:
    $ ./configure --enable-shared


  1. Add the WSGI module to the configuration. This varies with different distributions. with SUSE, the a2enmod script can be used:
    $ a2enmod wsgi
  2. Ensure Python 2.5 library paths are picked up. Although mod_wsgi has been built against Python 2.5 it may still be necessary to force it to pick up the Python 2.5 library paths. The WSGIPythonHome directive sets the Python prefix to enable this to be enforced. This should be placed outside a VirtualHost entry e.g. in /etc/apache/httpd.conf:
    WSGIPythonHome /usr/local
  3. Set Directory directive for WSGI scripts directory in the <fqdn> virtual host section in /etc/apache2/vhosts.d/ip-based_vhosts.conf:
    # Public area for placing WSGI scripts to be exposed outside
    <Directory /srv/www/vhosts/<fqdn>/wsgi-scripts>
        Order allow,deny
        Allow from all
  4. Run mod_wsgi in Daemon mode to enable separate processes and threads:
        WSGIDaemonProcess my-services processes=2 threads=15 display-name=%{GROUP}
        WSGIProcessGroup my-services
        # Test WSGI App
        WSGIScriptAlias /hello /srv/www/vhosts/<fqdn>/wsgi-scripts/test.wsgi
  5. Make a WSGI scripts directory as referred to in the above:
    $ mkdir /srv/www/vhosts/<fqdn>/wsgi-scripts
  6. Make a test application to try it all out:
    $ cat > /srv/www/vhosts/<fqdn>/wsgi-scripts/test.wsgi
    def application(environ, start_response):
        import sys
        print >>sys.stderr, "Python sys.prefix=%s" % sys.prefix
        status = '200 OK'
        output = 'Hello World!'
        response_headers = [('Content-type', 'text/plain'),
                            ('Content-Length', str(len(output)))]
        start_response(status, response_headers)
        return [output]
    Nb. the print statement enables checking in the system log that the WSGIPythonHome setting has worked and that the value really is /usr/local. IF not the application will load the WRONG Python libraries.
  7. Set execute permissions:
    $ chmod 755 /srv/www/vhosts/<fqdn>/wsgi-scripts/test.wsgi
  8. Restart Apache
    $ /etc/init.d/apache2 restart
  9. Try out the script in a browser typing in the URL:  http://<fqdn>/hello. Hello World! should be output on the browser page.
  10. Remove the entry from the conf file and restart Apache once testing is complete.

Services Configuration

Separate service configuration files provide a convenient means to manage the services being deployed.

  1. Create a separate user account for running services:
    $ groupadd wsgi-apache
    $ useradd -c "mod_wsgi user" -g wsgi-apache wsgi-apache
  2. Create service configuration.
    $ mkdir /etc/apache/services
    $ cat > /etc/apache/services/services.conf
    # Applications to be protected by NDG Security
    WSGIDaemonProcess my-services processes=2 threads=15 display-name=%{GROUP} python-eggs=/srv/www/vhosts/<fqdn>/wsgi-scripts/.python-eggs user=wsgi-a
    pache group=wsgi-apache
    WSGIProcessGroup my-services
    WSGIScriptAlias /myapp1 "/srv/www/vhosts/<fqdn>/wsgi-scripts/myapp1.wsgi"
    WSGIProcessGroup my-services
    WSGIScriptAlias /myapp2 "/srv/www/vhosts/<fqdn>/wsgi-scripts/myapp2.wsgi"
    Nb. each service will need the necessary script set up and configuration. Configuration files will need to be readable by the wsgi-apache user.
  3. Add to /etc/apache2/vhosts.d/ip-based_vhosts.conf:
    Include /etc/apache2/services/services.conf