Nginx - Reliably Deploying Rails Applications: Hassle free provisioning, reliable deployment (2014)

Reliably Deploying Rails Applications: Hassle free provisioning, reliable deployment (2014)

10.0 - Nginx

Overview

In this chapter we’ll cover the basic configuration of Nginx. We will not cover the details of configuring it to deploy Rails applications here, instead this is covered in part 2 on Capistrano (see ‘The Place of Virtualhost files below’).

The Nginx Recipe

Nginx is famously quick and simple to configure and the included Nginx recipe is correspondingly simple.

It begins by adding the official Nginx ppa so we can install a more up to date version than is available from the Ubuntu package manager by default:

1 bash 'adding stable nginx ppa' do

2 user 'root'

3 code <<-EOC

4 add-apt-repository ppa:nginx/stable

5 apt-get update

6 EOC

7 end

8

9 # install nginx

10 package "nginx"

It then adds a simple Nginx configuration file templates/nginx.conf.erb which defines some simple generic configuration options. As explained below, most configuration will be defined by the virtualhosts for individual apps.

As discussed in chapter 9, if the attribute node[:monit_address] is included, this recipe will include a simple virtual host mapping for the Monit web interface.

The Nginx configuration file this recipe uses is reproduced along with documentation below:

1 # run as the user www-data rather than root for security

2 user www-data;

3

4 # try and automatically determine the optimal number of

5 # worker processes for the system. Auto will, by default,

6 # set this to the number of cores available

7 worker_processes auto;

8

9 # store a pid file, this will be used to monitor the process

10 # with Monit

11 pid /var/run/nginx.pid;

12

13 events {

14 # number of worker connections which can be established.

15 # this combined with 'auto' for worker processes gives

16 # you a maximum of cpu_cores * 8000 concurrent connections

17 worker_connections 8000;

18 }

19

20

21 http {

22

23 ##

24 # Basic Settings

25 ##

26

27 # speed up file uplaods

28 sendfile on;

29

30 # don't send partial frames (increases throughput)

31 tcp_nopush on;

32

33 # don't collate small packets together to save bandwidth

34 # as more concerned about latency

35 tcp_nodelay on;

36

37 # how long a connection can remain idle before being closed

38 # in seconds.

39 keepalive_timeout 65;

40

41 # increase size of mime types hash (should be a power of 2)

42 # to allow for additional mime types

43 types_hash_max_size 2048;

44

45 # avoid problems with too many vhosts/ long domains preventing

46 # the server names hash from being built on config reload

47 server_names_hash_bucket_size 64;

48

49 # define mime types in separate config files (DRY) and set a

50 # fallback

51 include /etc/nginx/mime.types;

52 default_type application/octet-stream;

53

54 # default log locations (if they aren't overriden in the vhost

55 # files)

56 access_log /var/log/nginx/access.log;

57 error_log /var/log/nginx/error.log;

58

59 ##

60 # Gzip Settings

61 ##

62

63 # enable gzip compression

64 gzip on;

65

66 # disable gzip compression for ie6. Strictly speaking only the

67 # first version which doesn't support it but ie6 users aren't

68 # always the best known for being up to date.

69 gzip_disable "msie6";

70

71 # include any additional config files

72 include /etc/nginx/conf.d/*.conf;

73

74 # include virtual hosts for specific sites

75 include /etc/nginx/sites-enabled/*;

76 }

It is worth noting that at the end of the nginx config file there is the following:

1 include /etc/nginx/conf.d/*.conf;

2 include /etc/nginx/sites-enabled/*;

This allows us to load additional config files in a modular fashion similarly to how we load Monit configurations as opposed to relying on a single monolithic file. This is particularly important in the light of the suggested approach to virtualhost definition.

The place of Virtualhost files

Virtual hosts are used to define what Nginx should do when requests for a particular website are received. This might be to serve some static files from a filesystem location or proxy the request back to something like a Rails application server (such as Unicorn) or another interface like Monit.

The approach taken throughout this book is that anything specific to a single application being deployed, should be handled by the applications deployment process rather than the server provisioning process. This allows a single server to to be used to host multiple applications without provisioning changes which may be disruptive to all applications residing there.

With this in mind, the approach suggested is that only server specific virtual hosts, such as Monit configurations if you’re choosing to serve the Monit interface through nginx should be created during provisioning. All subsequent virtual hosts should be created and managed by the applications themselves.

This means that all site specific configuration, including how to setup SSL, is covered in the second part of this book.

The Default Virtualhost

A common problem is to find that having configured a server and deployed an application, the default “It Works” page is still displayed. This is often because the default virtualhost in /etc/nginx/sites-enabled has not been removed. This is covered again in the second part of the book but is worth mentioning here as well because there’s nothing more frustrating than spending hours troubleshooting a problem only to discover it was this.

If you run into such problems, double check that the default entry has been removed. If it hasn’t, remove it and then run nginx -s reload to reload the configurations.

In the following sections we’ll move on to configuring data stores. Feel free to skip to the chapters relevant to the stores you’ll be using. If you’re stuck deciding on which data store to use, my personal preference is PostgreSQL for its combination of out of the box simplicity with a powerful advanced feature set if needed.