Private files: 404 not found on nginx

when I try to access a private file even as a System Manager and even when it has been explicitly shared with me, I get a 404 not found error from nginx.

I have read the other similar threads, and tried this a few times:

bench update
bench setup nginx
sudo service nginx reload

But it did not fix the problem.

The upload is working correctly and the files are present in the folder:


This is my current nginx config:

upstream frappe-bench-frappe {
    server fail_timeout=0;

upstream frappe-bench-socketio-server {
    server fail_timeout=0;

server {
    listen 443;

    ssl_certificate /etc/letsencrypt/live/;
    ssl_certificate_key /etc/letsencrypt/live/;

    root /home/erpnext-user/frappe-bench/sites;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";

    location /assets {
        try_files $uri =404;

    location ~ ^/protected/(.*) {
        try_files /$1 =404;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Frappe-Site-Name;
        proxy_set_header Origin $scheme://$http_host;
        proxy_set_header Host $host;

        proxy_pass http://frappe-bench-socketio-server;

    location / {
        rewrite ^(.+)/$ $1 permanent;
        rewrite ^(.+)/index\.html$ $1 permanent;
        rewrite ^(.+)\.html$ $1 permanent;

        location ~ ^/files/.*.(htm|html|svg|xml) {
            add_header Content-disposition "attachment";
            try_files /$uri @webserver;

        try_files /$uri @webserver;

    location @webserver {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Frappe-Site-Name;
        proxy_set_header Host $host;
        proxy_set_header X-Use-X-Accel-Redirect True;
        proxy_read_timeout 120;
        proxy_redirect off;

        proxy_pass  http://frappe-bench-frappe;

    # error pages
    error_page 502 /502.html;
    location /502.html {
        root /home/erpnext-user/.bench/bench/config/templates;

    # optimizations
    sendfile on;
    keepalive_timeout 15;
    client_max_body_size 50m;
    client_body_buffer_size 16K;
    client_header_buffer_size 1k;

    # enable gzip compresion
    # based on
    gzip on;
    gzip_http_version 1.1;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_vary on;
        # text/html is always compressed by HttpGzipModule

the only parts I modified after running bench setup nginx is the listening port and the ssl_certificate.

Hello did you solve this isse?

Sadly no, still looking for help.
My next step would be to set up a second erpnext server from scratch and see if the issue persists.

I’m not an expert. But you should:

  1. Check what the nginx logs are saying. You might have a permission issue, meaning the user/group nginx runs as has no access to that file. A quick way to check is chmod 777 ./my-file this will give any user access to the file. So that’s just for quick checking.

  2. You haven’t said in which url are you looking for the file, in your nginx you configure the root as root /home/erpnext-user/frappe-bench/sites so anything you look for now is relative to that, your file should be in

concerning 1:
all files in /home/erpuser/frappe-bench/sites/ are world readable (644). I tried chmod 777 on one, still 404

the nginx log says:

"28/Aug/2020:17:17:49 +0200" method=GET request="GET /private/files/my_testfile.pdf HTTP/2.0" request_length=415 status=404 bytes_sent=432 body_bytes_sent=146 referer=- user_agent="Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:79.0) Gecko/20100101 Firefox/79.0" upstream_addr= upstream_status=200 request_time=0.085 upstream_cache_status="-" upstream_response_time=0.084 upstream_connect_time=0.000 upstream_header_time=0.084

interestingly the upstream python server seems to find the file (upstream_status=200), but somehow getting it to the client does not work.

concerning 2:

the root path is set the way that erpnext configures it out of the box. And I think that is probably correct. What I think is supposed to happen is:

  1. Incoming GET request to
  2. nginx matches the / location block
  3. the try_files directive checks the folder /$uri first (relative to the root, so the absolute path would be /home/erpnext-user/frappe-bench/sites/
  4. no public file of that name found so we pass the request to the upstream python server (@webserver)
  5. webserver verifies if user session has permission to access the file
  6. if permission is granted the webserver somehow redirects to the /protected/ location block (notice the internal directive).

Public files work normally, so I’m pretty sure the paths as well as the file permissions are correct.
When I try accessing the file without being logged in, I get a correct 403 forbidden response.
Therefore the problem is probably in step 6.

sudo bench setup production --user

overwrite your nginx and supervisorctl

then test nginx -t