How to Fix “Module Not Found” Error When Configuring mod_wsgi with Apache on Ubuntu


1 views

The error occurs when running a2enmod because Ubuntu/Debian packages name the module differently than expected. Here's what's happening under the hood:

# The package installs these config files:
/etc/apache2/mods-available/wsgi.load
/etc/apache2/mods-available/wsgi.conf

Instead of using mod-wsgi or libapache2-mod-wsgi as the module name, use the correct syntax:

sudo a2enmod wsgi  # Note: just 'wsgi' without any prefixes
sudo systemctl restart apache2

To confirm the module is properly loaded:

apache2ctl -t -D DUMP_MODULES | grep wsgi
# Should output: wsgi_module (shared)

Here's a proper virtual host configuration for WSGI applications:

<VirtualHost *:80>
    ServerName yourdomain.com
    WSGIDaemonProcess myapp python-home=/path/to/venv
    WSGIScriptAlias / /var/www/myapp/wsgi.py
    
    <Directory /var/www/myapp>
        WSGIProcessGroup myapp
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

If your WSGI script still shows as plain text:

# 1. Check file permissions:
sudo chmod 755 /var/www/myapp/wsgi.py

# 2. Verify MIME types are configured:
AddType text/html .py .wsgi

# 3. Ensure Python headers are correct:
def application(environ, start_response):
    status = '200 OK'
    headers = [('Content-type', 'text/html; charset=utf-8')]
    start_response(status, headers)
    return [b"Hello World"]

For production environments, consider these optimizations:

# In your WSGI configuration:
WSGIDaemonProcess myapp \
    python-home=/path/to/venv \
    python-path=/path/to/app \
    processes=4 \
    threads=25 \
    display-name=myapp-process

# For better performance:
WSGISocketPrefix /var/run/apache2/wsgi

Remember to always test your configuration changes before restarting Apache:

sudo apache2ctl configtest
sudo systemctl restart apache2

When setting up MOD_WSGI on Ubuntu, many developers encounter the frustrating "module not found" error despite successful package installation. The root cause typically lies in Ubuntu's package naming conventions and Apache module loading mechanisms.

First, confirm the package is properly installed:

dpkg -l libapache2-mod-wsgi
dpkg -s libapache2-mod-wsgi

The critical mistake is using wrong module names. Ubuntu expects:

sudo a2enmod wsgi
sudo systemctl restart apache2

For your virtual host configuration, ensure proper WSGI handler setup:

<Directory /var/www/>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Require all granted
    
    AddHandler wsgi-script .wsgi
    WSGIScriptAlias / /var/www/test.wsgi
</Directory>

Here's a more robust test application with debugging:

def application(environ, start_response):
    # Debug output to check environment
    import pprint
    with open('/tmp/wsgi_debug.log', 'w') as f:
        pprint.pprint(environ, stream=f)
    
    status = '200 OK'
    headers = [
        ('Content-type', 'text/plain; charset=utf-8'),
        ('Cache-Control', 'no-store, no-cache, must-revalidate')
    ]
    start_response(status, headers)
    
    return [b'WSGI Test Successful!\n',
            b'Python Version: ' + environ['mod_wsgi.version'].encode('utf-8')]
  • Check Apache error logs: tail -f /var/log/apache2/error.log
  • Verify module symlinks exist in /etc/apache2/mods-enabled/
  • Test WSGI configuration: apache2ctl configtest
  • Ensure correct permissions on WSGI files

If package installation fails, consider compiling from source:

sudo apt install apache2-dev python-dev
wget https://github.com/GrahamDumpleton/mod_wsgi/archive/refs/tags/4.9.3.tar.gz
tar xvfz 4.9.3.tar.gz
cd mod_wsgi-4.9.3
./configure --with-python=/usr/bin/python3
make
sudo make install

For deployment environments, consider these optimizations:

WSGIDaemonProcess myapp python-home=/path/to/venv python-path=/path/to/app
WSGIProcessGroup myapp
WSGIScriptReloading On
WSGIPassAuthorization On