🐪 LAMP Stack: Perl Installation & Configuration

About this Guide: This document covers the complete installation and configuration of Perl as the "P" in your LAMP stack (Linux, Apache, MySQL, Perl). We'll cover installing Perl itself, Apache mod_perl, CGI modules, essential CPAN modules, and proper security configurations.

Table of Contents

1. Prerequisites Check

Before installing Perl components, verify your system is ready:

# Check if Apache/HTTPD is installed
httpd -v
# or
apache2 -v

# Check Apache status
systemctl status httpd
# or
systemctl status apache2

# Verify MySQL/MariaDB is installed
mysql --version

# Check if Perl is already installed (most Linux distros include it)
perl -v

2. Installing Perl

Red Hat/CentOS/Rocky/Alma Linux

# Install Perl core
sudo dnf install perl perl-core -y

# Or on older systems
sudo yum install perl perl-core -y

# Install development tools needed for CPAN modules
sudo dnf groupinstall "Development Tools" -y
sudo dnf install perl-devel -y

# Additional useful Perl packages
sudo dnf install \
    perl-App-cpanminus \
    perl-CPAN \
    perl-ExtUtils-MakeMaker \
    perl-Test-Simple -y

Debian/Ubuntu

# Install Perl core
sudo apt update
sudo apt install perl -y

# Install development tools
sudo apt install build-essential -y
sudo apt install libperl-dev -y

# Install CPAN and cpanminus
sudo apt install \
    cpanminus \
    liblocal-lib-perl \
    perl-doc -y
Verify Installation:
perl -v
# Should show Perl version (typically 5.x)

which perl
# Should show /usr/bin/perl

perldoc -l perl
# Should show Perl documentation location

3. Apache mod_perl Installation

mod_perl embeds a Perl interpreter into Apache for better performance than CGI.

Red Hat/CentOS/Rocky/Alma

# Install mod_perl
sudo dnf install mod_perl mod_perl-devel -y

# Verify module is loaded
sudo httpd -M | grep perl

# Should see something like:
# perl_module (shared)

Debian/Ubuntu

# Install mod_perl
sudo apt install libapache2-mod-perl2 libapache2-mod-perl2-dev -y

# Enable the module
sudo a2enmod perl

# Restart Apache
sudo systemctl restart apache2
mod_perl vs CGI:

4. CGI Configuration

Install CGI Module

# CGI.pm is usually included, but ensure it's available
sudo dnf install perl-CGI -y
# or
sudo apt install libcgi-pm-perl -y

Create CGI Directory

# Create CGI-bin directory
sudo mkdir -p /var/www/cgi-bin

# Set proper ownership
sudo chown apache:apache /var/www/cgi-bin
# or on Ubuntu/Debian
sudo chown www-data:www-data /var/www/cgi-bin

# Set permissions
sudo chmod 755 /var/www/cgi-bin

5. Essential CPAN Modules

Configure CPAN

# First-time CPAN configuration (as root)
sudo cpan

# Or use cpanminus (recommended - simpler)
# Already installed via perl-App-cpanminus or cpanminus package

Essential Modules for Web Development

Module Purpose Installation Command
DBI Database interface sudo cpanm DBI
DBD::mysql MySQL driver for DBI sudo cpanm DBD::mysql
CGI CGI handling sudo cpanm CGI
CGI::Session Session management sudo cpanm CGI::Session
Template Template Toolkit sudo cpanm Template
JSON JSON encoding/decoding sudo cpanm JSON
LWP::UserAgent HTTP client sudo cpanm LWP::UserAgent
XML::Simple XML parsing sudo cpanm XML::Simple
Mojolicious Modern web framework sudo cpanm Mojolicious
Plack PSGI toolkit sudo cpanm Plack

Install All Essential Modules

# Install all essential modules at once
sudo cpanm DBI DBD::mysql CGI CGI::Session Template JSON LWP::UserAgent XML::Simple

# For modern web development, also install
sudo cpanm Mojolicious Plack Dancer2

# For better testing
sudo cpanm Test::More Test::Exception Test::Pod
Note: Installing DBD::mysql requires MySQL/MariaDB development libraries:
# Red Hat/CentOS
sudo dnf install mysql-devel -y
# or
sudo dnf install mariadb-devel -y

# Ubuntu/Debian
sudo apt install libmysqlclient-dev -y

6. Apache Configuration for Perl

Configure CGI Support

For Red Hat/CentOS/Rocky/Alma:

# Edit main Apache config or create new config file
sudo vi /etc/httpd/conf.d/perl-cgi.conf

Add the following configuration:

# CGI Configuration
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options +ExecCGI
    AddHandler cgi-script .cgi .pl
    Require all granted
    
    # Enable for mod_perl (optional)
    # SetHandler perl-script
    # PerlResponseHandler ModPerl::Registry
    # PerlOptions +ParseHeaders
