Setting up sockets with Django on gninx - python
I have a Django application running on nginx. This application use sockets, which (as far as I know) should be proxied. So I have troubles configuring nginx and other stuff. Same application works fine on Apache/2.4.7, so I assume that it is not a programming mistake.
Sockets using is based on Django-Channels and backend is very similar to code from Channels getting started.
For server configuration I used this manual.
In the beginning I had just one problem: I got 200 request answer instead of 101 on socket creation. After many manipulations (configuring and newer versions installing) and information collecting I came to current situation:
I start uwsgi separately for sockets:
uwsgi --virtualenv /home/appname/env/ --http-socket /var/run/redis/redis.sock --http-websock --wsgi-file /home/appname/appname/appname/wsgi.py
On this step on socket creation var socket = new WebSocket("ws://appname.ch/ws/64"); I get
WebSocket connection to 'ws://appname.ch/ws/64' failed: Error during WebSocket handshake: Unexpected response code: 502
and sure
2016/09/12 12:00:26 [crit] 30070#0: *2141 connect() to unix:/var/run/redis/redis.sock failed (13: Permission denied) while connecting to upstream, client: 140.70.82.220, server: appname.ch,, request: "GET /ws/64 HTTP/1.1", upstream: "http://unix:/var/run/redis/redis.sock:/ws/64", host: "appname.ch"
in nginx error log.
After chmod 777 /var/run/redis/redis.sock I get responce
WebSocket connection to 'ws://appname.ch/ws/64' failed: Error during WebSocket handshake: Unexpected response code: 404
and in uwsgi
[pid: 6572|app: 0|req: 1/1] 0.0.0.0 () {46 vars in 916 bytes} [Mon Sep 12 12:01:29 2016] GET /ws/64 => generated 3357 bytes in 24 msecs (HTTP/1.1 404) 2 headers in 80 bytes (1 switches on core 0)
nginx.conf file
user www-data;
worker_processes 4;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
redis.conf
daemonize yes
pidfile /var/run/redis/redis-server.pid
port 6379
unixsocket /var/run/redis/redis.sock
unixsocketperm 777
timeout 0
loglevel notice
logfile /var/log/redis/redis-server.log
databases 16
save 900 1
save 300 10
save 60 10000
rdbcompression yes
dbfilename dump.rdb
dir /var/lib/redis
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
/etc/nginx/sites-enabled/appname
server {
listen 80;
server_name appname.ch, 177.62.206.170;
#charset koi8-r;
client_max_body_size 8M;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
include uwsgi_params;
uwsgi_pass unix:///home/appname/appname/app.sock;
#add_header Access-Control-Allow-Origin *;
}
location /ws/ {
#proxy_redirect off;
proxy_pass http://unix:/var/run/redis/redis.sock;
#proxy_http_version 1.1;
#proxy_set_header Upgrade $http_upgrade;
#proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location /static {
alias /home/appname/appname/static_files;
}
location /media {
alias /home/appname/appname/media;
}
}
uwsgi.ini
[uwsgi]
chdir=/home/appname/appname
env=DJANGO_SETTINGS_MODULE=appname.settings
wsgi-file=appname/wsgi.py
master=True
pidfile=/home/appname/appname/appname-master.pid
vacuum=True
max-requests=5000
daemonize=/home/appname/appname/uwsgi.log
socket=/home/appname/appname/app.sock
virtualenv=/home/appname/env
uid=appname
gid=appname
Django app settings.py
"""
Django settings for appname project.
For more information on this file, see
https://docs.djangoproject.com/en/1.7/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.7/ref/settings/
"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ''
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = ['.appname.ch', '177.62.206.170', '127.0.0.1']
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'customers',
'projects',
'moodboard',
'channels',
'debug_toolbar',
'rest_framework',
'appname',
)
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
ROOT_URLCONF = 'appname.urls'
WSGI_APPLICATION = 'appname.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static_files'),
)
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
)
AUTH_PROFILE_MODULE = 'customers.Customer'
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
LOGIN_REDIRECT_URL = '/accounts/home'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts": [("localhost", 6379)],
},
"ROUTING": "appname.routing.channel_routing",
},
}
App urls
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.contrib.auth import views as auth_views
from projects.views import ProjectViewSet
from customers.views import UserHomeView, RegistrationView, CustomerViewSet, UserViewSet
from moodboard.views import MoodBoardViewSet, BoardItemViewSet, BoardTextViewSet, ShareMoodBoardItem, LiveViewSet
from rest_framework import routers
from django.conf import settings
from django.conf.urls.static import static
router = routers.DefaultRouter()
router.register(r'projects', ProjectViewSet)
router.register(r'moodboards', MoodBoardViewSet)
router.register(r'items', BoardItemViewSet)
router.register(r'texts', BoardTextViewSet)
router.register(r'share', ShareMoodBoardItem)
router.register(r'customers', CustomerViewSet)
router.register(r'users', UserViewSet)
router.register(r'live', LiveViewSet)
urlpatterns = patterns('',
url(r'^$', 'appname.views.home', name='landing_page'),
url(r'^api/', include(router.urls)),
url(r'^accounts/login/$', auth_views.login, name='login'),
url(r'^accounts/logout/$', auth_views.logout, name='logout'),
url(r'^accounts/home/$', UserHomeView.as_view(), name='home'),
url(r'^accounts/register/$', RegistrationView.as_view(), name='registration'),
url(r'^admin/', include(admin.site.urls)),
url(r'^customers/', include('customers.urls')),
url(r'^projects/', include('projects.urls')),
url(r'^moodboard/', include('moodboard.urls')),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)root
nginx version: 1.6.2
Redis server version: 2.4.14
uwsgi version: 2.1
Django version: 1.8.0 'final'
Python version: 2.7.3
Seems 404 should not be a complicated error, but after many days of fixing I have no idea what the problem is and if I am on the right way generally.
First of all, do not ever try to create sock manually.
Just set up a path, and it will be created automatically.
This is example nginx and uwsgi conf:
server {
root /your/djang/app/main/folder/;
# the port your site will be served on
listen 80;
server_name your-domain.com *.your-domain.com # if you have subdomains
charset utf-8;
access_log /path/to/logs/if/you/have/access_log.log
error_log /path/to/logs/if/you/have/error_log.log
# max upload size
client_max_body_size 1G;
location /media/ {
alias /path/to/django/media/if/exist/;
}
location /static/ {
alias /path/to/django/static/if/exist/;
}
# Note three slash
location / {
uwsgi_pass unix:///home/path/to/sock/file/your-sock.sock
}
}
and this cna be your uwsgi config file
# suprasl_uwsgi.ini file
[uwsgi]
uid = www-data
gid = www-data
chmod-socket = 755
chown-socket = www-data
# Django-related settings
# the base directory (full path)
chdir = /your/djang/app/main/folder/
# Django's wsgi file
wsgi-file = /your/djang/app/main/folder/main-folder/wsgi.py;
# the virtualenv (full path)
home = /your/env/folder/;
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 2
# the socket (use the full path to be safe
socket = /home/path/to/sock/file/your-sock.soc
logto = /path/to/logs/if/you/have/uwsgi_logs.log
All you have to do is just run this command:
uwsgi --ini your_uwsgi_file.ini # the --ini option is used to specify a file
If you are up for creating a socket manually you can use python.
Try:
python -c "import socket as s; sock = s.socket(s.AF_UNIX); sock.bind('/tmp/test.sock')"
But this does not create a socket. The socket is created by the application if its missing when the web server requests for it.
So we only need to declare our nginx.conf files mapping
location /{
include uwsgi_params;
uwsgi_pass unix:///to/where/you wish/the/file.sock;
}
The server will run socket() command returning a file descriptor checkout man socket.
Related
Multiple websites on single VPS (nginx + centos + django)
I'm using VPS with nginx + centos + django. I already have one website running on it. Now i want to add one more domain, but after reading a lot of articles i still have troubles with it. Here is my nginx.conf file: user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/sites-enabled/*.conf; server_names_hash_bucket_size 64; server { listen 443 ssl; server_name website1.com www.website1.com; ssl_certificate /etc/ssl/www.website1.com.crt; ssl_certificate_key /etc/ssl/www.website1.com.key; location /static/ { root /var/www/website1; index index.html index.htm index.php; } location / { root /var/www/website1; proxy_pass http://127.0.0.1:8888; index index.html index.htm index.php; proxy_connect_timeout 300s; proxy_read_timeout 300s; } } server { listen 80; server_name website1.com www.website1.com; return 301 https://$host:443$request_uri; location = /favicon.ico { alias /var/www/website1/static/img/favicon.png; } location /static/ { root /var/www/website1; index index.html index.htm index.php; } location / { root /var/www/website1; proxy_pass http://127.0.0.1:8888; index index.html index.htm index.php; proxy_connect_timeout 300s; proxy_read_timeout 300s; } } server { listen 443 ssl; server_name website2.com www.website2.com; ssl_certificate /etc/ssl/www.website2.com.crt; ssl_certificate_key /etc/ssl/www.website2.com.key; location /static/ { root /var/www/website2; index index.html index.htm index.php; } location / { root /var/www/website2; proxy_pass http://127.0.0.1:8888; index index.html index.htm index.php; proxy_connect_timeout 300s; proxy_read_timeout 300s; } } server { listen 80; server_name website2.com www.website2.com; return 301 https://$host:443$request_uri; location = /favicon.ico { alias /var/www/website2/static/img/favicon.png; } location /static/ { root /var/www/website2; index index.html index.htm index.php; } location / { root /var/www/website2; proxy_pass http://127.0.0.1:8888; index index.html index.htm index.php; proxy_connect_timeout 300s; proxy_read_timeout 300s; } } } I've tried using one short main file and two files for each website with server blocks same as in the file above. In this case both website doesn't open at all. user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/sites-enabled/*.conf; server_names_hash_bucket_size 64; } Here is my django settings file, it is almost the same for both domains, so i leave here only one """ Django settings for apartment project. Generated by 'django-admin startproject' using Django 2.1.4. For more information on this file, see https://docs.djangoproject.com/en/2.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.1/ref/settings/ """ import os # Logging settings for django projects, works with django 1.5+ # If DEBUG=True, all logs (including django logs) will be # written to console and to debug_file. # If DEBUG=False, logs with level INFO or higher will be # saved to production_file. # Logging usage: # import logging # logger = logging.getLogger(__name__) # logger.info("Log this message") # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = False ALLOWED_HOSTS = ['*'] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'website1.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'website1.wsgi.application' # Database # https://docs.djangoproject.com/en/2.1/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.1/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.1/howto/static-files/ STATIC_ROOT = os.path.join(BASE_DIR, "static") STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'website1', "static") ] What i'm doing wrong? Now it seems to me both website adress the same path, so i get the same content for different domains, but i can't find where is my mistake.
it seems for me, you are trying to start django manually, at some port and connect it with nginx but it is wrong, nginx can serve only static files, and defualt django core python manage.py runserver isn't good enough to use it in production, it is only for testing purpose. You need to connenct it with gunicorn, gunicorn can serve scripts, and nginx for static files. I'll share my configuration which is 100% working with multiple django projects, but i use it on ubuntu this example project called mail, so you can change "mail" on what you want mail project deployment: mkdir mail cd mail virtualenv venv source venv/bin/activate pip install django gunicorn nginx django-admin.py startproject mail ~/mail nano ~/mail/mail/settings.py in settings.py add: 8.a) import os 8.b) ALLOWED_HOSTS = ["*"] 8.c) TIME_ZONE = 'Europe/Moscow' 8.d) STATIC_ROOT = os.path.join(BASE_DIR, 'static/') python manage.py makemigrations python manage.py migrate python manage.py createsuperuser python manage.py collectstatic python manage.py runserver 0.0.0.0:8000 13.a) go to "(ip)0.0.0.0:8000/admin" in your browser the site should work and css styles should be in the admin panel gunicorn --bind 0.0.0.0:8000 mail.wsgi 14.a) (run command above^^ in a folder with manage.py ) 14.b) go to "(ip)0.0.0.0:8000/admin" the site should work and css styles MUST NOT work deactivate sudo nano /etc/systemd/system/mail.service Carefully replace all the words "mail" with the name of your project, /home/admin/mail >> this is root folder (in config under), keep it in mind, you can check your real path to your project by typing pwd command inside your projects folder [Unit] Description=gunicorn daemon After=network.target [Service] User=admin Group=www-data WorkingDirectory=/home/admin/mail ExecStart=/home/admin/mail/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/admin/mail/mail.sock mail.wsgi:application [Install] WantedBy=multi-user.target sudo systemctl start mail sudo systemctl enable mail in the mail project folder (where manage.py ) The file SHOULD (MUST) appear “mail.sock”, if it doesn't go to 16 paragraph, you made misstake there list your folders: ~/mail$ ls output should look like this: db.sqlite3 mail mail.sock manage.py static venv sudo systemctl status mail it will check status of service for project mail, which should start it with gunicorn Nginx configuration: sudo nano /etc/nginx/sites-available/mail replace mail in the config with your project (3 places and 1 address) /home/admin/mail >> this is root folder (in config under), keep it in mind, you can check your real path to your project by typing pwd command inside your projects folder server { listen 80; server_name adress.mail.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/admin/mail; } location / { include proxy_params; proxy_pass http://unix:/home/admin/mail/mail.sock; } } sudo ln -s /etc/nginx/sites-available/mail /etc/nginx/sites-enabled 23.a) cd /etc/nginx/sites-enabled 23.b) type ls project mail must appear in this folder sudo nginx -t this will check nginx for errors sudo systemctl reload nginx next you need to assign a domain name in this example adress.mail.com to your ip adress of you virtual machine, with CNAME or A type. But if you have no any domains name, you can assign you ip adress server_name 222.333.444.555;, but in this case you can't use different port, so no multiple django projects for you (buy a domain) your project will work super good if you done all correctly, if you want to add one more project, just simply redo everything in this list
Django static files not serving in Nginx
My first website with Django on hobby production. I'am follow the setting guide this tutorial https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-20-04#checking-for-the-gunicorn-socket-file my setting.py STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'static/') MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR,'media/') and my nginx config server { listen 80; server_name MYIP; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/azhimeblog/needhobby; } location /media/ { root /home/azhimeblog/needhobby; } location / { include proxy_params; proxy_pass http://unix:/run/gunicorn.sock; } } This result
Django admin dashboard CSS is missing
I just deployed my application to DigitalOcean. Everything works very well, excep admin panel's styling although I've used nginx. Here are my codes: settings.py: STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, "static_root") STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"), ] nginx configuration: server { listen 80; server_name server_domain_or_IP; location = /favicon.ico { access_log off; log_not_found off; } location /static_root/ { root /home/my_username/myproject; } location / { include proxy_params; proxy_pass http://unix:/home/my_username/myproject/myproject.sock; } }
Django duplicate admin prefix in url
I'm running Django in Fastcgi Mode ./manage.py runfcgi method=threaded host=127.0.0.1 port=8080 with Nginx server { listen 80; server_name myhostname.com; access_log /var/log/nginx/sample_project.access.log; error_log /var/log/nginx/sample_project.error.log; location /static/ { # STATIC_URL alias /home/www/myhostname.com/static/; # STATIC_ROOT expires 30d; } location /media/ { # MEDIA_URL alias /home/www/myhostname/static/; # MEDIA_ROOT expires 30d; } location / { include fastcgi_params; fastcgi_pass 127.0.0.1:8080; } } The admin url is http://myhostname.com/admin/ I notice that every HTML link generated is wrong like this one below ... Log out ... Below my url.py from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'configuratore.views.home', name='home'), # url(r'^blog/', include('blog.urls')), url(r'^admin/', include(admin.site.urls)), ) It seems that Django is duplicating admin URL but i'm not understanding why.
Make sure to add fastcgi_param SCRIPT_NAME ""; to your location / block in nginx configuration. By default django prepends it's value to reversed urls, thus setting to empty url should make it work.
Django won't recognize my static files on my dev machine
I've been tasked with fixing some aspects of a django 1.3 site, that runs on Apache/PostgreSql on the server. I'm trying to set it up on my development machine, with a virtual environment with postgres and the internal python developer server. I managed to get the site running and reading from my local pg instance, but I can't get it to recognize my static files, which are stored in /site_media. The site will soon be rewritten to use django 1.6 and the proper /static folder but for now I need to fix this site. I also tried running it with nginx and gnunicorn but the result is the same, the site displays but with no style and all references to files in the static dir give a 404. further inspection of the 404 reveals that django is trying to resolve the resources with its router. Here are the relevant settings: settings.py: # Absolute path to the directory that holds media. # Example: "/home/media/media.lawrence.com/" MEDIA_ROOT = '/home/nico/src/df2/datos/site_media/' # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash if there is a path component (optional in other cases). # Examples: "http://media.lawrence.com", "http://example.com/media/" MEDIA_URL = 'http://localhost:8000/site_media/' I also added the following config, to no avail: INSTALLED_APPS = ( 'django.contrib.staticfiles', ) STATICFILES_DIRS = ( '/home/nico/src/df2/datos/site_media/', ) STATIC_URL = 'http://localhost:8000/site_media' nginx config file: server { server_name localhost; access_log off; location /site_media/ { alias /home/nico/src/df2/datos/site_media; } location / { proxy_pass http://127.0.0.1:8001; proxy_set_header X-Forwarded-Host $server_name; proxy_set_header X-Real-IP $remote_addr; add_header P3P 'CP="ALL DSP COR PSAa PSDa OUR NOR ONL UNI COM NAV"'; } } If you need any other config please tell me. I'd prefer to run this purely from the python server, but a solution with gunicorn/nginx is also fine
The fix was in adding a static handler to the urlpatterns variable: from django.conf import settings if settings.DEBUG: # static files (images, css, javascript, etc.) urlpatterns += patterns('', (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', { 'document_root': settings.MEDIA_ROOT}))