By Mohamad Wael

Posted :

How to setup nginx with cgi , fastcgi and c , bash , lisp , or any other programming language on debian and freebsd ?

What is CGI , fastCGI , fcgiwrap , FastCGI Development Kit , featured image

CGI stands for the common gateway interface . It is a way , for a web server to run external applications .

Each application or script or whatever , will have a process created and destroyed for each request . The web server is in charge of creating and destroying the processes , and is the owner of the process .

Messages are transferred from the web server , to the application , using environment variables . nginx does not actually support CGI .

FastCGI stands for the fast common gateway interface .

The basic concept to get , is that it is not the server who is responsible for creating , or owning the external application process . The external application is created once , is a long running process , is supposed to handle multiple requests , as for example in having a loop , which handles all the received requests .

Messages are also transferred using environment variables , through for example a pipe , or a unix socket , or TCP/IP .

This model of work allows caching , for example of database connections , and might help in the prevention of a denial of service , which might occur in the case of CGI .

To use fastCGI with nginx , two software libraries can be used , fcgiwrap or the FastCGI Development Kit .

fcgiwrap is simply a simple server , which acts as a wrapper for CGI using fastCGI . This enables nginx to run any script or application , as if by using the CGI specification , which is more correctly put , as having CGI wrapped using fastCGI .

Install nginx , and fcgiwrap , using :

  1. root$ pkg install nginx-full fcgiwrap
  2. # install nginx and fcgiwrap on FreeBSD .
  3.  
  4. root$ apt-get install nginx-full fcgiwrap
  5. # install nginx and fcgiwrap on Debian .

