<!--toc--> |
|
## Introduction |
|
There are many options to connect CppCMS application to web server: |
|
- Protocol: you can use FastCGI or SCGI protocols, |
you can also run over HTTP protocol behind proxy. |
|
Recommendation: use FastCGI as it has best support |
over various web servers. |
|
- Application start: it can be started by the web server |
and controlled by it or it can run as independent |
service when web server only connects to it. |
|
- Communication method: you can use Unix domain sockets |
or tcp/ip sockets. For local communication unix sockets |
are preferred. |
|
Please note, this tutorial is provided for running |
CppCMS based systems in production environment. |
|
It is less friendly for debugging. If you want to debug |
your application behind web server, use `cppcms_run` |
utility which allows you to prepare web server configurations automatically and run web servers themselves. |
|
It allows you to run your web application behind 3 most popular web servers: Apache, Lighttpd and Nginx using FastCGI, SCGI protocols or use them as Reverse HTTP Proxy. |
|
|
## Using HTTP Protocol |
|
CppCMS provides basic implementation of HTTP protocol and thus it can run behind reverse HTTP Proxy or be used |
in embedded environments. This option is not recommended for use in production environment as internal web |
server has quite weak performance in serving static |
files and it is very limited options in comparison |
to widely used web servers. |
|
|
## Assumptions |
|
In all our examples we assume: |
|
- Application's executable placed in `/opt/app/bin/hello` |
- Application's configuration file placed in `/opt/app/etc/config.js` |
- The document root is `/var/www` |
- Our application's URL (script) is `/hello` |
|
|
## Lighttpd |
|
Lighttpd supports both fastcgi/scgi protocols over unix and tcp/ip sockets. It can start the application for you and use external FastCGI/SCGI application. |
|
### Lighttpd, FastCGI |
#### Lighttpd, FastCGI, Start by Web Server |
|
You should enable mod-fastcgi and then use this Configuration file: |
|
fastcgi.server = ( |
## The script name of the application |
"/hello" => (( |
## Command line to run |
"bin-path" => "/opt/app/bin/hello -c /opt/app/etc/config.js", |
"socket" => "/tmp/hello-fcgi-socket", |
## Important - only one process should start |
"max-procs" => 1, |
"check-local" => "disable" |
)) |
) |
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket" : "stdin" // use server's socket |
} |
} |
|
#### Lighttpd, FastCGI, External Start |
|
You should enable mod-scgi and then use this Configuration file: |
|
fastcgi.server = ( |
## The script name of the application |
"/hello" => (( |
"socket" => "/tmp/hello-fastcgi-socket", |
## Important - only one process should start |
"max-procs" => 1, |
"check-local" => "disable" |
)) |
) |
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket" : "/tmp/hello-fastcgi-socket" |
} |
} |
|
|
If you want to use TCP/IP rather then Unix sockets, replace |
|
- In lighttpd configuration: `"socket" => "/tmp/hello-fastcgi-socket",` by `"host" => "127.0.0.1", "port" => 8081,` |
- In cppcms configuration: `"socket" : "/tmp/hello-fastcgi-socket"`, by `"ip": "127.0.0.1" , "port" : 8081,` |
|
### Lighttpd, SCGI |
#### Lighttpd, SCGI, Start by Web Server (lighttpd >=1.4.23) |
|
You should enable mod-scgi and then use this Configuration file: |
|
scgi.server = ( |
## The script name of the application |
"/hello" => (( |
## Command line to run |
"bin-path" => "/opt/app/bin/hello -c /opt/app/etc/config.js", |
"socket" => "/tmp/hello-fcgi-socket", |
## Important - only one process should start |
"max-procs" => 1, |
"check-local" => "disable" |
)) |
) |
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "scgi", |
"socket" : "stdin" // use server's socket |
} |
} |
|
|
|
#### Lighttpd, SCGI, External Start |
|
You should enable mod-scgi and then use this Configuration file: |
|
scgi.server = ( |
## The script name of the application |
"/hello" => (( |
"socket" => "/tmp/hello-scgi-socket", |
## Important - only one process should start |
"max-procs" => 1, |
"check-local" => "disable" |
)) |
) |
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "scgi", |
"socket" : "/tmp/hello-scgi-socket" // use server's socket |
} |
} |
|
|
|
If you want to use TCP/IP rather then Unix sockets, replace |
|
- In lighttpd configuration: `"socket" => "/tmp/hello-scgi-socket",` by `"host" => "127.0.0.1", "port" => 8081,` |
- In cppcms configuration: `"socket" : "/tmp/hello-scgi-socket"`, by `"ip": "127.0.0.1" , "port" : 8081,` |
|
|
## Apache |
|
### Apache, FastCGI |
|
You need to enable at least two modules: `mod_fastcgi` and `mod_alias` |
|
For each case we prepare `mod_fastcgi` configuration file |
and out config.js. |
|
**Note:** below we present you an example fastcgi.conf configuration. Be aware that these settings will affect your whole web server. If instead you desire to set these to affect only one specific virtual host, you must place the settings in your virtual host's configuration file (e.g. within `/etc/apache2/sites-available` on a Debian system). Check the official Apache documentation for details. |
|
#### Apache, FastCGI, Start by Web Server |
|
Apache configuration: |
|
|
FastCgiIpcDir /var/lib/apache2/fastcgi |
# Usually it is given in fastcgi.conf by default |
|
FastCgiServer /opt/app/bin/hello -initial-env CPPCMS_CONFIG=/opt/app/etc/config.js -socket /tmp/hello-fcgi-socket |
# CPPCMS_CONFIG should hold the path to configuration file. |
# Note: you can't pass command line parameter |
# so you pass the location of configuration file |
# via CPPCMS_CONFIG environment variable |
|
FastCGIConfig -maxProcesses 1 -processSlack 1 |
# This is important - we want apache to use only |
# one process as we have cache and many other |
# goodies handled by outsefs |
|
ScriptAliasMatch ^/hello(.*)$ /opt/app/bin/hello$1 |
# We map script "/hello" to our application |
|
AddHandler fastcgi-script /opt/app/bin/hello |
|
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket": "stdin" // we use socket given by server |
} |
} |
|
#### Apache, FastCGI, Independent start |
|
Apache configuration: |
|
|
FastCgiIpcDir /var/lib/apache2/fastcgi |
# Usually it is given in fastcgi.conf by default |
|
FastCgiExternalServer /opt/app/bin/hello -socket /tmp/hello-fcgi-socket |
# We provide a socket the application listens on. |
|
ScriptAliasMatch ^/hello(.*)$ /opt/app/bin/hello$1 |
# We map script "/hello" to our application |
|
AddHandler fastcgi-script /opt/app/bin/hello |
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket": "/tmp/hello-fcgi-socket" |
// Same as in apache config |
} |
} |
|
Now you should run the CppCMS application independently |
as `/opt/app/bin/hello -c /opt/app/etc/config.js` |
|
If you want to use TCP/IP sockets and not Unix one change |
|
- in `FastCgiExternalServer` line parameter `-socket` to `-host 127.0.0.1:8081` |
- in CppCMS config change `"socket": "/tmp/hello-fcgi-socket"` to `"ip" : "127.0.0.1", "port" : 8081` |
|
### Apache, SCGI |
|
Apache's `mod_scgi` supports only in-depended/external start and works over TCP/IP sockets, so the configuration is quite simple: |
|
Apache's module configuration: |
|
SCGIMount /hello 127.0.0.1:8081 |
|
We pass the script name as mount point and ip:port as |
point to connect cppcms application. |
|
CppCMS configuration: |
|
{ |
"service" : { |
"api" : "scgi", |
"ip" : "127.0.0.1", |
"port" : 8081 |
} |
} |
|
Now you should run the CppCMS application independently |
as `/opt/app/bin/hello -c /opt/app/etc/config.js` and Apache would connect to it. |
|
|
## Nginx |
|
Nginx supports only FastCGI protocol with external application start. |
|
Note: Nginx's SCGI module is broken as it does not confirm SCGI specifications: it requires rather HTTP response then CGI one. It does not generate `SCRIPT_NAME` and `PATH_INFO` variables at all. Don't use it! |
|
Also Nginx's fastcgi module require manual generation |
of `SCRIPT_NAME` and `PATH_INFO` variables. |
|
### Nginx, FastCGI |
|
Web Server Configuration under `server` section: |
|
|
# Specify UTL to match |
location ~ ^/hello.*$ { |
# Socket to communicate |
fastcgi_pass unix:/tmp/hello-fcgi-socket; |
|
|
# Setup value of PATH_INFO variable |
fastcgi_split_path_info ^(/hello)((?:/.*))?$; |
fastcgi_param PATH_INFO $fastcgi_path_info; |
|
# |
# You can either use "include fastcgi_params;" |
# or set the variables below manually |
# |
|
# All supported CGI variables |
fastcgi_param SCRIPT_NAME /hello; |
fastcgi_param QUERY_STRING $query_string; |
fastcgi_param REQUEST_METHOD $request_method; |
fastcgi_param CONTENT_TYPE $content_type; |
fastcgi_param CONTENT_LENGTH $content_length; |
|
# Setup value of PATH_INFO variable |
fastcgi_split_path_info ^(/hello)((?:/.*))?$; |
|
# Rest CGI variales |
fastcgi_param SCRIPT_NAME /hello; |
fastcgi_param PATH_INFO $fastcgi_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; |
|
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; |
|
# end of server variables |
} |
|
|
And the usual CppCMS's config: |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket" : "/tmp/hello-fcgi-socket" |
} |
} |
|
Of course the CppCMS's service should be started independently. |
|
For using TCP/IP protocol replace: |
|
- In nginx's configuration replace the line `fastcgi_pass unix:/tmp/hello-fcgi-socket;` by `fastcgi_pass 127.0.0.1:8081;` |
- In CppCMS's configuration as usual: `"socket" : "/tmp/hello-fcgi-socket"`, by `"ip": "127.0.0.1" , "port" : 8081,` |
|
### Nginx, SCGI |
|
First of all before you tru use SCGI I'd recommend |
to use FastCGI protocol unless you have very good |
reasons. |
|
SCGI protocol implementation for Nginx as several |
limitations: |
|
1. It does not define PATH_INFO properly, and thus the |
rewriting trick shown below does not fully simulate |
it as it does not urldecode PATH_INFO variable |
as it is required by CGI specifications. |
2. It does not handle CGI headers as expected so |
CppCMS should create HTTP headers instead of |
CGI ones. |
|
Thus `service.generate_http_headers` option |
should be set to true |
|
|
Web Server Configuration under `server` section: |
|
# Small hack to create something close to PATH_INFO |
set $path_info ""; |
if ( $document_uri ~ ^/hello(.*)$ ) { |
set $path_info $1; |
} |
|
location ~ ^/hello.*$ { |
# Communication protocol |
scgi_pass unix:/tmp/hello-scgi-socket; |
|
# Setup CGI variables |
|
scgi_param SCRIPT_NAME /hello; |
scgi_param PATH_INFO $path_info; |
|
# |
# You can either use "include scgi_params;" |
# or set the variables below manually |
# |
|
scgi_param QUERY_STRING $query_string; |
scgi_param REQUEST_METHOD $request_method; |
scgi_param CONTENT_TYPE $content_type; |
scgi_param CONTENT_LENGTH $content_length; |
|
scgi_param SCRIPT_NAME /hello; |
scgi_param PATH_INFO $path_info; |
scgi_param REQUEST_URI $request_uri; |
scgi_param DOCUMENT_URI $document_uri; |
scgi_param DOCUMENT_ROOT $document_root; |
scgi_param SERVER_PROTOCOL $server_protocol; |
|
scgi_param GATEWAY_INTERFACE CGI/1.1; |
scgi_param SERVER_SOFTWARE nginx; |
|
scgi_param REMOTE_ADDR $remote_addr; |
scgi_param REMOTE_PORT $remote_port; |
scgi_param SERVER_ADDR $server_addr; |
scgi_param SERVER_PORT $server_port; |
scgi_param SERVER_NAME $server_name; |
|
# end of scgi_params |
} |
|
And the special CppCMS's configuration for Nginx. |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket" : "/tmp/hello-fcgi-socket", |
"generate_http_headers" : true |
} |
} |
|
Of course the CppCMS's service should be started independently. |
|
For using TCP/IP protocol replace: |
|
In nginx's configuration replace the line `scgi_pass unix:/tmp/hello-fcgi-socket;` by `scgi_pass 127.0.0.1:8081;` |
|
|
## IIS |
|
Before you try to use IIS in front of CppCMS I'd recommend |
you to chose another web server that is more friendly |
to web developers who use web server independent |
API like FastCGI. |
|
### Best Approach |
|
Configure CppCMS with some other good web server like |
Apache or Nginx and forward requests from IIS to it. |
|
### HTTP Connectivity |
|
Is probably the most solid option. Forward all requests |
relevant to the web application the the CppCMS |
internal web server - use IIS as reverse proxy. |
|
Note: give IIS the job of serving static files. It |
would likely do it better then CppCMS internal |
web server. |
|
### FastCGI Connectivity |
|
FastCGI - don't use it, it was designed to run PHP and |
nothing more. |
|
IIS's FastCGI implementation is broken and |
[does not support](http://forums.iis.net/t/1155551.aspx) |
multi-threaded FastCGI applications. |
|
It also does not provide an option to configure |
specific port making it even impossible to use |
CppCMS application with IIS. |
|
### SCGI Connectivity |
|
#### Using with ISAPI SCGI. |
|
There is SCGI ISAPI extension that allows to use |
external SCGI applications: |
[isapi\_scgi](http://woof.magicsplat.com/isapi_scgi/home) |
|
However it has two big limitations: |
|
1. It does not support real CGI response from the client |
and expects HTTP response. |
|
Starting from CppCMS 0.99.10 it is possible to |
set an option `service.generate_http_headers` to `true`. |
This option tells CppCMS to generate HTTP rather |
then CGI response headers. |
|
Using this option it was possible to run successfully |
CppCMS application with IIS. |
|
2. It supports only predefined set of HTTP headers |
so if you will need to get custom headers from |
for example AJAX responses you'll need to alter |
`isapi_scgi` sources. |
|
|
In order to configure ISAPI extension follow |
the instructions on this |
[web site](http://woof.magicsplat.com/isapi_scgi/home). |
|
The CppCMS configuration should look like this: |
|
{ |
"service" : { |
"api" : "scgi", |
"ip" : "127.0.0.1", |
"port" : 9999, |
"generate_http_headers" : true |
} |
} |
|
|
#### Troubleshooting ISAPI SCGI extension. |
|
First of all you can get sources for `isapi_scgi.dll` |
at: |
|
<http://twapi.cvs.sourceforge.net/viewvc/twapi/isapi/> |
|
Just click download GNU Tarball. |
|
There are several reasons to build it on your own: |
|
- Currently the project provides only 32 bit builds of |
this dll, if you need 64 bit or you'll need to build |
it manually. |
|
- If you need support of custom HTTP headers you'll have |
to add them in scgi.c. |
|
If you want to build it with gcc you need to apply |
following changes: |
|
--- scgi_old.h 2011-08-17 10:48:32.109547500 +0300 |
+++ scgi.h 2011-08-17 10:50:26.184022000 +0300 |
@@ -37,3 +37,3 @@ |
*/ |
-#if defined(_MSC_VER) |
+#if defined(_MSC_VER) || defined(__GNUC__) |
# define COPY_MEMORY(d, s, n) memcpy((d), (s), (n)) |
@@ -48,3 +48,3 @@ |
ZLINK_CREATE_TYPEDEFS(context_t); |
-typedef struct context { |
+struct context { |
OVERLAPPED ovl; /* Must be first structure */ |
@@ -81,3 +81,3 @@ |
buffer_t buf; /* Data buffer */ |
-} context_t; |
+}; |
|
And the you'll be able to build the DLL as: |
|
gcc -O2 -shared buffer.c scgi.c logger.c -lws2_32 -o isapi_scgi.dll |
|
|
## Configuring Other Web Servers |
|
When it comes to configuration of the web servers not mentioned above you should consider following points: |
|
1. If the web server allows you to start the application |
you should make sure it starts only a single process. |
|
Otherwise you may experience problems with cache |
invalidation, session management and your asynchronous |
applications would likely not work as they don't |
share the same process. |
|
2. Make sure that the FastCGI or SCGI support confirm |
to the standard. For example: Nginx's |
SCGI connectors do not parse `Status` HTTP header |
and create correct response; IIS's SCGI module |
does not send HTTP status line at all and expect |
HTTP like CGI output. |
|
3. Prefer FastCGI protocol if available as implementations |
of SCGI usually have lower quality. |
|
4. Under Microsoft Windows platform, named pipes |
are not supported, only TCP/IP connections |
should be used. |
|
Note: under Windows named pipes are frequently |
used as replacement of Unix sockets, they are not |
supported as they have very different behavior. |
|
5. Make sure that `SCRIPT_NAME` and `PATH_INFO` CGI |
variables are set correctly. |
In our case, given URL `/hello/you` |
`SCRIPT_NAME` should be `/hello` and `PATH_INFO` |
should be `/you` |
|
## Notes for CppCMS 0.0.x users |
|
CppCMS 0.0.x's web server setup is similar to CppCMS 1.x.x |
one, as both support FastCGI and SCGI protocols, however |
the configuration file of the 0.0.x version is quite different. |
|
See: |
|
- [CppCMS 0.0.x Configuration](/wikipp/en/page/ref_config#server-api) |
- [CppCMS 1.x.x Configuration](/wikipp/en/page/cppcms_1x_config#service) |
|
The protocol is specified as "service.api" and allows options "fastcgi" and "scgi". |
|
However the communication is different. |
|
- Unix domain socket defined as: |
|
`service.socket = "/path/to/socket"` |
|
- TCP/IP socket defined as |
|
`service.socket = "IP:PORT"` |
|
- Socket taken from standard input - just make sure that `service.socket` is not defined. |
|
For example: |
|
1. FastCGI, TCP/IP |
|
|
CppCMS 1.x.x |
|
{ |
"service" : { |
"api" : "fastcgi", |
"ip" : "127.0.0.1", |
"port" : 6000 |
} |
} |
|
|
CppCMS 0.0.x |
|
service.api = "fastcgi" |
service.socket = "127.0.0.1:6000" |
|
|
2. SCGI, Unix Socket |
|
|
CppCMS 1.x.x |
|
{ |
"service" : { |
"api" : "scgi", |
"socket" : "/tmp/app.sock", |
} |
} |
|
|
CppCMS 0.0.x |
|
service.api = "scgi" |
service.socket = "/tmp/app.sock" |
|
3. FastCGI, standard input (started by web server) |
|
|
|
CppCMS 1.x.x |
|
{ |
"service" : { |
"api" : "fastcgi", |
"socket" : "stdin", |
} |
} |
|
|
CppCMS 0.0.x |
|
service.api = "fastcgi" |
# service.socket - undefined |
|
|
|