1

I'm deploying RoR application to Amazon Elastic Beanstalk. Static files are served with nginx. App root is: /var/app/current, it contains current Rails application. public dir tree:

=> /var/app/current/public
drwxr-xr-x  6 webapp webapp 4096 Aug 31 12:53 .
drwxr-xr-x 13 webapp webapp 4096 Aug 31 12:54 ..
-rw-r--r--  1 webapp webapp 1722 Aug 31 12:52 404.html
-rw-r--r--  1 webapp webapp 1705 Aug 31 12:52 422.html
-rw-r--r--  1 webapp webapp 1635 Aug 31 12:52 500.html
-rw-r--r--  1 webapp webapp    0 Aug 31 12:52 apple-touch-icon.png
-rw-r--r--  1 webapp webapp    0 Aug 31 12:52 apple-touch-icon-precomposed.png
drwxr-xr-x  3 webapp webapp 4096 Aug 31 12:54 assets
drwxr-xr-x  2 webapp webapp 4096 Aug 31 12:52 debug
-rw-r--r--  1 webapp webapp    0 Aug 31 12:52 favicon.ico
drwxr-xr-x  4 webapp webapp 4096 Aug 31 12:52 fonts
drwxr-xr-x  3 webapp webapp 4096 Aug 31 12:52 images
-rw-r--r--  1 webapp webapp   98 Aug 31 12:52 robots.txt

The problem is assets are not served completely. Here's my nginx config I'm pushing to EBS servers:

# 0.02
upstream my_app {
  server unix:///var/run/puma/my_app.sock;
}

log_format healthd '$msec"$uri"'
                '$status"$request_time"$upstream_response_time"'
                '$http_x_forwarded_for';

server {
  listen 80;
  server_name _ localhost; # need to listen to localhost for worker tier

  if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})T(\d{2})") {
    set $year $1;
    set $month $2;
    set $day $3;
    set $hour $4;
  }

  access_log  /var/log/nginx/access.log  main;
  access_log /var/log/nginx/healthd/application.log.$year-$month-$day-$hour healthd;

  location /assets {
    alias /var/app/current/public/assets;
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
  }

  location /fonts {
    alias /var/app/current/public/fonts;
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
  }

  location /images {
    alias /var/app/current/public/images;
    gzip_static on;
    gzip on;
    expires max;
    add_header Cache-Control public;
  }

  location / {
    proxy_pass http://my_app; # match the name of upstream directive which is defined above
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

}

Blocks /assets and /fonts are served poperly, returning code 200.

But /images return 301, redirecting to URL with trailing slash, which cannot be found:

301 to 404

If I request PNG image with curl, image is served properly. Redirection /images/stubs/banner.png -> 301 => /images/stubs/banner.png/ -> 404 happens only in browser.

Any ideas? Thank you in advance.

2
  • Just to make you aware - you really should be using curl to test this. That "from disk cache" thing you have there is gonna cause problems in testing. Curl doesn't cache a single thing, so you really should be using that to test this. Just do curl -v http://myapp.com/image.png to get a fresh copy of the response every time.
    – Big T
    Aug 31, 2017 at 14:00
  • The way you extract time information from current time and date can be implemented in a simpler way using map directive. Then, gzip_static means that nginx will serve the pre-compressed version of a resource, if it exists. For example, if /image.png.gz exists, nginx will send that file directly when a request for /image.png is made. As said below, gzipping images isn't useful. For fonts and JS/CSS files it is useful, and best result can be achieved with pre-compression of files. Aug 31, 2017 at 20:15

2 Answers 2

1

Please check that your mime.types file contains the following line:

types {
    ...
    image/png        png;
    ...
}

It may be that nginx is trying to serve it as HTML as it doesn't know what mime type to give it when serving it out.

Also, make sure that this file is included in your nginx.conf and you haven't removed it by accident! :) should be like this:

html {
    ...
    include /etc/nginx/mime.types;
    ...
}
2
  • This helped! Thought, this option was uncommented, I've restarted nginx once again and than it worked. Not sure, what caused the problem, but it seems my nginx restart hook isn't launched during env rebuild. That you very much! Aug 31, 2017 at 14:31
  • errr. Sure! :D haha. Glad you got it fixed bud.
    – Big T
    Aug 31, 2017 at 15:00
0

PNG is already a compressed format, no need to use the gzip here.

Try by removing the gzip compression for the location /images, and adding this line in this location too:

default_type image/png;

as from the dev tools is showing, the browser received text/html instead of image/png

1
  • What if you're serving a jpeg? The best way would be to properly configure the included types file. That way nginx will know what mime type to give to any assets being served in future too. Though - this would be a good debugging step to find out if it's the mime type, OR gzip that's the issue. I doubt it's Gzip though ;)
    – Big T
    Aug 31, 2017 at 14:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .