Enable Apache CGI for Dynamic Programming Languages on Ubuntu 19.04

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:

[terminal]
sudo nano /etc/apache2/sites-available/ubuntu.lan.conf
[/terminal]

 

2. Then, add the below statements anywhere in the file before the closing </VirtualHost> tag:

[terminal]
<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>
[/terminal]

cgi statements

cgi statements

 

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:

[terminal]
<Directory "/var/www/html/ubuntu.lan/cgi-scripts">
[/terminal]

 

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:

 

[terminal]
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>
[/terminal]

or
 

[terminal]
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>
[/terminal]

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:

[terminal]
sudo a2enmod cgi cgid
sudo service apache2 restart
[/terminal]

 
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.

[terminal]
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
[/terminal]

 

script.cgi file excerpt:

[terminal]
#!/bin/bash
echo "Content-type: text/html"
echo ""

echo "$REMOTE_ADDR"
echo "<pre> `env` </pre>"
[/terminal]

 

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

test bash cgi script

test bash cgi script

 

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:

[terminal]
<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>
[/terminal]

 

enable cgi scripts

enable cgi scripts

 

7. To test the the CGI environment configuration, crate a file for every enabled extension as it follows:

– For Perl:

[terminal]
sudo nano /var/www/html/ubuntu.lan/script.pl
[/terminal]

script.pl file excerpt:

[terminal]
#!/usr/bin/perl
print "Content-type: text/html\n\n"; foreach my $keys (sort keys %ENV) { print "$keys =
$ENV{$keys}<br/>\n";
}
[/terminal]

perl cgi script

perl cgi script

 

– For Python:

[terminal]
sudo nano /var/www/html/ubuntu.lan/script.py
[/terminal]

script.py file excerpt:

[terminal]
#!/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])
[/terminal]

python cgi script

python cgi script

– For Ruby:

First install the Ruby interpreter then create the Ruby script:

[terminal]
sudo apt-get install ruby
sudo nano /var/www/html/ubuntu.lan/script.rb
[/terminal]

script.py file excerpt:

[terminal]
#!/usr/bin/env ruby
print "Content-type: text/plain\n\n"

print `echo $REMOTE_ADDR`;
puts `env`;
[/terminal]

ruby cgi script

ruby cgi script

 

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:

[terminal]
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
[/terminal]

 

http://www.domain.tld/script.pl

run cgi perl script

run cgi perl script

http://www.domain.tld/script.py

run cgi python script

run cgi python script

http://www.domain.tld/script.rb

run cgi ruby script

run cgi ruby script

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.

Leave a Reply