Question on Nginx ERPNext/Frappe configuration

I’m trying to understand the rationale behind Frappe’s default Nginx setup, and I’m just curious if there’s a reason it’s done this way.

From what I understand, Frappe typically serves public files under the /files prefix. In the standard config, though, Nginx is set up to try serving any URI directly from the site’s public folder first, and only falls back to the backend if the file isn’t found:

location / {
  try_files /$host/public/$uri @webserver;
}

So for something like https://erpnext-yes.com/files/star.png, Nginx would try /$host/public/files/star.png first, and only forward to the backend if it doesn’t exist.

Would it be cleaner (or is there a downside) to making the intent more explicit - i.e., only handling /files/* as static public files, and proxying everything else straight to the Frappe backend?

Something like:

location ~ ^/files/(.*) {
  try_files /$host/public/files/$1 =404;
}

location / {
  proxy_pass http://backend-server;
  ...
}

In other words:

  • If the URI starts with /files/, serve it from public/files (and return 404 if missing)
  • Otherwise, forward to the backend

Would a structure like this be acceptable in practice, and does it improve readability/maintainability? Or does the default try_files /$host/public/$uri approach provide some benefit that I’m missing?

For example, would something like the below be considered “cleaner,” or is there a reason Frappe avoids it?

server {
  listen 80;
  server_name super-erpnext.com;
  root /home/frappe/frappe-bench/sites;

  # Serve asset
  location /assets {
    try_files $uri =404;
  }

  # Serve private files (via X-Accel-Redirect only)
  location ~ ^/protected/(.*) {
    internal;
    try_files /$host/$1 =404;
  }

  # Serve public files
  location ~ ^/files/(.*) {
    try_files /$host/public/files/$1 =404;
  }

  # Proxy to socket.io
  location /socket.io {
    ...
    proxy_pass http://socketio-server;
  }

  # Proxy to backend-server
  location / {
    ...
    proxy_pass http://backend-server;
  }
}

Reference:

Updates:

  • I did tryout with this nginx config and things works as it should.