I have to set up the Django server with WebSockets and HTTP requests. It works fine in my local system. and also on the server without SSL, but when we use the SSL on the server the HTTP request works fine on the https but WebSocket does not work with wss
I am using Nginx for the webserver and daphne.
this is my Nginx conf file
server {
listen 80;
server_name domain.name;
error_log /var/log/nginx/error.log;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
autoindex on;
alias /root/myprojectdir/staff_hiring/static;
}
location /media/ {
autoindex on;
alias /root/myprojectdir/staff_hiring/media;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
and this is my asgi file
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import staff_admin.routing
from channels.security.websocket import AllowedHostsOriginValidator
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'staff_hiring.settings')
django.setup()
application = ProtocolTypeRouter({
"https": get_asgi_application(),
'websocket':AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
staff_admin.routing.websocket_urlpatterns
)
)
)
})
and routing file
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()), # Using asgi
# url(r'/ws/chat/', consumers.ChatConsumer.as_asgi())
]
Related
I've been stuck for days just to find a way to fix this problem.
Why my Nginx can't connect to WebSocket? and always get these errors on the console:
WebSocket connection to '<URL>' failed: WebSocket is closed before the connection is established.
or
WebSocket connection to 'wss://domain.com/virtualexpo/' failed: Error during WebSocket handshake: Unexpected response code: 404
Here's my Nginx setup looks like:
upstream projectname {
server localhost:9001;
}
upstream uvsock {
server 127.0.0.1:6379;
# server unix://var/run/supervisor.sock;
}
server {
server_name domain.com www.domain.com;
sendfile on;
charset utf-8;
client_max_body_size 20M;
client_body_buffer_size 80M;
client_body_timeout 50;
location /ws/ {
proxy_pass http://uvsock;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
location / {
proxy_pass http://projectname;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
...
}
location /static {
alias /home/username/server/vier/staticfiles;
}
location /media {
alias /home/username/server/vier/media;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/domain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.domain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = domain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name domain.com www.domain.com;
return 404; # managed by Certbot
}
How can I connect this Nginx with my WebSocket for use with Django Channel?
Here's my routing.py looks like:
application = ProtocolTypeRouter({
# "http": get_asgi_application(),
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
path('stream/<pk>/', LiveStreamConsumer),
path('discussion/global/', GlobalLiveChatConsumer),
path('somepath/', VirtualExpoConsumer)
]
)
)
)
})
The ASGI setup:
...
from django.core.asgi import get_asgi_application
from channels.layers import get_channel_layer
from channels.routing import get_default_application
os.environ['DJANGO_SETTINGS_MODULE'] = 'core.settings'
django.setup()
channel_layer = get_channel_layer()
application = get_default_application()
# application = get_asgi_application()
And my settings.py looks like this:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("localhost", 6379)],
},
},
}
Been around looking for a way to fix them but can't find any.
The celery and Redis themselves have already run with no issue.
But it seems that the WebSocket can't connect with my Nginx config.
This is might due to your daphne server wasn't able to access the cert to redirect to wss. You may refer article here.
I am trying to use django-private-storage package to protect a model's file from being accessed
or downloaded by users who are not owners of the file.
I was able to do it successfully in development (using python manage.py runserver)
In development, I am using nginx configured via docker.
I can create objects with both FileField and PrivateFileField. My problem is accessing the urls associated with a PrivateFileField.
The mediafiles are being served as expected (e.g. when I access the url of a FileField), but I get a "404 Not Found" error from nginx when I access the url of a PrivateFileField.
My hunch is that the server response is not properly configured to have a 'X-Accel-Redirect' data,
thus treating the response not internal.
If I remove the line "internal;" in my nginx.conf for the private-data location, the PrivateFile is served
properly, although, now, it is not private.
location /private-data/ {
internal; #<------ the PrivateFile can be accessed if this line is removed
alias /home/app/web/private-data/;
}
Also, I am sure that the private file was saved in /home/app/web/private-data
Am I missing out something in the implementation?
Thanks in advance.
Additional info:
nginx version: 1.17.4
django-private-storage version: 2.2.2
My production setup follows this:
https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/
FILES -----------------------------------
docker-compose.prod.yml
version: '3.7'
services:
web:
build:
context: ./web_app
dockerfile: Dockerfile.prod
command: gunicorn notify_django_project.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
- private_volume:/home/app/web/private-data
expose:
- 8000
env_file:
- ./.env.prod
depends_on:
- db
db:
image: postgres:12.0-alpine
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- ./.env.prod.db
nginx:
build: ./nginx
volumes:
- static_volume:/home/app/web/staticfiles
- media_volume:/home/app/web/mediafiles
- private_volume:/home/app/web/private-data
ports:
- 1337:80
depends_on:
- web
volumes:
postgres_data:
static_volume:
media_volume:
private_volume:
nginx.conf
upstream django_project {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://django_project;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /staticfiles/ {
alias /home/app/web/staticfiles/;
}
location /mediafiles/ {
alias /home/app/web/mediafiles/;
}
location /private-data/ {
internal;
alias /home/app/web/private-data/;
}
}
settings.py
INSTALLED_APPS = [
...
'private_storage',
....
]
PRIVATE_STORAGE_ROOT = os.path.join(BASE_DIR, "private-data")
PRIVATE_STORAGE_AUTH_FUNCTION = 'private_storage.permissions.allow_authenticated'
PRIVATE_STORAGE_INTERNAL_URL = '/private-data/'
PRIVATE_STORAGE_SERVER = 'nginx'
models.py
class Message(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False)
subject = models.CharField(max_length=255)
attachment = models.FileField(upload_to=get_attachment_save_path, null=True, blank=True)
private_attachment = PrivateFileField(upload_subfolder=get_private_attachment_save_path, null=True, blank=True)
urls.py
urlpatterns = [
...
path('private-data/<str:code>/<int:year>/<str:subdir>/<uuid:pk>/<str:filename>', DownloadPrivateFileView.as_view(), name="file_download"),
url('^private-data/', include(private_storage.urls)),
...
]
views.py
#method_decorator(login_required, name='dispatch')
class DownloadPrivateFileView(PrivateStorageDetailView):
model = Message
model_file_field = 'private_attachment'
def can_access_file(self, private_file):
# When the object can be accessed, the file may be downloaded.
# This overrides PRIVATE_STORAGE_AUTH_FUNCTION
# grant_access checks private_file ownership
grant_access = grant_note_access(private_file.request, message=self.get_object())
return grant_access
Iam in the testing phase with this library too!
I did not use these lines that indicated, which serves to speed up uploading large files.
without these settings and debug = False, everything worked correctly.
Take the test please.
Sorry for the Translation, I don't speak English
My conf for my site in nginx mysite.conf
server {
listen 80;
server_name mysite.com.br;
return 301 https://mysite.com.br$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mysite.com.br;
location ~ ^/.well-known{
root /var/www/myapp;
}
location / {
proxy_pass http://127.0.0.1:6010; # My container is at port 3020
}
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off;
# Certificate free letsencrypt
ssl_certificate /etc/letsencrypt/live/mysite.com.br/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mysite.com.br/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
}
My setting.py for django:
MEDIA_ROOT = os.path.join(BASE_DIR, 'anexosapp') # Folder for files private app
MEDIA_URL = '/docs/'
# Conf for django-private-storage
INSTALLED_APPS += (
'private_storage',
)
PRIVATE_STORAGE_ROOT = os.path.join(BASE_DIR, 'anexosapp/')
PRIVATE_STORAGE_AUTH_FUNCTION = 'private_storage.permissions.allow_authenticated' # allow user authenticated
# settings for static server over whitenoise
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"), ]
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'
urls.py app main:
urlpatterns += [
path('private-media/', include(private_storage.urls)),
]
The file access url looks like this
https : //mysite.com.br/private-media/docs/namefile.pdf
If anyone finds errors, tips for improving the settings, please indicate! Thank you
I just removed from nginx.conf location that refers to private media like so:
upstream "my domain" {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://"my domain";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /staticfiles/ {
alias /home/app/web/staticfiles/;
}
location /mediafiles/ {
alias /home/app/web/mediafiles/;
}
#location /privatefiles/ {
# alias /home/app/web/privatefiles/;
#}
# Error & Access logs
error_log /home/app/logs/error.log error;
access_log /home/app/logs/access.log;
client_max_body_size 128m;
}
Don't forget to set DEBUG = False, then it should worked perfectly. Every time I tried to access to private media without login in, it redirected me to login page.
This is my settings.py
...
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
STATIC_URL = "/staticfiles/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
MEDIA_URL = "/mediafiles/"
MEDIA_ROOT = os.path.join(BASE_DIR, "mediafiles")
PRIVATE_STORAGE_ROOT = os.path.join(BASE_DIR, "privatefiles")
PRIVATE_STORAGE_AUTH_FUNCTION = 'private_storage.permissions.allow_authenticated'
...
and my main urls.py
from django.conf.urls.static import static
from django.conf.urls import url
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
import private_storage.urls <--- this is for private storage
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('core.urls')),
path('rubric/', include('rubric.urls')),
path('warehouse/', include('warehouse.urls')),
path('preoffers/', include('preoffers.urls')),
path('offers/', include('offers.urls')),
url('^privatefiles/', include(private_storage.urls)) <--- this is for private storage
]
if settings.DEBUG:
urlpatterns += static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(
settings.STATIC_URL, document_root=settings.STATIC_ROOT)
'internal' param tells nginx it's not accessible from the outside.
We access application and then redirect to nginx
settings.py
PRIVATE_STORAGE_ROOT = os.path.join(BASE_DIR, 'private-media')
PRIVATE_STORAGE_AUTH_FUNCTION = 'private_storage.permissions.allow_staff'
PRIVATE_STORAGE_SERVER = 'nginx'
PRIVATE_STORAGE_INTERNAL_URL = '/private-x-accel-redirect/'
nginx
location /private-x-accel-redirect/ {
internal;
alias /var/www/private-media/;
}
After adding the SSL certificate, my static files do not work only in django-admin. Other files on the entire website work very well.
How can I fix this situation (preferably without brutal copying of django-admin static files to my application)?
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app.urls', namespace='app')),
path('media/<path>/', serve,{'document_root': settings.MEDIA_ROOT}),
path('static/<path>/', serve,{'document_root': settings.STATIC_ROOT}),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '../static/')
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'app/media')
app (/etc/nginx/sites-available/app) After making changes to this file, they django-admin static file stopped working.
upstream app_server {
server unix:/home/app/run/gunicorn.sock fail_timeout=0;
}
server {
#listen 80;
# add here the ip address of your server
# or a domain pointing to that ip (like example.com or www.example.com)
listen 443 ssl;
server_name ebluedesign.online;
ssl_certificate /etc/letsencrypt/live/ebluedesign.online/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ebluedesign.online/privkey.pem;
server_name 101.170.18.112;
keepalive_timeout 5;
client_max_body_size 4G;
access_log /home/app/logs/nginx-access.log;
error_log /home/app/logs/nginx-error.log;
location /static/ {
alias /home/app/app/app/static/;
}
# checks for static file, if not found proxy to app
location / {
try_files $uri #proxy_to_app;
}
location #proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
server {
listen 80;
server_name ebluedesign.online;
return 301 https://$host$request_uri;
}
I'm deploying my Wagtail application to production but could not get it to work. I'm following this tutorial https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04.
The website is work as expected on my server when using development settings, as soon as I changed to production it won't work.
On production, I'm only able to access the admin and sitemap URL.
production.py
from .base import *
with open('/etc/secret_key.txt') as f:
SECRET_KEY = f.read().strip()
DEBUG = False
try:
from .local import *
except ImportError:
pass
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'name',
'USER': 'user',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
# SECURITY WARNING: define the correct hosts in production!
INTERNAL_IPS = ("127.0.0.1")
ALLOWED_HOSTS = ['*']
nginx
# Redirect unencrypted traffic to the encrypted site
server {
listen 80;
server_name domain www.domain IP;
return 301 https://domain$request_uri;
}
server {
client_max_body_size 20M;
listen 443 default ssl;
server_name domain.com IP;
keepalive_timeout 70;
ssl on;
ssl_certificate /etc/nginx/certs.pem;
ssl_certificate_key /etc/nginx/privkey.pem;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/user/projectdir;
}
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
}
Gunicorn.service
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target
[Service]
User=sherpa
Group=www-data
WorkingDirectory=/home/user/projectdir
ExecStart=/home/user/projectenv/bin/gunicorn \
--access-logfile - \
--workers 3 \
--bind unix:/run/gunicorn.sock \
project.wsgi_production:application
[Install]
WantedBy=multi-user.target
urls.py
urlpatterns = [
url(r'^django-admin/', admin.site.urls),
url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
url(r'^search/$', search_views.search, name='search'),
url(r'^sitemap.xml', sitemap),
# For anything not caught by a more specific rule above, hand over to
# Wagtail's page serving mechanism. This should be the last pattern in
# the list:
url(r'', include(wagtail_urls)),
# Alternatively, if you want Wagtail pages to be served from a subpath
# of your site, rather than the site root:
# url(r'^pages/', include(wagtail_urls)),
]
I'm having the same issue. If I set to Debug = True, everything works fine. If I set Debug = False I get the 500 error page, but nothing in the logs to tell me an error has been fired. I am using Apache and not nginx.
Got problem with static css. I already did collectstatic.
Css works fine if run
./manage.py runserver 0.0.0.0:8000
but can not be found if run
gunicorn --bind 0.0.0.0:8000 hotel_main.wsgi:application
same situation with Dajango admin
settings.py
STATIC_URL = '/static/'
STATIC_ROOT = "/opt/static/"
STATICFILES_DIRS = [
('static', os.path.join(BASE_DIR, 'hotel_site/static'),),
('static', os.path.join(BASE_DIR, 'static'),),
]
Urls.py
from django.conf.urls import include, url
from django.conf.urls.static import static
from django.conf import settings
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
url(r'^', include('hotel_site.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Nginx file
upstream 78.155.199.17 {
server localhost:8000 fail_timeout=0;
}
server {
listen 80;
server_name 78.155.199.17;
return 301 78.155.199.17$request_uri;
}
server {
listen 80;
server_name 78.155.199.17;
location /static/ {
root /opt/;
}
location /media/ {
root /root/;
}
location / {
proxy_set_header X-Forwarded-For
$proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass 78.155.199.17;
}
}
Project tree
opt/
└─ static/
├─admin/
├─ckeditor/
└─static/
└─foundation/
root/
└─ ramn_hotel/
Recently did as here. It worked as it should.