Apache / Gunicorn and Django Issue - django

I have an application that runs using
client --> apache --> gunicorn --> wsgi --> django
When I run my code it starts to run and then I receive the following within the apache logs,
(20014)Internal error: proxy: error reading status line from remote server 127.0.0.1
proxy: Error reading from remote server returned by /app/view
No exceptions show in the code. However if I run the code without the gunicord/proxy layer it works. Also this only affects some requests.
Heres is my apache conf.d file.
<VirtualHost 10.0.6.1:443>
ServerName app.domain.net
Alias /static /production/pythonenv/app/lib/python2.7/site-packages/rest_framework/static/
ErrorLog /var/log/httpd/app-error.log
CustomLog /var/log/httpd/app-access.log common
LogLevel warn
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*) http://127.0.0.1:9008/$1 [P]
ProxyPassReverse / http://127.0.0.1:9008/
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
RequestHeader unset Expect early
ErrorLog logs/app-ssl-error.log
CustomLog logs/app-ssl-access.log common
SSLEngine on
SSLCertificateFile /opt/ssl/crt/cert.crt
SSLCertificateKeyFile /opt/ssl/crt/key.key
</VirtualHost>

Related

Django showing 500 Internal Server Error on HTTPS

I am getting the following error in error.log in apache2 directory : Segmentation fault (11), possible coredump in /etc/apache2.
I have the following configuration in my example-instance.conf :
ErrorDocument 404 "/error-pages/404.html"
ErrorDocument 500 "/error-pages/500.html"
ErrorDocument 403 "/error-pages/403.html"
# Change the following three lines for your server
ServerName example.app
SetEnv HTTP_HOST "example.app"
ServerAdmin admin#example.app
SetEnv LC_TIME "en_GB.UTF-8"
SetEnv LANG "en_US.UTF-8"
SSLEngine on
SSLCertificateFile "path/to/certificate"
SSLCertificateChainFile "path/to/certificate"
SSLCertificateKeyFile "path/to/private_key"
WSGIScriptAlias /app "path/to/wsgi_prod.py"
# Comment next 2 lines if using older Apache than v2.4
WSGIApplicationGroup %{GLOBAL}
WSGIDaemonProcess instance1_wsgi python-path="__PATH_TO_ENV_SITE-PACKAGES_FOLDER__"
WSGIProcessGroup instance1_wsgi
# Comment 'Require all granted' for older Apache than v2.4
<Location "/">
Require all granted
Options FollowSymLinks
</Location>
Alias /static/ "path/to/static/"
Alias /app/static/ "path/to/static/"
<Directory "path/to/static/">
Require all granted
Options -Indexes
</Directory>
Alias /data/ "path/to/data/"
<Directory "path/to/data/">
Require all granted
Options -Indexes
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example-instance-error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/example-instance-access.log combined
The site worked perfectly fine on http however on configuring it for https, I am getting 500 Internal Server Error on '/app' subdirectory where my Django app lies. The landing page of the site is perfectly fine, which indicates that https is working.
I have this same problem :/ Only option for now was to turn off mod_ssl and get back to port 80 in config file.
Strange is that i have Debug = True in settings.py but when app crashes i receive only error 500 page from apache.
Turns out pip install psycopg2-binary did the trick!

Deploy django-channels with Apache2 and Daphne

I'm trying to learn to use django-channels and have worked through both the tutorial and this multichat example. I am now trying to deploy it on a Digital Ocean droplet using Apache and Daphne. I would happily use Daphne by itself but I do not understand how to.
So this is my Apache conf file:
<VirtualHost *:80>
ServerAdmin webmaster#mysite.co.uk
ServerName multichat.mysite.co.uk
ServerAlias www.multichat.mysite.co.uk
DocumentRoot /var/www/multichat
WSGIDaemonProcess multichat python-path=/var/www/multichat python-home=/var/www/multichat/env
WSGIProcessGroup multichat
WSGIScriptAlias / /var/www/multichat/multichat/wsgi.py
Alias /robots.txt /var/www/multichat/static/robots.txt
Alias /favicon.ico /var/www/multichat/static/favicon.ico
Alias /media/ /var/www/multichat/media/
Alias /static/ /var/www/multichat/static/
<Directory /var/www/multichat/static>
Require all granted
</Directory>
<Directory /var/www/multichat/media>
Require all granted
</Directory>
WSGIScriptAlias / /var/www/multichat/multichat/wsgi.py
<Directory /var/www/multichat/multichat>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
I've installed Redis and have it up and running.
I've included this file in /etc/systemd/system/daphne.service
[Unit]
Description=daphne daemon for multichat
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/var/www/multichat/multichat
ExecStart=/var/www/multichat/env/bin/daphne -b 0.0.0.0 -p 8001 multichat.asgi:application
# Not sure if should use 'on-failure' or 'always'.
Restart=on-failure
[Install]
WantedBy=multi-user.target
Although the webpage comes up and I can login etc, when it comes to a chatroom I have the following error in console:
WebSocket connection to 'ws://multichat.mysite.co.uk/chat/stream/'
failed: Error during WebSocket handshake: Unexpected response code:
404
I'm clearly not setting up something correctly but I don't know where to turn. I would happily scrape Apache if I can get a pointer on how to use just Daphne, but I've tried and got nowhere with that either
You've configured Apache to serve Django content using WSGI protocol, but WSGI doesn't support web sockets. That is why Daphne is here. It doesn't use WSGI to serve Django content, so you can use it with web sockets.
To use Daphne instead, you should remove WSGI settings from apache file and put ProxyPass instead, which should point to your daphne server. The proper line should look like this:
<Location />
ProxyPass http://127.0.0.1:8001/
</Location>
As your daphne server is running on the same server, but on port 8001.
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC,OR]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://127.0.0.1:8001%{REQUEST_URI} [P,QSA,L]
<Location />
ProxyPass http://127.0.0.1:8001/
</Location>
#And load the next modules in the main file config:
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_module modules/mod_proxy.so
#remove WSGI settings