</Directory>

# Allow .pl files to execute in document root (optional - less secure)
# <Directory "/var/www/html">
#     Options +ExecCGI
#     AddHandler cgi-script .pl
# </Directory>

For Debian/Ubuntu:

# Enable CGI module
sudo a2enmod cgi

# Edit or create CGI configuration
sudo vi /etc/apache2/conf-available/perl-cgi.conf

Add configuration (same as above), then:

# Enable the configuration
sudo a2enconf perl-cgi

# Restart Apache
sudo systemctl restart apache2

Configure mod_perl (Optional but Recommended)

Create /etc/httpd/conf.d/mod_perl.conf (Red Hat) or /etc/apache2/mods-available/perl.conf (Debian):

# mod_perl Configuration
LoadModule perl_module modules/mod_perl.so

# Perl handler for /perl-bin directory
<Directory "/var/www/perl-bin">
    SetHandler perl-script
    PerlResponseHandler ModPerl::Registry
    PerlOptions +ParseHeaders
    Options +ExecCGI
    Require all granted
</Directory>

# Preload commonly used modules
PerlModule Apache2::Request
PerlModule Apache2::RequestRec
PerlModule Apache2::RequestIO
PerlModule Apache2::Connection

# Startup script for initializing
# PerlRequire /etc/httpd/conf.d/startup.pl

Create Perl Startup Script (mod_perl)

sudo vi /etc/httpd/conf.d/startup.pl

Add:

#!/usr/bin/perl
use strict;
use warnings;

# Preload modules
use DBI;
use CGI;
use JSON;

# Set environment variables
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;

1; # Must return true

Set Permissions

sudo chmod 644 /etc/httpd/conf.d/startup.pl

7. Testing the Installation

Create Test CGI Script

sudo vi /var/www/cgi-bin/test.cgi

Add the following:

#!/usr/bin/perl
use strict;
use warnings;
use CGI;

my $cgi = CGI->new;

print $cgi->header('text/html');
print "<html>\n";
print "<head><title>Perl CGI Test</title></head>\n";
print "<body>\n";
print "<h1>Perl CGI is Working!</h1>\n";
print "<p>Perl Version: $]</p>\n";
print "<p>Server Time: " . scalar(localtime) . "</p>\n";

# Test DBI
eval {
    require DBI;
    print "<p>✓ DBI module loaded</p>\n";
};
print "<p>✗ DBI module not available: $@</p>\n" if $@;

# Test CGI::Session
eval {
    require CGI::Session;
    print "<p>✓ CGI::Session module loaded</p>\n";
};
print "<p>✗ CGI::Session module not available: $@</p>\n" if $@;

print "<h2>Environment Variables</h2>\n";
print "<pre>\n";
foreach my $key (sort keys %ENV) {
    print "$key = $ENV{$key}\n";
}
print "</pre>\n";

print "</body></html>\n";

Set Execute Permissions

sudo chmod 755 /var/www/cgi-bin/test.cgi

# Verify shebang line
head -1 /var/www/cgi-bin/test.cgi
# Should show: #!/usr/bin/perl

# Test syntax
perl -c /var/www/cgi-bin/test.cgi
# Should show: syntax OK

Test Database Connection

sudo vi /var/www/cgi-bin/dbtest.cgi

Add:

#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use DBI;

my $cgi = CGI->new;

print $cgi->header('text/html');
print "<html><head><title>Database Test</title></head><body>\n";
print "<h1>MySQL/MariaDB Connection Test</h1>\n";

# Update these with your actual database credentials
my $dsn = "DBI:mysql:database=mysql;host=localhost";
my $username = "root";
my $password = "your_password";

eval {
    my $dbh = DBI->connect($dsn, $username, $password, {
        RaiseError => 1,
        PrintError => 0,
    });
    
    print "<p style='color: green;'>✓ Database connection successful!</p>\n";
    
    # Get MySQL version
    my $sth = $dbh->prepare("SELECT VERSION()");
    $sth->execute();
    my ($version) = $sth->fetchrow_array();
    print "<p>MySQL Version: $version</p>\n";
    
    $dbh->disconnect();
};

if ($@) {
    print "<p style='color: red;'>✗ Database connection failed: $@</p>\n";
}

print "</body></html>\n";
sudo chmod 755 /var/www/cgi-bin/dbtest.cgi

Restart Apache and Test

# Check Apache configuration
sudo httpd -t
# or
sudo apache2ctl configtest

# Restart Apache
sudo systemctl restart httpd
# or
sudo systemctl restart apache2

# Check Apache status
sudo systemctl status httpd

