Serving static assets in nginx.

645 views
Skip to first unread message

HittingSmoke

unread,
Aug 21, 2013, 3:00:47 PM8/21/13
to
I've been going back over my configuration compared to various other deployment recipes after realizing I was missing some non-critical uwsgi related parameters. I noticed my static location block in nginx was different than the one recommended in the web2py nginx+uwsgi setup script.

Here's what I use, which I took from the config I use on PHP vhosts, with only the commented out gzip line added for web2py:

location ~* \.(jpg|jpeg|gif|png|svg|css|js|ico|xml|ttf|otf|woff)$ {
    access_log        off
;
    log_not_found     off
;
    expires           max
;
 
   
#include ~/nginx/conf/web2py/gzip_static.conf;
}

Here is what's created by the stock web2py script:

location ~* ^/(\w+)/static/ {
    root
/home/www-data/web2py/applications/;
   
#remove next comment on production
   
#expires max;
   
### if you want to use pre-gzipped static files (recommended)
   
### check scripts/zip_static_files.py and remove the comments
   
# include /etc/nginx/conf.d/web2py/gzip_static.conf;
   
###
}

Is there any disadvantage to my static handling over what's recommended? It seems mine would be advantageous as it would also serve file system uploads that are not saved to the static directory directly with nginx.

Additionally, is it okay to enable static_gzip before zipping my static assets? If I've not yet reached production with an app will the server fallback to the unzipped assets in the absence of zipped files?

Niphlod

unread,
Aug 21, 2013, 4:46:06 PM8/21/13
to web...@googlegroups.com
with your config you enable for everything that ends with those extensions:
- the "disable" of the access log
- the cache header set to a very distant time in the future
This means that if someone by any chance requests an url from your application that ends in xml, you short-circuit nginx to think it should be served as a static file instead of a dynamic xml response from your app.

the web2py config instead stands by the convention that everything is supplied by a dynamic "something" (i.e. usually a controller) and that everything under "/static/" is a real static file to be served.
Optionally, it enables the same cache headers and, if you want, it enables the serving of pre-compressed static files.

PS: More on the precompression topic: usually you'd want everything served compressed. it cuts off response times considerably, because you shorten the time a resource takes to be transferred in the compressed format vs the original one (the compressed format is a gz compression, kinda like a zip archive).
But, for static files, you don't want your nginx server to use cpu cycles for every request to compress those files, because they are static and they never change.
Web2py uses the same convention: if a ".gz" file is found, it serves that instead of the original one to cut off the size of the transferred files.
So, if you have bootstrap.css and bootstrap.css.gz in your folder, with that
include /etc/nginx/conf.d/web2py/gzip_static.conf;
line you enable serving boostrap.css.gx instead of bootstrap.css without requiring nginx to compress dinamically the bootstrap.css file.
There's a script (scripts/zip_static_file.py) that creates those ".gz" files for you.
This is explained at http://web2py.com/books/default/chapter/29/13/deployment-recipes#Compress-static-files

HittingSmoke

unread,
Aug 21, 2013, 6:31:59 PM8/21/13
to web...@googlegroups.com
I can see how serving XML as static could be an issue with web2py since it can be used in so many different ways. I think I'll remove that part.

I was thinking that there seems to be instances when images would be served from outside of the static directory, like an app's custom upload directory, dynamically generated imagery similar to those you'd get from PHP's GD or Imagick libraries, etc. I can think of circumstances where those might not be best stored in the static directory. Perhaps two static location blocks would be beneficial. One to cover the whole static folder and one to cover any static file types you may find yourself wanting to store outside of the static directory.

Thanks for the clarification on gzip. I already had it enabled for pages, I'll enable it for static content as well and zip up my static folder before deploying.

HittingSmoke

unread,
Aug 21, 2013, 10:06:58 PM8/21/13
to web...@googlegroups.com
It looks like the zip_static_files.py script only gzips css and js files. There's a lot more that can be compressed, such as web fonts and vector graphics. I understand why jpg and png images are left out, but why only css and js?

Niphlod

unread,
Aug 22, 2013, 3:07:49 AM8/22/13
to web...@googlegroups.com
I was thinking that there seems to be instances when images would be served from outside of the static directory, like an app's custom upload directory, dynamically generated imagery similar to those you'd get from PHP's GD or Imagick libraries, etc. I can think of circumstances where those might not be best stored in the static directory. Perhaps two static location blocks would be beneficial. One to cover the whole static folder and one to cover any static file types you may find yourself wanting to store outside of the static directory.

it's quite unclear why should you do such a thing by default with web2py, given usually everything that is not /application/static/ is a dynamic page. Uploads dirs are for files that need to go through web2py's auth system (so, no nginx serving). That being said, you're free to edit your own config to match your particular url scheme, but it's clearly not something "universally" valid.

It looks like the zip_static_files.py script only gzips css and js files. There's a lot more that can be compressed, such as web fonts and vector graphics. I understand why jpg and png images are left out, but why only css and js?

because as anything in web2py there's a sane default. you can tune as you wish. 
Reply all
Reply to author
Forward
0 new messages