skip to Main Content

What am I missing? This is my first time trying to use Django. The server that is built into Django will serve the file locally just fine, but I can’t get Apache to do the same. The following is what I’m doing from a brand new, clean, Linux 2 instance.

sudo yum update
sudo yum install -y python3
sudo yum install httpd-devel
sudo yum install -y mod_wsgi
cd /etc/httpd/modules     (verify that mod_wsgi is there)
cd /var/www/
sudo mkdir myApp
sudo chown ec2-user myApp
cd myApp
sudo pip3 install virtualenv
virtualenv myprojectenv
source myprojectenv/bin/activate
sudo pip3 install django==2.1.1
django-admin startproject myApp
cd myApp
python manage.py migrate
python manage.py runserver
wget http://127.0.0.1:8000/      (works correctly as it should and I receive test page)
python manage.py startapp hello
cd myApp
vim settings.py

settings.py: edit this part to look like this:

INSTALLED_APPS = [
     'django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.messages',
     'django.contrib.staticfiles',
      'hello.apps.HelloConfig',
]

.

vim urls.py

urls.py: entire file looks like this:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('hello.urls')),
]

.

cd ..
cd hello
vim views.py

views.py: entire file looks like this

from django.shortcuts import render
# Create your views here.

# hello/views.py
from django.http import HttpResponse
def homePageView(request):
return HttpResponse('Hello, World!')

.

vim urls.py

hello/urls.py: entire file looks like this:

# hello/urls.py
from django.urls import path
from .views import homePageView

urlpatterns = [
         path('', homePageView, name='home')
]

.

cd ..
python manage.py runserver
wget http://127.0.0.1:8000/      (works correctly as it should, now gets “Hello World!”)

Now for the Apache part:

sudo vim /etc/httpd/conf/httpd.conf
    

Paste the following to the bottom of httpd.conf:

WSGIScriptAlias / /var/www/myApp/myApp/myApp/wsgi.py
WSGIPythonHome /var/www/myApp/myprojectenv
WSGIPythonPath /var/www/myApp

<Directory /var/www/myApp/myApp/myApp>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

.

sudo service httpd restart
wget http://127.0.0.1

Connecting to 127.0.0.1:80… connected.
HTTP request sent, awaiting response…

and that is all it does until it times out. Connecting to the public IP address through a browser does the same thing; it connects and just sits there waiting for a response.

Apache error log (/var/log/httpd/error_log) says this:

Django ImportError: No module named site

A quick search suggests that this is because mod_wsgi is using a different version of python than my virtual environment. I’m using python3.7

cd /etc/httpd/modules
ldd mod_wsgi.so

outputs

    linux-vdso.so.1 (0x00007ffd7dec3000)
    libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007fe35815d000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe357f3f000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007fe357d3b000)
    libutil.so.1 => /lib64/libutil.so.1 (0x00007fe357b38000)
    libm.so.6 => /lib64/libm.so.6 (0x00007fe3577f8000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fe35744d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fe358755000)

Clearly that is a different version. I’ve uninstalled it, and installed it again while in the python3.7 virtual environment, but the result is the same. It still says "libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0".

2

