Fcgiwrap, or How to run CGI-scripts without Apache and mod_cgi

Date August 25th, 2015 Author Vitaly Agapov

This buzz is not without the reason.

Soviet cartoon «Winnie the Pooh»

pooh-buzz

It’s definitely a bad idea to get Apache running only for executing some lightweight CGI-scripts. And it’s definitely a good idea to use Nginx where possible. But Nginx while being a perfect reverse proxy just cannot run GGI because of its event-based paradigm. This is the situation where the strengths become weaknesses. But we can still deal with this by virtue of some third-party tools like fastcgi wrappers. One of such tools is fcgiwrap server and in this post I’ll show how to build it and how to use it.

Building the RPM package

This paragraph is only useful if you run some RPM-based distributive.

The SPEC-file and systemd unit-files can be found in this repo: https://github.com/agapoff/fcgiwrap_spec.

The compiling and building itself can be done by such snippet which I have taken right from my Jenkins (assuming you have cloned the source repository from https://github.com/gnosek/fcgiwrap right to sub-directory fcgiwrap-1.1.0):

Version=`cat fcgiwrap_spec/fcgiwrap.spec | grep "^Version:" | awk '{print $2}'`
PkgName="fcgiwrap-${Version}"

cp fcgiwrap_spec/fcgiwrap.spec $PkgName
cp fcgiwrap_spec/fcgiwrap.service $PkgName/systemd/
cp fcgiwrap_spec/fcgiwrap.socket $PkgName/systemd/
tar cvzf ${PkgName}.tgz --exclude=*/.git $PkgName

rpmbuild --define "_topdir %(pwd)/rpm-build" --define "_builddir %{_topdir}" \
    --define "_rpmdir %{_topdir}" --define "_srcrpmdir %{_topdir}" --define '_rpmfilename %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm' \
    --define "_specdir %(pwd)" --define "_sourcedir  %(pwd)" -ta ${PkgName}.tgz

build_num=`ls -v rpm-build/fcgiwrap-${Version}-*rpm | grep -v src | grep -v debuginfo | tail -1 | cut -f2 -d / | cut -f 2,3 -d-`

scp rpm-build/fcgiwrap-${build_num} repouser@reposerver:repo/path/${OS_Version}/x86_64/
ssh repouser@reposerver "createrepo --update repo/path/${OS_Version}/x86_64/"

Thus we have built the RPM-package with systemd unit-files. One unit-file is for socket and the second is for fcgiwrapper itself.

Running the fcgiwrap

Then we just install fcgiwrap (yum install fcgiwrap if we have own RPM-repo). Socket will be started right after the installation and manual starting of the service is not needed because it will be started automatically when socket is accessed.

But anyway we can use systemctl if needed for some reason:

systemctl start fcgiwrap.socket
systemctl start fcgiwrap.service

Configuring Nginx

The last step is configuring Nginx. The main idea is to set SCRIPT_FILENAME fastcgi parameter with the script needed to be executed.

server {
...
   location /cgi-bin/ {
     # Disable gzip (this will allow asynchronous output)
     gzip off;
     # Set the root to /var/www
     root  /var/www;
     # Fastcgi socket
     fastcgi_pass  unix:/run/fcgiwrap.sock;
     # Fastcgi parameters, include the standard ones
     include /etc/nginx/fastcgi_params;
     # Adjust non standard parameters (SCRIPT_FILENAME)
     fastcgi_param SCRIPT_FILENAME  $document_root$fastcgi_script_name;
   }
}

Testing

Now let’s create file /var/www/cgi-bin/helloworld.cgi with such contents:

#!/bin/bash
cat << EOF
Content-type: text/html

<html>
  <head>
     <title>Hello World</title>
  </head>
  <body>
     <h1>Hello World</h1>
  </body>
</html>
EOF

And try to access it via Nginx with URL http://server/cgi-bin/helloworld.cgi.

Tags: , ,
Category: Apache, Linux, Nginx | No comments »

Comments

Leave a comment

 Comment Form