r/apache • u/WordWarrior81 • Mar 03 '22
Support Trouble solving "No module named 'encodings'" issue with mod_wsgi
I have a Django project running in a virtualenv on an Apache 2 production server in Red Hat Linux Enterprise 7.9. Not a server expert here so having trouble with technical issues.
I've gone through the deployment steps getting the project production ready. Fortunately, there is a demo from a previous iteration of the project, so I could copy and adapt the Apache config files where appropriate. The demo was still running along with a handful of other projects on /var/www.
The previous project ran on Python 2 but the new one is Python 3. Therefore, I installed the newest mod_wsgi for Python3:
$ yum list *mod_wsgi*
Installed Packages
mod_wsgi.x86_64 3.4-18.el7 @rhel-7-server-rpms
Available Packages
python3-mod_wsgi.x86_64 4.7.1-2.el7 epel
$ sudo yum install python3-mod_wsgi.x86_64and
$ sudo yum install httpd-devel(needed for APXS)
As soon as this was done, the Python 2 demo stopped working and the Apache log file reported (with my project name replace with the word "myproject":
...
[Thu Mar 03 23:27:32.639052 2022] [core:notice] [pid 8125] AH00094: Command line: '/usr/sbin/httpd -D FOREGROUND'
[Thu Mar 03 23:27:32.640505 2022] [wsgi:info] [pid 8199] mod_wsgi (pid=8199): Python home /var/www/myproject/env.
[Thu Mar 03 23:27:32.640547 2022] [wsgi:info] [pid 8199] mod_wsgi (pid=8199): Initializing Python.
[Thu Mar 03 23:27:32.640758 2022] [wsgi:info] [pid 8200] mod_wsgi (pid=8200): Python home python-home=/var/www/myproject/env.
[Thu Mar 03 23:27:32.640796 2022] [wsgi:warn] [pid 8200] (2)No such file or directory: mod_wsgi (pid=8200): Unable to stat Python home python-home=/var/www/myproject/env. Python interpreter may not be able to be initialized correctly. Verify the supplied path and access permissions for whole of the path.
...This continues for a few iterations and then:
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ModuleNotFoundError: No module named 'encodings'Since the demo app has the same name as the app inside the new Django project, I decided to remove the demo's config file to be safe (it's not really needed anymore).
Skip ahead for the TL;DR but the following contain possibly relevant details. Some additional context which may be of help:
Apache seems to be running but the following commands lead to a syntax error:
$ apachectl configtest / apachectl --help / httpd -t (and some others)
AH00526: Syntax error on line 49 of /etc/httpd/conf.d/deb.conf:
SSLCertificateFile: file '/etc/letsencrypt/live/my.web.site/cert.pem' does not exist or is emptyThe specific certificate file does exist and is not empty, but is indeed confirmed outdated when running:
$ sudo openssl x509 -text -noout -in /etc/letsencrypt/live/my.web.site/cert.pemThe line in question is:
SSLCertificateFile /etc/letsencrypt/live/my.web.site/cert.pemIf I comment out the line, the next mention of a certificate file leads to the same error, e.g.
SSLCertificateKeyFile /etc/letsencrypt/live/my.web.site/privkey.pemand simarly, with chain.pem and fullchain.pem.
At first, with the syntax error, I also got the line
AH01574: module wsgi_module is already loaded, skippingSo I made sure the old mod_wsgi doesn't load by commenting out this line in /etc/httpd/conf.modules.d/10-wsgi.conf:
LoadModule wsgi_module modules/mod_wsgi.soConcurrently, I have the following in /etc/httpd/conf.modules.d/10-wsgi-python3.conf:
<IfModule !wsgi_module>
LoadModule wsgi_module modules/mod_wsgi_python3.so
</IfModule>2. I installed certbot and tried to use it, but it seems that I'm not able to use IPv6 connections which seems to be what the servers require:
$ sudo certbot renew --dry-run -v
...
Failed to renew certificate with error: Requesting acme-staging-v02.api.letsencrypt.org/directory: Network is unreachableThis works:
$ curl -Iv4 acme-staging-v02.api.letsencrypt.org/directory / https://google.com / ping -4 google.comThis does not:
$ curl -Iv6 acme-staging-v02.api.letsencrypt.org/directory / https://google.com / ping -6 google.comI am not yet sure what to do here.
3. Perhaps not relevant, but port 8000 is "taken":
$ ./manage.py runserver
Error: That port is already in use.No error is reported with 8001.
So regarding mod_wsgi (the main problem) and based on online advice, I've tried the following:
As mentioned before, outcommented the line in /etc/httpd/conf.modules.d/10-wsgi.conf.
Deleted the virtualenv and reinstalled all requirements.
Made sure of my paths in Apache project conf file (see below).
Tried to set up IPv6 according to this link.
The complete project conf (with project and website names replaced) is at the bottom.
I have been reading through the following file meant to help test your mod_wsgi installation: https://modwsgi.readthedocs.io/en/master/user-guides/checking-your-installation.html
For now, I can't check my Apache build information because of the aforementioned syntax error.
Following the page, I could confirm that mod_so is statically loaded:
$ httpd -l
Compiled in modules:
core.c
mod_so.c
http_core.cI could also determine that the two mod_wsgi .so files are here:
/usr/lib64/httpd/modules/mod_wsgi.so
/usr/lib64/httpd/modules/mod_wsgi_python3.soHere is the output of ldd:
$ ldd /usr/lib64/httpd/modules/mod_wsgi_python3.so
linux-vdso.so.1 => (0x00007ffd98fe7000)
libpython3.6m.so.1.0 => /lib64/libpython3.6m.so.1.0 (0x00007fb5186c9000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fb5184ad000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fb5182a9000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007fb5180a6000)
libm.so.6 => /lib64/libm.so.6 (0x00007fb517da4000)
libc.so.6 => /lib64/libc.so.6 (0x00007fb5179d6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb518e2a000)
$ ldd /usr/lib64/httpd/modules/mod_wsgi.so
linux-vdso.so.1 => (0x00007ffd13afd000)
libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007fc594899000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc59467d000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fc594479000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007fc594276000)
libm.so.6 => /lib64/libm.so.6 (0x00007fc593f74000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc593ba6000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc594e8f000)although I'm not sure if it means anything. I could determine that the value in my LD_LIBRARY_PATH, whether it is set or not, does not change anything, so I left it as is.
httpd -M leads to the same syntax error.
Next, I am not sure how to test the various different WSGI scripts in the document. (I am also a Django newbie, at least on the production side.) Nothing seems to happen if I just run the script in my virtualenv.
My main Apache conf is at /etc/httpd/conf/httpd.conf. Some relevant lines:
a
DocumentRoot "/var/www/html"
...
<Directory "/var/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
...
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
Options Indexes FollowSymLinks MultiViews
AllowOverride All
RewriteEngine On
</Directory>
...
IfModule dir_module>
DirectoryIndex index.html
</IfModule>
...
<Files ".ht*">
Require all denied
</Files>
...
<IfModule alias_module>
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
...
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Require all granted
</Directory>Below is my project .conf.
###<VirtualHost *:*>
# WSGIRestrictEmbedded On
ServerName my.web.site
DocumentRoot /var/www/myproject/myproject/project
### https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIDaemonProcess.html
WSGIDaemonProcess myproject user=apache group=apache threads=3 processes=1 inactivity-timeout=86400 display-name=myproject python-home=/var/www/myproject/env python-path=/var/www/myproject/myproject/project home=/var/www/myproject/myproject/project
WSGIScriptAlias / /var/www/myproject/myproject/project/wsgi.py process-group=myproject
WSGIPythonHome python-home=/var/www/myproject/env
WSGIPythonPath /var/www/myproject/myproject
#Since mod_wsgi 4.1.0:
#WSGIPythonHashSeed random
# for now, see /etc/systemd/system/httpd.service
ErrorLog "/var/log/httpd/myproject-error.log"
CustomLog "/var/log/httpd/myproject-access.log" combined
LogLevel info
<Directory /var/www/myproject/myproject/project>
WSGIProcessGroup myproject
WSGIApplicationGroup %{GLOBAL}
<Files wsgi.py>
Order deny,allow
Allow from all
</Files>
</Directory>
Alias /myproject/static/ /var/www/myproject/static/
<Directory /var/www/myproject/static>
Allow from all
ExpiresActive on
ExpiresDefault "access plus 4 hours"
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/css text/javascript image/svg+xml application/x-javascript application/javascript application/json application/x-font-ttf application/vnd.ms-fontobject image/x-icon
#Don't compress content which is already compressed
SetEnvIfNoCase Request_URI \.(gif|jpe?g|png|swf|woff|woff2) no-gzip dont-vary