Django Elastic Beanstalk Deploy showing 404 - python

I'm attempting to deploy my first Django app to Elastic Beanstalk. The Beanstalk created successfully via command line tools, I uploaded from my Mercurial via ZIP, that seemed to work just fine. But I'm getting a 404 when attempting to access it.
Elastic Beanstalk HTTP Error (the log is huge, I can parse more, but I only see this for an error)
[Fri Jan 03 18:08:26 2014] [error] [client 127.0.0.1] Target WSGI script not found or unable to stat: /opt/python/current/app/application.py
WSGI Settings for the Django app
wsgi.py
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "company.settings")
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
settings.py
WSGI_APPLICATION = 'company.wsgi.application'
This works fine locally and I'm sure I'm just not understanding something that I should be.
Please help!
Folder structure:
/opt/python/current/app/
- company
- static
- templates
- wsgi.py
- settings.py
- __init__.py
- urls.py
- webapp
- templates
- manage.py
- requirements.txt

AWS Elastic Beanstalk's default configuration sets WSGIPath to application.py, you either need to rename your file with mappings to application.py or configure the environment to point to your mappings script.
Detailed information can be found in AWS Elastic Beanstalk Python Container Options: Option Values
You can set it with the management console
Or with .ebextensions option_settings
NB: It should be relative path.

Related

Deploying a Django Application (Apache, Passenger, Virtualenv)

Im stuck in deploying my working Django Application on a production PLESK server.
The project can be started as a development server successfully by typing:
httpdocs# cd mysite
httpdocs/mysite# source myvenv/bin/activate
httpdocs/mysite# export LD_LIBRARY_PATH="/usr/local/lib"
httpdocs/mysite# python manage.py runserver <freyt.de>:8000
Then, if I point the browser to freyt.de:8000 I can see my app. Fine.
Right now, I'm trying to call my app by Passenger from Apache. When checking with "passenger-config restart-app" it seems to run, but when curl freyt.de it shows me html with 403 Forbidden. So, I assume my Django app is not started successfully.
This is my current folder structure:
I already adjusted some topics in PLESK as follows:
Apache Webserver: wsgi is activated
I created a Service Plan and subscribed it with my domain freyt.de
In the Service Plan under tab "Webserver" I added additional directives for HTTP as follows.
PassengerEnabled On
PassengerAppType wsgi
PassengerStartupFile passenger_wsgi.py
In the Service Plan under "Hosting Parameters" I enabled SSH access to the server shell: /bin/bash
For the "Domain" I set the Document root to "..httpdocs/public". Also I added in "Apache & nginx Settings" the same directives. (I also tried without, but dont seem to have an effect.)
Some details at Document Root:
I added .htaccess in public with again same directives (just for testing). No other files in public.
My passenger_wsgi.py contains, which seems to be ok:
import sys, os
cwd = os.getcwd()
sys.path.append(cwd)
sys.path.append(cwd + '/mysite')
if sys.version < "2.7.9":
os.execl(cwd + "/mysite/myvenv/bin/python", "python3.6", *sys.argv)
sys.path.insert(0, cwd + '/mysite/myvenv/bin')
sys.path.insert(0, cwd + '/mysite/myvenv/lib/python3.6')
#sys.path.insert(0, cwd + '/mysite/myvenv/lib/python3.6/site-packages/django')
sys.path.insert(0, cwd + '/mysite/myvenv/lib/python3.6/site-packages')
os.environ['DJANGO_SETTINGS_MODULE'] = "mysite.settings"
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
The file mysite/mysite/wsgi.py is untouched:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
application = get_wsgi_application()
Would be great, if someone could point me in the correct direction. I think its just a small mistake somewhere :-) Thanks in advance.

How to deploy Django/React/Webpack app on Digital Ocean through Passenger/Nginx

