{"id":336,"date":"2026-10-13T16:21:10","date_gmt":"2026-10-13T16:21:10","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2013\/05\/17\/introduction-of-cgi\/"},"modified":"2026-10-13T16:21:10","modified_gmt":"2026-10-13T16:21:10","slug":"introduction-of-cgi","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/introduction-of-cgi\/","title":{"rendered":"Common Gateway Interface (CGI): How It Works, Server Requirements, and Basic Setup"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Common Gateway Interface (CGI) is a standard way for a web server to run a program and return that program\u2019s output as an HTTP response. This is most useful for engineers maintaining legacy systems, troubleshooting old form handlers, or learning how server-side execution works at a low level.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This article is a technical revision of the original post: <a href=\"https:\/\/www.devopsschool.com\/blog\/introduction-of-cgi\/\">Introduction of CGI | What is Common Gateway Interface (CGI)?<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Originally published on 2013-05-17; fully revised and updated.<\/em><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2013\/05\/cgi-introduction.png\" alt=\"CGI introduction\" width=\"600\" height=\"400\"\/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">What CGI is<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CGI<\/strong> stands for <strong>Common Gateway Interface<\/strong>. It defines how a web server passes request data to an external program and how that program returns response data back to the server.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>CGI programs run on the server, not in the browser.<\/li><li>They can be written in multiple languages (for example Perl, PHP, shell, C\/C++), as long as the runtime is available on the server.<\/li><li>A CGI program receives request context through environment variables and may receive request body data through standard input (STDIN).<\/li><li>The CGI program must output valid HTTP headers (such as <code>Content-Type<\/code>) before the response body.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites before you deploy CGI scripts<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>A web server that allows CGI execution.<\/li><li>Access to server logs for debugging.<\/li><li>Basic experience in at least one scripting\/programming language.<\/li><li>Knowledge of HTTP headers and request methods.<\/li><li>For local practice: a local stack such as WAMP or XAMPP can be used if CGI execution is enabled.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Server requirements and environment differences<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">CGI behavior depends on server configuration. The core idea is the same everywhere, but handler mapping, file extensions, and permissions vary by platform.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Environment<\/th><th>Typical CGI setup<\/th><th>What to verify first<\/th><\/tr><\/thead><tbody><tr><td>Unix\/Linux with Apache<\/td><td>Enable CGI execution and map script extensions (for example <code>.cgi<\/code>, <code>.pl<\/code>)<\/td><td>Executable permission (often 755), correct interpreter path, Apache error log access<\/td><\/tr><tr><td>Windows-based hosting\/servers<\/td><td>Handler mapping by extension (for example <code>.pl<\/code>, <code>.php<\/code>, <code>.asp<\/code>, <code>.aspx<\/code>)<\/td><td>Language runtime availability, handler mapping rules, error log visibility<\/td><\/tr><tr><td>Local lab (WAMP\/XAMPP)<\/td><td>Use bundled web stack for testing scripts locally<\/td><td>CGI module\/handler enabled, correct file location, local execution permissions<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">How CGI request and response flow works<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The web server sits between the browser and the CGI program. It passes request details to the script and forwards script output back to the client.<\/p>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Browser sends HTTP request] --> B[Web server receives request]\n    B --> C{Target is CGI script?}\n    C -- no --> D[Serve normal content]\n    C -- yes --> E[Start CGI process]\n    E --> F[Pass environment and body data]\n    F --> G[CGI writes headers and body]\n    G --> H[Server returns HTTP response]\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Minimal CGI example and basic setup checks<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1) Example CGI script (Bash)<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\">#!\/usr\/bin\/env bash<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Content-Type: text\/plain\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"Hello from CGI\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"REQUEST_METHOD=$REQUEST_METHOD\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"QUERY_STRING=$QUERY_STRING\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">2) Make it executable and test it<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">chmod <span class=\"hljs-number\">755<\/span> hello.cgi\ncurl -i <span class=\"hljs-string\">\"http:\/\/localhost\/cgi-bin\/hello.cgi?name=devops\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">3) Example Apache directives often used for CGI<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Exact directives depend on host policy and Apache layout, but these are common patterns seen in CGI setups:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css language-apache\"><span class=\"hljs-selector-tag\">Options<\/span> +<span class=\"hljs-selector-tag\">ExecCGI<\/span>\n<span class=\"hljs-selector-tag\">AddHandler<\/span> <span class=\"hljs-selector-tag\">cgi-script<\/span> <span class=\"hljs-selector-class\">.cgi<\/span> <span class=\"hljs-selector-class\">.pl<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting checklist<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Check server error logs first; CGI failures are usually visible there.<\/li><li>Confirm the script has executable permission where required.<\/li><li>Confirm the script extension matches configured handler rules.<\/li><li>Verify the interpreter path (shebang) is valid on the server.<\/li><li>Ensure the script prints headers correctly (at minimum <code>Content-Type<\/code> and a blank line after headers).<\/li><li>Test with a very small script before adding application logic.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Common pitfalls and best practices<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Pitfall:<\/strong> assuming CGI is enabled by default. <strong>Best practice:<\/strong> verify module\/handler configuration explicitly.<\/li><li><strong>Pitfall:<\/strong> weak visibility into failures. <strong>Best practice:<\/strong> require access to web server and CGI logs before deployment.<\/li><li><strong>Pitfall:<\/strong> environment-specific assumptions. <strong>Best practice:<\/strong> document per-server requirements (extensions, permissions, runtime paths).<\/li><li><strong>Pitfall:<\/strong> jumping into full app debugging first. <strong>Best practice:<\/strong> start from a minimal known-good CGI script and iterate.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>CGI is the classic interface that lets a web server execute server-side programs in response to HTTP requests. This revised guide covers CGI fundamentals, server prerequisites, setup checks, and a minimal working example.<\/p>\n","protected":false},"author":1,"featured_media":3777,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[2372,2377,2369,2371,2370,2373,2376,2379,2375,719,2378,2374],"class_list":["post-336","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorised","tag-about-cgi","tag-about-common-gateway-interface","tag-cgi","tag-cgi-introduction","tag-cgi-overview","tag-common-gateway-interface","tag-introduction-of-common-gateway-interface","tag-know-about-cgi","tag-servers","tag-start","tag-understand-cgi","tag-what-is-cgi"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/336","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=336"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/336\/revisions"}],"predecessor-version":[{"id":79206,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/336\/revisions\/79206"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/3777"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=336"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}