I'm working with a shared hosting account which uses apache 2.4 , trying to deploy a flask app using http://fgimian.github.io/blog/2014/02/14/serving-a-python-flask-website-on-hostmonster . I've put the code and the fcgi script in public_html folder The contents of the folder are in the screenshot above:
The manage_apache.fcgi script is:
#!/home/username/anaconda2/bin/python
import sys,os
from flup.server.fcgi import WSGIServer
sys.path.insert(0, '/home/username/public_html')
from myflaskapp.settings import Config, SharedConfig
from myflaskapp.app import create_app
if __name__ == '__main__':
app = create_app(SharedConfig)
WSGIServer(app).run()
I've gotten to the last step and while testing it at the command line using putty to SSH in:
[~/public_html]# ./manage_apache.fcgi
I can see the correct web page being generated, so I assume that fast cgi is supported by my host. I'm not getting any python errors.
The .htaccess file out of the article is :
AddHandler fcgid-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ manage_apache.fcgi/$1 [QSA,L]
In the browser when I surf to mysite.org I am getting
Not Found
The requested URL /manage_apache.fcgi/ was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
according to support The .htaccess file is redirecting to manage_apache.fcgi/$1
-rwxr-xr-x 1 myusername myusername Nov 22 17:26 manage_apache.fcgi*
How can I fix this?
I suspect
sys.path.insert(0, '/home/username/public_html')
is an absolute path, but flask application is looking to a relative path respect to flask gateway, and cannot find it.
Have you tried to wrap the libraries in the app instance - move the absolute path in the app instance?
As an example, see http://werkzeug.pocoo.org/:
from werkzeug.wrappers import Request, Response
#Request.application
def application(request):
return Response('Hello World!')
if __name__ == '__main__':
from werkzeug.serving import run_simple
# move absolute path here
run_simple('localhost', 4000, application)
I suspect that fcgi is not supported on that host. Just because a host lets you run a Python script on the command line does not mean that they have configured mod_fcgi in Apache.
Try this: apachectl -t -D DUMP_MODULES | grep cgi. You should see fcgi_module or fastcgi_module, or possibly a cgi_module.
If you only see a cgi_module, then you should be able to use AddHandler cgi-script .py instead of AddHandler fcgid-script .fcgi.
If you see none of those, then you can try wsgi: apachectl -t -D DUMP_MODULES | grep wsgi. If you see wsgi_module, then you know you can use wsgi. At that point, you might be able to follow instructions here under .htaccess.
Related
I registered a domain and it allows the use of CGI scripts. But I don't know how to run flask + python with the script.
https://flask.palletsprojects.com/en/1.1.x/deploying/cgi/ gives a decent description of what to do but still was unable to get flask and python to run. My python file:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return '<h1>Hello World!</h1>'
Also the cgi file:
#!/usr/bin/python
from wsgiref.handlers import CGIHandler
from yourapplication import app
CGIHandler().run(app)
And the htaccess file:
DirectoryIndex Home.html
# Begin EnforceSSL double-numbersign-freelancer.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www.)?double-numbersign-freelancer.com$
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L]
</IfModule>
# End EnforceSSL
Okay. I checked it
Answering for my configuration → CentOS 7 / httpd 2.4.6
Open /etc/httpd/conf/httpd.conf and add python handler
# standard part
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Require all granted
# add handler here
AddHandler cgi-script .py
</Directory>
Put run.py inside /var/www/cgi-bin
#!/usr/bin/python3
from wsgiref.handlers import CGIHandler
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return '<h1>Hello World!</h1>'
#app.route('/suburl')
def index2():
return '<h1>Hello World 2!</h1>'
CGIHandler().run(app)
Change script permissions to allow execution:
chmod +x /var/www/cgi-bin/run.py
Now you can access:
http://your_server_url.com/cgi-bin/run.py → Hello World!
http://your_server_url.com/cgi-bin/run.py/suburl → Hello World 2!
Huh. That was my first experience with Flask CGI. Pretty simple and good for small or test projects.
Anyway I recommend to use gunicorn, uwsgi or mod_wsgi for apache in production.
EDIT1: Using CGI without flask
Actually you don't need flask for run CGI scripts. It can be written with any language that can read environment variables and output some data.
Bash example /var/www/cgi-bin/run.cgi:
#!/usr/bin/bash
echo "Content-type:text/plain"
echo
echo -e "HELLO WORLD\nYour URL path is $PATH_INFO"
Output will be:
http://example.com/cgi-bin/run.cgi/suburl
HELLO WORLD
Your URL path is /suburl
I've been trying now for some time to deploy my flask app on a Godaddy hosting server. I have done extensive searches online and followed them but I'm still having issues. Right now my app is just displaying as ordinary html so I'm having things like {{my_var}} displayed on the page. My flask app works locally and this is the folder structure;
myApp folder, which contains static folder for css,javascript, and images, templates folder for my html, and the myapp.py and forms.py files come under the myApp folder
On my hosting server my folder structure is currently this; $HOME/public_html which contains the index.html and base.html (index.html inherits from this file for the header and footers), $HOME/public_html/cgi-bin which contains myapp.cgi, myapp.py, and .htaccess files.
I've created a cgi file and made it executable which is saved in the public_html/cgi-bin folder. The file is also made executable with 755 permission. These are the contents;
#!/home/username/public_html/cgi-bin/flask_app/bin/python
from wsgiref.handlers import CGIHandler
from myapp import app
import os
import cgitb; cgitb.enable()
os.environ["SERVER_NAME"] = "127.0.0.1"
os.environ["SERVER_PORT"] = "4000"
os.environ["REQUEST_METHOD"] = "GET"
os.environ["SERVER_PROTOCOL"] = "http/1.1"
CGIHandler().run(app)
Note the shebang on my files is the path to my virtualenv where I have flask installed. The version of python is v2.7
I also have my main flask app (myapp.py which is also executable and with 755 permissions) file with the routes and the contents are as follows;
#!/home/username/public_html/cgi-bin/flask_app/bin/python
import os
import sys
sys.path.insert(0, '/home/aofadero/public_html/cgi-bin')#path to myapp.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/')
def home():
return render_template("index.html")
if __name__ == "__main__":
app.run()
This file is also in my public_html/cgi-bin folder. I also have a .htaccess file which has the following content;
AddHandler cgi-script .cgi .py
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(/home/username/public_html/cgi-bin/myapp.cgi)
RewriteRule ^(.*)$ /home/username/public_html/cgi-bin/myapp.cgi/$1 [L]
Now this .htaccess file is currently in my public_html/cgi-bin folder because if I place it in public_html folder, I get a 500 error message. The only time I don't get the error is when the .htaccess file is in the cgi-bin folder. Some of the research I've done say to place it in the cgi-bin folder, others say in the public_html folder. I find that it only works for me when it's in the cgi-bin folder. If I do ./myapp.cgi I get the following error;
Status: 404 NOT FOUND
Content-Type: text/html
Content-Length: 233
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>...
Can anyone help me please because I've tried about everything I could on my own. Right now I'm just getting ordinary html and none of the flask components are showing. Thanks
I have similar problems. I understand that an index.htm file must be placed at public_html, but when you try to do render_template("index.htm"), Flask will look for this file in the templates folder. The rendering is not actually executed. The index.htm file will always be displayed on the browser as a default page. Have you been able to find the solution ?
You don't need to include the Python script in the public_html. If you go to the Cpanel main page and search for Python. From there, you can create a Python app which will let you direct your website to run the Python script.
Application root = path to the folder your python is stored. I stored mine in a Python folder in the root of the private html.
Application url = what URL should you need to put into the browser to get that script.
Application startup file = The name of your Python script.
Application Entry point = The callable object in your Python script (in your case, it would be app).
Please see the video here for a walkthrough of this process: https://www.youtube.com/watch?v=xFxL7Mvut6g&ab_channel=Hob-iZadeAdemEfendi
I'm having trouble deploying my REST API and keep getting a 500 Internal Server Error. I've gone through several possible solutions and guides to fix this problem, including those below:
http://flask.pocoo.org/docs/0.10/deploying/cgi/
Deploy flask application on 1&1 shared hosting (with CGI)
and was following this guide:
http://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask
Here is my code:
restapplication.py
#!/home/myusername/public_html/todo-api/flask/bin/python
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return "Hello, World!"
run.cgi
#!/home/myusername/public_html/todo-api/flask/bin/python
import cgitb; cgitb.enable()
from wsgiref.handlers import CGIHandler
from restapplication import app
CGIHandler().run(app)
.htaccess (stored at /home/myusername/public_html/)
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /home/myusername/public_html/todo-api/flask/run.cgi/$1 [L]
I appreciate all the help I can get.
Not sure if you got the solution, but for records-
if you have your virtual environment set, then you will have to add these lines in your restapplication.py to point to the site-packages, so that your code can access Flask library.
import os
import sys
sys.path.insert(0, '/home/username/public_html/cgi-bin/myenv/lib/python2.6/site-packages')
Rest everything looks okay.
Maybe you can check the file permissions of the .cgi file and .py file. The file permissions should be 755.
refer : http://www.comfycoder.com/home/how_to_deploy_a_flask_app_in_apache_shared_hosting
Summary
Django 1.6
Python 2.6
Apache 2.2.27
PostgreSQL 8.4.20
psycopg2
flup
Viewing the FastCGI wrapper page for my Django site via the command line seems to work fine, but I always get a 404: Page Not Found when viewing my site via a browser. What am I doing wrong? I suspect it has to do with my Apache setup.
Versions and Setup
The Django 1.8 documentation says fastcgi support is deprecated as of Django 1.7, and I can't use mod_wsgi, so I am using Django 1.6. Python 2.7 and later are unavailable, so I am using Python 2.6. And the hosting company won't install Python packages for me, but I managed to install flup and psycopg2 myself. (Note that I had to compile psycopg2 on my Linux64 machine and upload it to the server.)
Django, flup, and psycopg2 are installed in /home/account/public_html/sitename/site-packages/. My Django site is located in /home/account/public_html/sitename/sitename/. Issuing set | grep -e PYTHON -e DJANGO at the command prompt returns no results (i.e., no PYTHON or DJANGO environment variables are set).
Full Story
I am trying to set up Django on shared hosting. And before anyone suggests it: unfortunately, mod_wsgi is out of the question.
I followed the directions here: https://docs.djangoproject.com/en/1.6/howto/deployment/fastcgi/#apache-shared-hosting and ended up with this /home/account/public_html/.htaccess:
AddHandler fastcgi-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ sitename/site.fcgi/$1 [QSA,L]
and this /home/account/public_html/sitename/site.fcgi:
#!/usr/bin/python
import sys, os
# Add a custom Python path.
sys.path.insert(0, "/home/account/public_html/sitename")
sys.path.insert(0, "/home/account/public_html/sitename/site-packages")
# Switch to the directory of your project. (Optional.)
os.chdir("/home/account/public_html/sitename")
# Set the DJANGO_SETTINGS_MODULE environment variable.
os.environ['DJANGO_SETTINGS_MODULE'] = "sitename.settings"
# From Django
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="prefork", daemonize="false", debug="true")
When I do cd /home/account/public_html/sitename/ ; ./site.fcgi, I get:
WSGIServer: missing FastCGI param REQUEST_METHOD required by WSGI!
WSGIServer: missing FastCGI param SERVER_NAME required by WSGI!
WSGIServer: missing FastCGI param SERVER_PORT required by WSGI!
WSGIServer: missing FastCGI param SERVER_PROTOCOL required by WSGI!
Status: 200 OK
X-Frame-Options: SAMEORIGIN
Content-Type: text/html; charset=utf-8
<!DOCTYPE html>
<html>
<head>
...etc...
which is the correct index page for my Django site. So that works. (I am ignoring the WSGIServer errors for now, because calling site.fcgi from the command prompt is, obviously, outside the WSGI environment.)
However, when I navigate my browser to http://example.com/, I get a 404: Page Not Found error, and the server error log shows only:
[error] File does not exist: /home/account/public_html/sitename/site.fcgi/
Navigating to http://example.com/valid-page also produces a 404, with the server error:
[error] File does not exist: /home/account/public_html/sitename/site.fcgi/valid-page
What am I doing wrong? Or how does WSGI work, so I can debug this better?
Variations I've Tried
Use the HostGator approach to site.fcgi by doing this instead:
# From Django
#from django.core.servers.fastcgi import runfastcgi
#runfastcgi(method="prefork", daemonize="false", debug="true")
# From HostGator
from flup.server.fcgi import WSGIServer
from django.core.wsgi import get_wsgi_application
WSGIServer(get_wsgi_application()).run()
Same result: 404. This makes sense, because manually walking the code shows that the From Django code is just a wrapper for the From HostGator code.
Use the fcgid-script handler in .htaccess instead of fastcgi-script:
#AddHandler fastcgi-script .fcgi
AddHandler fcgid-script .fcgi
Use a RewriteCond in .htaccess that I found in another tutorial:
#RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(sitename/site.fcgi)
RewriteRule ^(.*)$ sitename/site.fcgi/$1 [QSA,L]
Pass the WSGI URI as command-prompt-style parameter (note the space instead of /):
#RewriteRule ^(.*)$ sitename/site.fcgi/$1 [QSA,L]
RewriteRule ^(.*)$ sitename/site.fcgi $1 [QSA,L]
Ensure the REQUEST_URI environment variable is set:
SetEnv REQUEST_URI %{REQUEST_URI}
Even make site.fcgi a CGI script, just to see if I could reproduce the success of running site.fcgi from the command prompt (probably not a permanent solution):
#AddHandler fastcgi-script .fcgi
#RewriteEngine On
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteRule ^(.*)$ sitename/site.fcgi/$1 [QSA,L]
Options -Indexes +ExecCGI
AddHandler cgi-script .fcgi
and then navigating to http://example.com/sitename/site.fcgi.
None of the above variations worked, nor did many combinations of several of them. Many of them returned 404: Page Not Found, and some returned more glaring errors, while others just displayed the source of site.fcgi.
Edit
I am getting the same/similar results for shared hosting with both Arvixe and LunarPages. The above description is using only my Arvixe account, because my LunarPages account does not have SSH access and is therefore harder to debug.
I'd even be willing to entertain low-cost alternative hosting plans (e.g., other hosting companies) that would enable this to work. This is just a personal website, not generating any money, so I don't want to spend the ~$20/month that Arvixe and LunarPages are asking to have dedicated hosting in order to have mod_wsgi access.
Thanks in advance for any help or suggestions!
I ran into the same problem (posted here) and ended up determining that it was due to restrictions on the shared hosting account I was subscribed to with bluehost. I switched a dreamhost shared hosting plan and was up and running in no time.
I readed the deploying django app from Alwaysdata and I have a problem.
We I run bash django.fcgi, terminal shows :
import: unable to open X server `' # import.c/ImportImageCommand/367.
django.fcgi: line 5: syntax error near unexpected token `('
django.fcgi: line 5: `PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))'
I made all they said but I can't fix that. I run on Django 1.5.
- mymodule
- mysite
... __init__.py
... settings.py
... urls.py
.. wsgi.py
- public
... django.fcgi
... .htaccess
... static
... media
- manage.py
- statics
- templates
- __init__.py
This is django.fcgi and .htaccess :
#!/usr/bin/python
import os, sys
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, PROJECT_DIR)
sys.path.insert(0, os.path.dirname(PROJECT_DIR))
PROJECT_NAME = PROJECT_DIR.split('/')[-1]
os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")
AddHandler fcgid-script .fcgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ django.fcgi/$1 [QSA,L]
Where is my problem ? I encoded my django.fcgi file in Unicode BOM, like here but no results. Have you any idea ?
Thank you...
EDIT: And well, my website doesn't work : 500 Internal Server Error.
Server configuration : Apache, Python 2.6, Django 1.5
I think you are not supposed to run that file that way. Despite having the shebang line at the beginning, the file should be interpreted as a shell script (bash) and not a python script, hence the "import" error (import seems to be an ImageMagick command which makes something like a screenshot).
So the correct way to run that file would one of those
bash -c "./django.fcgi" # file must have execution permission
python django.fcgi
./django.fcgi # also
The 500 error can be debugged either turning DEBUG=True on settings.py or reading the logs, if your application is configured to log somewhere.
Edit:
Regarding the import error, I think the right configuration is
os.environ['DJANGO_SETTINGS_MODULE'] = "mysite.settings"
The way you have it Django is trying to load public/settings.py which fails. More info here.
If that doesn't work try to specify the full path to settings.py:
os.environ['DJANGO_SETTINGS_MODULE'] = os.path.join(PROJECT_DIR, "mysite", "settings")
Hope it helps.