I'm trying to deploy a web app built with Django/Redux/React/Webpack on a Digital Ocean droplet. I'm using Phusion Passenger and Nginx on the deployment server.
I used create-react-app to build a Django app which has a frontend that uses React/Redux, and a backend api that uses django-rest-framework. I built the frontend using npm run build.
The Django app is configured to look in the frontend/build folder for its files and everything works as expected, including authentication. It's based on this tutorial: http://v1k45.com/blog/modern-django-part-1-setting-up-django-and-react/
In settings.py:
ALLOWED_HOSTS = ['*']
TEMPLATES = [
...
'DIRS': [
os.path.join(BASE_DIR, 'frontend/build'),
],
...
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'frontend/build/static'),
]
On my development machine, I activate a Python 3.6 virtual environment and run ./manage.py runserver, and the app is displayed at localhost:3000.
On the deployment server, I've cloned the files into a folder in var/www/ and built the frontend.
I've set up Passenger according to the docs with a file passenger_wsgi.py:
import myapp.wsgi
application = myapp.wsgi.application
And the wsgi.py file is in the djangoapp folder below:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
application = get_wsgi_application()
The Passenger docs only cover a single-part app:
https://www.phusionpassenger.com/library/walkthroughs/start/python.html
https://www.phusionpassenger.com/library/walkthroughs/deploy/python/digital_ocean/nginx/oss/xenial/deploy_app.html
https://www.phusionpassenger.com/library/deploy/wsgi_spec.html
I've tried cloning the tutorial part 1 code directly onto my server and following the instructions to run it. I got this to work on the server by adding "proxy": "http://localhost:8000" to frontend/package.json. If I run the Django server with ./manage.py runserver --settings=ponynote.production_settings xxx.x.x.x:8000
then the app is correctly served up at myserver:8000. However Passenger is still not serving up the right files.
I have changed wsgi.py to say this:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.production_settings")
application = get_wsgi_application()
The page served by Passenger at URL root now appears to have the right links to the js files such as "text/javascript" src="/static/bundles/js/main.a416835a.js, but the links don't work: the expected js is not present. Passenger is failing to serve the js files from static/bundles/js, even though the Django server can find them.
Very grateful for any help or ideas.
Create-react-app has a fairly opinionated setup for local and production environments.
Locally, running npm start will run a webpack-dev-server, which you would typically access on port 3000. It runs a local nodejs web server to serve the files. You can route requests to your local Django server via the proxy setting.
It's worth noting that at this point there is little or no connection between your React app and Django. If you use the proxy setting, the only thing connecting the two apps is the routing of any requests not handled by your React app to your Django app via the port.
By default in create-react-app (and as noted in the tutorial you mentioned you are following) in production you would run npm run build which will process your create-react-app files into static JS and CSS files, which are then accessed in Django like static files any other Django app.
One thing Django is missing in order to access the static files is a way to know what files are generated when running npm run build. Running a build will typically result in files output like this:
- css
|- main.e0c3cfcb.css
|- main.e0c3cfcb.css.map
- js
|- 0.eb5a2873.chunk.js
|- 0.eb5a2873.chunk.js.map
|- 1.951bae33.chunk.js
|- 1.951bae33.chunk.js.map
A random hash is added to filenames to ensure cache busting. This is where webpack-bundle-tracker and django-webpack-loader come in. When build files are generated, an accompanying file is also created called manifest.json, listing the files created for the build. This is generated in Webpack and picked up by django-webpack-loader so that Django can know which files to import.
It is possible to run a nodejs server in production, or to use server-side rendering, but if you're following the tutorial you mentioned and using create-react-app default settings, then running npm run build and deploying the static files is the simplest, safest option.
Nothing in any of the Passenger deployment links you mention cover anything beyond deploying a Python/Django app - you would need to manage two apps and deployments to have both Django and React running as servers in production.
Note that the tutorial you mention covers how to get your build files into Django in production, but you will need to ensure that you have webpack-bundle-tracker, django-webpack-loader and your Django staticfiles configuration all configured to work together.
The key missing setting was the 'location' setting in the Passenger config file.
Although the Django server serves up the static files, including the build files for your React app, Nginx doesn't see any static files except those in a 'public' directory.
So to deploy a Django app built with Webpack to production, you need to tell Nginx about those files. If you're using Passenger, these settings are probably in a separate Passenger config file. 'alias' is the command to use in this case where the folder has a different name from 'static' (which is where the web page links point).
If you use a virtual environment for your app, you need to specify where Passenger can find the right Python executable.
/etc/nginx/sites-enabled/myapp.conf
server {
listen 80;
server_name xx.xx.xx.xx;
# Tell Passenger where the Python executable is
passenger_python /var/www/myapp/venv36/bin/python3.6;
# Tell Nginx and Passenger where your app's 'public' directory is
# And where to find wsgi.py file
root /var/www/myapp/myapp/myapp;
# Tell Nginx where Webpack puts the bundle folder
location /static/ {
autoindex on;
alias /var/www/myapp/myapp/assets/;
}
# Turn on Passenger
passenger_enabled on;
}
Passenger uses the wsgi.py file as an entry point to your app. You need a passenger_wsgi.py file one level above the wsgi.py file. This tells Passenger where to find the wsgi.py file.
/var/www/myapp/myapp/passenger_wsgi.py
import myapp.wsgi
application = myapp.wsgi.application
/var/www/myapp/myapp/myapp/wsgi.py
If you are using a separate production_settings.py file, make sure this is specified here.
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.production_settings")
application = get_wsgi_application()

