Apache httpd not able to access local MongoDB (permission denied) - python

I am using to apache httpd to serve my python application. The application is running perfectly in standalone mode using the binary executable command inginious-webapp. MongoDB also works fine.
But the problem arises when serving it though Apache HTTPD
When I browse the website I get a 500 error. This is the error_log
[Wed Jun 14 06:00:20.113043 2017] [wsgi:error] [pid 1194] [client 125.99.159.82:29947] pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 13] Permission denied, referer: http://<my_domain>.eastus.cloudapp.azure.com/
Config Info
Added apache to mongodb -> usermod -aG mongodb apache
Changed owner to apache -> chown -R apache:apache /var/www/INGInious
httpd.conf
# Default config till here. Changes follows
Include conf.modules.d/*.conf
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# 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 apache
Group apache
LoadModule wsgi_module /usr/lib64/python3.5/site-packages/mod_wsgi/server/mod_wsgi-py35.cpython-35m-x86_64-linux-gnu.so
WSGIScriptAlias / "/usr/bin/inginious-webapp"
WSGIScriptReloading On
Alias /static/common /usr/lib/python3.5/site-packages/inginious/frontend/common/static/
Alias /static/webapp /usr/lib/python3.5/site-packages/inginious/frontend/webapp/static/
Alias /static/lti /usr/lib/python3.5/site-packages/inginious/frontend/lti/static/
# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition. These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed. This address appears on some server-generated pages, such
# as error documents. e.g. admin#your-domain.com
#
ServerAdmin root#localhost
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName http://<my_domain>.eastus.cloudapp.azure.com:80
#
# Deny access to the entirety of your server's filesystem. You must
# explicitly permit access to web content directories in other
# <Directory> blocks below.
#
<Directory />
AllowOverride none
Require all denied
</Directory>
#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#
<Directory "/usr/bin">
<Files "inginious-webapp">
Require all granted
</Files>
</Directory>
<DirectoryMatch "/usr/lib/python3.5/site-packages/inginious/frontend/(.+)/static/">
Require all granted
</DirectoryMatch>
# Rest Unchanged

I was having the same issue, and after a fair bit of hair pulling I found out that selinux was enabled on the virtual machine I was using.
If it so happens you also have selinux enabled (http://www.microhowto.info/howto/determine_whether_selinux_is_enabled.html), to get around this issue you need to allow the httpd process make network requests. You can do that by executing the following:
sudo /usr/sbin/setsebool -P httpd_can_network_connect 1
and then restart the apache service.
Unfortunately, you will most likely run into another road block afterwards when INGInious attempts to connect to the docker daemon. To get around this you will need to create a local policy module. The local policy module will then permit INGInious to connect to the docker daemon. I recommend installing sealert. This can be done by running:
sudo yum install setroubleshoot setools
if you are using CentOS (and likely RedHat). Once you have sealert installed run:
sealert -a /var/log/audit/audit.log
This will give you some info about operations being blocked by selinux. If you dig through the log you will see that the httpd is being denied access to the socket for the docker daemon. Chances are it will give you some instructions on how to generate the local policy module for httpd. Using CentOS, I had to run:
ausearch -c 'httpd' --raw | audit2allow -M my-httpd
semodule -i my-httpd.pp
If ausearch returns an error indicating that /etc/selinux/targeted/contexts/files/file_contexts.local is not present, simply run:
sudo touch /etc/selinux/targeted/contexts/files/file_contexts.local

Related

OSError: [Errno 98] Address already in use Running Flask Application on Apache2

I have my flask code in app.py
/some code//
if __name__ == '__main__':
app.run()
and i have set up my wsgi file as in the path /var/www/AutomateTests
#!/usr/bin/python3.6
import sys
import logging
sys.path.insert(0,"/var/www/AutomateTests/")
from app import app as application
application.root_path = '/var/www/AutomateTests/'
and I have /etc/apache2/sites-available/automate_tests.conf
VirtualHost *:80>
ServerName htstool.arubanetworks.com
ServerAdmin admin#htstool.arubanetworks.com
ServerAlias htstool.arubanetworks.com
ErrorLog /var/log/apache2/hts-error.log
CustomLog /var/log/apache2/htstool-access.log combined
WSGIDaemonProcess AutomateTests user=www-data group=www-data threads=5
WSGIScriptAlias / /var/www/AutomateTests/automate_tests.wsgi
<Directory /var/www/AutomateTests>
WSGIProcessGroup AutomateTests
WSGIApplicationGroup %{GLOBAL}
Order allow,deny
Allow from all
</Directory>
LogLevel info
</VirtualHost>
I have set up everything rightly and i have been stuck on this problem for weeks now. Can someplease help me on how to bring it up on the server. Is there a step i am missing.
im setting the same error of my port is in use although ITS NOT!
See the picture of my error
enter image description here
But as you can see my ports are empty and not being used. I check that using the command netstat -ntlp
see my ports are listening and not established
Can someone please please help me. I am stuck and don't mark it as already answered before checking it completely. I have tried all the answers and they don't work! Please be patient and let others help me because I can't do it myself.
My server is running fine and I'm seeing the default ubuntu page which means that my apache2 server is working fine so there is something wrong with either the configuration or my ports
Two things come to mind when I see this.
Do you have Apache installed and running on the server? Apache may be listening on port 80 and preventing your Python script from binding to that port, but the way you ran netcat won't show this. You can check this at [sever_ip]:80.
But as you can see my ports are empty and not being used. I check that using the command netstat -ntlp
Note the first line of output from that command: (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) Apache runs with elevated privileges, so you'll need to run as root (append sudo to the beginning of your command) to see its port binding. I'd bet that this is the issue. Once this is fixed, you may run in to the following issue:
Are you running the script as root? On Linux, you need to use sudo to bind to ports 0 through 1024 (as explained here).
One more thing, not related to the script specifically, but it looks like you're using AWS EC2 in the screenshots (correct me if I'm wrong). If you want to be able to reach the instance on port 80 from the public internet, you'll need to make sure you allow it in the Security Group. I know this can cause some confusion for people using AWS EC2 for the first time, sure did for me.
Hope this helps!

Flask App visible to localhost only

Trying to host python flask app on Ubuntu 18.04 vps. I am using python version 3.6 and not using virtual environment since that vps will be used to host one app only.
This is the content of apache2 config file for this app:
<VirtualHost *:80>
ServerName 15.16.541.21
WSGIScriptAlias / /var/www/psoftware-nis-app/Backend/flask-api/api.wsgi
<Directory /var/www/psoftware-nis-app/Backend/flask-api>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
Static IP address I provided is of course not real, but in conf it is the real static IP address of the machine that hosts this app.
When I curl http://localhost/api/test_endpoint I get a valid response (from vps).
But when I curl http://15.16.541.21/api/test_endpoint from my laptop I get:
Connection timed out
When I execute this: nmap -p 80 15.16.541.21 i get:
Host seems down. If it is really up, but blocking our ping probes,
try -Pn
So when i add -Pn and execute: nmap -p 80 18.191.182.118 -Pn I get:
Host is up. PORT STATE SERVICE 80/tcp filtered http
Is something wrong with my config file? Or any other idea why the app is not visible to outside world?
EDIT:
I have configured main python module, host option is set:
if __name__ == '__main__':
app.run(host='0.0.0.0')
By default, flask app is only visible for local access. You need to specify the host option --host=0.0.0.0 to make it visible for other network.
Externally Visible Server
If you run the server you will notice that the server is only
accessible from your own computer, not from any other in the network.
This is the default because in debugging mode a user of the
application can execute arbitrary Python code on your computer.
If you have the debugger disabled or trust the users on your network,
you can make the server publicly available simply by adding
--host=0.0.0.0 to the command line:
flask run --host=0.0.0.0
This tells your operating system to listen on all public IPs.
Check this http://flask.pocoo.org/docs/1.0/quickstart/#quickstart

django deploy - ubuntu 14.04 and apache2

https://www.sitepoint.com/deploying-a-django-app-with-mod_wsgi-on-ubuntu-14-04/
and
https://www.youtube.com/watch?v=hBMVVruB9Vs
This was the first time I deploy a website.And these are the tutorials I followed.
Now I can access to the server(by typing 10.231.XX.XX) from other machine and see the Apache2 Ubuntu Default Page.
Then I tried to access my django project. I run:
python manage.py runserver 8000
Validating models...
0 errors found August 03, 2016 - 09:44:20 Django version 1.6.1, using
settings 'settings' Starting development server at
http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Then I type 10.231.XX.XX:8000 to try to acess the django page. But I failed.
It said:
This site can’t be reached
10.231.XX.XX refused to connect. Search Google for 231 8000 ERR_CONNECTION_REFUSED
I have tried every thing I can but still can't figure why.
(as followed the website https://www.sitepoint.com/deploying-a-django-app-with-mod_wsgi-on-ubuntu-14-04/)
I have apache folder in mysite folder, and in override.py:
from mysite.settings import *
DEBUG = True
ALLOWED_HOSTS = ['10.231.XX.XX']
in wsgi.py:
import os, sys
# Calculate the path based on the location of the WSGI script.
apache_configuration= os.path.dirname(__file__)
project = os.path.dirname(apache_configuration)
workspace = os.path.dirname(project)
sys.path.append(workspace)
sys.path.append(project)
# Add the path to 3rd party django application and to django itself.
sys.path.append('/home/zhaojf1')
os.environ['DJANGO_SETTINGS_MODULE'] = '10.231.52.XX.apache.override'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
and __init__py is empty.
in /etc/apache2/sites-enabled/000-default.conf :
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster#localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
WSGIScriptAlias /msa.html /home/zhaojf1/Web-Interaction/apache/wsgi.py
<Directory "/home/zhaojf1/Web-Interaction-APP">
<Files wsgi.py>
Require all granted
</Files>
</Directory>
I have also restart apache after I do everything.
Thanks for help
The connection refused error is likely going to come down to Apache being incorrectly configured for the VirtualHost or you accessing wrong port. You also have other basic mistakes in your wsgi.py file as well.
Starting with the wsgi.py file, the DJANGO_SETTINGS_MODULE value is wrong:
os.environ['DJANGO_SETTINGS_MODULE'] = '10.231.52.XX.apache.override'
The value is meant to be a Python module path. Having the IP address in there looks very wrong and is unlikely to yield what you need.
Next is changes to sys.path. The location of your project and activation of any Python virtual environment is better done through options for mod_wsgi in the Apache configuration file.
That you are adding a home directory into the path is also a flag to potential other issues you may encounter. Specifically, the user that Apache runs as often cannot read into home directories as the home directories are not readable/accessible to others. You may need to move the project out of your home directory.
As to the Apache configuration, your VirtualHost lacks a ServerName directive. If this was an additional VirtualHost you added and not the default (first one appearing in Apache configuration when parsed), it will be ignored, with all requests going to the first VirtualHost. You do show this as in the default site file, so may be you are okay.
Even so, that VirtualHost is set up to listed on port 80. You are trying to connect to port 8000, so there wouldn't be anything listening.
Next issue is the WSGIScriptAlias line.
WSGIScriptAlias /msa.html /home/zhaojf1/Web-Interaction/apache/wsgi.py
It is strange to have msg.html as the mount point as that makes it appear as if you are accessing a single HTML page, but you have it mapped to a whole Django project. If you were accessing the root of the host, it also wouldn't map through to the Django application as you have it mounted at a sub URL. Thus perhaps need to use:
WSGIScriptAlias / /home/zhaojf1/Web-Interaction/apache/wsgi.py
Next problem is that the directory specified in Directory directive doesn't match where you said the wsgi.py file existed in the WSGIScriptAlias. They should match. So maybe you meant:
<Directory /home/zhaojf1/Web-Interaction/apache>
Even then that doesn't look right as where is the apache directory coming from. That last directory in the path should normally be the name of the Django project.
One final thing, you may need to change ALLOWED_HOSTS as well. If you find you start getting bad request errors it probably doesn't match properly. Change it to ['*'] to see if that helps.
So lots of little things wrong.
Suggestions are:
Make sure you read the official Django documentation for setting up mod_wsgi. See https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/modwsgi/
If you are only wanting to do development at this point, use mod_wsgi-express instead. See http://blog.dscpl.com.au/2015/04/using-modwsgi-express-with-django.html and http://blog.dscpl.com.au/2015/04/integrating-modwsgi-express-as-django.html

OperationalError: attempt to write a readonly database in ubuntu server

I'm running a FlaskApp using mod_wsgi and apache2 on Ubuntu server. I tried running the flask app on localhost successfully and then deployed it on ubuntu server.
But when i try to update database, its giving error:
Failed to update model. (OperationalError) attempt to write a readonly database u'UPDATE mysongs SET songurl=? WHERE songid.id = ?' (u'www.site.com/I_wanna_dance', 1)
Now i tried look for database file permission which is:
-rwxr-xr-x 1 www-data www-data 10240 Jul 14 15:35 /var/www/mywebsite/appfolder/appdata.db`
When i try changing permission to 777, 755, 644 etc. it shows another error: unable to open database file Although database file works fine with 644 permission on localhost but not on ubuntu server.
Also i checked permission of directories and for /var /var/www /var/www/mywebsite /var/www/mywebsite/appfolder etc., all have www-data:www-data as its owner username and group.
I tried googling and but no proper solution other than suggestion of changing file/dir permissions, which i have tried myself.
Why can't it read/access the database file?
Please suggest.
This issue is related to the files permissions management AND mostly to the user chosen in the Apache configuration file (*.conf) defined to holds the application processes. In a few words : the write permissions need to match this user.
Most of the time, the sqlite database file has been created by a specific user (for example your current user) and the site application is running under child processes launched by the Apache default user www-data (if the parameter user wasn't specified inside the directive WSGIDaemonProcess). In this case, the database can be read but it will throw this error if you try to modify anything :
(OperationalError) attempt to write a readonly database...
because www-data has no permission on the file (or on the parent folder)
First way : Apply permissions to the user www-data
You can set the write permissions on the database file and its parent folder.
If the folder contains other files, you can add write permission on it and only change the ownership of the database file to the user www-data, for example :
sudo chmod o+w db_directory
sudo chown www-data: db_directory/site_database.db
Or if the folder contains only the database file, you can try to change the folder owner directly :
sudo chown -R www-data: db_directory
Then check that read/write permissions are well set (with ls -l site_database.db)
More help in this post.
Other solution : Add a specific user to hold the application processes
This can be done by giving the user and group parameters in the directive WSGIDaemonProcess in Apache configuration.
It will make Apache launch the child processes under a specific user.
For example :
...
WSGIDaemonProcess main user=myuser group=myuser threads=3 python-home=/path/to/the/virtualenv/
WSGIProcessGroup main
WSGIApplicationGroup %{GLOBAL}
...
This user will manage all operation, including read/write to any files, so check that it has all needed permissions on every related files.
For security concerns, you may not use a wide-privileged user.
Some comments can help in this post.
Note : be careful if you manage your own logging files with directives like ErrorLog in the Apache configuration, these files will follow the same logic of permissions. The same for any file that could be changed by the application.
Resolved the issue. It was due to database file permission conflict.
Just give www-data permision to your project and db
sudo chown www-data:www-data ProjectPath
sudo chown www-data:www-data dbPath
Faced this issue while hosting Django Rest Framework on IIS 7.5 / Windows 2008 Server. It was working fine on local host . I added new feature to handle file upload feature along with "file name" . The files were uploaded properly but the database seemed to not accept the text from "file name" string.
Solution :
Go to your concern database. (if you have not assigned any particular database,consider the file db.sqlite3 in base folder)
Right click on the db.sqlite3 --> Properties --> Security --> Edit --> Add
In the text box enter Everyone --> Checkname --> ok
Refresh the server at IIS and try to run the application.

Running pdb in daemon mode with WSGI

I am running a Python script on Apache 2.2 with mod wsgi.
Is it possible to run pdb.set_trace() in a python script using daemon mode in wsgi?
Edit
The reason I want to use daemon mode instead of embedded mode is to have the capability to reload code without having to restart the Apache server every time (which embedded mode requires). I would like to be able to use code reloading without restarting Apache everytime and still be able to use pdb...
I had the same need to be able to use the amazingly powerful pdb, dropping a pdb.set_trace() wherever I wanted to debug some part of the Python server code.
Yes, Apache spawns the WSGI application in a place where it is out of your control [1]. But I found a good compromise is to
maintain your Apache WSGIScriptAlias
and also give yourself the option of starting your Python server in a terminal as well (testing locally and not through Apache anymore in this case)
So if one uses WSGIScriptAlias somewhat like this...
pointing to your python WSGI script called webserver.py
<VirtualHost *:443>
ServerName myawesomeserver
DocumentRoot /opt/local/apache2/htdocs
<Directory /opt/local/apache2/htdocs>
[...]
</Directory>
WSGIScriptAlias /myapp /opt/local/apache2/my_wsgi_scripts/webserver.py/
<Directory /opt/local/apache2/my_wsgi_scripts/>
[...]
</Directory>
[...]
SSLEngine on
[...]
</VirtualHost>
And so your webserver.py can have a simple switch to go between being used by Apache and getting started up for debugging manually.
Keep a flag in your config file such as, in some settings.py:
WEBPY_WSGI_IS_ON = True
And webserver.py :
import web
import settings
urls = (
'/', 'excellentWebClass',
'/store', 'evenClassier',)
if settings.WEBPY_WSGI_IS_ON is True:
# MODE #1: Non-interactive web.py ; using WSGI
# So whenever true, the Web.py application here will talk wsgi.
application = web.application(urls, globals()).wsgifunc()
class excellentWebClass:
def GET(self, name):
# Drop a pdb wherever you want only if running manually from terminal.
pdb.set_trace()
try:
f = open (name)
return f.read()
except IOError:
print 'Error: No such file %s' % name
if __name__ == "__main__":
# MODE #2: Interactive web.py , for debugging.
# Here you call it directly.
app = web.application(urls, globals())
app.run()
So when you want to test out your webserver interactively, you just run it from a terminal,
$ python webserver.py 8080
starting web...
http://0.0.0.0:8080/
[1] Footnote: There are some really complex ways of getting Apache child processes under your control, but I think the above is much simpler if you just want to debug your Python server code. And if there are actually easy ways, then I would love to learn about those too.

Categories