Skip to content

Instantly share code, notes, and snippets.

@maksadbek
Forked from vishaltelangre/nginx_assets.md
Created September 14, 2018 09:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maksadbek/b419b4c285c94b5733e53cc85d505fe2 to your computer and use it in GitHub Desktop.
Save maksadbek/b419b4c285c94b5733e53cc85d505fe2 to your computer and use it in GitHub Desktop.
Serving Static Assets via Nginx

Concept

  • People talk about two servers: a web server (e.g. Nginx, Apache, etc.) and a app server (e.g. Language specific servers like Unicorn, Node.js, Tomcat, Http-Kit, etc.). There are exceptions where app servers not required at all (as web server itself provides preprocessors for handling), but let's not talk about now.
  • Web servers are really fast and supports lot of standard and commonly used MIME-type requests. Concept of serving a file is -- forming and sending a response of bytes of data and labeling it with requested MIME-type by a client (e.g. web browser).
  • Every response format (in layman's language, a file) is recognized by it's MIME-type, for e.g. a PNG image file has "image/png" MIME-type. JavaScript file has "text/javascript". HTML responses (or files) has "text/html". Plain text files have "text/plain".
  • Modern Browsers supports a lot of standard MIME-types. Images, videos, text files (XML, HTML, SVG, JS), and they better know how to visualize it. Browser also knows unrecognized and suspicious formats (like an EXE file is warned before starting downloading, an EOT font file is asked for download as browsers yet ain't capable of rendering those).
  • Browsers just need to know the MIME-type, so even if a "http://example.com/download.php?id=39fjg5" is a PHP file request, and browsers don't know what to do with it, server can fool browser it by sending a response with a recognizable MIME-type to it -- for example, a simple HTML or a MP3 MIME-type -- and browsers dance as they told!
  • App servers can directly handle and are able to serve each and every request. So even if "http://example.com/users/new.jsp" is a JSP request, app server (such as Tomcat) sends in "text/html" response which browsers understands. But that involves processing the request and generating response for it, which is unnecessary for the static asset requests.
  • Static assets are considered physically present files on disk on the server computer, i.e. they are not generated on-the-fly (by a app-server after some intensive processing)!
  • Examples of static assets are any files present on a disk.
  • Example of a non-static file could be gathering data from a database and serving a spreadsheet or PDF response in run-time. These no-need-to-process requests are considered static assets and are considered to be served by a web server rather by a app server. Web server don't need to do anything, it gets such file from disk and sends it to the client. App server would have resolved and processed it before doing so, and is a long-way process.
  • There is a common and standard practice to serve static assets via a web server (such as Nginx) and proxy other need-to-process requests to the app server.

Example

  • Imagine your app server is running on a 8080 port.
  • You have told client to ask assets at /static/ path.
  • Static assets are located at /var/www/example.com/current/static/ directory.
  • You have registered at a registrar a domain name which could be resolved to the DNS which matches your server host IP address. Or rather for local development, you can register your domain in hosts file on the client machine.
  • You would like to serve assets via Ngnix but proxy other requests to the app server running at 8080 port.
  • Following is an example Nginx configuration:
upstream http_backend {
  server 127.0.0.1:8080;
}
 
server {
  listen 80;
  server_name example.com;
  access_log /var/log/example_com_access.log;
  error_log /var/log/example_com_error.log;
 
  location /static/ {
    alias /var/www/example.com/current/static/;
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }
 
  location / {
    proxy_pass http://http_backend;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}
 
  • Above configuration can be put in a file inside sites-enabled directory of Nginx.
  • "location /static/" block serves static assets by compressing those with gunzip utility (and caches for further requests). Also adds a browser caching response header. It searches for static files in the directory provided to the alias option.
  • location / block in above configuration proxies every request but static to the app server (defined as http_backend) running at 8080 port.
  • This web server is itself runs on 80 port, and there could many other sites running on the same port. There is a concept of virtual-host, which adds a layer to achieve this. Here, this configuration also acts as a virtual host configuration for the site example.com which is provided as server_name example.com; in above configuration.
  • Voila!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment