 |
|
| |
| Introduction
| |
The Common Gateway Interface (CGI) is the original standard for making a web server produce
dynamic content. Instead of returning a static file, the server runs a program for each request and sends
back whatever that program prints. A CGI script can be written in any language — Perl, Python, a
shell, or a compiled binary — as long as it is executable and emits a proper HTTP header. Both
FreeBSD 15 and Rocky Linux 10 support CGI through
Apache.
CGI is simple and universal, which is why it endures for small utilities and legacy tools. Busier
applications today usually run through a persistent process such as
PHP-FPM or an application server,
because a CGI program starts a fresh process on every request and so does not scale well. This page enables
CGI, walks through installing a script, and lists the classic ready-made CGI programs.
| |
| Enabling CGI in Apache
| |
Apache runs CGI through mod_cgi (or mod_cgid when the threaded event MPM is in
use) — see the Dynamic Modules
section. Both systems already ship a cgi-bin directory wired up with a ScriptAlias, so any
executable script you drop into it is treated as a CGI program automatically:
# FreeBSD (already present in httpd.conf)
ScriptAlias "/cgi-bin/" "/usr/local/www/apache24/cgi-bin/"
# Rocky Linux (already present in httpd.conf)
ScriptAlias "/cgi-bin/" "/var/www/cgi-bin/"
To run CGI scripts from an ordinary content directory instead — so a .cgi or .pl
file executes in place — add ExecCGI to that directory’s Options and map the
extensions to the CGI handler:
<Directory "/usr/local/www/apache24/data/scripts">
Options +ExecCGI
AddHandler cgi-script .cgi .pl
</Directory>
Place that in an Includes/ (FreeBSD) or conf.d/ (Rocky Linux) file, then test and reload
— apachectl configtest && service apache24 reload on FreeBSD,
apachectl configtest && systemctl reload httpd on Rocky Linux.
| |
| Installing and Running a Script
| |
A CGI program needs three things: a shebang line naming its interpreter, the executable
bit, and a valid HTTP header at the start of its output. A minimal Perl example, saved as
cgi-bin/hello.cgi:
#!/usr/bin/perl
print "Content-Type: text/html\n\n";
print "<h1>Hello from CGI</h1>\n";
Make it executable, then request it:
# chmod 755 hello.cgi
$ curl https://your-domain.example/cgi-bin/hello.cgi
A few things trip people up:
The blank line after the Content-Type header is required — without it Apache
logs “malformed header from script.”
Transfer scripts so Unix line endings are preserved (see
SFTP/FTP). A Windows CR/LF on the
shebang line is the classic cause of a “Premature end of script headers” or 500 error.
Match the shebang to your system: Perl is /usr/local/bin/perl on FreeBSD but
/usr/bin/perl on Rocky Linux; Python is /usr/local/bin/python3 versus
/usr/bin/python3.
On Rocky Linux, scripts under /var/www/cgi-bin are already SELinux-labeled to run.
In a custom directory you must label them yourself:
semanage fcontext -a -t httpd_sys_script_exec_t '/path(/.*)?' then
restorecon -Rv /path.
When a script misbehaves, run it from the shell first to catch syntax errors, then check Apache’s
error log for the exact failure.
| |
| Securing CGI Scripts
| |
A CGI program runs on your server with the web user’s privileges, so treat every byte of input as
hostile:
|
WARNING: Never pass form input straight to a shell or to system() / backticks;
if you must call an external command, use a list form and validate every argument. Constrain
and validate all fields, rejecting anything unexpected. In Perl, run under taint mode
(#!/usr/bin/perl -T), which forces you to launder external input before using it. Keep
scripts small, delete ones you no longer use — a forgotten CGI is a classic break-in
vector — and prefer maintained software to copy-pasted scripts of unknown origin. See
Securing Your VPS.
|
| |
| Ready-Made Scripts: Modern Alternatives
| |
A library of ready-made CGI scripts — canned form-mailers, hit counters, guestbooks, message
boards, site search, and the like — was once offered for customers to drop in. Those classics
(FormMail, WWWBoard, Count, SWISH-E, and the rest) are decades old, unmaintained, and carry well-known
security holes, so they are no longer provided. Meet the same needs with maintained software instead:
Forms and contact pages: use a maintained mail handler or your application’s own
form processing — not the old FormMail, which was widely abused as a spam relay.
Site search: use a current search engine, or your CMS’s built-in search.
Password-protected directories: use Apache Basic authentication with htpasswd
(see Apache).
Forums, guestbooks, and visitor counters: use maintained CMS or forum software such as
WordPress, and read traffic
from your logs with Analog
rather than an inline hit counter.
Image manipulation: ImageMagick is still actively developed — install it with
pkg or dnf and call it from your own scripts.
| |
| Documentation
| |
|
Toll Free 1-866-GSP-4400 • 1-301-464-9363 • service@gsp.com
Copyright © 1994-2026 GSP Services, Inc.
|