I have a couple of questions regarding my nginx configuration as it pertains to serving webp files as well as using named locations with try_files
.
Current config:
server {
listen 80;
server_name assets.manager manager;
passenger_app_env production;
passenger_ruby /home/web-server/.rvm/gems/ruby-2.2.1@manager/wrappers/ruby;
passenger_enabled on;
error_log /home/web-server/web-applications/manager/current/log/nginx-error.log;
root /home/web-server/web-applications/manager/current/public;
satisfy any;
allow 127.0.0.1;
allow 192.168.0.0/24;
deny all;
location ~ ^/assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
}
location ~* .+\.(?:png|jpe?g|gif)$ {
if ($webp_suffix != "") {
add_header Vary Accept;
}
try_files $uri$webp_suffix $uri =404;
}
}
As it stands, nginx is not serving the webp files. If I were to place add_header X-Webp-Uri "$uri$webp_suffix";
inside the first location
block, the header is added. If I were to put that in the second png/jpeg matching location
block the header doesn't get set. It was my understanding that regular expression location blocks are sequential (i.e., it doesn't stop matching at the 1st match).
1) I want to serve webp images if present (my attempt at this is the 2nd location
block). Would having a nested location
block help in this circumstance? I want to set gzip_static, expires, etc. for ALL files in /assets/, but I only want to serve webp version if they exist for certain file extensions within /assets/.
2) On another topic, I want to serve static .html files if present. To do this (after looking up tutorials on the web) I need a combination of try_files
and a named location block that points to an upstream application (Rails). However I can't seem to find out how to declare the upstream block if I'm using Passenger (installed using passenger-install-nginx-module
). The only configurations I can find for a Passenger/Nginx setup is to use passenger_enabled on;
EDIT: I found a sample configuration; here's an example (this ignores problem #1):
server {
listen 80;
server_name assets.staging.pos staging.pos;
passenger_app_env staging;
passenger_ruby /home/vagrant/.rvm/gems/ruby-2.2.1@pos/wrappers/ruby;
passenger_enabled on;
error_log /home/vagrant/rails/staging.pos/log/nginx-error.log;
root /home/vagrant/rails/staging.pos/public;
try_files $uri /cache/$uri /cache/$uri.html @app;
location @app {
proxy_set_header X-Forwarded-Proto http;
}
location ~* ^/images/.+\.(png|jpe?g)$ {
if ($webp_suffix != "") {
add_header Vary Accept;
}
try_files $uri$webp_suffix $uri =404;
}
}
EDIT 2: I've discovered that nginx completely wipes out any instruction outside of the if
block!
This will result in only the Vary Accept
header being set:
server {
location ~* ^/images/.+\.(png|jpe?g)$ {
add_header X-Whatever "Yo";
if ($webp_suffix != "") {
add_header Vary Accept;
}
}
}
This will result in both headers being set:
server {
location ~* ^/images/.+\.(png|jpe?g)$ {
if ($webp_suffix != "") {
add_header Vary Accept;
add_header X-Whatever "Yo";
}
}
}
EDIT 3: So now it's even more befuddling. It's like any prior add_header
that isn't within the last code block (location or if statement) is completely ignored. i.e., with the following, only the X-Whatever header is set:
location ~ ^/assets/ {
gzip_static on;
expires max;
add_header Cache-Control public; # Ignored?!
add_header Last-Modified ""; # Ignored?!
add_header ETag ""; # Ignored?!
location ~* ^/assets/.+\.(?:png|gif|jpe?g)$ {
add_header X-Something "$uri$webp_suffix"; # Not ignored!
}
}
I had to remove the Vary Accept
header condition and simply always apply it. I don't know if that's good or bad but I don't have any other choice considering it just removes every other header I've applied! I also had to move the webp location block above the assets block and duplicate code which sucks.
Working configuration:
server {
listen 80;
server_name assets.staging.pos staging.pos;
passenger_app_env staging;
passenger_ruby /home/vagrant/.rvm/gems/ruby-2.2.1@pos/wrappers/ruby;
passenger_enabled on;
error_log /home/vagrant/rails/staging.pos/log/nginx-error.log;
root /home/vagrant/rails/staging.pos/public;
# Try to return cached responses without hitting the app
try_files $uri /cache/$uri /cache/$uri.html @app;
location @app {
proxy_set_header X-Forwarded-Proto http;
}
# Return webp images when possible
location ~* ^/assets/.+\.(?:png|gif|jpe?g)$ {
expires max;
add_header Cache-Control public;
add_header Vary Accept;
add_header Last-Modified "";
add_header ETag "";
try_files $uri$webp_suffix $uri =404;
}
# Regular asset headers
location ~ ^/assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
add_header Last-Modified "";
add_header ETag "";
}
}