0

Maybe some needed context:

I installed python3.9 into a directory /opt/python39/. I compiled mod_wsgi with this version of python (as per this post) and was able to conduct a test to make sure that it was working correctly. I am not using a virtual environment.

I am trying to move my django project to production, so naturally, I am following the django docs. When I use the default file configurations at the very beginning, i.e.:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonHome /opt/python39/bin/python3.9
WSGIPythonPath /path/to/mysite.com

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

It works (for the most part - there are resources missing on the page, but thats for another SO post) like a charm.

So I continue through the docs (which is now telling me that I should move it to "Daemon mode"):

“Daemon mode” is the recommended mode for running mod_wsgi (on non-Windows platforms). To create the required daemon process group and delegate the Django instance to run in it, you will need to add appropriate WSGIDaemonProcess and WSGIProcessGroup directives. A further change required to the above configuration if you use daemon mode is that you can’t use WSGIPythonPath; instead you should use the python-path option to WSGIDaemonProcess, for example:

So I change my file to look like:

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
#WSGIPythonHome /opt/python39/bin/python3.9
#WSGIPythonPath /path/to/mysite.com
WSGIDaemonProcess mysite.com python-home=/opt/python39/bin/python3.9 python-path=/path/to/mysite.com
WSGIProcessGroup mysite.com

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

then run sudo apachectl restart, go back to my browser, refresh, shows 500 internal server error, check my logs, and "what do you know?" - ImportError: "No module named 'django'".

I've come across this SO article that seems to be describing my problem, but for virtual environments, and offers a solution, but I give it a go anyway:

WSGIProcessGroup mysite.com
WSGIDaemonProcess mysite.com python-home=/opt/python39 python-path=/path/to/mysite.com
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py process-group=iengravethat.com application-group=%{GLOBAL}

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

I rerun sudo apachectl restart, check my browser - same error, check the logs - same error.

I have tried a multitude of other configurations, but they all boil down to this error. Does anyone have any idea as to how to remedy this problem?

---UPDATE---

SUTerliakov and I opened up a channel for discussion, the end conclusion was thus:

