Project

General

Profile

Fastcgi on nginx » History » Version 29

Georgiy Gluhoedov, 07/12/2016 08:59 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 28 Georgiy Gluhoedov
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 that.
13 1 Pieter Libin
14
15 27 Checheta Yan
16
h2. Ubuntu configuration 
17 1 Pieter Libin
18
* Installing nginx and spawn-fcgi (which comes with lighttpd):
19
20
<pre>
21 20 Nuika Sanders
 $ sudo apt-get install nginx lighttpd
22 1 Pieter Libin
</pre>
23
24
* Start your application (linked against wtfcgi) using spawn-fcgi. Spawn-fcgi wraps the FastCGI application to listen to a socket or network connection.
25
26
<pre>
27
 $ spawn-fcgi -n -f ../../build/examples/hello/hello.wt -a 0.0.0.0 -p 9091
28
</pre>
29
30 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!):
31 1 Pieter Libin
32
<pre>
33
        location /hello.wt {
34
                fastcgi_pass   127.0.0.1:9091;
35
 
36
                fastcgi_param  QUERY_STRING       $query_string;
37
                fastcgi_param  REQUEST_METHOD     $request_method;
38
                fastcgi_param  CONTENT_TYPE       $content_type;
39
                fastcgi_param  CONTENT_LENGTH     $content_length;
40
 
41
                if ($document_uri ~ "^/hello.wt/(.*)") {
42
                        set $apache_path_info /$1;
43
                }
44
 
45
                fastcgi_param  SCRIPT_NAME        /hello.wt;
46
                fastcgi_param  PATH_INFO          $apache_path_info;
47
                fastcgi_param  REQUEST_URI        $request_uri;
48
                fastcgi_param  DOCUMENT_URI       $document_uri;
49
                fastcgi_param  DOCUMENT_ROOT      $document_root;
50
                fastcgi_param  SERVER_PROTOCOL    $server_protocol;
51
 
52
                fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
53
                fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
54
 
55
                fastcgi_param  REMOTE_ADDR        $remote_addr;
56
                fastcgi_param  REMOTE_PORT        $remote_port;
57
                fastcgi_param  SERVER_ADDR        $server_addr;
58
                fastcgi_param  SERVER_PORT        $server_port;
59
                fastcgi_param  SERVER_NAME        $server_name;
60
        }
61
</pre>
62
63 15 Andy Z
* Alternatively to avoid 'if' in declaration just indicate the root of your application:
64
<pre>
65
        location ~ ^/hello.wt(?<path_info>/.*|$) {
66
                fastcgi_pass   127.0.0.1:9000;
67
                fastcgi_param  SCRIPT_NAME /hello.wt;
68
                fastcgi_param  PATH_INFO $path_info;
69
                include        fastcgi_params.conf;
70
        }
71
</pre>
72
73 3 Koen Deforche
* Reload (or restart) your nginx server and you are ready to go:
74 1 Pieter Libin
75
 $ sudo /etc/init.d/nginx restart
76 16 Laurence Withers
77
78
79
h2. Debian (Wheezy) configuration
80
81 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/
82 16 Laurence Withers
83
h3. spawn-fcgi
84
85
First, install the spawn-fcgi package:
86
87
<pre>
88
 $ sudo apt-get install spawn-fcgi
89
</pre>
90
91
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).
92
93 24 Nuika Sanders
The application may be started with a command such as: http://kupit-chemodan24.ru/
94 16 Laurence Withers
95
<pre>
96
 $ spawn-fcgi -s /var/run/fastcgi-<app>.sock -- /path/to/app.wt
97
</pre>
98
99 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().
100 16 Laurence Withers
101
h3. spawn-fcgi systemd unit files
102
103
If using systemd, you can trivially create a unit file under @/etc/systemd/system@, named @/etc/systemd/system/fastcgi-<app>.service@:
104
105
<pre>
106
[Unit]
107
Description=FastCGI spawner for amazing Wt web app
108
109
[Service]
110
ExecStart=/usr/bin/spawn-fcgi -s /var/run/fastcgi-<app>.sock \
111
        -P /var/run/fastcgi-<app>.pid \
112
        -u <username> -g <primary-group> -G www-data -M 0660 \
113
        -- /path/to/app.wt
114
Environment="WT_APP_ROOT=/path/to/app/root"
115
116
Type=forking
117
PIDFile=/var/run/fastcgi-<app>.pid
118
Restart=always
119
SyslogIdentifier=fastcgi-<app>
120
121
# Security-conscious users may wish to research:
122
#   PrivateTmp, PrivateDevices, ProtectSystem, ProtectHome
123
#   CapabilityBoundingSet=
124
#   NoNewPrivileges
125
126
[Install]
127
WantedBy=multi-user.target
128
</pre>
129
130 29 Georgiy Gluhoedov
Again, replace the paths, usernames etc. as appropriate. In the @ExecStart@ line:
131 16 Laurence Withers
* @-s <socket>@ is the Unix socket over which nginx will contact your application
132
* @-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)
133
* @-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
134
* @-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.
135
* @-M 0660@ sets the mode on the Unix socket; here we set it to allow group read/write.
136
137 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().
138 16 Laurence Withers
139
Once set up, the service may be enabled at system startup with:
140
141
<pre>
142
 $ sudo systemctl enable fastcgi-<app>.service
143
</pre>
144
145
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.
146
147
h3. nginx configuration
148
149
Under the relevant @server@ section, simply add the following:
150
151
<pre>
152
  location /my/app.wt {
153
    fastcgi_pass unix:/var/run/fastcgi-<app>.sock;
154
    include fastcgi_params;
155
    fastcgi_split_path_info ^(/my/app.wt)(.*)$;
156
    fastcgi_param PATH_INFO $fastcgi_path_info;
157
  }
158
</pre>
159
160
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.
161
162
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()@.