Add Nginx post.
[blog.git] / posts / Nginx.mdwn
1 I transitioned from [Apache][] to [Nginx][] a week or so ago, since
2 words like “minimal” and “streamlined” are appealing to me ;).  I was
3 quite happy with Apache, but it's always nice to try something new.
4 Anyhow here's a quick review my configuration.
5
6 On [[Gentoo]], set the the [modules][] you want to install by adding
7 the following lines to your `/etc/make.conf`:
8
9     NGINX_MODULES_HTTP="access auth_basic autoindex charset fastcgi gzip gzip_static limit_req map proxy rewrite scgi ssi stub_status"
10     NGINX_MODULES_MAIL=""
11
12 Then install Nginx with:
13
14     # emerge -av nginx
15
16 Make any adjustments you like to `/etc/nginx/mime.types`.  I added:
17
18     types {
19         …
20         application/x-python                  py;
21         application/x-shell                   sh;
22         …
23     }
24
25 Now it's time to setup `/etc/nginx/nginx.conf`.  Poking about online
26 will give you lots of examples.  Here are things that were useful to
27 me, in the order they appear in the `http` block of my `nginx.conf`.
28
29 Gitweb (and general CGI approach)
30 =================================
31
32 [[gitweb]] server:
33
34     server {
35       listen 80;
36       server_name git.example.com;
37
38       access_log /var/log/nginx/git.example.com.access_log main;
39       error_log /var/log/nginx/git.example.com.error_log info;
40
41       root /usr/share/gitweb/;
42
43       index gitweb.cgi;
44
45       location /gitweb.cgi {
46         include fastcgi_params;
47         fastcgi_pass  unix:/var/run/fcgiwrap.sock-1;
48       }
49     }
50
51 Because Nginx lacks built-in [[CGI]] support, we need some tricks to
52 get `gitweb.cgi` working.  We use the [fcgi module][fcgi] to pass the
53 requests on to a FastCGI server which wraps `gitweb.cgi`.  On
54 [[Gentoo]], I installed the following packages:
55
56 * `www-misc/fcgiwrap`, a [[FastCGI]] server for wrapping [[CGI]] scripts
57 * `www-servers/spawn-fcgi`, a [[FastCGI]] manager for spawning `fcgiwrap`.
58
59 Configure `spawn-fcgi` to launch `fcgiwrap` with:
60
61     # cp /etc/conf.d/spawn-fcgi /etc/conf.d/spawn-fcgi.fcgiwrap
62     # emacs /etc/conf.d/spawn-fcgi.fcgiwrap
63     # cat /etc/conf.d/spawn-fcgi.fcgiwrap
64     FCGI_SOCKET=/var/run/fcgiwrap.sock
65     FCGI_ADDRESS=
66     FCGI_PORT=
67     FCGI_PROGRAM=/usr/sbin/fcgiwrap
68     FCGI_USER=nginx
69     FCGI_GROUP=nginx
70     FCGI_EXTRA_OPTIONS="-M 0700"
71     ALLOWED_ENV="PATH"
72     FCGI_CHILDREN=1
73     FCGI_CHROOT=
74     # cd /etc/init.d/
75     # ln -s spawn-fcgi spawn-fcgi.fcgiwrap
76
77 Start `fcgiwrap` with:
78
79     # /etc/init.d/spawn-fcgi.fcgiwrap start
80
81 Add it to the default runlevel with:
82
83    # sudo rc-update add spawn-fcgi.fcgiwrap default
84
85 Wildcard virtual hosts
86 ======================
87
88 To add support for virual hosts stored under `/var/www/$host`, use:
89
90     server {
91       listen 80;
92       #listen 443 ssl;
93
94       server_name star.example.com *.example.com;
95
96       access_log /var/log/nginx/star.example.com.access_log main;
97       error_log /var/log/nginx/star.example.com.error_log info;
98
99       #ssl_certificate /etc/ssl/nginx/$host.pem;
100       #ssl_certificate_key /etc/ssl/nginx/$host.key;
101
102       root /var/www/$host/htdocs;
103
104       # deny access to .htaccess files
105       location ~ /\.ht {
106         deny all;
107       }
108     }
109
110 Then adding a new host is as simple as creating a new entry in
111 `/var/www/` and updating your [[DNS]] to get the new name pointed at
112 your server.  Unfortunately, [[SSL/TLS|GnuTLS]] doesn't work with this
113 approach.  It appears that certificates and keys are loaded when Nginx
114 starts up, but `$host` is only defined after a request is received.
115 Nginx does support [[SNI]] though, so it will work if you write SSL
116 entries by hand for hosts that need them.
117
118 Main host
119 =========
120
121 The configuration for my main host is more complicated, so I'll
122 intersperse some more comments.  I setup both clear-text and SSL in
123 the same definition using the [SSL module][SSL].  The `_` server name
124 is a special name that matches any requests which haven't already
125 matched and been handled by an earlier `server`.
126
127     server {
128       # catchall virtual host (optional SSL, example.com)
129       listen 80 default_server;
130       listen 443 default_server ssl;
131       server_name _;
132
133       ssl_certificate /etc/ssl/nginx/example.com.pem;
134       ssl_certificate_key /etc/ssl/nginx/example.com-key.pem;
135
136 Nothing special with the logging or root.
137
138       access_log /var/log/nginx/example.com.access_log main;
139       error_log /var/log/nginx/example.com.error_log info;
140
141       root /var/www/example.com/htdocs;
142
143 Turn on [[SSI]], and also use `index.shtml` as index pages.
144
145       index index.html index.shtml;
146       ssi on;
147
148 Use the [proxy module][proxy] to pass requests for `/cookbook/` and
149 subdirectories on to their [[underlying Django app|cookbook]].
150
151       location /cookbook/ {
152         proxy_pass  http://localhost:33333/cookbook/;
153         proxy_set_header  X-Real-IP  $remote_addr;
154       }
155
156 Use the [scgi module][scgi] to pass requests for `/gallery/` and
157 subdirectories on to their [[underlying SCGI app|gallery]].
158
159       location /gallery/ {
160         include scgi_params;
161         scgi_pass localhost:4000;
162       }
163
164 Turn on autoindexing for `/RAD/` and subdirectories using the
165 [autoindex module][autoindex].
166
167       location /RAD/ {
168         autoindex on;
169       }
170
171 Force SSL/TLS for `/tree/` and subdirectories, redirecting plain-text
172 requests to the equivalent HTTPS page.  Use the [auth_basic
173 module][auth_basic] for authentication, the [SSL module][SSL] for
174 `$ssl_protocol`, and the [rewrite module][rewrite] for the
175 redirection.
176
177       location /tree/ {
178         auth_basic "Family Tree";
179         auth_basic_user_file /home/jdoe/htpasswd;
180         if ($ssl_protocol = "") {
181           rewrite ^   https://example.com$request_uri? permanent;
182         }
183       }
184
185 Nothing special with the end of this `server` block.
186
187       # deny access to .htaccess files
188       location ~ /\.ht {
189         deny all;
190       }
191     }
192
193 [Apache]: http://www.apache.org/
194 [Nginx]: http://nginx.org/
195 [modules]: http://wiki.nginx.org/Modules
196 [fcgi]: http://wiki.nginx.org/HttpFcgiModule
197 [SSL]: http://wiki.nginx.org/HttpSslModule
198 [proxy]: http://wiki.nginx.org/HttpProxyModule
199 [scgi]: http://wiki.nginx.org/HttpScgiModule
200 [autoindex]: http://wiki.nginx.org/HttpAutoindexModule
201 [auth_basic]: http://wiki.nginx.org/HttpAuthBasicModule
202 [rewrite]: http://wiki.nginx.org/HttpRewriteModule
203
204 [[!tag tags/tools]]
205 [[!tag tags/web]]