Basic nginx Setup and Configuration

nginx is a powerful and modern HTTP server. It is perhaps most commonly used as a reverse proxy, also known as a load balancer or front end proxy. It follows the UNIX philosophy of doing one thing, and doing it well, and as such, it relies on several helper daemons to become a full-featured web server such as Apache. For example, to serve PHP, it relies on php-fpm to do the processing, while nginx itself handles the caching and speaking the HTTP protocol itself. In this article, we will talk about common configuration options, and how they relate to it's performance. We'll also discuss some basic administrative tasks. The configuration is organized in to various sections, such as event, http, and server. "event" defines global settings such as event models and some connection handeling. The "http" section defines variables concering the HTTP protocol itself, such as keepalive timeouts. "server" is where you define individual sites to be cached, proxied, and served. There is also a "main" section, which has no definition block. The exact location and structure of your nginx configuration depends on your distribtion of Linux or BSD, but it is most likely under /etc/nginx or /usr/local/etc/nginx. Some distributions like to seperate out the "server" blocks in to individual files in their default setups. While not required, it certainly makes adding and removing sites a lot easier, and it makes it easier to automate. We'll start with the "main" section. A typical section looks like this:

user www-data;
worker_processes 4;
pid /var/run/;

"user" defines the user that the server runs as, "worker_processes" defines how many nginx instances actually run, and "pid" refers to where it stores the process ID of the master process. Fairly standard stuff for any daemon. It is of course important to ensure the nginx process can read the files to be served, so pay close attention to file ownership. "worker_processes" should be initially set to the number of CPU cores available. The first section is "events". The settings here define how the daemon handles incoming requests at the system level.

events {
        #worker_connections 4096; #this is a lot
        worker_connections 1024; #this is not a lot
        multi_accept on;
        use epoll; #linux, kqueue for bsd

  • worker_connections – This is how many connections a single worker thread is allowed to process. Connections made past this number will result in the user seeing an error page. This number, times the number of worker_processes, is the maximum amount of connections your nginx server will handle.
  • multi_accept – Keep accepting connections even though the server hasn't finished handeling incoming connections. Enable it if your host OS supports it.
  • use epoll/kqueue/select/poll – Host OS dependent. Use what is supported and compiled in to nginx itself.

The next section is "http". This is where most of your tuning will take place. It also contains all "server" directives, which, in the example configuration shown are included from a directory.

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        gzip on;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

There are many more options than what we have defined in this example, but the ones shown are of the highest priority, and the defaults often just won't do what you want.

  • sendfile – Enabling this will increase the speed that nginx can cache, and retreive from cache. Enable it if your kernel supports it.
  • tcp_nopush – Setting this option causes nginx to attempt to send it's HTTP response headers in one packet. Enable it if your kernel supports it.
  • tcp_nodelay – This disables a buffer that when used with keep-alive connections, can slow things down. It is generally advised to enable this.
  • keepalive_timeout – The maximum time between keepalive requests from client browsers. Setting this to just over a minute is in line with current standards, and will keep network resource waste to a minimum.
  • types_hash_max_size – The maximum size of hash tables. This directly influences cache performance. Higher numbers use more memory, and offer potentially higher performance. A value of 2048 is usually good for 4GB of RAM.
  • gzip – Enables standard gzip compression. Turn this on unless your backend is doing the compression.

The rest of the parameters are either self explanitory (such as access_log), or situational depending on your particular setup (such as the includes & default_type). It is important to note that the following "server" section is a part of the "http" section! Here is an example "server" section that is set up to serve out HTML and other static files. PHP and other server-side scripting support is beyond the scope of this introductory article. Remember, this is nested within the "http" section! You can have as many of these sections as you'd like, and most settings from the "http" section can be overridden here on a per-server basis. This is analogous to Apache's Virtual Host mechanisms.

server {
        listen 80 default_server;
        listen 443 default_server ssl;

        #ssl on;
        ssl_certificate /etc/nginx/startcom/ssl-unified.crt;
        ssl_certificate_key /etc/nginx/startcom/startcom.key;

        #access_log /var/log/nginx/website.access_log;
        #error_log /var/log/nginx/website.error_log;

        root /var/www/;
        index index.html;

        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                expires max;
                log_not_found off;

Out of all of this, the most important lines are the "listen", "root", and "index" directives. With those three you can have a fully functional site.

  • listen – This specifies what port, and optionally what host IP to listen on (in the form of When given the "default_server" parameter, that means that any request not matching a server directive will be directed to this server directive. When given the "ssl" parameter, it will use SSL to transfer data. One or more of these is required!
  • server_name – This is the domain name of the site being hosted.
  • ssl – In the above example it is commented out. This forces all requests to be treated as SSL requests, even if coming in on port 80. This is for testing purposes only.
  • ssl_certificate – Your signed certificate. Startcom ( offers free certs that are valid for one year, perfect for testing and learning. Modern browsers recognize Startcom as a valid CA.
  • ssl_certificate_key – Your private key.
  • access_log & error_log – You can have seperate log files per server, if they are undefined then they will go in to the global nginx log files as defined in the "http" section.
  • root – The document root containing all of the site's files. Required!
  • index – What page to load when no page is specified in the request from the browser. Required!
  • location – This is what makes nginx so magical. Location directives are analogous to Apache's mod_rewrite, however they are far more powerful. They allow a multitude of operations to take place on a selected group of files. In this case, we are forcing the client browser to cache those file types for the longest possible time the browser is willing to do. We are also telling nginx to not log requests to files of those types that don't exist. Depending on your site's content, the contents of that regex can change wildly. You may wish to add "swf", "mp4", and others to the list.

With the above you are ready to host a static website. nginx does not require you to restart the server to pick up on configuration changes. The safe way to do this is:

nginx -s reload

This will test the configuration for sanity, then reload the configuration and start using it. It takes place immediately. For more information about nginx, refer to nginx's wiki.