Project

General

Profile

Fastcgi on nginx » History » Version 23

Nuika Sanders, 06/23/2015 09:14 PM

1 13 Peter Mortensen
h1. FastCGI on nginx
2 1 Pieter Libin
3
{{toc}}
4
5
6 16 Laurence Withers
h2. About nginx 
7 1 Pieter Libin
8 3 Koen Deforche
On paper, nginx is an excellent choice for use as a reverse proxy (together with wthttpd), or for deploying Wt applications using FastCGI, especially if you are using server-initiated updates (server push).
9 1 Pieter Libin
10 13 Peter Mortensen
The reason is that nginx, like wthttpd, is completely based on asynchronous I/O, and therefore scales easily to many open connections (unlike other web servers such as Apache, lighttpd, etc.). Server-initiated updates use an open connection for every web client.
11 1 Pieter Libin
12 23 Nuika Sanders
We have tested nginx succesfully for both its use as a reverse proxy or for FastCGI deployment of Wt applications. Its FastCGI implementation is a bit clumsy, but newer versions of nginx (>= 0.7.31) than the version currently available in ubuntu should improve on [[http://kupit-chemodan24.ru/|that]].
13 1 Pieter Libin
14
15 16 Laurence Withers
h2. Ubuntu configuration
16 1 Pieter Libin
17
* Installing nginx and spawn-fcgi (which comes with lighttpd):
18
19
<pre>
20 20 Nuika Sanders
 $ sudo apt-get install nginx lighttpd
21 1 Pieter Libin
</pre>
22
23
* Start your application (linked against wtfcgi) using spawn-fcgi. Spawn-fcgi wraps the FastCGI application to listen to a socket or network connection.
24
25
<pre>
26
 $ spawn-fcgi -n -f ../../build/examples/hello/hello.wt -a 0.0.0.0 -p 9091
27
</pre>
28
29 13 Peter Mortensen
* Edit your nginx configuration to redirect a particular URL to your application (replace all occurences of /hello.wt with the path for your application!):
30 1 Pieter Libin
31
<pre>
32
        location /hello.wt {
33
                fastcgi_pass   127.0.0.1:9091;
34
 
35
                fastcgi_param  QUERY_STRING       $query_string;
36
                fastcgi_param  REQUEST_METHOD     $request_method;
37
                fastcgi_param  CONTENT_TYPE       $content_type;
38
                fastcgi_param  CONTENT_LENGTH     $content_length;
39
 
40
                if ($document_uri ~ "^/hello.wt/(.*)") {
41
                        set $apache_path_info /$1;
42
                }
43
 
44
                fastcgi_param  SCRIPT_NAME        /hello.wt;
45
                fastcgi_param  PATH_INFO          $apache_path_info;
46
                fastcgi_param  REQUEST_URI        $request_uri;
47
                fastcgi_param  DOCUMENT_URI       $document_uri;
48
                fastcgi_param  DOCUMENT_ROOT      $document_root;
49
                fastcgi_param  SERVER_PROTOCOL    $server_protocol;
50
 
51
                fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
52
                fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
53
 
54
                fastcgi_param  REMOTE_ADDR        $remote_addr;
55
                fastcgi_param  REMOTE_PORT        $remote_port;
56
                fastcgi_param  SERVER_ADDR        $server_addr;
57
                fastcgi_param  SERVER_PORT        $server_port;
58
                fastcgi_param  SERVER_NAME        $server_name;
59
        }
60
</pre>
61
62 15 Andy Z
* Alternatively to avoid 'if' in declaration just indicate the root of your application:
63
<pre>
64
        location ~ ^/hello.wt(?<path_info>/.*|$) {
65
                fastcgi_pass   127.0.0.1:9000;
66
                fastcgi_param  SCRIPT_NAME /hello.wt;
67
                fastcgi_param  PATH_INFO $path_info;
68
                include        fastcgi_params.conf;
69
        }
70
</pre>
71
72 3 Koen Deforche
* Reload (or restart) your nginx server and you are ready to go:
73 1 Pieter Libin
74
 $ sudo /etc/init.d/nginx restart
75 16 Laurence Withers
76
77
78
h2. Debian (Wheezy) configuration
79
80 21 Nuika Sanders
This configuration uses the FastCGI support of nginx, which is enabled in both of the available Debian packages nginx-light and nginx-full. Unlike apache/lighttpd, nginx will not directly spawn the FastCGI application, and so we need an intermediate package to take care of this for us. Fortunately, the end result is very neat, and allows the fastcgi application to be restarted independently of the web server (as well as to easily enable it to run under a different uid). http://amodaa.ru/
81 16 Laurence Withers
82
h3. spawn-fcgi
83
84
First, install the spawn-fcgi package:
85
86
<pre>
87
 $ sudo apt-get install spawn-fcgi
88
</pre>
89
90
This package is responsible for getting the Wt application (a fastcgi application) to listen on a unix socket, which nginx will be configured to talk to. (Note that this does not involve any sort of proxying/copying: spawn-fcgi only needs to set up sockets before executing our application directly).
91
92
The application may be started with a command such as:
93
94
<pre>
95
 $ spawn-fcgi -s /var/run/fastcgi-<app>.sock -- /path/to/app.wt
96
</pre>
97
98 17 Laurence Withers
(obviously replacing the paths as appropriate). The environment variable @WT_APP_ROOT@ can, if desired, be set to point to a directory containing @wt_config.xml@. This is also exposed as Wt::WApplication::appRoot().
99 16 Laurence Withers
100
h3. spawn-fcgi systemd unit files
101
102
If using systemd, you can trivially create a unit file under @/etc/systemd/system@, named @/etc/systemd/system/fastcgi-<app>.service@:
103
104
<pre>
105
[Unit]
106
Description=FastCGI spawner for amazing Wt web app
107
108
[Service]
109
ExecStart=/usr/bin/spawn-fcgi -s /var/run/fastcgi-<app>.sock \
110
        -P /var/run/fastcgi-<app>.pid \
111
        -u <username> -g <primary-group> -G www-data -M 0660 \
112
        -- /path/to/app.wt
113
Environment="WT_APP_ROOT=/path/to/app/root"
114
115
Type=forking
116
PIDFile=/var/run/fastcgi-<app>.pid
117
Restart=always
118
SyslogIdentifier=fastcgi-<app>
119
120
# Security-conscious users may wish to research:
121
#   PrivateTmp, PrivateDevices, ProtectSystem, ProtectHome
122
#   CapabilityBoundingSet=
123
#   NoNewPrivileges
124
125
[Install]
126
WantedBy=multi-user.target
127
</pre>
128
129
Again, replace the paths, usernames etc. as appropriate. In the @ExecStart@ line:
130
* @-s <socket>@ is the Unix socket over which nginx will contact your application
131
* @-P <path>@ is the PID file that will be monitored by systemd (so it must match the @PIDFile=@ line further below in the unit file)
132
* @-u <username>@ and @-g <primary-group>@ set the UID/GID to run the application as; this avoids needing to run your application as root at any point
133
* @-G www-data@ sets the group for the Unix socket; obviously it must allow read/write access for nginx (which by default uses the @www-data@ group). Since the socket does not have to have the same permissions as the application, this means that nginx can trivially run under a different uid/gid from your application.
134
* @-M 0660@ sets the mode on the Unix socket; here we set it to allow group read/write.
135
136 18 Laurence Withers
The @WT_APP_ROOT@ environment variable is set to allow an application-specific @wt_config.xml@ file to be placed in a specific directory, rather than relying on a system-wide @/etc/wt_config.xml@. The value of this variable is also exposed as Wt::WApplication::appRoot().
137 16 Laurence Withers
138
Once set up, the service may be enabled at system startup with:
139
140
<pre>
141
 $ sudo systemctl enable fastcgi-<app>.service
142
</pre>
143
144
It must be started manually for the first time (use @systemctl start@), and may at any time be started/stopped/restarted/disabled in the same manner.
145
146
h3. nginx configuration
147
148
Under the relevant @server@ section, simply add the following:
149
150
<pre>
151
  location /my/app.wt {
152
    fastcgi_pass unix:/var/run/fastcgi-<app>.sock;
153
    include fastcgi_params;
154
    fastcgi_split_path_info ^(/my/app.wt)(.*)$;
155
    fastcgi_param PATH_INFO $fastcgi_path_info;
156
  }
157
</pre>
158
159
The @fastcgi_pass@ line hands off the connection to our Wt application via the fastcgi protocol over a Unix socket. Obviously adjust the path as appropriate.
160
161
In order to get internal paths working properly under all situations (including when the application is installed at the server root), we need to set up a regular expression on the request URI with two captures. The first capture is used as the script name, and the second as the internal path. This is the purpose of the @fastcgi_split_path_info@ line and the @PATH_INFO@ parameter. The first capture is made available as @Wt::WEnvironment::deploymentPath()@ and the second as @Wt::WEnvironment::internalPath()@.