Steve Stacha
Steve Stacha

Reputation: 198

Nginx root directive inside location doesn't seem to be working

nginx version: nginx/1.10.3 (Ubuntu) built with OpenSSL 1.0.2g 1 Mar 2016 TLS SNI support enabled Installed via apt-get using html5 boilerplate config project as a base

I have been trying to do a simple task and it is not working like I thought it would. I have a directory structure like so:

/var/www$ tree
.
├── docroot
│   └── files
│       ├── booger.txt
│       └── favicon.ico
└── static
    ├── h5bp
    │   ├── humans.txt
    │   ├── js
    │   │   ├── main.js
    │   │   ├── plugins.js
    │   │   └── vendor
    │   │       ├── jquery-1.12.0.min.js
    │   │       └── modernizr-2.8.3.min.js
    │   ├── tile.png
    │   └── tile-wide.png

I thought the best approach was to have a server root of the docroot/files (the real docroot) and then redefine the root for the static files. Here is my default config in /etc/nginx/sites-available:

# Choose between www and non-www, listen on the *wrong* one and redirect to
# the right one -- http://wiki.nginx.org/Pitfalls#Server_Name
#
server {
  listen [::]:80 default_server;
  listen 80 default_server;

  # listen on all hosts
  server_name _;

  # and redirect to the https host (declared below)
  # avoiding http://www -> https://www -> https:// chain.
  return 301 https://www.ubercode.io$request_uri;
}

server {

  # listen [::]:443 ssl http2 accept_filter=dataready;  # for FreeBSD
  # listen 443 ssl http2 accept_filter=dataready;  # for FreeBSD
  listen [::]:443 ssl http2 deferred default_server;  # for Linux
  listen 443 ssl http2 deferred default_server;  # for Linux
  # listen [::]:443 ssl http2;
  # listen 443 ssl http2;

  # The host name to respond to
  server_name www.ubercode.io;

  include h5bp/directive-only/ssl.conf;

#  root /var/www/docroot/files;
  root /var/www;
  index index.html index.htm index.nginx-debian.html;

    # return forbidden for any php, asp, jsp, our .dt templates, or myadmin requests
#    location ~ (\.dt$|myadmin|\.php$|\.jsp$|\.asmx$|\.asp$) {
#       deny all;
#    }

#    location ~*  \.(jpg|jpeg|png|gif|ico|css|js)$ {
#        expires 1d;
#    }
#    location ~*  \.(pdf)$ {
#        expires 5d;
#    }

  # static
  location /static/ {
#    root /var/www;
    autoindex on;
#     expires 1d;
  }

  location / {
    alias /var/www/docroot/files;
    autoindex on;
  }
  #Specify a charset
  charset utf-8;

  # Custom 404 page
  error_page 404 /404.html;

  # Include the basic h5bp config set
  include h5bp/basic.conf;
}

server {
  listen [::]:443 ssl http2;
  listen 443 ssl http2;

  # listen on the wrong host
  server_name _;

  include h5bp/directive-only/ssl.conf;

  # and redirect to the non-www host (declared below)
  return 301 https://www.ubercode.io$request_uri;
}

If I use it like it is shown, the static files work but the alias at the root does not seem to work as they throw a 404. If I comment the alias under the / location and the /var/www server root then uncomment the other lines the server returns docroot/files assets but no static files. It just seems like the overriding root inside a location block doesn't work. Can anyone explain whats going on and possibly give me some direction to how to fix it?

Upvotes: 1

Views: 3889

Answers (1)

Richard Smith
Richard Smith

Reputation: 49812

If I use it like it is shown, the static files work but the alias at the root does not seem to work as they throw a 404.

You should not use an alias directive in the location / statement. Use a root statement with the same value instead.

If I comment the alias under the / location and the /var/www server root then uncomment the other lines the server returns docroot/files assets but no static files.

If you enable the location ~* \.(jpg|jpeg|png|gif|ico|css|js)$, then it will override the location /static/ block, and setting any value for root within the latter will be ignored. Also, it will override the location / block for URIs ending with .ico so /favicon.ico will no longer work as it's from a different document root.

See how nginx processes a request and note that regular expression locations take precedence over prefix locations.

If you need to fine tune the expires value, you cannot add location blocks without considering which document root they influence.

See this answer for an alternative approach, using a map directive to set the expires value based on the $request_uri.

Upvotes: 2

Related Questions