Skip to content

Instantly share code, notes, and snippets.

@vishaltelangre
Last active October 3, 2023 19:30
Show Gist options
  • Star 43 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save vishaltelangre/bcc95485b97f534a8c27 to your computer and use it in GitHub Desktop.
Save vishaltelangre/bcc95485b97f534a8c27 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!
@jhourlad
Copy link

jhourlad commented Mar 5, 2018

WARNING: This only serves static files inside /static folder and won't render static files necessarily located in the web root (e.g. robots.txt, sitemap.xml, etc.)

@imran21
Copy link

imran21 commented Jul 16, 2018

i have the same problem
Now I am on server 1(nginx)
when is type this link in url it should navigate to my server 2(Apapche) which runs on port 8080.
It is working fine. That is, it is getting navigated and displaying the contents of the directory(demo_static_file) but not displaying the file ie; a1.txt

the down is my nginx config.

location /a1.txt {
proxy_pass http://35.10.28.10:8080/demo_static_file;

    }

Please any one help

@jon49
Copy link

jon49 commented Mar 20, 2021

See: https://www.rewriteguide.com/nginx-add-caching-directives-static-assets/

And add root to the directory you would like the static files to be retrieved from.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment