Getting a "403 access denied" error instead of serving file (using django, gunicorn nginx)

I am attempting to use nginx to serve private files from django. For X-Access-Redirect settings I followed the following guide


Here is my site config file (/etc/nginx/site-available/sitename):

server {
    listen 80;
    listen 443 default_server ssl;

    server_name localhost;

    client_max_body_size    50M;

    ssl_certificate /home/user/site.crt;
    ssl_certificate_key /home/user/site.key;

    access_log /home/user/nginx/access.log;
    error_log  /home/user/nginx/error.log;

    location / {
           access_log /home/user/gunicorn/access.log;
           error_log /home/user/gunicorn/error.log;
           alias /path_to/app;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header Host $http_host;
           proxy_redirect off;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Scheme $scheme;
           proxy_connect_timeout 100s;
           proxy_send_timeout 100s;
           proxy_read_timeout 100s;

    location /protected/ {
            alias /home/user/protected;

I then tried using the following in my django view to test the download:

response = HttpResponse()
response['Content-Type'] = "application/zip"
response['X-Accel-Redirect'] = '/protected/test.zip'
return response

but instead of the file download I get:

403 Forbidden

Please note: I have removed all the personal data from the the config file, so if there are any obvious mistakes not related to my error that is probably why.

My nginx error log gives me the following:

**2012/09/18 13:44:36 [error] 23705#0: *44 directory index of "/home/user/protected/" is forbidden, client:, server: localhost, request: "GET /icbdazzled/tmpdir/ HTTP/1.1", host: "www.icb.fi"**
  • can you post what your error log says when you make a request?
    – Mike
    Sep 18 '12 at 12:25
  • @Mike. Thanks for responding, I have now added the output from the nginx error log to my question. There is no error output from gunicorn.
    – Finglish
    Sep 18 '12 at 15:15
  • The only output when i run gunicorn in debug mode is "[debug]x_forwarded_for_header: X-FORWARDED-FOR"
    – Finglish
    Sep 18 '12 at 15:40

You should use root:

location /protected/ {
        root /home/user;

instead of your alias:

location /protected/ {
        alias /home/user/protected;
  • This seems to have had some effect, but now I am getting a 404 error. If I tried testing the view without the "X-Accel-Redirect" statement and the view url is working so it like it is a file referencing issue.
    – Finglish
    Sep 18 '12 at 19:13
  • I was under the impression that using root inside a location block was not considere best practice?
    – Finglish
    Sep 18 '12 at 19:23
  • Using alias instead of root is a bad practice. Official documentation recommends root where it's possible. But to be more precise your problem was missing / at the end of alias path while the location has it.
    – VBart
    Sep 18 '12 at 19:49
  • See this answer for details.
    – VBart
    Sep 18 '12 at 19:59
  • 1
    I have it working now. It ended up being a combination of issues. The first being the use of alias instead of root, and the second being the file/folder permissions. To serve files from a folder permissions MUST be set to the same as the server (in my case gunicorn, but its probably the same for other server setups)
    – Finglish
    Sep 20 '12 at 23:12

I had the same issue no long ago. It might be a combination of factors. I found how to fix 403 access denied by replacing the user in the nginx.conf file.

  • I deployed my website on an ubuntu server using Digital Ocean.
  • I created a new user on my new ubuntu server and give admin priviliges
    adduser newuser

    usermod -aG sudo newuser 
  • I updated my new server and installed few packages
    sudo apt update

    sudo apt install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx curl 
  • I followed all this beautiful instruction on how to deploy your site on Digital Ocean
  • Since I changed the user and I ssh into my new server using this new user, I need to replace the user on the nginx.conf. By default nginx.conf user is www-data:
    user www-data;

    worker_processes auto;

    pid /run/nginx.pid;

Then I replaced with my sudo user and solved my problem. 😀

    user newuser;

    worker_processes auto;

    pid /run/nginx.pid;
  • Then I restart nginx, gunicorn and postgresql(even if the last one it is not really necessary)
    sudo systemctl restart nginx 

    sudo systemctl restart gunicorn

    sudo systemctl restart postgresql

And tada.. :) no more issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.