Configure nginx , to add a location block , to the default server block , as in :

  1. # For FreeBSD
  2.  
  3. root$ nano /usr/local/etc/nginx/nginx.conf
  4. # ctrl-w to search for : server
  5. # and add a location block under
  6. # server as in :
  7.  
  8. server {
  9. listen 80;
  10. server_name localhost;
  11. ...
  12.  
  13. # add this location block
  14. location /cgi/ {
  15. gzip off;
  16. root /home/difyel/;
  17. fastcgi_pass unix:/var/run/fcgiwrap/fcgiwrap.sock;
  18. include fastcgi_params;
  19. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  20. }
  21. ...
  22.  
  23.  
  24. # For Debian
  25.  
  26. root$ nano /etc/nginx/sites-enabled/default
  27. # ctrl-w to search for server {
  28. # Add under server the content
  29. server {
  30. listen 80 default_server;
  31. listen [::]:80 default_server;
  32. ...
  33.  
  34. # add this location block
  35. location /cgi/ {
  36. gzip off;
  37. root /home/difyel/;
  38. fastcgi_pass unix:/var/run/fcgiwrap.socket;
  39. include fastcgi_params;
  40. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  41. }
  42. ...
  43.  
  44.  
  45.  
  46. # Finally for Debian , and FreeBSD
  47.  
  48. # Create a directory named cgi under
  49. # the location you specified in the
  50. # root directive , for example as
  51. # a regular user , you can issue :
  52. # mkdir -p /home/difyel/cgi/
  53. # You can test the configuration for
  54. # correctness using nginx -t
  55. # for debian only , restart nginx
  56. # using service nginx restart

For freeBSD additionally , fcgiwrap and nginx must be configured as follows :

  1. root$ nano /etc/rc.conf
  2. # edit /etc/rc.conf , and add the following
  3.  
  4. nginx_enable="yes"
  5. fcgiwrap_enable="yes"
  6. fcgiwrap_socket_owner="www"
  7. fcgiwrap_flags="-f -c 2"
  8. # -c 2 means prefork 2 fcgiwrap
  9. # processes , and -f means
  10. # redirect errors to web server
  11. # logs .
  12.  
  13. # ctrl-x to exit and save when prompted
  14.  
  15.  
  16. root$ service nginx start
  17. # start the nginx service
  18.  
  19. root$ service fcgiwrap start
  20. # start the fcgiwrap service

Test the programming languages that you want , by placing your executables or scripts , in the cgi folder which was just created , and visiting the address localhost/cgi/your-program .

  1. # example hello.lsp
  2.  
  3. # sbcl must be installed using
  4. # debian : apt-get install sbcl
  5. # freeBSD : pkg install sbcl
  6. # The script must be made executable
  7. # as in chmod +x hello.lsp
  8. # note that the first line for debian
  9. # must be #!/usr/bin/sbcl --script
  10.  
  11. #!/usr/local/bin/sbcl --script
  12. (format t "Content-Type:text/html~%~%")
  13. (format t "~a" (sb-unix::posix-getenv "HTTP_USER_AGENT"))
  14.  
  15.  
  16. # example hello.bash
  17.  
  18. # For freeBSD bash must be
  19. # installed , or another shell
  20. # must be specified .
  21. # Bash can be installed under
  22. # freeBSD by using :
  23. # pkg install bash
  24. # The script must be made
  25. # executable , as in :
  26. # chmod+x hello.bash
  27. # note that for debian , the
  28. # first line of the script ,
  29. # must be #!/usr/bin/bash
  30.  
  31. #!/usr/local/bin/bash
  32. printf 'Content-type: text/html\n\n'
  33. echo $HTTP_USER_AGENT
  34.  
  35.  
  36. # example hello.out
  37.  
  38. # For c , just write a hello.c
  39. # program and compile it , for example
  40. # using gcc -o hello.out hello.c
  41.  
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44.  
  45. int
  46. main
  47. (void ) {
  48. printf ("Content-type: text/html\n\n" );
  49. printf ("%s\n" , getenv("HTTP_USER_AGENT" ) );}

The list of environment variables that can be used , can be found under the wikipedia cgi article .

Concerning the fastCGI specification , it was created by the Open Market company , and the official website was fastcgi.com , which is not operational nowadays , but can be accessed using web archive , as in the provided link .

To install fastCGI , it can be done as follows :

  1. root$ pkg install fcgi-devkit spawn-fcgi
  2. # For FreeBSD
  3.  
  4. root$ apt-get install libfcgi-dev spawn-fcgi
  5. # For debian

Add an nginx location , which will be handled by a fastCGI application .

  1. # For FreeBSD
  2.  
  3. root$ nano /usr/local/etc/nginx/nginx.conf
  4. # ctrl-w to search for : server
  5. # and add a location block under
  6. # server as in :
  7.  
  8. server {
  9. listen 80;
  10. server_name localhost;
  11. ...
  12.  
  13. # add this location block
  14. location /fcgi/ {
  15. gzip off;
  16. fastcgi_pass 127.0.0.1:9100;
  17. include fastcgi_params;
  18. }
  19. ...
  20.  
  21.  
  22. # For Debian
  23.  
  24. root$ nano /etc/nginx/sites-enabled/default
  25. # ctrl-w to search for server {
  26. # Add under server the content
  27. server {
  28. listen 80 default_server;
  29. listen [::]:80 default_server;
  30. ...
  31.  
  32. # add this location block
  33. location /fcgi/ {
  34. gzip off;
  35. fastcgi_pass 127.0.0.1:9100;
  36. include fastcgi_params;
  37. }
  38. ...
  39.  
  40.  
  41.  
  42. # Finally for Debian , and FreeBSD
  43.  
  44. # Test the configuration for any
  45. # error using nginx -t , and
  46. # restart the server using
  47. # service nginx restart

Now , for example , to create a fastCGI application using C , It can be done as follows :

  1.  
  2. # example /home/difyel/hello.c
  3.  
  4. # Create a C source file , for
  5. # example hello.c
  6.  
  7. #include "fcgi_stdio.h"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10.  
  11. int
  12. main
  13. (void ){
  14. while (FCGI_Accept ( ) >= 0 ){
  15. printf ("Content-type: text/html;\n\n" );
  16. printf ("%s\n" , getenv("HTTP_USER_AGENT" ) );}}
  17.  
  18. # Compile the C source file using the command
  19. difyel$ gcc -lfcgi -o hello.out hello.c
  20.  
  21. # spawn a process using spawn-fcgi as in :
  22. spawn-fcgi -a127.0.0.1 -p9100 ./hello.out

Now , if you visit any page under localhost/fcgi/ , the hello.out process will be in charge of returning a response , in this example program , it just returns the user agent .

Examples on fastcgi.com/devkit/doc/fcgi-tcl.htm , are provided on how to integrate the fastCGI library , with for example , the Tcl interpreter .