nginx configuration

Originally published Dec 3, 2014·Tagged deployment, nginx, configuration

I use [nginx](http://nginx.org/) over [Apache](https://httpd.apache.org/) for a number of reasons. First of all, its config files make a lot more sense to me. Since I work mostly with C-family languages, I'd rather have a [nice-looking config file](http://wiki.nginx.org/FullExample) with curly braces rather than some [fake knockoff XML](https://collab.itc.virginia.edu/wiki/toolbox/example%20httpd.conf%20file.html). Plus, it's [blazing fast](http://wiki.dreamhost.com/Web_Server_Performance_Comparison) compared to Apache. Plus, if you're using Apache to proxy requests to an app running on another machine/port, Apache will remember that your app is down and automatically serve a "Bad Gateway" page for a while, even after you start the server again. This is pretty annoying for a development environment, since if you refresh the page but forgot to restart the server, Apache will cache the fact that the server is down, and you'll have to restart Apache to clear this cache. Nginx will also show the "Bad Gateway" page if the app is down, but will still try to proxy requests through _as they come in_, meaning that if you forgot to start your app server, you can just bring it up and retry the request and nginx will just work as expected. 99% of the time, when I use nginx, I'm using it to reverse-proxy some app I'm working on. It's much easier, more flexible, and more secure to run an application as a non-root user and then update my nginx config to point to it, than to try and run something on port 80. Doing this (mostly) decouples where my app's running from the address that users type to get to it, meaning I can move stuff around very fluidly. Despite its simplicity, I still occasionally forget the syntax for specifying a virtual host. The term "virtual host" comes from Apache, and represents a particular machine on a particular port, referred to by a particular hostname. (Nginx calls them "server blocks", but the term "virtual host" is a little closer to how I think about them.) Suppose I have a server `appserver.example.org` running an app _Foo_ on port 3000 and another app _Bar_ on port 4000. I'd set up my domain names so that `foo.example.org` and `bar.example.org` point to `appserver.example.org`. Then, in nginx, I'd create two virtual hosts, one for _Foo_ and one for _Bar_, that reverse proxy the apps' contents to the outside world. **nginx.conf** would look like this: ```config worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # Block 1: foo.example.org server { listen 80; server_name foo.example.org; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost:3000; } } # Block 2: bar.example.org server { listen 80; server_name bar.example.org; location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost:4000; } } # Block 3: catch-all server { listen 80 default_server; server_name _; root /usr/share/nginx/html; } } ``` Blocks 1 and 2 ensure that requests to those hostnames are routed to our app servers, which are listening on their ports on localhost. Block 3 isn't really necessary, but a catch-all so that any requests that don't match one of the above hosts gets served static HTML from our `/usr/share/nginx/html` directory.