mod_wsgi unable to connect WSGI daemon process - django

I am using Easy apache 4, mod_wsgi, and Python 3.5. When I called a Django project in the server I got the following error:
(13)Permission denied: mod_wsgi (pid=24223): Unable to connect to WSGI daemon
process 'user123' on '/var/run/wsgi.8442.6.7.sock' as user with uid=3708.

Your Apache installation is likely set up to run with SECURE privileges mode. This means that the Apache child worker process is forked and privileges dropped before handling the request, which in this case is simply trying to proxy the request through to the mod_wsgi daemon process. The consequence of this is that it cannot connect to the socket for the daemon process, as it was setup with ownership to match the original Apache child worker process before privileges were dropped.
This is evident because the error message has uid in the range of a normal user and not the special apache or nobody user.
To fix it, you need to modify the WSGIDaemonProcess directive configuration and add the option:
socket-user=#3708
or:
socket-user=username
where username is replaced with the actual name of the user with uid of 3708.
The addition of this option seems to be required due to recent changes in CPanel configurations for Apache.

Sometime socket-user setting does not work.
This may occur because of WSGISocketPrefix path not found
If it is VPS:
WSGISocketPrefix /var/run/wsgi
If you are in a shared hosting:
WSGISocketPrefix ../../var/run/wsgi
Thank You

Related

apache creates more then one process

I am running django application in apache using mod wsgi. I have set server limit to 1 as of the following configuration.
00-mpm.conf
<IfModule worker.c>
StartServers 1
ServerLimit 1
#MaxClients 300
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
At beginning apache runs with one server. But after some time when i am checking it runs with two servers. And i got the following error in the error.log
[mpm_worker:notice] [pid 46754:tid 139924109117568] AH00297: SIGUSR1 received. Doing graceful restart.
How can i make sure that apache to run with only one server. And not doing restart.
Apache runs a parent process and then one child worker process with that configuration. The parent process would be quite small in size as all it is doing is managing the child worker process and restarts it if it dies etc. Requests are only handled by the child worker process. So what you are seeing is normal.
Why are you trying to restrict it to one process? If it is to satisfy some requirement of your WSGI application that can only have one process, you should not be using embedded mode anyway. Use daemon mode of mod_wsgi, in which case the WSGI application will use one process by default.
So put back the Apache MPM settings and then use:
WSGIRestrictEmbedded On
WSGIDaemonProcess myapp
WSGIScriptAlias / /some/path/myapp.wsgi process-group=myapp application-group=%{GLOBAL}
This will result in the Apache parent process, however many child worker process Apache needs to accept and proxy requests, and the single mod_wsgi daemon process running the WSGI application, to which the child worker processes are proxying requests.

Rooting log files with daemon mode

I'm using mod_wsgi (v.4.5.20), installed with pip, in daemon mode, using a "main" apache instance as front (reverse proxy). I'm serving a django application, the "main" server hosts some other applications.
I'ld like to record the log files to a "known" directory. For now, the log files are recorded into the directory generated by the daemon-mode, aka. --server-root directory. The process is launched through a systemd service.
On the "main" apache settings, I've set the ErrorLog and CustomLog directives to my "wanted" log directory, but no files are recorded.
The "main" apache settings: (Note the X-Forwarded-For switch for company reverse proxy)
https://gist.github.com/frague59/0c9717bd5668140de392019874373f0a
Thanks for your help !
When you use mod_wsgi-express behind a front end Apache serving as proxy, the mod_wsgi-express configuration is completely independent to the front end. If you want to change where logs go for mod_wsgi-express use the --log-directory option. Presuming mod_wsgi-express is started as not root user, it will not be able to write to a root owned directory. If it needed to, you would need to start it as root and define --user and --group options to then be what user and group you want the WSGI application to run as. Because it start as root initially, then it can write logs to a root owned directory. Run mod_wsgi-express with the --help option to see all the command line options.

Trouble with Django and mod_wsgi: "Script timed out before returning headers: wsgi.py"

I'm running a Django app on Apache 2.4.7 with mod_wsgi 3.4. The whole setup is on an EC2 ubuntu instance. Ever since I deployed the app, the server has gone down with 504/503 errors every few days with this message in the logs:
Script timed out before returning headers: wsgi.py
I've searched extensively but all I can conclude is I have a memory leak somewhere? I can't seem to figure out what's actually going wrong, since my Django install is pretty vanilla. This is the relevant part of my conf file:
WSGIScriptAlias / /home/ubuntu/projects/appname/app/app/app/wsgi.py
WSGIDaemonProcess app python-path=/home/ubuntu/projects/appname/app user=ubuntu
WSGIProcessGroup app
WSGIApplicationGroup %{GLOBAL}
Could this be from some third party library? The only extras I have installed are ImageMagick and exiftool, the latter of which isn't being used. Is there anything else I can do to debug?
Does your application call out to any backend services?
If you are getting 503/504 and that message, then it would generally indicate that your code is either hanging on backend services or that your code is blocking indefinitely on thread locks.
So basically all request threads become busy and get used up.
If they didn't provide such an ancient version of mod_wsgi then newer versions do at least have better options to combat this sort of problem in your application and recover automatically, plus log information to help you work out why.
For such an old version, you can set 'inactivity-timeout' option to WSGIDaemonProcess to '60' as a way of recovering, but this will also have the effect of restarting your application after 60 seconds if it wasn't receiving any requests as well, which may in itself not be ideal for some apps. In newer versions the inactivity timeout is separated from the concept of a request timeout.

how to configure WSGISocketPrefix

I am getting a permissions issue when running django in daemon mode. Reading here https://code.google.com/p/modwsgi/wiki/ConfigurationIssues#Location_Of_UNIX_Sockets I think the solution is to configure the WSGISocketPrefix
The problem is that /var/run/wsgi is no where to be found on my centos server.
The closes thing I can find is: /etc/httpd/run/httpd.pid
How can I find where wsgi is installed?
Or what other value can I set the WSGISocketPrefix equal to?
With Ubuntu 14.0.4 LTS, Django11.1, Python 3.6.1, and mod_wsgi-4.5.15 it works for me as follows:
Apache was showing the following error:
503 Service Unavailable
Apache error log showed the following:
[wsgi:error] [pid 5411] (2)No such file or directory: [client 1.2.3.4:12345] mod_wsgi (pid=5411): Unable to connect to WSGI daemon process 'mywsgi' on '/var/run/apache2/wsgi.5403.0.1.sock' as user with uid=123.
Note that I'm running WSGI as a different user than the default www-data. This is changed with 'user' from WSGIDaemonProcess.
Solution:
At the bottom of /etc/apache2/apache2.conf, add:
WSGISocketPrefix /var/run/apache2/wsgi
After restarting Apache, I can ls -la and see the lock files under /var/run/apache2:
apache2.pid
wsgi.5017.0.1.sock
Sources:
http://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGISocketPrefix.html?highlight=WSGISocketPrefix%20
https://code.google.com/archive/p/modwsgi/wikis/ConfigurationIssues.wiki#Location_Of_UNIX_Sockets

Apache Permission for a bat file w/ Django