# Test in browser or with curl
curl http://localhost/cgi-bin/test.cgi

# Or open in browser
# http://your-server-ip/cgi-bin/test.cgi

8. Security Configurations

SELinux Contexts (Red Hat/CentOS)

# Set proper SELinux contexts
sudo semanage fcontext -a -t httpd_sys_script_exec_t "/var/www/cgi-bin(/.*)?"
sudo restorecon -Rv /var/www/cgi-bin/

# Allow Apache to connect to network (if needed)
sudo setsebool -P httpd_can_network_connect 1

# Allow Apache to connect to database
sudo setsebool -P httpd_can_network_connect_db 1

File Permissions Best Practices

# CGI scripts should be:
# - Owned by root or apache user
# - Executable (755)
# - NOT writable by web server

sudo chown root:apache /var/www/cgi-bin/*.cgi
sudo chmod 755 /var/www/cgi-bin/*.cgi

# Directory permissions
sudo chmod 755 /var/www/cgi-bin

Apache Security Directives

Add to your Perl configuration:

<Directory "/var/www/cgi-bin">
    # Prevent .htaccess overrides
    AllowOverride None
    
    # Disable directory listing
    Options -Indexes +ExecCGI
    
    # Disable following symlinks (security)
    Options -FollowSymLinks
    
    # Limit request methods
    <LimitExcept GET POST>
        Require all denied
    </LimitExcept>
    
    # Hide Perl version in errors
    PerlOptions -SetupEnv
</Directory>

Perl Security Best Practices

Always use in your Perl scripts:

Example Secure CGI Script

#!/usr/bin/perl -T
use strict;
use warnings;
use CGI;
use DBI;

# Taint mode enabled with -T flag
$ENV{PATH} = '/bin:/usr/bin';  # Secure PATH
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};  # Clean environment

my $cgi = CGI->new;
my $user_input = $cgi->param('name') || '';

# Validate input (untaint)
if ($user_input =~ /^([\w\s]{1,50})$/) {
    $user_input = $1;  # Untainted
} else {
    die "Invalid input";
}

# Use parameterized queries
my $dbh = DBI->connect($dsn, $user, $pass, {RaiseError => 1});
my $sth = $dbh->prepare("SELECT * FROM users WHERE name = ?");
$sth->execute($user_input);  # Safe from SQL injection

# ... rest of script

9. Troubleshooting

Common Issues and Solutions

Problem Possible Cause Solution
500 Internal Server Error Syntax error in script perl -c script.cgi
Script downloads instead of executing Handler not configured Check AddHandler directive
Permission denied Wrong file permissions chmod 755 script.cgi
Bad interpreter Wrong shebang line Use #!/usr/bin/perl
Module not found Missing CPAN module sudo cpanm Module::Name
SELinux blocking Incorrect context Check audit.log, adjust contexts

Check Apache Error Logs

# Red Hat/CentOS
sudo tail -f /var/log/httpd/error_log

# Ubuntu/Debian
sudo tail -f /var/log/apache2/error.log

# Look for specific errors
sudo grep -i "perl\|cgi" /var/log/httpd/error_log

Test Perl Module Installation

# Check if module is installed
perl -MDBI -e 'print "DBI version: $DBI::VERSION\n"'

# List installed modules
cpan -l

# Or
perldoc -l DBI  # Shows path if installed

Debug CGI Scripts

# Run script from command line
cd /var/www/cgi-bin
perl -w test.cgi

# Run with taint checking
perl -Tw test.cgi

# Check for compilation errors
perl -c test.cgi

# Set CGI environment variable for testing
export REQUEST_METHOD=GET
perl test.cgi

Verify Apache Modules

# List loaded modules
httpd -M | grep -E "cgi|perl"
# or
apache2ctl -M | grep -E "cgi|perl"

# Should see:
# cgi_module (shared)
# perl_module (shared)

Quick Reference Commands

# Check Perl version
perl -v

# Install CPAN module
sudo cpanm Module::Name

# Test script syntax
perl -c script.pl

# Run script with warnings
perl -w script.pl

# Check module location
perldoc -l Module::Name

# Apache syntax check
httpd -t

# Restart Apache
sudo systemctl restart httpd

# View Apache errors
sudo tail -f /var/log/httpd/error_log

# Check SELinux denials
sudo ausearch -m avc -ts recent

✓ Installation Complete!

Your LAMP stack with Perl is now fully configured. You have:

Next Steps:

  1. Test with provided example scripts
  2. Create your first Perl web application
  3. Review security configurations for production
  4. Consider using modern frameworks like Mojolicious or Dancer2

LAMP Stack - Perl Configuration Guide
For use with Apache HTTPD and MySQL/MariaDB

← Back to LAMPS Index ↑ Back to EXPANDED