Serving CGI Scripts With Nginx On Ubuntu 12.04

This tutorial shows how you can serve CGI scripts (Perl scripts) with nginx on Ubuntu 12.04. While nginx itself does not serve CGI, there are several ways to work around this. I will outline three solutions: the first is to proxy requests for CGI scripts to Thttpd, a small web server that has CGI support, while the second and third solution are very similar – both use a CGI wrapper to serve CGI scripts.

I do not issue any guarantee that this will work for you!

1 Preliminary Note

I’m using the website here with the document root /var/www/ and the Nginx vhost configuration file /etc/nginx/sites-enabled/

Because we must run all the steps from this tutorial with root privileges, we can either prepend all commands in this tutorial with the string sudo, or we become root right now by typing

sudo su

2 Using Thttpd

In this chapter I am going to describe how to configure nginx to proxy requests for CGI scripts (extensions .cgi or .pl) to Thttpd. I will configure Thttpd to run on port 8000.

First we install Thttpd:

apt-get install thttpd

The nginx ThttpdCGI page says that Thttpd should be patched – fortunately this patch is already included in Ubuntu’s thttpd package, so we don’t need to do this.

Next we open /etc/default/thttpd…

vi /etc/default/thttpd

… and set ENABLED to yes:


Then we make a backup of the original /etc/thttpd/thttpd.conf file and create a new one as follows:

mv /etc/thttpd/thttpd.conf /etc/thttpd/thttpd.conf_orig
vi /etc/thttpd/thttpd.conf

# BEWARE : No empty lines are allowed!
# This section overrides defaults
# This section _documents_ defaults in effect
# port=80
# nosymlink         # default = !chroot
# novhost
# nocgipat
# nothrottles
# host=
# charset=iso-8859-1

This will make Thttpd listen on port 8000 on; its document root is /var/www.

Start Thttpd:

/etc/init.d/thttpd start

Next create /etc/nginx/proxy.conf:

vi /etc/nginx/proxy.conf

proxy_redirect          off;
proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;

Now open your vhost configuration file…

vi /etc/nginx/sites-enabled/

… and add a location /cgi-bin {} section to the server {} container:

server {
   location /cgi-bin {
      include proxy.conf;

Reload nginx:

/etc/init.d/nginx reload

Because Thttpd’s document root is /var/www, location /cgi-bin translates to the directory /var/www/cgi-bin (this is true for all your vhosts, which means each vhost must place its CGI scripts in /var/www/cgi-bin; this is a drawback for shared hosting environments; the solution is to use a CGI wrapper as described in chapters 3 and 4 instead of Thttpd).

Create the directory…

mkdir /var/www/cgi-bin

… and then place your CGI scripts in it and make them executable. For testing purposes I will create a small Hello World Perl script (instead of hello_world.cgi you can also use the extension .pl ->

vi /var/www/cgi-bin/hello_world.cgi

#!/usr/bin/perl -w

     # Tell perl to send a html header.
     # So your browser gets the output
     # rather then <stdout>(command line
     # on the server.)
print "Content-type: text/html\n\n";

     # print your basic html tags.
     # and the content of them.
print "<html><head><title>Hello World!! </title></head>\n";
print "<body><h1>Hello world</h1></body></html>\n";

chmod 755 /var/www/cgi-bin/hello_world.cgi

Open a browser and test the script:

If all goes well, you should get the following output:




Leave a Reply

Please log in using one of these methods to post your comment: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s