10

I'm trying to get Cache-Control working on Nginx for assets on my server and it is not taking as expected. Here is my server config for Nginx.

Everything but Cache-Control is working.

Server Blocks

server {
   listen 80;
   server_name www.example.com;
   rewrite ^ https://$server_name$request_uri? permanent;
}

server {
   listen 80;
   server_name example.com;
   rewrite ^ https://www.$server_name$request_uri? permanent;
}

server {
   listen 443 ssl;
   server_name default;
   root /app/public;

   ssl_certificate /etc/nginx/ssl/default/crt/server.crt;
   ssl_certificate_key /etc/nginx/ssl/default/crt/server.key;
   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   index index.html index.htm index.php;
   charset utf-8;
   add_header "X-UA-Compatible" "IE=Edge,chrome=1";

   location ~* \.(ico|css|js|gif|jpeg|jpg|png|woff|ttf|otf|svg|woff2|eot)$ {
       expires 1d;
       access_log off;
       add_header Pragma public;
       add_header Cache-Control "public, max-age=86400";
       add_header X-Asset "yes";
   }

   location / {
      try_files $uri $uri/ /index.php?$query_string;
   }

   location = /favicon.ico { access_log off; log_not_found off; }
   location = /robots.txt { access_log off; log_not_found off; }
   access_log off;
   error_log /var/log/nginx/default-error.log error;

   error_page 404 /index.php;
   location ~ \.php$ {
      fastcgi_split_path_info ^(.+\.php)(/.+)$;
      fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
      fastcgi_index index.php;
      include fastcgi_params;
   }

   location ~ /\.ht {
      deny all;
   }
}

Here is my server's response for https://www.example.com/icons/facebook.png:

Accept-Ranges:bytes
Cache-Control:public, max-age=120
Connection:keep-alive
Content-Length:416
Content-Type:image/png
Date:Tue, 04 Oct 2016 14:46:26 GMT
ETag:"57f2a0fd-1a0"
Last-Modified:Mon, 03 Oct 2016 18:18:37 GMT
Server:nginx/1.11.2

The max-age is 120 where I am expecting 86400 and there is no custom X-Asset header too.

HTTP Block

The /etc/nginx/conf.d/ folder is empty.

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # SSL Settings
    ##

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;

    ##
    # Logging Settings
    ##

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 5;
    # gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}
Kevin
  • 301
  • 1
  • 3
  • 12
  • also, do you really need "add_header Pragma public;" ? it's never been used properly and it has since been deprecated – pcarvalho Nov 25 '16 at 06:47

1 Answers1

2

Is your origin sending back a Cache-Control header? Or is this one of the files that would be served directly from file system.

If so, perhaps you just have not reloaded nginx after the change? sudo nginx -s reload

Separate from your direct question, but just a note that the line:

add_header "X-UA-Compatible" "IE=Edge,chrome=1";

won't apply on any location that contains it's own add_header directive (you can see this in your pasted output).

Kevin
  • 301
  • 1
  • 3
  • 12
Joshua DeWald
  • 316
  • 1
  • 6
  • I have restarted Nginx. Should I reload the config or does restart do the same thing? – Kevin Oct 04 '16 at 16:03
  • The facebook.png file is being returned from the server as expected it is just not loading the correct cache-control header. – Kevin Oct 04 '16 at 16:04
  • I just added a custom header and it is not showing up as well. I'm wondering if my location regex is bad but I'm not seeing it. – Kevin Oct 04 '16 at 16:34
  • Well the question is whether the `Cache-Control` header is coming back from the original server (from fastcgi) or something. If your intent is to override then you will need to hide it from the original response to be able to re-add. – Joshua DeWald Oct 04 '16 at 21:47
  • What do you mean by "original server"? Nginx, assets, and application code are all on the same server. Just for clarity, my main goal is to have the browsers cache assets not Nginx. I'm not using Nginx as a proxy for caching. Also, are you saying the fastcgi gateway might be adding headers and looping back to Nginx? I have looked through all other configs and no `Cache-Control` headers are being set by Nginx. – Kevin Oct 05 '16 at 18:14
  • What's still not clear is whether this particular asset is being served directly from the file system by nginx, or if it is going through your application (and proxied by nginx). If the latter, then have you 100% confirmed that if you curl directly to the application for that resource that it does not set the `Cache-Control` header. Generally speaking, nginx will not add on it's own. – Joshua DeWald Oct 05 '16 at 18:58
  • The files are not passing through the application code and are being served directly through Nginx. I found out that `sudo service nginx restart` was not reloading the config. When I ran `sudo service nginx reload` it gave me an error. So, I had to run `sudo nginx -s reload` instead and that did the trick. It is working now. – Kevin Oct 05 '16 at 19:39