CGI (Common Gateway Interface) is an protocol which allows Apache Web Server to interact with external programs, especially scripts written in interpreted languages, such as Bash, Python, Perl, Ruby, or even compiled programs, written in C, C++ or others, in order to generate dynamic web content. Basically, CGI programs or scripts can be written in any programming language which is capable of reading from standard input (STDIN), write to standard output (STDOUT) and process environment variables.
This article will guide you on how you can activate and use Apache CGI Gateway for interpreted dynamic scripting languages used in Linux, such as Bash, Perl, Python and Ruby and how to write simple CGI scripts in order to get you server environment variables and test Apache Web Server CGI interface.
REQUIREMENTS
STEP ONE – Create CGI Apache Configuration File
1. The first step needed, in order for Apache to parse CGI scripts under a specific directory or under the main webroot directory, is to permit CGI file execution by adding the ScriptAlias
(for directories outside of the DocumentRoot
directory), ExecCGI
and AddHandler cgi-script
directives on your domain configuration file. Assuming that you have read the previous guide concerning Virtual Hosting and configured a virtual host file for www.ubuntu.lan domain, let’s start adding the directives in order to run a simple Bash script hosted on our domain webroot. So, first open ubuntu.lan configuration file for editing by issuing the following command:
sudo nano /etc/apache2/sites-available/ubuntu.lan.conf
2. Then, add the below statements anywhere in the file before the closing </VirtualHost>
tag:
<Directory "/var/www/html/ubuntu.lan">
Options Indexes ExecCGI MultiViews
AddHandler cgi-script .cgi
DirectoryIndex index.cgi
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
CGI Statements Explanations
The Options ExecCGI
and AddHandler cgi-script
statements have the role to permit Apache to execute CGI files that end with a .cgi
extension. Remember that on this example all the scrips must be placed under the DocumentRoot
absolute path, which is /var/www/html/ubuntu.lan
. (Alternate syntax to define DocumentRoot is <Directory "/">
). If you want to execute CGI files from a different location under the webroot path, such as /var/www/html/ubuntu.lan/cgi-scripts/
, then you need to specify that path at the beginning of CGI <Directory>
statement like this:
<Directory "/var/www/html/ubuntu.lan/cgi-scripts">
To allow CGI execution for scripts that are hosted outside the server DocumentRoot
path a ScriptAlias
directive must be placed before <Directory>
or < Location>
statement, like in the following examples:
ScriptAlias /run-cgi/ /usr/share/cgi-scripts/
<Directory "/usr/share/cgi-scripts">
Options +Indexes +ExecCGI
AddHandler cgi-script .cgi
DirectoryIndex index.cgi
Order allow,deny
Allow from all
Require all granted
</Directory>
or
ScriptAlias /run-cgi/ /usr/share/cgi-scripts/
<Location /run-cgi>
Options +Indexes +ExecCGI
AddHandler cgi-script .cgi
DirectoryIndex index.cgi
Order allow,deny
Allow from all
Require all granted
</Location>
In order to execute the scripts hosted outside the webroot you must specify the first part of the ScriptAlias
directive on URL path as it follows:
http://www.ubuntu.lan/run-cgi/your_cgi_script.cgi
STEP TWO – Activate Apache CGI Module
3. After you have edited your domain configuration file with the specific CGI directives, you must enable Apache CGI modules in order to properly execute CGI programs and restart the httpd daemon to reflect changes by issuing the following commands:
sudo a2enmod cgi cgid
sudo service apache2 restart
STEP THREE – Test CGI Scripts
4. The configurations made so far allows just the execution of Bash scrips, so we need to crate a simple Bash file to get the server’s environment variables and test the server CGI gateway.
On your domain webroot path create the following .cgi
file with the below content and, for security reasons, make sure the file has only the executable permissions set for the user that Apache runs in order to be parsed by server.
sudo touch /var/www/html/ubuntu.lan/script.cgi
sudo chown www-data:www-data /var/www/html/ubuntu.lan/script.cgi
sudo chmod 750 /var/www/html/ubuntu.lan/script.cgi
sudo nano /var/www/html/ubuntu.lan/script.cgi
script.cgi
file excerpt:
#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "$REMOTE_ADDR"
echo "<pre> `env` </pre>"
Note that all CGI files must include a HTTP MIME-type header echo "Content-type: text/html"
or echo ""
after the shell used to interpret the code #!/bin/bash
, in order to tell the browser what type of content it will receive. (most of the time the content will be HTML)
5. Save the script, then run it by opening a browser at the following URL address:
http://www.domain.tld/script.cgi
STEP FOUR – Run Perl, Python and Ruby CGI Scripts
6. To run Perl, Python and Ruby scripts, just add the AddHandler
specific file extension on your domain configuration file for every dynamic interpreted language you want to use (.rb
for Ruby scripts, .py
for Python scripts and .pl
for Perl scripts) as in the following example which enables all four:
<Directory "/var/www/html/ubuntu.lan">
Options Indexes ExecCGI MultiViews
AddHandler cgi-script .cgi .pl .rb .py
DirectoryIndex index.cgi index.pl index.rb index.py
AllowOverride All
Order allow,deny
Allow from all
Require all granted
</Directory>
7. To test the the CGI environment configuration, crate a file for every enabled extension as it follows:
– For Perl:
sudo nano /var/www/html/ubuntu.lan/script.pl
script.pl
file excerpt:
#!/usr/bin/perl
print "Content-type: text/html\n\n"; foreach my $keys (sort keys %ENV) { print "$keys =
$ENV{$keys}<br/>\n";
}
– For Python:
sudo nano /var/www/html/ubuntu.lan/script.py
script.py
file excerpt:
#!/usr/bin/python
import os
print "Content-type: text/html\r\n\r\n";
for param in os.environ.keys():
print "<pre><b>%20s</b>: %s" % (param, os.environ[param])
– For Ruby:
First install the Ruby interpreter then create the Ruby script:
sudo apt-get install ruby
sudo nano /var/www/html/ubuntu.lan/script.rb
script.py
file excerpt:
#!/usr/bin/env ruby
print "Content-type: text/plain\n\n"
print `echo $REMOTE_ADDR`;
puts `env`;
8. After you have created the above files, add execute permissions only for Apache user, restart Apache daemon to reflect changes and direct the browser at your domain URL scripts path as it follows:
sudo chown www-data:www-data /var/www/html/ubuntu.lan/script.*
sudo chmod 750 /var/www/html/ubuntu.lan/script.*
sudo service apache2 restart
http://www.domain.tld/script.pl
http://www.domain.tld/script.py
http://www.domain.tld/script.rb
That’s all! Running simple CGI programs can provide an effective way through which you can generate dynamic content for websites,validate HTML forms or create custom web monitoring tools for Linux systems. However, you must take proper security measures on what type of CGI programs you produce, how and who executes them on your system, since most of them runs on system shells.