mkogg.py: Prefix imports with underscores for a clean namespace
[mw2txt.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 Redirecting `www.example.com` to `example.com`
30 ==============================================
31
32 This keeps people who accidentally add a `www.` prefix to your URL
33 from matching the wildcard virtual host block defined below.
34
35     server {
36       # www.example.com -> example.com
37       listen 80;
38       listen 443 ssl;
39       server_name www.example.com;
40       ssl_certificate /etc/ssl/nginx/www.example.com.pem;
41       ssl_certificate_key /etc/ssl/nginx/www.example.com-key.pem;
42       rewrite  ^/(.*)$  $scheme://example.com/$1  permanent;
43     }
44
45 Gitweb (and general CGI approach)
46 =================================
47
48 [[gitweb]] server:
49
50     server {
51       listen 80;
52       server_name git.example.com;
53
54       access_log /var/log/nginx/git.example.com.access_log main;
55       error_log /var/log/nginx/git.example.com.error_log info;
56
57       root /usr/share/gitweb/;
58
59       index gitweb.cgi;
60
61       location /gitweb.cgi {
62         include fastcgi_params;
63         fastcgi_pass  unix:/var/run/fcgiwrap.sock-1;
64       }
65     }
66
67 Because Nginx lacks built-in [[CGI]] support, we need some tricks to
68 get `gitweb.cgi` working.  We use the [fcgi module][fcgi] to pass the
69 requests on to a FastCGI server which wraps `gitweb.cgi`.  On
70 [[Gentoo]], I installed the following packages:
71
72 * `www-misc/fcgiwrap`, a [[FastCGI]] server for wrapping [[CGI]] scripts
73 * `www-servers/spawn-fcgi`, a [[FastCGI]] manager for spawning `fcgiwrap`.
74
75 Configure `spawn-fcgi` to launch `fcgiwrap` with:
76
77     # cp /etc/conf.d/spawn-fcgi /etc/conf.d/spawn-fcgi.fcgiwrap
78     # emacs /etc/conf.d/spawn-fcgi.fcgiwrap
79     # cat /etc/conf.d/spawn-fcgi.fcgiwrap
80     FCGI_SOCKET=/var/run/fcgiwrap.sock
81     FCGI_ADDRESS=
82     FCGI_PORT=
83     FCGI_PROGRAM=/usr/sbin/fcgiwrap
84     FCGI_USER=nginx
85     FCGI_GROUP=nginx
86     FCGI_EXTRA_OPTIONS="-M 0700"
87     ALLOWED_ENV="PATH"
88     FCGI_CHILDREN=1
89     FCGI_CHROOT=
90     # cd /etc/init.d/
91     # ln -s spawn-fcgi spawn-fcgi.fcgiwrap
92
93 Start `fcgiwrap` with:
94
95     # /etc/init.d/spawn-fcgi.fcgiwrap start
96
97 Add it to the default runlevel with:
98
99    # sudo rc-update add spawn-fcgi.fcgiwrap default
100
101 If you also want a virtual host serving Git over HTTP, you can add a
102 virtual host like:
103
104     server {
105       # http-git.example.com
106       listen 80;
107       server_name http-git.example.com;
108
109       access_log /var/log/nginx/http-git.example.com.access_log main;
110       error_log /var/log/nginx/http-git.example.com.error_log info;
111
112       location / {
113         include fastcgi_params;
114         fastcgi_param SCRIPT_FILENAME /usr/libexec/git-core/git-http-backend;
115         fastcgi_param GIT_HTTP_EXPORT_ALL "";
116         fastcgi_param GIT_PROJECT_ROOT /var/git;
117         fastcgi_param PATH_INFO $document_uri;
118         fastcgi_pass  unix:/var/run/fcgiwrap.sock-1;
119       }
120     }
121
122 This uses the same FastCGI server we used for gitweb, but this time
123 the backend CGI script is `git-http-backend`.
124
125 Wildcard virtual hosts
126 ======================
127
128 To add support for virual hosts stored under `/var/www/$host`, use:
129
130     server {
131       listen 80;
132       #listen 443 ssl;
133
134       server_name star.example.com *.example.com;
135
136       access_log /var/log/nginx/star.example.com.access_log main;
137       error_log /var/log/nginx/star.example.com.error_log info;
138
139       #ssl_certificate /etc/ssl/nginx/$host.pem;
140       #ssl_certificate_key /etc/ssl/nginx/$host.key;
141
142       root /var/www/$host/htdocs;
143
144       # deny access to .htaccess files
145       location ~ /\.ht {
146         deny all;
147       }
148     }
149
150 Then adding a new host is as simple as creating a new entry in
151 `/var/www/` and updating your [[DNS]] to get the new name pointed at
152 your server.  Unfortunately, [[SSL/TLS|GnuTLS]] doesn't work with this
153 approach.  It appears that certificates and keys are loaded when Nginx
154 starts up, but `$host` is only defined after a request is received.
155 Nginx does support [[SNI]] though, so it will work if you write SSL
156 entries by hand for hosts that need them.
157
158 Main host
159 =========
160
161 The configuration for my main host is more complicated, so I'll
162 intersperse some more comments.  I setup both clear-text and SSL in
163 the same definition using the [SSL module][SSL].  The `_` server name
164 is a special name that matches any requests which haven't already
165 matched and been handled by an earlier `server`.
166
167     server {
168       # catchall virtual host (optional SSL, example.com)
169       listen 80 default_server;
170       listen 443 default_server ssl;
171       server_name _;
172
173       ssl_certificate /etc/ssl/nginx/example.com.pem;
174       ssl_certificate_key /etc/ssl/nginx/example.com-key.pem;
175
176 Nothing special with the logging or root.
177
178       access_log /var/log/nginx/example.com.access_log main;
179       error_log /var/log/nginx/example.com.error_log info;
180
181       root /var/www/example.com/htdocs;
182
183 Turn on [[SSI]], and also use `index.shtml` as index pages.
184
185       index index.html index.shtml;
186       ssi on;
187
188 Use the [proxy module][proxy] to pass requests for `/cookbook/` and
189 subdirectories on to their [[underlying Django app|cookbook]].
190
191       location /cookbook/ {
192         proxy_pass  http://localhost:33333/cookbook/;
193         proxy_set_header  X-Real-IP  $remote_addr;
194       }
195
196 Use the [scgi module][scgi] to pass requests for `/gallery/` and
197 subdirectories on to their [[underlying SCGI app|gallery]].
198
199       location /gallery/ {
200         include scgi_params;
201         scgi_pass localhost:4000;
202       }
203
204 Turn on autoindexing for `/RAD/` and subdirectories using the
205 [autoindex module][autoindex].
206
207       location /RAD/ {
208         autoindex on;
209       }
210
211 Force SSL/TLS for `/tree/` and subdirectories, redirecting plain-text
212 requests to the equivalent HTTPS page.  Use the [auth_basic
213 module][auth_basic] for authentication, the [SSL module][SSL] for
214 `$ssl_protocol`, and the [rewrite module][rewrite] for the
215 redirection.
216
217       location /tree/ {
218         auth_basic "Family Tree";
219         auth_basic_user_file /home/jdoe/htpasswd;
220         if ($ssl_protocol = "") {
221           rewrite ^   https://example.com$request_uri? permanent;
222         }
223       }
224
225 Nothing special with the end of this `server` block.
226
227       # deny access to .htaccess files
228       location ~ /\.ht {
229         deny all;
230       }
231     }
232
233 [Apache]: http://www.apache.org/
234 [Nginx]: http://nginx.org/
235 [modules]: http://wiki.nginx.org/Modules
236 [fcgi]: http://wiki.nginx.org/HttpFcgiModule
237 [SSL]: http://wiki.nginx.org/HttpSslModule
238 [proxy]: http://wiki.nginx.org/HttpProxyModule
239 [scgi]: http://wiki.nginx.org/HttpScgiModule
240 [autoindex]: http://wiki.nginx.org/HttpAutoindexModule
241 [auth_basic]: http://wiki.nginx.org/HttpAuthBasicModule
242 [rewrite]: http://wiki.nginx.org/HttpRewriteModule
243
244 [[!tag tags/tools]]
245 [[!tag tags/web]]