I have seen a lot of similar questions, but still i am failing. I have win XP, Apache 2.2, Django 1.4, Python 2.7 and mod_wsgi 3.3. All i am trying to do is when you hit the page the bat file executes and which echoes hi. This works when i run it on the django internal dev server. But when i got to Apache, it fails and in the error.log i get the message
The system cannot write to the specified device.
The system cannot write to the specified device.
The system cannot write to the specified device.
The system cannot write to the specified device.
The system cannot write to the specified device.
I have not seen that error in many other places. Most people seem to get "Permission denied". I still think the permissions are wrong. So when i run it is the django internal server i get in the console:
Validating models...
0 errors found
Django version 1.4, using settings 'testsite.settings'
Development server is running at http:`//127.0.0.1:8000/
Quit the server with CTRL-BREAK.
C:\Sites\cprm>echo hi
hi
[18/Sep/2012 14:58:45] "GET / HTTP/1.1" 200 63
That seems fine. The only thing throwing me off that I'm running from /testsite and not /cprm. I could just cd .. before. Anyway, so since in the internal server it is writing to the console, i guess i need to do the equivalent in apache. I'm not sure where the apache console is. I tried adding permission to the apache log file as that is where the error gets generated. I'm not sure that is equivalent to the regular console.
My Apache file looks like this (ignore back ticks):
<`VirtualHost *>
ServerName http://example.com:80
WSGIScriptAlias /cprm "C:/sites/cprm/wsgi.py"
WSGIScriptAlias /testsite "C:/sites/testsite/wsgi.py"
<Directory "C:/sites">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
<Directory "C:/Program Files/Apache Software Foundation/Apache2.2/logs">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
<`/VirtualHost>
My view just looks like this:
from django.http import HttpResponse
import datetime, os
def home(request):
os.system('C:/Sites/testsite/testsite/test.bat')
now = datetime.datetime.now()
html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
It's basically just a quick test I tried doing.
EDIT
Hi pacha. Thanks for the response. I have done some reading on the topic now. So I made the changes you indicated. My wsgi.py file looks like such:
import os, sys
path = 'C:/Sites/testsite'
if path not in sys.path:
sys.path.append(path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testsite.settings")
sys.stdout = sys.stderr
print 'hi'
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
Then when i go to error.log, i do in fact see 'hi' printed. So that is good. However, the test.bat file w/ the echo hello does not execute and i still get the same message. And thanks for the permission advice. I am now no longer using virtual. I am not ready for that yet. Any other ideas for what I could try?
Things to check
Permissions what are the user permissions on the file
C:/Sites/testsite/testsite/test.bat?
Are they read for the same user that is running the Apache Process?
Have you installed python for all logged in users not just for?
Have you reviewed your Apache conf directives?
User/Group: The name (or #number) of the user/group to run httpd as.
It is usually good practice to create a dedicated user and group for
running httpd, as with most system services.
User carlos
Group Administrators
Does that same user have permissions to read the file on the file system?
<Directory "C:/Sites/testsite/testsite/">
AllowOverride None
Options None
Order deny,allow
Allow from all
</Directory>
Your problem seems to be related to how the standard output is handled. WSGI disables standard output by default. That's why your program works fine in the development server (which redirects the output to the terminal where the server was launched) but doesn't work with Apache.
You can enable stdout in WSGI using a configuration directive that you put in your virtual host conf file (together with the other WSGI directives):
WSGIRestrictStdout Off
However, take into account that Apache isn't associated to any terminal. If you want to see the output of your program then one thing you can do is to redirect the standard output to the standard error stream by adding this to your WSGI file:
sys.stdout = sys.stderr
Restart Apache an you should see any output of your application (or any child process, as it is your case) in the error.log file of Apache.
Note: Don't add the Apache log files directory to your virtual host configuration. You aren't granting permissions to Apache over those files but allowing anyone to see them, which is as you can imagine a non-trivial security risk.
Update
Avoiding permission problems
You may want to try to use WSGI in daemon mode. That way the web application can be executed under your username (much like when using the internal development server). In your case, the configuration directives should be something along the lines:
WSGIDaemonProcess site1 user=<USERNAME> group=<GROUP> processes=1 threads=1
WSGIScriptAlias /testsite "C:/sites/testsite/wsgi.py"
<Directory "C:/sites/testsite/">
WSGIProcessGroup site1
WSGIApplicationGroup %{GLOBAL}
Order allow,deny
Allow from all
</Directory>
You have to substitute <USERNAME> and <GROUP> by your username and group in your Windows machine (it may work by just setting the username though). This is usually a nice way of avoiding permission issues since your application will be executed in a very similar way to how it is executed by the development server. (Notice that we're using just one process and one thread just to make Apache behave even more closely to how the development server does. You surely want to change those values in production to higher values).
You can check the daemon mode documentation here
Executing your script
To call external program from Python code, the module subprocess is usually preferred over os.system calls. The former allows you to have much more control over how the new process has to be executed whereas the later just passes the call to the operating system.
You can try the subprocess.check_output function. It executes a script/program and allows you to capture its output:
print subprocess.check_output(['C:\Sites\testsite\testsite\test.bat'], shell=True)
It has the additional advantage that you can capture the output in a string variable. (Btw, you may or may not need the shell=True param in Windows when calling a bat script, I'm not sure about that).