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
# 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
# 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
perl -v # Should show Perl version (typically 5.x) which perl # Should show /usr/bin/perl perldoc -l perl # Should show Perl documentation location
mod_perl embeds a Perl interpreter into Apache for better performance than CGI.
# 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)
# 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
# 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-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
# First-time CPAN configuration (as root) sudo cpan # Or use cpanminus (recommended - simpler) # Already installed via perl-App-cpanminus or cpanminus package
| 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 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
# Red Hat/CentOS sudo dnf install mysql-devel -y # or sudo dnf install mariadb-devel -y # Ubuntu/Debian sudo apt install libmysqlclient-dev -y
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
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
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
sudo chmod 644 /etc/httpd/conf.d/startup.pl
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";
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
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
# 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
# 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
# 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
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>
use strict; - Enforces variable declarationsuse warnings; - Shows potential problemsuse CGI; - Use CGI.pm for parameter handling (built-in taint checking)#!/usr/bin/perl -Tsystem() or exec() with user input#!/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
| 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 |
# 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
# 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
# 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
# List loaded modules httpd -M | grep -E "cgi|perl" # or apache2ctl -M | grep -E "cgi|perl" # Should see: # cgi_module (shared) # perl_module (shared)
# 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
Your LAMP stack with Perl is now fully configured. You have:
Next Steps:
LAMP Stack - Perl Configuration Guide
For use with Apache HTTPD and MySQL/MariaDB