Fastcgi on nginx » History » Revision 19
« Previous |
Revision 19/31
(diff)
| Next »
Nuika Sanders, 05/22/2015 01:36 PM
h1. FastCGI on nginx
- Table of contents
- Security-conscious users may wish to research:
- PrivateTmp, PrivateDevices, ProtectSystem, ProtectHome
- CapabilityBoundingSet=
- NoNewPrivileges
h2. About nginx
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).
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.
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.
h2. Ubuntu configuration
- Installing nginx and spawn-fcgi (which comes with lighttpd):
$ sudo apt-get install nginx lig[[http://amodaa.ru/ http]]d
- Start your application (linked against wtfcgi) using spawn-fcgi. Spawn-fcgi wraps the FastCGI application to listen to a socket or network connection.
$ spawn-fcgi -n -f ../../build/examples/hello/hello.wt -a 0.0.0.0 -p 9091
- Edit your nginx configuration to redirect a particular URL to your application (replace all occurences of /hello.wt with the path for your application!):
location /hello.wt {
fastcgi_pass 127.0.0.1:9091;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
if ($document_uri ~ "^/hello.wt/(.*)") {
set $apache_path_info /$1;
}
fastcgi_param SCRIPT_NAME /hello.wt;
fastcgi_param PATH_INFO $apache_path_info;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}
Alternatively to avoid 'if' in declaration just indicate the root of your application:
location ~ /hello.wt(?/.*|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_NAME /hello.wt;
fastcgi_param PATH_INFO $path_info;
include fastcgi_params.conf;
}Reload (or restart) your nginx server and you are ready to go:
$ sudo /etc/init.d/nginx restart
h2. Debian (Wheezy) configuration
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).
h3. spawn-fcgi
First, install the spawn-fcgi package:
$ sudo apt-get install spawn-fcgi
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).
The application may be started with a command such as:
$ spawn-fcgi -s /var/run/fastcgi-.sock -- /path/to/app.wt
(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().
h3. spawn-fcgi systemd unit files
If using systemd, you can trivially create a unit file under @/etc/systemd/system@, named @/etc/systemd/system/fastcgi-.service@:
[Unit]
Description=FastCGI spawner for amazing Wt web app
[Service]
ExecStart=/usr/bin/spawn-fcgi -s /var/run/fastcgi-.sock \
-P /var/run/fastcgi-.pid \
-u -g -G www-data -M 0660 \
-- /path/to/app.wt
Environment="WT_APP_ROOT=/path/to/app/root"
Type=forking
PIDFile=/var/run/fastcgi-.pid
Restart=always
SyslogIdentifier=fastcgi-
Security-conscious users may wish to research:¶
PrivateTmp, PrivateDevices, ProtectSystem, ProtectHome¶
CapabilityBoundingSet=¶
NoNewPrivileges¶
[Install]
WantedBy=multi-user.target
Again, replace the paths, usernames etc. as appropriate. In the @ExecStart@ line:
- @-s @ is the Unix socket over which nginx will contact your application
- @-P @ is the PID file that will be monitored by systemd (so it must match the @PIDFile=@ line further below in the unit file)
- @-u @ and @-g @ set the UID/GID to run the application as; this avoids needing to run your application as root at any point
- @-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.
- @-M 0660@ sets the mode on the Unix socket; here we set it to allow group read/write.
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().
Once set up, the service may be enabled at system startup with:
$ sudo systemctl enable fastcgi-.service
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.
h3. nginx configuration
Under the relevant @server@ section, simply add the following:
location /my/app.wt {
fastcgi_pass unix:/var/run/fastcgi-.sock;
include fastcgi_params;
fastcgi_split_path_info /my/app.wt(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
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.
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()@.
Updated by Nuika Sanders over 9 years ago · 19 revisions