Django app on AWS Elastic Beanstalk - DJANGO_SETTINGS_MODULE

Where should the DJANGO_SETTINGS_MODULE environment variable be set?
Multiple possible locations:
In a config file (.ebextensions) as follows:
option_settings: aws:elasticbeanstalk:application:environment:
DJANGO_SETTINGS_MODULE: "app.settings"
In the wsgi.py file before application is loaded
In manage.py (I also see this on different Django projects on the web)
If I don't specify it in wsgi.py, it looks like it can't be found at all. Therefore, I wonder if the environment variables set in .ebextensions are set before wsgi.py is loaded.
Any idea?
Introduce your wsgi.py in a config file in .ebextensions
django_aws_eb.config:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: "my_site/wsgi.py"
Specifly your DJANGO_SETTING_MODULE in your `wsgi.py' file
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_site.settings")
application = get_wsgi_application()
aws beanstalk first looks for configs in .ebextension to then locate wsgi.py to then locate settings.
more info: Configure Your Django Application for Elastic Beanstalk

Django 403 Forbidden on AWS Elastic Beanstalk

I am following the tutorial for Deploying a Django Application on AWS.
Source I am using http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create-deploy-python-django.html
I get the following error:
[Tue Feb 23 21:05:22.883666 2016] [core:error] [pid 3394] (13)Permission denied: [client 172.31.46.155:37871] AH00035: access to / denied (filesystem path '/opt/python/current/app/mysite/wsgi.py') because search permissions are missing on a component of the path
My web page shows:
Forbidden
You don't have permission to access / on this server.
Here is my file path:
virtualenvFolder
- requirements.txt
mysite
-db.sqlite3.db
-manage.py
mysite
-__init__.py
-__init__.pyc
-settings.py
-settings.pyc
-urls.py
-urls.pyc
-wsgi.py
-wsgi.pyc
.ebextensions
-django.config
.elasticbeanstalk
-config.yml
requirements.txt:
Django==1.9.2
MySQL-python==1.2.5
django.config:
option_settings:
aws:elasticbeanstalk:container:python:
WSGIPath: mysite/wsgi.py
config.yml:
branch-defaults:
default:
environment: django-env
group_suffix: null
global:
application_name: mysite
default_ec2_keyname: my-keypair
default_platform: python2.7
default_region: us-west-2
profile: eb-cli
sc: null
Note: I did not write or change config.yml it was auto generated.
This has nothing to do with Django and everything to do with Apache and file permissions. It looks like you are storing your Django application in an directory that the Apache process does not have permission to access.
Please see this question for a solution.

Python/Flask app using apache/fastcgi producing 500 Error

I've been doing Flask microblog tutorial by Miguel Grinberg and have got stuck on trying to deploy to my linux VPS.(http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xvii-deployment-on-linux-even-on-the-raspberry-pi)
I'm getting a 500 internal server error produced by apache, not flask, and I can't figure it out. It works when running it using the interpreter, but I can't launch it with apache. I've read through so many google searches and SO questions and I'm lost. I'm relatively new to linux/python/flask but I'm willing to learn if someone can point me in the right direction.
Setup:
I'm running a fresh CentOS 6.6 install with Python 2.6.6 and Apache 2.2.15. I'm running it off sqlite. I'm using these flask modules if you're interested: http://pastebin.com/bPnH83bs
Basic App Structure: (left out things for brevity)
Located in: /home/apps/portal
I have the whole directory chown'd to: chown -R apps:apache
User 'apps' is a member of the apache group
flask\ (virtualenv)
app\
static\
templates\
__init__.py
models.py
views.py
forms.py
decorators.py
db_repository\
search.db\
tmp\
app.db
config.py
run.py
runp.py
runp-sqlite.fcgi
Apache conf file setup:
FcgidIPCDir /tmp
AddHandler fcgid-script .fcgi
<VirtualHost *:80>
DocumentRoot /home/apps/portal/app/static
Alias /static /home/apps/portal/app/static
ScriptAlias / /home/apps/portal/runp-sqlite.fcgi/
ErrorLog /var/log/httpd/error_log
CustomLog /var/log/httpd/access_log combined
</VirtualHost>
runp-sqlite.fcgi Contents:
#!flask/bin/python
from flipflop import WSGIServer
from app import app
if __name__ == '__main__':
WSGIServer(app).run()
Error from apache logs when trying to access page and getting 500 error:
[Mon Dec 15 22:21:44 2014] [warn] [client *.*.*.*] mod_fcgid: read data timeout in 40 seconds
[Mon Dec 15 22:21:44 2014] [error] [client *.*.*.*] Premature end of script headers: runp-sqlite.fcgi
Error when I run "runp-sqlite.fcgi" from the console:
[root#**** portal]# sudo -u apache ./runp-sqlite.fcgi
Traceback (most recent call last):
File "./runp-sqlite.fcgi", line 6, in <module>
WSGIServer(app).run()
File "/home/apps/portal/flask/lib/python2.6/site-packages/flipflop.py", line 938, in run
sock.getpeername()
socket.error: [Errno 88] Socket operation on non-socket
Things I've checked:
I've disabled SELinux as it was causing a different problem, didn't fix this issue.
Checked that folders were chown'd to the correct user/group.
Checked that '/etc/httpd/conf/httpd.conf' and '/etc/sysconfig/httpd' PIDFILE locations are correct
Checked that iptables is accepting traffic to ports 80 and 5000(for testing). If I remove the apache configuration I've added I am successfully serving from /var/www/html
Lots and lots of googling and playing around
Sorry for the wall of text, I just don't know what you'll need to see. If anyone can help with this I'll be really greatful. If it's something dumb, I apologise. :)
Update 1:
Changed runp-sqlite.fcgi to call virtualenv:
#!flask/bin/python
activate_this = '/home/apps/portal/flask/bin/activate_this.py')
execfile(activate_this, dict(__file__=activate_this))
from flipflop import WSGIServer
from app import app
if __name__ == '__main__':
WSGIServer(app).run()
Now apache errors_log has a new error message:
[Fri Dec 19 13:43:03 2014] [notice] Apache/2.2.15 (Unix) DAV/2 mod_fcgid/2.3.9 PHP/5.3.3 mod_wsgi/3.2 Python/2.6.6 configured -- resuming normal operations
[Fri Dec 19 13:43:05 2014] [warn] [client 110.143.38.80] (104)Connection reset by peer: mod_fcgid: error reading data from FastCGI server
[Fri Dec 19 13:43:05 2014] [error] [client 110.143.38.80] Premature end of script headers: runp-sqlite.fcgi
Do you have Flask installed in a virtuelenv? If so, the problem may be that your WSGI file isn't activating it. This causes an ImportError or something similar when Apache tries to serve the site, which results in a not-very-helpful 500 Error.
The fix is to activate the virtualenv in your WSGI file before importing the app like this:
#!/bin/python
VENV_DIR = 'your_app/your_venv'
activate_this = os.path.join(VENV_DIR, 'bin', 'activate_this.py')
execfile(activate_this, dict(__file__=activate_this))
from flipflop import WSGIServer
from app import app
if __name__ == '__main__':
WSGIServer(app).run()
See also this previous SO question: Running Python from a virtualenv with Apache/mod_wsgi, on Windows

Categories

Resources