Anybody know how to deploy a simple Flask application on Webfaction?
I know Webfaction support mod_wsgi and I read the guide on the Flask site but still I can't make my app working. Anybody have a working configuration?
UPDATE to answer a comment by Graham Dumpleton.
I get a 500 Internal server error. Apache does not show any error in the logs. The WSGI script is executed and seems to create the application correctly, but I keep getting a 500 error.
Thanks.
I got it working with the following procedure:
create and app named 'myapp' of type mod_wsgi 3.3/Python 2.7. Webfaction will create the following folders:
myapp
|- apache2
|- htdocs
Webfaction will also automatically create a simple script index.py in your htdocs directory. Check if the sample script work visiting the root of your newly created application (to do thin on Webfaction you need to "mount" the app on a website). If it's all OK modify the script deleting the content and adding:
from myapp import app as application
In apache2/conf/httpd.conf add the follwing lines:
WSGIPythonPath /home/username/webapps/myapp/htdocs/
#If you do not specify the next directive the app *will* work but you will
#see index.py in the path of all subdir
WSGIScriptAlias / /home/username/webapps/myapp/htdocs/index.py
<Directory /home/username/webapps/myapp/htdocs>
AddHandler wsgi-script .py
RewriteEngine on
RewriteBase /
WSGIScriptReloading On
</Directory>
Restart apache2
You need to set up a "Custom app (listening on port)" application. Make a note of the port that is assigned. Then in your Flask code, you need to put hardcode the port:
if __name__ == __main__:
app.run(host='0.0.0.0' port=XXXXXXX)
Where you substitute XXXXXXX with the port that is randomly assigned to your custom app.
Hope that helps.
EDIT:
Please use Raben's Answer, this way should not to be used in Production.
Related
I am trying to load a Flask app in a subdirectory on my domain. Below is my virtual host configuration. the Flask app is kept at /var/www/FlaskApps/Recommender/
Apache's error log keeps saying "Target WSGI script not found or unable to stat: /var/www/FlaskApps/FlaskApp.wsgi" when i try to reach the endpoint /recommender
From online other people said it might be a permission issue, but I'm not sure if it's the case per snapshot below.
Thanks for your help
You have FlaskApps.wsgi in directory, but FlaskApp.wsgi in WSGIScriptAlias directive. So they don't match.
I'm really struggling here. I have a simple Python Flask REST API that I've developed. The API runs fine in my local development environment (Mac OS X) and when directly executed via the console on my EC2 instance.
I want to move this service into production and as such would like to host it behind Apache running on the EC2 instance. This is where I keep hitting a wall and I can't seem to get past the configurations and errors. I've research several articles online and questions here, none seem to be able to help me.
I'm hoping someone here can please provide me with step-by-step directions on how to deploy my service to production behind Apache running on an Amazon Linux EC2 instance.
Here are the steps I've taken:
Launched a basic Amazon Linux EC2 instance.
Apply updates to the instance, sudo yum update
Install Apache and WSIG, sudo yum install httpd24 mod24_wsgi
Start Apache, sudo service httpd start
Configure Apache to start automatically, sudo chkconfig httpd on
Test by hitting the DNS of my EC2 box. I successfully get the Amazon Linux AMI test page.
Adjust permissions on /var/www as follows
sudo groupadd www
sudo usermod -a -G www ec2-user
Logon/off and confirm membership, groups
sudo chown -R root:www /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;
Test by hitting DNS of my EC2 box - still good so far.
Now that I know my instance is running, I would like to create two folders where I can test and run my Python Flask code. I do so as follows:
I create two folders, one for development and one for production.
/var/www/rest-dev/
/var/www/rest-prod/
I setup a virtual environment within each of the folders and install Flask.
virtualenv env
env/bin/pip install Flask
I then place a copy of my service in each folder.
Then I set permissions on app.py, chmod a+x app.py
I can successfully execute ./app.py and test the service by hitting the DNS name + port 5000. It works.
Now this is where I get tripped up. My goal is to be able to hit api.example.com and have my service's root load up. In the example code below, "Hello, World!" should simply display.
I've followed the tutorials found here with no luck.
http://peatiscoding.me/geek-stuff/mod_wsgi-apache-virtualenv/
http://webpy.org/cookbook/mod_wsgi-apache
http://www.jakowicz.com/flask-apache-wsgi/
After executing any of the steps in any of the articles above, I get an HTTP error page and nothing loads anymore, including the default Amazon Linux AMI test page. Below are the pieces of code and configurations that I've changed. I haven't changed my httpd.conf ... should I? There are probably several other things I'm missing.
Can someone please help me by providing me the necessary steps in detail to correct my mistakes?
Many thanks in advance!
When I view the error_log for HTTPD, it lists errors like this:
mod_wsgi (pid=8270): Target WSGI script '/var/www/rest-dev/deploy.wsgi' cannot be loaded as Python module.
mod_wsgi (pid=8270): Exception occurred processing WSGI script '/var/www/rest-dev/deploy.wsgi'.
Traceback (most recent call last):
File "/var/www/rest-dev/deploy.wsgi", line 16, in <module>
from app import app as application
File "/var/www/rest-dev/app.py", line 2, in <module>
from flask import Flask
ImportError: No module named flask
Here is my deploy.wsgi file, located in the rest-dev folder:
import os
import sys
import site
# Add virtualenv site packages
site.addsitedir(os.path.join(os.path.dirname(__file__), 'env/local/lib64/python2.7/site-packages'))
# Path of execution
sys.path.append('/var/www/rest-dev')
# Fired up virtualenv before include application
activate_env = os.path.expanduser(os.path.join(os.path.dirname(__file__), 'env/bin/activate_this.py'))
execfile(activate_env, dict(__file__=activate_env))
# import my_flask_app as application
from app import app as application
Here is my vhost.conf file located in /etc/httpd/conf.d/
<VirtualHost *:80>
ServerName api.example.com
WSGIDaemonProcess webtool user=ec2-user group=www threads=5 home=/var/www/rest-dev/
WSGIScriptAlias / /var/www/rest-dev/deploy.wsgi
<directory /var/www/rest-dev>
WSGIProcessGroup webtool
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
Order deny,allow
Allow from all
</directory>
</VirtualHost>
Here is my app.py example service code for reference:
#!env/bin/python
from flask import Flask
app = Flask(__name__)
#app.route('/')
def index():
return "Hello, World!"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Turns out, in my deploy.wsgi file I'm referencing lib64 instead of just lib. All the site packages exist in lib.
After changing it and restarting Apache, I'm able to successfully hit my service from the URL.
I have a test django project that I have been using the django development server for. I want to start using an actual apache server to properly simulate a production environment. I am using Mac OS X.
I have been using this tutorial here, but in the first set of instructions I am getting a 403 from localhost. The browser says I do not have permission to access / on the server.
When I comment out the apache config line from the tutorial, WSGIScriptAlias / /Users/username/Projects/django_books/django_books/django.wsgi I can access localhost.
This is the contents of my django.wsgi file:
import os
import sys
os.environ['DJANGO_SETTINGS_MODULE'] = 'django_books.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
path = '/Users/username/Projects/django_books/django_books'
if path not in sys.path:
sys.path.append(path)
What is causing the 403 and why can't I see my django application?
EDIT
Directory structure:
django_books
apache (empty directory right now)
random_book
__init__.py
models.py
views.py
django_books
__init__.py
django.wsgi
settings.py
urls.py
views.py
wsgi.py
media
static
css
style.css
manage.py
2ND EDIT
Permissions on all the directories:
/Users/username/Projects/django_books/django_books/django.wsgi
-rw-r--r--
/Users/username/Projects/django_books/django_books
drwxr-xr-x
/Users/username/Projects/django_books/
drwxr-xr-x
/Users/username/Projects/
drwxr-xr-x
/Users/username/
drwxr-xr-x+
/Users/
drwxr-xr-x
According to my small experience I think you must add the following lines "just below the import sys line to place your project on the path" (so juste under "import sys") like it's said in the tutorial you quote. Also, erase the second "django_books" in your path because you want to link to your site not the app in your site ;-) ("mysite" in the tutorial, not mysite/mysite)
import os
import sys
path = '/Users/username/Projects/django_books'
if path not in sys.path:
sys.path.append(path)
os.environ['DJANGO_SETTINGS_MODULE'] = 'django_books.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Bye
It's likely an issue related either to your Apache installation, python library, or the filesystem's permissions.
Testing Apache
You don't say it in your question, but I assume from your link you are working with Apache2 and mod_wsgi.
You can test if Apache and mod_wsgi (or your wsgi module) are working properly by placing a dummy wsgi script in the place of django.wsgi . This script (stolen from mod_wsgi's docs) doesn't rely on Django and helps make sure that Apache can read and execute the wsgi script:
# test version of django.wsgi
def application(environ, start_response):
status = '200 OK'
output = 'Hello World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
And restart apache
sudo service apache2 restart
Go ahead and test the page. Did it work? Great. Undo the changes to the django.wsgi script, restart Apache and test again. If the Django site still doesn't work, we need to keep looking. If the test script didn't work, there may be a problem with your Apache installation. Check apache's error log for more information about what happened. On linux it's commonly at /var/log/apache2/error.log . mod_wsgi could be improperly installed, the script's daemon may not have appropriate permission to the wsgi file.
Correcting permission errors
Apache may not be able to read and execute the wsgi file. Running ls -l in the wsgi file's directory as indicated in other answers will tell you the user and group a file belongs to (and if that user and group can read, write, or execute a given file). It's common for a default installation to have the wsgi permissions like so:
-rw------- 1 www-data www-data 1470 Aug 29 16:00 django.wsgi
If you want to use a different user for the daemon process, you need to make sure that the apache conf file defines WSGIDaemonProccess
WSGIScriptAlias / /Users/username/Projects/django_books/django_books/django.wsgi
WSGIDaemonProcess wsgi_user processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup wsgi_group
Testing changes to these files and restarting Apache can help narrow down what's up. Keep checking the Apache log files.
Apache Configuration
Django's tutorial on setting up mod_wsgi is good, but read through mod_wsgi's wiki as well. There are a lot of helpful things to consider in your apache conf file besides WSGIScriptAlias. Make sure there is a tag pointing to the folder with your wsgi file. If there are non-public files (like django project files) in that directory, either use the apache directory (update your apache conf file) or add a tag under the node to keep those other files private. While you're in there, you may notice other things that look wrong, like an improperly configured servername, multiple virtual hosts, or other errors.
Testing Python
If you're using virtualenv (do it), make sure that
1. The WSGIDaemonProcess variable defines the appropriate site-packages and the wsgi script's location in the variable's python-path attribute
2. The daemon has rights to read the site packages in your virtualenv.
3. Your wsgi script properly imports django and your site's settings.
Logging Apache
You can increase the level of logging reported by Apache by adding a few lines to your Apache conf file. This setup gives you very verbose logging that you may want during deployment (make sure to make a log folder):
LogLevel info
ErrorLog /Users/username/Projects/django_books/logs/apache_error.log
CustomLog /Users/username/Projects/django_books/logs/apache_access.log combined
I would suspect that the www-data (or whatever user apache is running as) doesn't have access to /Users/username/Projects/django_books/django_books.
su to that user and try and access that directory and the wsgi file within it.
To print all the relevant permissions:
ls -ld /Users /Users/username /Users/username/Projects /Users/username/Projects/django_books /Users/username/Projects/django_books/django_books /Users/username/Projects/django_books/django_books/django.wsgi
You should also check the apache error logs, they might tell you what is going wrong.
I am a beginner programmer. I started using Python and Bottle for a small web app to print a form, so far so good. The real issue is configuring Apache and mod_wsgi, as my knowledge is almost none.
My problem: I keep getting this error:
Error 404: Not Found
Sorry, the requested URL /factura/ caused an error: Not found
In work they gave me and address redirecting to a IP:port; after some days of reading Apache docs and looking examples through the web I managed to set up the configuration so my VirtualHost doesn't breaks the others virtualhosts already running. The config looks like this (based on the bottle tutorial deployment section):
Listen port
NameVirtualHost IP:port
<VirtualHost IP:port>
ServerName IP:port
WSGIDaemonProcess factura processes=1 threads=5
WSGIScriptAlias / /var/www/factura/app.wsgi
<Directory /var/www/factura>
WSGIProcessGroup factura
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
My app.wsgi is almost the same as the one in the Bottle tutorial-deployment section. I only added the line sys.stdout = sys.stderr:
import sys, os, bottle
# Change working directory so relative paths (and template lookup) work again
sys.path = ['/var/www/factura'] + sys.path
os.chdir(os.path.dirname(__file__))
# Error output redirect
# Exception KeyError in 'threading' module
sys.stdout = sys.stderr
import factura
application = bottle.default_app()
Here is a bit of the python code which is related to Bottle:
from lib import bottle
app = bottle.Bottle()
#serves files in folder 'static'
#app.route('/static/:path#.+#', name='static')
def ...
#app.route("/factura")
#bottle.view("factura")
def ...
#app.route("/print_factura", method="POST")
def ...
I have read some of the others question similar to this, but I can't manage to see what I'mm missing. I suppose the problem is in app.wsgi?
UPDATE
file structure
/var/www/factura/ ## .py files
/views ## here is the web template
/static ## .css and .js of template
/lib ## package with bottle and peewee source files
/data ## inkscape file to play with
/bin ## backup stuff in repo, not used in code
Apache error log only shows
Exception KeyError: KeyError(-1211426160,) in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored
that is a warning from wsgi/python issues, harmless by wsgi issue 197
UPDATE 2 working
added #app.route("/factura/") notice the trail slash, that with the change in app import from factura import app as application those two together made it work
If you create your application explicitly:
app = bottle.Bottle()
then you should import it in your app.wsgi instead of application = bottle.default_app():
from factura import app as application
But what is far important is this. In your WSGI file, you do import bottle, yet in the app code file, you do from lib import bottle. As you have explained, you have two copies of Bottle: one installed server-wide, another under the lib directory.
That's why you were receiving 404 Not Found. You were actually working with one instance of the library (creating app), and then giving Apache a different (default_app) from a different instance of the library!
It started to work okay when you began to return the proper app.
I have been trying to get Flask to work on my webfaction server for hours with no results.
I followed the instructions at http://flask.pocoo.org/snippets/65/
I have my index.py file stored under htdocs.
import sys
yourappname = "/home/<myusername>/webapps/myapp/htdocs"
if not yourappname in sys.path:
sys.path.insert(0, yourappname)
from yourappname import app as application
Then I have added this to my httpd.conf file:
WSGIPythonPath /home/yourusername/webapps/yourapp/htdocs/
#If you do not specify the following directive the app *will* work but you will
#see index.py in the path of all URLs
WSGIScriptAlias / /home/yourusername/webapps/yourapp/htdocs/index.py
<Directory /home/yourusername/webapps/yourapp/htdocs/>
AddHandler wsgi-script .py
RewriteEngine on
RewriteBase /
WSGIScriptReloading On
</Directory>
then i have myapp.py in the same htdocs directory next to index.py:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
I have my domain pointed to my project in webfaction. The default index.py was working prior to me overwriting with the new one as stated in the instructions. However, I only get the server 500. I apologize but I am a complete noob when it comes to linux and managing servers. I cannot even access my error log under users because it says I do not have permission.
I think that it has something to do with my installation of flask on the linux server, i installed it through easy install it says it installed all of the dependencies and did not give any errors.
A couple of suggestions:
Shouldn't you have myapp everywhere you have yourappname in your index.py?
Also, I am assuming that you have made the appropriate substitutions in `WSGIPythonPath /home/yourusername/webapps/yourapp/htdocs
Have you tried restarting the apache server by issuing a ~/webapps/<app_name>/apache2/bin/restart