Apache config with flask, wsgi, and reverse proxy

Below is my Apache config. What I am trying to do have a reverse proxy set up for the main part of the site. So when users go to mysite.xyz, they get what is running on port 5000 (this is working). I also want to run a flask app on mysite.xyz/page1 This is coming back with a 404 not found page. When I switch them and put the app at / and put the main site at page1, then the app works but page1 can't find any of the correct js assets so I'd like to avoid that. But the app does work and works on apache but the reverse proxy must be over-riding the WSGI deployment of the flask app or something?
<VirtualHost *:80>
ServerName mysite.xyz
ServerAdmin email#gmail.com
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
RewriteCond %{HTTP_HOST} !^mysite\.xyz$ [NC]
RewriteRule ^/$ http://%{HTTP_HOST}/ [L,R=301]
WSGIScriptAlias /page1 /var/www/FlaskApp/FlaskApp.wsgi
<Directory /var/www/FlaskApp/>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Instead of ProxyPass, try:
RewriteRule ^/$ http://127.0.0.1:5000/ [P]
ProxyPassReverse / http://127.0.0.1:5000/
I know this is stale but it may help someone. Flask hates reverse proxy. You need to add flask-reverse-proxy-fix to your app.
https://pypi.org/project/flask-reverse-proxy-fix/

Configure apache to respond with error page for incorrect hosts

django docs:
You should also configure the Web server that sits in front of Django to validate the host. It should respond with a static error page or ignore requests for incorrect hosts instead of forwarding the request to Django. This way you’ll avoid spurious errors in your Django logs (or emails if you have error reporting configured that way). For example, on nginx you might setup a default server to return “444 No Response” on an unrecognized host:
I am using Apache and this works:
http://serverip -> 404 error
http://www.example.com -> https://www.example.com -> django site
http://example.com -> https://example.com -> django site
Now I have a problem with https://serverip
I get a not secure message by my browser because I only have a SSL Cert for example.com, www.example.com and after I accept the security warning I see the django site but I want 404 error page.
How can I achieve this or do I misunderstand the django docs?
Update Config:
assume the django site is /var/www/html/index.html for simplification
000-default.conf:
<VirtualHost *:80>
Redirect 404 /
</VirtualHost>
example.com.conf:
<VirtualHost *:80>
ServerAdmin example#example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.example.com [OR]
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
example.com-le-ssl.conf:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin example#example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Redirection of domain within <VirtualHost> tag

I have the following in my apache2.conf file for a django project:
#ServerRoot "/etc/apache2"
<VirtualHost *:80>
Alias /static /home/ubuntu/Avails/static
# virtual host configuration
WSGIScriptAlias / home/ubuntu/Avails/wsgi.py
</VirtualHost>
Similar to a previous question I asked here (How to redirect one domain to another).
I have two domains:
www.new.example1.com/ --> IP=1.2.3.4
www.new.example2.com/ --> IP=1.2.3.4 (same IP for both domains)
I want all requests that go to www.example2.com/* to access the requested page. I want all requests that go to www.example1.com/* to redirect to www.example2.com/*. how would I redirect a domain within the VirtualHost block, instead of using the .htaccess file?
Here is what worked. Special thanks to anubhava for the help:
1) Enable module rewrite:
$ sudo a2enmod rewrite
2) Edit apache2.conf file:
<VirtualHost *:80>
Alias /static /home/ubuntu/Avails/static
# virtual host configuration
WSGIScriptAlias / home/ubuntu/Avails/wsgi.py
RewriteEngine On
RewriteCond %{HTTP_HOST} ^new\.example1\.net [NC]
RewriteRule ^ http://new.example2.net%{REQUEST_URI} [NE,R=301,L]
</VirtualHost>
3) Restart apache:
$ sudo service apache2 restart