Django 301 and 403 forbidden errors on my static files in production
Asked Answered
P

6

8

I'm trying to deploy a django website on a ubuntu 14.04 vps using nginx and gunicorn but my css files and js files are not getting loaded.i developed it on the default django development server and it worked very well, but when i deploy my site and collectstatic and try to access it through the browser only the HTML text gets loaded and on checking on my browser console i find 301 and 403 forbidden errors on my static folder. i a newbie to ubuntu and django as well and all the threads and forums i've found online simply point to permissions and ownership of files and haven't had any luck when i correct my permissions.

screenshot of my browser error when i try to access django admin

here is my settings.py

import os

# 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/1.11/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 = ['mysite.com','www.mysite.com']


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'powerlineapp',
]

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 = 'powerlineproject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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 = 'powerlineproject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.11/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/1.11/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/1.11/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.11/howto/static-files/


STATIC_URL = '/static/'

if not DEBUG: 
    STATIC_ROOT = '/var/www/powerline/powerlineproject/static/'


MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL = '/media/'

here is my main urls.py

from django.conf.urls import include,url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^',include('powerlineapp.urls')),

]

nginx.conf

user www-data www-data;
pid /var/run/nginx.pid;
worker_processes 1;
worker_rlimit_nofile 100000;

events {
    worker_connections  4096;
    include /etc/nginx.custom.events.d/*.conf;
}

http {
    default_type application/octet-stream;

    access_log off;
    error_log  /var/log/nginx/error.log crit;

    sendfile on;
    tcp_nopush on;

    keepalive_timeout 20;
    client_header_timeout 20;
    client_body_timeout 20;
    reset_timedout_connection on;
    send_timeout 20;

    types_hash_max_size 2048;

    gzip on;
    gzip_disable "msie6";
    gzip_proxied any;
    gzip_min_length 256;
    gzip_comp_level 4;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;

    server_names_hash_bucket_size 128;

    include mime.conf;
    charset UTF-8;

    open_file_cache max=100000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    server_tokens off;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    include proxy.conf;
    include fcgi.conf;

    include conf.d/*.conf;
    include /etc/nginx.custom.d/*.conf;
}

include /etc/nginx.custom.global.d/*.conf;

my site conf file

server {
    listen *:80;



    server_name powerlineagencies.co.ke;

    access_log /var/log/nginx/powerline-agencies.access.log;
    error_log /var/log/nginx/powerline-agencies.error.log;

    root /var/www/powerline/powerlineproject;
    index index.html index.htm index.php;





    location  / {



        proxy_pass http://unix:/var/run/ajenti-v-gunicorn-powerline-agencies-python-wsgi-0.sock;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    }


    location ~ /static/.* {
        alias /var/www/powerline/powerlineproject;




    }

}

here is my directories structure

screenshot of my directory structure

Can someone please help me solve this problem?

Pocketful answered 5/7, 2017 at 6:41 Comment(5)
show your main urls.pyOliviaolivie
updated my question and included my main urls.py, its nothing fancy but i believe that is adequate enough to load my admin dashboard at least. but i'm not sure why it doesn't work in production.Pocketful
Are you sure your nginx user www-data can access /var/www/powerline/powerlineproject. You should try nginx config as location /static/ { root /var/www/powerline/powerlineproject; }Vespers
if i said im sure id be lying. let me explain what i did so you can give me your correct input. first i created a user with sudo priviledges and the logged i to server with the user account. navigated to var/www and created a folder powerline then inside the folder i created a virtualenv and activated it and created my django project named powerlineproject, then i edited my settings.py and added STATIC_ROOT as advised by @Oliviaolivie then made my migrations and collected static..then setup my nginx confs as directed.navigated to the browser and tried to access django admin..still 403 :-(Pocketful
did you try the edited ans @PocketfulOliviaolivie
O
1
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

in ngix

location /static/ {    

            alias /var/www/powerline/powerlineproject/static/;    
         }  

add this lines to urls.py and collectstatic and then check

Oliviaolivie answered 5/7, 2017 at 6:57 Comment(13)
i've tried your solution but still no luck. my files are still forbidden.Pocketful
are you serving it with any server? like nginx?Oliviaolivie
updated my question. i have included both nginx conf files for both my site and the default nginx.conf file.Pocketful
i have tried your solution and updated my nginx files but still nothing happened..the errors still remains. :-( .Even tried to reload and restart nginxPocketful
why dont you keep the static root as /static and remove the full path from your settings? and check again by doing collectstaticOliviaolivie
you mean remove the full path on my STATIC_ROOT?Pocketful
yup, and keep STATIC_ROOT = os.path.join(BASE_DIR,'static')Oliviaolivie
I changed the static root to what You specified above and still not getting any change..still 403..can it be a problem with my slashes(/) im not sure how to place them correctly for django to access my static folderPocketful
tell me the path where the static files are created when used collectstatic? @PocketfulOliviaolivie
i have added a screenshot of my directory structure.see editPocketful
I have redone the whole deployment again from scratch and ended up with the same errors.@Oliviaolivie including edit above. i really can't figure out where exactly i'm going wrong.Pocketful
well i did everything you told me to but now i have a new problem Resource interpreted as Stylesheet but transferred with MIME type text/html: http://example.com/static/admin/css/base.css/ thats what im getting on the console now.Pocketful
great bro :) hope could help @PocketfulOliviaolivie
R
29

Nginx needs to be able to read the static folder. You can do this by adding the www-data user to the group that your project user is in.

sudo usermod -a -G your_user www-data

Then restart nginx.

Ravel answered 13/1, 2022 at 6:48 Comment(1)
this helped me after several hours of searching and debugging!Springclean
P
7

I have fixed my issue by putting the username (that I am using in the prod server) in nginx.conf file.

nginx.conf file can be found in this location: /etc/nginx/nginx.conf

When I was getting the 403 Forbidden error, the user section was: user www-data;. I had to change that to user ubuntu; (as I am using ubuntu user to run my application).

Pietro answered 26/4, 2023 at 18:53 Comment(0)
O
1
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

in ngix

location /static/ {    

            alias /var/www/powerline/powerlineproject/static/;    
         }  

add this lines to urls.py and collectstatic and then check

Oliviaolivie answered 5/7, 2017 at 6:57 Comment(13)
i've tried your solution but still no luck. my files are still forbidden.Pocketful
are you serving it with any server? like nginx?Oliviaolivie
updated my question. i have included both nginx conf files for both my site and the default nginx.conf file.Pocketful
i have tried your solution and updated my nginx files but still nothing happened..the errors still remains. :-( .Even tried to reload and restart nginxPocketful
why dont you keep the static root as /static and remove the full path from your settings? and check again by doing collectstaticOliviaolivie
you mean remove the full path on my STATIC_ROOT?Pocketful
yup, and keep STATIC_ROOT = os.path.join(BASE_DIR,'static')Oliviaolivie
I changed the static root to what You specified above and still not getting any change..still 403..can it be a problem with my slashes(/) im not sure how to place them correctly for django to access my static folderPocketful
tell me the path where the static files are created when used collectstatic? @PocketfulOliviaolivie
i have added a screenshot of my directory structure.see editPocketful
I have redone the whole deployment again from scratch and ended up with the same errors.@Oliviaolivie including edit above. i really can't figure out where exactly i'm going wrong.Pocketful
well i did everything you told me to but now i have a new problem Resource interpreted as Stylesheet but transferred with MIME type text/html: http://example.com/static/admin/css/base.css/ thats what im getting on the console now.Pocketful
great bro :) hope could help @PocketfulOliviaolivie
G
0

Check your project ownership: ls -l <YOUR_PROJECT_FOLDER> and make sure that your user and group are the same as the user you have in nginx.conf.

In your case you have user www-data www-data;

Graph answered 20/10, 2021 at 22:5 Comment(0)
L
0

Check user and group permissions,may be some javascripts does'nt have execute permission. I mean rwx permisson for static folder and subfolders.

Leyla answered 10/12, 2022 at 18:49 Comment(0)
M
0

You have to just add the root or ubuntu user in your Nginx configs to allow the default user all access for static files.

Run the command: sudo nano  /etc/nginx/nginx.conf
At the top replace user www-data with user root; OR user ubuntu;
Mon answered 13/9, 2024 at 10:5 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.