Regarding recompilation - I was absolutely happy with the following installation (from Dockerfile, but it doesn't really matter):

pip install -U --no-cache-dir mod-wsgi
mod_wsgi-express install-module | tee /etc/apache2/mods-available/wsgi_express.load /etc/apache2/mods-available/wsgi_express.conf

And it can be done from venv too. I really don't understand why did your paths stop working after switching to daemon mode. I just suggest to try virtualenv instead, because this method is recommended by maintainer. You can just drop "tee" part and use standalone mod_wsgi-express install-module. It will print two lines of config, you can add them to your config file manually. It will print WSGIPythonHome, take this value and use for python-home option of WSGIDaemonProcess. (may require root, AFAIR)

So, basically just create a venv and link it in your .conf file.

  1. Create a virtual environment with the python interpreter you want to use and activate it.
  2. pip install the packages you were using for django.
  3. pip install mod-wsgi.
  4. Grab the version of mod_wsgi you want.
  5. untar it and enter the directory.
  6. ./configure --with-python=python3 (This python3 is the same version as the python3 I wanted - not python 3.6 which comes pre-installed on centos7).
  7. make LDFLAGS='-L/path/to/venv/lib -Wl,-rpath,/path/to/venv/lib'.
  8. sudo make install.
  9. run mod_wsgi-express module-config and copy and paste it at the top of your .conf file.
  10. deactivate your environment.
  11. restart apache - sudo apachectl restart
Shmack
  • 1,933
  • 2
  • 18
  • 23
  • @larsks If you have time to look at this, I'd appreciate it. – Shmack Jun 09 '22 at 19:13
  • I have the following config: `WSGIDaemonProcess processes=1 threads=5 display-name=%{GROUP} home=` `WSGIScriptAlias / process-group= application-group=%{GLOBAL}` (+ SSL and WebSocket config). `` is any alias, `` is folder with `manage.py` and `` is `/something/wsgi.py`. It is deployed with docker (system-level package installation as root, no venv). – STerliakov Jun 09 '22 at 19:53
  • @SUTerliakov Could you add it as an answer for readability? – Shmack Jun 09 '22 at 19:55

1 Answers1

1

I have the following config:

ServerName ${SERVER_NAME}
ServerAdmin ${SERVER_ADMIN}

<IfModule unixd_module>
    User ${APP_USER}
    Group ${APP_USER}
</IfModule>

WSGIRestrictEmbedded On
WSGIPassAuthorization On

IncludeOptional /etc/apache2/conf.d/*.conf
Timeout 60

<VirtualHost *:80>
    Redirect permanent / https://${SERVER_NAME}/
</VirtualHost>

<VirtualHost *:443>
    Alias /media <media folder>
    <Directory <media_folder> >
        Options -Indexes
        Require all granted
    </Directory>
    Alias /static <static_folder>
    <Directory <static_folder> >
        Options -Indexes
        Require all granted
    </Directory>
    WSGIDaemonProcess <name> processes=1 threads=5 display-name=%{GROUP} home=<top_folder> 
    WSGIScriptAlias / <wsgi.py path> process-group=<name> application-group=%{GLOBAL}
    ... SSL config here ...
</VirtualHost>

It is not a full config: logging, SSL and WebSocket proxies are thrown away.

  • <name> is any alias
  • <top_folder> is folder with manage.py file
  • <wsgi.py path> is <top_folder>/something/wsgi.py
  • <media_folder> and <static_folder> are paths of MEDIA_ROOT and STATIC_ROOT settings.

It is deployed with docker (system-level package installation as root, no virtual environment).

Final attempt

Probably something gets messed up when using system python that is not the default interpreter. You can set up virtual environment and make httpd use it. To avoid manual recompilation, mod_wsgi pip package can be used:

# With venv activated
pip install mod_wsgi
sudo mod_wsgi-express install-module

This will install mod_wsgi for venv python and print two lines of config: LoadModule ... and WSGIPythonHome <path>. You can add LoadModule to configuration file and use the following daemon config:

WSGIDaemonProcess mysite.com home=/path/to/mysite.com python-home=<venv_root>

Note

You don't need to recompile mod_wsgi manually with this package, it is the most amazing aspect of such installation! Two commands above are sufficient to install mod_wsgi. It will copy module files to required folders for you (see end of this readme), so your steps 4-8 can be omitted.

STerliakov
  • 4,983
  • 3
  • 15
  • 37
  • See, the thing is, I'm not using docker :| - though I don't think that matters too much. I mean just following the tutorial from the django docs should be enough, no? Thanks for posting. – Shmack Jun 09 '22 at 20:05
  • I had a lot of troubles when writing this config initially, most of them were related to python path and packages discovery. Do you use system-level packages or virtualenv? Is `/opt/python3.9` a default interpreter? – STerliakov Jun 09 '22 at 20:07
  • System-level. `/opt/python3.9` is not a default. I had to `configure` mod_wsgi with the --with-python arg, and its in my LD_RUN_PATH and LD_LIBRARY_PATH and used `make LDFLAGS='-L/opt/python39/lib -Wl,-rpath,/opt/python39/lib'` when making the makefile – Shmack Jun 09 '22 at 20:09
  • @Shmack I added first attempt to the answer, please try that. – STerliakov Jun 09 '22 at 20:30
  • I think I gave that a go before you recommended it (though not recorded in my question), needless to say, unfortunately it didn't work. Still throws the same error. – Shmack Jun 09 '22 at 20:36
  • Do you think it could be a permissions issue? Any idea how I might go about giving access to to the proper group / user - seeing that WSGIDaemonProcess creates a new user? – Shmack Jun 09 '22 at 20:43
  • I doubt it is related to permissions, because your initial configuration with embedded mode was working. Could you try to get more info with `LogLevel Info` and add apache logs to your question? – STerliakov Jun 09 '22 at 20:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/245473/discussion-between-suterliakov-and-shmack). – STerliakov Jun 09 '22 at 20:53
  • I created a virtual environment, recompiled my mod_wsgi with the environment active - being sure to point the --with-python= to my venv and the make LDFLAGS to the venv resources, installed all my packages, loaded the `mod_wsgi-express module config` output into my file, restarted apache, and the page loaded... yay. I am going to add an update to the bottom of my post. If you could update your answer to reflect the update, I can mark your post as the correct answer and upvote it. I can't express my gratitude enough for your help! – Shmack Jun 09 '22 at 23:39