How to Enable Server-Side Scripting in Apache

How to enable server-side scripting in Apache

How to enable server-side scripting in Apache

When I first started managing servers, the idea of “server-side scripting” felt abstract until I actually enabled it and watched a static HTML page turn into something that could talk to a database. In this guide, I’ll explain what server-side scripting means in the context of Apache, and walk through enabling it for the most common languages, along with the configuration details that trip people up.

What Is Server-Side Scripting?

Server-side scripting means running code on the web server before the response is sent to the browser, rather than in the visitor’s browser (which is client-side scripting, like JavaScript running in Chrome). Common server-side languages include PHP, Python, Perl, and Ruby.

Apache doesn’t execute these languages natively. Instead, it relies on modules or protocols to hand off requests to an interpreter:

This guide covers the general mechanism and setup for CGI and FastCGI, since those are the foundation most language-specific guides (PHP, Python, Ruby) build on. For deep dives into specific stacks, see our companion articles on PHP and Python with Apache.

Prerequisites

Enabling CGI Scripting (The Foundation)

CGI (Common Gateway Interface) is the original method for server-side scripting and still useful for simple scripts or legacy systems.

Step 1: Enable mod_cgi

Debian/Ubuntu (using the threaded mpm_event, use mod_cgid instead):

sudo a2enmod cgid
sudo systemctl restart apache2

CentOS/RHEL:

LoadModule cgid_module modules/mod_cgid.so

Step 2: Designate a CGI Directory

Edit your virtual host configuration:

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/example.com/public_html

    ScriptAlias /cgi-bin/ /var/www/example.com/cgi-bin/

    <Directory "/var/www/example.com/cgi-bin">
        AllowOverride None
        Options +ExecCGI
        Require all granted
        AddHandler cgi-script .cgi .pl .py
    </Directory>
</VirtualHost>

Step 3: Write a Test Script

sudo mkdir -p /var/www/example.com/cgi-bin
sudo nano /var/www/example.com/cgi-bin/test.cgi
#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "<html><body><h1>CGI is working!</h1></body></html>";

Make it executable:

sudo chmod +x /var/www/example.com/cgi-bin/test.cgi

Restart Apache and visit http://example.com/cgi-bin/test.cgi to confirm it works.

Enabling FastCGI (Modern, Recommended Approach)

FastCGI keeps interpreter processes running persistently instead of starting a new process per request, which is dramatically faster under load. This is the backbone of modern PHP-FPM and many Python deployments.

Step 1: Enable Proxy and FastCGI Modules

sudo a2enmod proxy
sudo a2enmod proxy_fcgi
sudo a2enmod setenvif
sudo systemctl restart apache2

Step 2: Configure a FastCGI Handler

Example configuration pointing to a FastCGI process listening on a Unix socket (this pattern applies whether the backend is PHP-FPM, a Python WSGI server behind FastCGI, or similar):

<FilesMatch "\.php$">
    SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost/"
</FilesMatch>

This exact pattern is explored in depth in our PHP-specific guide, since PHP-FPM is the most common real-world use of FastCGI with Apache.

Real-World Use Cases

Common Mistakes to Avoid

  1. Forgetting +ExecCGI or the correct SetHandler – Without explicitly allowing script execution, Apache will serve the raw script source code instead of running it, which is both a functionality bug and a security risk.
  2. Incorrect file permissions – Scripts need execute permissions (chmod +x) for CGI; FastCGI sockets need correct ownership matching the Apache/FPM user.
  3. Mixing mod_php and PHP-FPM – Running both simultaneously can cause confusing behavior; pick one approach per site.
  4. Not restarting after enabling modules – Module changes require a full restart, not just a reload, in some cases.
  5. Leaving default/test scripts accessible in production – Test CGI scripts left in place can become an attack surface.

Security Best Practices

Performance Optimization Tips

Troubleshooting

“Internal Server Error” (500):

Script downloads instead of executing:

“Premature end of script headers”:

FastCGI socket connection errors:

Frequently Asked Questions

What’s the difference between CGI and FastCGI? CGI spawns a new process for every request, which is simple but slow. FastCGI keeps a pool of persistent processes running, dramatically reducing overhead per request.

Do I need mod_cgi if I’m using PHP-FPM? No. PHP-FPM uses mod_proxy_fcgi, not classic CGI. mod_cgi is only needed for traditional CGI scripts (Perl, Python scripts written as standalone CGI programs, shell scripts, etc.).

Is server-side scripting a security risk by itself? Not inherently, but misconfigured scripting handlers (enabling execution in upload directories, running as root, outdated interpreters) are among the most common causes of server compromise.

Can I run multiple languages on the same Apache server? Yes. It’s common to run PHP-FPM for one site and a Python WSGI app (via mod_wsgi or a reverse-proxied app server) for another, all behind the same Apache instance using separate virtual hosts.

Summary and Key Takeaways

References

Exit mobile version