I have used mod_wsgi-express to whump up an Apache config. But I found a problem whereby when run by user "apache" it can't find a python module which I know is present when running under "root" :
# whoami
root
# python -c "import django;"
#
# su apache
$ python -c "import django;"
File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'django'
I recall reading that mod_wsgi and mod_wsgi-express is installed with python running in some virtual environment. But as I am running this in a Docker container, I am really not interested in and know little about outdated old stuff like venv, virtualenv, and suchlike (and I wish there was a mod_wsgi-express option to use the system-wide python, and not bother with spinning a virtual cocoon round the python it uses, as doing this simply complicates things when using Docker! )
So my question is how can I "devirtualise" this python that runs under user "apache", so it runs the system-wide python3 and its libraries, and thus pick up the django module among others, the same as "root"?
Thanks in anticipation
Regards
John R Ramsden
P.S. The annoying thing is I had the perishing thing working on Friday, and carefully preserved my changes, or thought I had. But upon rebuilding the Docker container, something is not quite the same as before and the Apache error log has reverted to containing the "Not found 'django'" error as above. I'd be happy to set the access right to every file in the container to 777 if that is what it takes, as this app will be running inside an intranet. But I have a feeling that won't fix the problem, and probably isn't entirely sound from a security standpoint.
P.S. As a service to this mailing list, which I hope others may find useful, I append a python script I wrote to strip out all the extra "ifs and buts" cruft from the generated httpd.conf file, so one can see more clearly what is going on. (IMHO it would be a good idea to have a mod_wsgi-express option that generates the httpd.conf file without them to start with.) The script may not win any prizes for elegance, but it did the job for me. (But use it with care, as some version numbers are hard-coded! )
#!/usr/bin/python
import re
env_vars = dict()
# Fetch '-D' tokens from httpd command arguments
#
# HTTPD_ARGS="-f /application/apache/httpd.conf -E /application/apache/startup.log -DMOD_WSGI_VIRTUAL_HOST -DMOD_WSGI_WITH_HTTPS .."
#
funit = open('apachectl', 'r')
lines = funit.read().splitlines()
httpd_args = 'HTTPD_ARGS='
for line in lines:
if len(httpd_args) < len(line) and httpd_args == line[0:len(httpd_args)]:
matches = re.finditer(' -D[A-Z_]+', line)
for match in matches:
env_vars[match.group()[3:]] = 1
break
funit.close()
# Output httpd.conf file with Ifs and Buts removed
#
n_blank_line = 0
old_version = False
skip_level = 0
skip_flags = []
defined_no = '<IfDefine !'
defined_yes = '<IfDefine '
funit = open('httpd.conf', 'r')
lines = funit.read().splitlines()
for line in lines:
skip = None
if '<IfVersion >= 2.2.15>' == line or '<IfVersion >= 2.4>' == line:
continue
elif '<IfVersion < 2.4>' == line:
old_version = True
continue
elif '</IfVersion>' == line:
if old_version:
old_version = False
continue
elif old_version:
continue
elif '</IfDefine>' == line:
skip = skip_flags.pop()
if skip:
skip_level -= 1
continue
elif defined_no == line[0:len(defined_no)]:
key = line[len(defined_no) : -1]
skip = True if key in env_vars else False
elif defined_yes == line[0:len(defined_yes)]:
key = line[len(defined_yes) : -1]
skip = True if key not in env_vars else False
if skip is not None:
skip_flags.append(skip)
if skip:
skip_level += 1
continue
if skip_level == 0:
# Compress multiple output blank lines to single blank line
#
if re.match(r'^\s*$', line):
n_blank_line += 1
else:
n_blank_line = 0
if n_blank_line > 1:
continue
print(line)
funit.close()