Answers


  1. Chosen as BEST ANSWER

    Ultimately, the problem here was a matter of getting Python to use the correct/new version of sqlite3. The error log located at /var/log/httpd/error_log proved very useful for troubleshooting (surprise).

    In searching through other Q&A I found a lot of answers that involved LD_LIBRARY_PATH and LD_RUN_PATH. However, with deeper research I found that these are not the preferred method for instructing the compiler as to library paths. As shown below, ldconfig is used instead, along with a .conf file placed in the /etc/ld.so.conf.d/ directory.

    The following is the step-by-step instructions for getting the latest Django served up by Apache; beginning with a fresh Linux 2 EC2 instance.

    sudo yum update
    sudo su
    yum groupinstall "Development Tools"
    crtl-d
    sudo yum -y install libffi-devel
    sudo yum install -y openssl-devel
    sudo vim /etc/ld.so.conf.d/usrlocal.conf
    

    In this empty file you created, add:

    /usr/local/lib
    /usr/local/lib64
    

    next:

    sudo ldconfig -v
    cd ~
    mkdir downloads
    cd downloads
    wget https://sqlite.org/2020/sqlite-autoconf-3320300.tar.gz
    tar -xvf sqlite-autoconf-3320300.tar.gz
    cd sqlite-autoconf-3320300
    ./configure --prefix=/usr/local
    make -L
    sudo make install
    sudo ldconfig -v
    cd ~downloads
    wget https://www.python.org/ftp/python/3.7.7/Python-3.7.7.tgz
    tar -xvf Python-3.7.7.tgz
    cd Python-3.7.7
    ./configure --enable-shared --enable-optimizations --with-threads --enable-loadable-sqlite-extensions --with-openssl=/usr/local/lib64
    sudo make -L
    sudo make altinstall        (altinstall keeps old 2.7 version)
    sudo ldconfig -v
    python 3.7                  (to verify installation ctrl-d to quit)
    >>>import sqlite3
    >>> sqlite3.sqlite_version
    ctrl-d
    sudo chown -R ec2-user /usr/local/lib/python3.7
    sudo chown ec2-user /usr/local/bin
    sudo chown ec2-user /usr/local/lib
    sudo yum install httpd-devel
    sudo ldconfig -v
    cd /var/www/
    sudo mkdir django
    sudo chown ec2-user django
    cd django
    pip3.7 install virtualenv
    virtualenv myprojectenv
    source myprojectenv/bin/activate
    python -c 'import sys; print(sys.prefix)'
    pip3.7 install mod_wsgi           
    mod_wsgi-express module-config
    

    That will output something like the following. You will copy that and paste it to the bottom of your httpd.conf file. sudo vim /etc/httpd/conf/httpd.conf

    LoadModule wsgi_module "/var/www/django/myprojectenv/lib/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so"
    WSGIPythonHome "/var/www/django/myprojectenv"
    

    next:

    pip3.7 install Django==3.0.7
    django-admin startproject myApp
    cd myApp
    python manage.py migrate
    python manage.py startapp hello
    cd myApp
    vim wsgi.py
    

    edit to look like the following (add ‘import sys’ and ‘sys.path…….’)

    import os
    import sys
    from django.core.wsgi import get_wsgi_application
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myApp.settings')
    sys.path.append('/var/www/myApp/myApp/myApp')
    sys.path.append('/var/www/myApp/myApp')
    
    application = get_wsgi_application()
    

    next:

    vim settings.py
    

    edit to look like the following, substituting your EC2 instance public IP

        ALLOWED_HOSTS = ['xx.xxx.xx.xxx']     (substitute your EC2 public IP address)
    
        INSTALLED_APPS = [
         'django.contrib.admin',
         'django.contrib.auth',
         'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
         'django.contrib.staticfiles',
          'hello.apps',
         ]
    
    
    vim urls.py
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', include('hello.urls')),
    ]
    

    next:

    cd ../hello
    vim views.py
    

    Edit to look like the following. These are Python files. So, mind your indentations

    from django.shortcuts import render
    # Create your views here.
    
    # hello/views.py
    from django.http import HttpResponse
    def homePageView(request):
        return HttpResponse('Hello, World!')
    

    This next file you will create.

    vim urls.py
    

    Paste:

    # hello/urls.py
    from django.urls import path
    from .views import homePageView
    
    urlpatterns = [
        path('', homePageView, name='home')
    ]
    

    Now back to Apache:

    sudo vim /etc/httpd/conf/httpd.conf
        
    

    Paste the following to the bottom of httpd.conf:

    WSGIScriptAlias / /var/www/django/myApp/myApp/wsgi.py
    WSGIPythonPath /var/www/django
    
    <Directory /var/www/django/myApp/myApp>
    <Files wsgi.py>
    Require all granted
    </Files>
    </Directory>
    

    .

    sudo service httpd start
    

    At this point you should be able to make a request to the public IP of your instance and get the “Hello World!” response.

    Finally:

    sudo su
    vim /var/log/httpd/error_log
    

    and viola, you have some new issues to address!


  2. On Amazon Linux 2 you need to compile the mod_wsgi against Python 3.7 yourself (EDIT: If you want to install the traditional apache module version of mod_wsgi). For some reason Amazon only has a yum package for a 2.7 compiled version included.

    I recently did the same and followed the instructions here http://www.marek.tokyo/2018/08/apache-24-modwsgi-python-37-django.html. But essentially:

    1. Download mod_wsgi (latest is 4.7.1)
    2. Expand the tar.gz archive
    3. Run ./configure --with-python=/usr/bin/python3
    4. Run LD_RUN_PATH=/usr/local/lib make
    5. Run make install
    6. Open /etc/ld.so.conf and add: /usr/local/lib to the end of the file if it’s not there already
    7. Run ldconfig
    8. Check if mod_wsgi is linked properly by running ldd /usr/lib64/httpd/modules/mod_wsgi.so, if it is you’ll see a link to libpython3.7
    9. Finally, you need to tell Apache to load the new module so create a module file in the apache config (echo "LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so" > /etc/httpd/conf.modules.d/01-wsgi.conf)

    You might need to install gcc or some other build tools if they aren’t installed already.

    EDIT:
    In case it’s not clear, you should only download source code from sources you trust, so in this case, while that instruction page has a link, you could also just use the mod_wsgi github page (https://github.com/GrahamDumpleton/mod_wsgi/releases).

    As an alternative, you can also use pip to install a mod_wsgi-express which doesn’t take additional apache config (https://modwsgi.readthedocs.io/en/develop/).

    Either way, you can’t use the Amazon Linux 2 package if you are using the latest build of Python 3.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search