How to execute CGI scripts using fcgiwrap

I am enthusiast of the uWSGI project, but you are not limited to it as you can use fcgiwrap a very lightweight and simple FastCGI wrapper for CGI scripts that does not require additional configuration.

CGI script
Sample output of the CGI script

Install FastCGI wrapper

Install fcgiwrap package.

$ sudo apt-get install fcgiwrap

Service will be started immidiately.

$ systemctl status fcgiwrap.service 
● fcgiwrap.service - Simple CGI Server
   Loaded: loaded (/lib/systemd/system/fcgiwrap.service; indirect; vendor preset: enabled)
   Active: active (running) since Sun 2017-09-03 07:32:22 CDT; 3 days ago
 Main PID: 820 (fcgiwrap)
    Tasks: 1 (limit: 4915)
   CGroup: /system.slice/fcgiwrap.service
           └─820 /usr/sbin/fcgiwrap -f
$ systemctl status fcgiwrap.socket 
● fcgiwrap.socket - fcgiwrap Socket
   Loaded: loaded (/lib/systemd/system/fcgiwrap.socket; enabled; vendor preset: enabled)
   Active: active (running) since Sun 2017-09-03 07:32:22 CDT; 26min ago
   Listen: /run/fcgiwrap.socket (Stream)

Service will be automatically configured to start at boot.

$ systemctl is-enabled fcgiwrap.service 
indirect
$ systemctl is-enabled fcgiwrap.socket 
enabled

systemd unit configuration files are very simple and straightforward.

$ cat /lib/systemd/system/fcgiwrap.socket 
[Unit]
Description=fcgiwrap Socket

[Socket]
ListenStream=/run/fcgiwrap.socket

[Install]
WantedBy=sockets.target
$ cat /lib/systemd/system/fcgiwrap.service 
[Unit]
Description=Simple CGI Server
After=nss-user-lookup.target
Requires=fcgiwrap.socket

[Service]
Environment=DAEMON_OPTS=-f
EnvironmentFile=-/etc/default/fcgiwrap
ExecStart=/usr/sbin/fcgiwrap ${DAEMON_OPTS}
User=www-data
Group=www-data

[Install]
Also=fcgiwrap.socket

Read fcgiwrap manual page to define or modify number processes to prefork and an URL for the listen socket to bind to.

Install and configure nginx

Install nginx package.

$ sudo apt-get install --no-install-recommends nginx

Disable default nginx site.

$ sudo unlink /etc/nginx/sites-enabled/default

Use single CGI script

Create document root directory.

$ sudo mkdir -p /var/www/localhost/

Define owner and group for the document root directory.

$ sudo chown www-data:www-data /var/www/localhost/

Create CGI script.

$ cat << EOF | sudo tee /var/www/localhost/index.cgi
#!/bin/bash

echo "Content-type: text/html"
echo ""

echo "<html>"
echo "<head>"
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
echo "<title>Bash CGI script</title>"
echo "</head>"
echo "<body>"
echo "<p>Hello, Your IP address is \$REMOTE_ADDR</p>"
echo "<pre>"
env
echo "</pre>"
echo "</body>"
echo "</html>"

exit 0
EOF

Define owner and group for the created CGI script.

$ sudo chown www-data:www-data /var/www/localhost/index.cgi

Set executable bit.

$ sudo chmod +x /var/www/localhost/index.cgi

Prepare nginx virtual host configuration.

$ cat << EOF | sudo tee /etc/nginx/sites-available/cgi.example.org
server {
  listen 80 default_server;
  server_name default;

  location / {
    index index.cgi;
    root /var/www/localhost;
  }

  location /index.cgi {
    root /var/www/localhost;

    fastcgi_intercept_errors on;
    include fastcgi_params;

    #fastcgi_param DOCUMENT_ROOT \$document_root;
    #fastcgi_param SCRIPT_NAME   \$fastcgi_script_name;
    fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;

    fastcgi_pass unix:/var/run/fcgiwrap.socket;
  }
}
EOF

Enable virtual host.

$ sudo ln -s /etc/nginx/sites-available/cgi.example.org /etc/nginx/sites-enabled/

Reload HTTP server configuration.

$ sudo systemctl reload nginx

Open web browser and point to the configured HTTP server.

Use multiple CGI scripts

Create cgi-bin directory.

$ sudo mkdir -p /usr/lib/cgi-bin

Define owner and group for the cgi-bin directory.

$ sudo chown www-data:www-data /usr/lib/cgi-bin

Create CGI script.

$ cat << EOF | sudo tee /usr/lib/cgi-bin/bashcgiscript.cgi
#!/bin/bash

echo "Content-type: text/html"
echo ""

echo "<html>"
echo "<head>"
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
echo "<title>Bash CGI script</title>"
echo "</head>"
echo "<body>"
echo "<p>Hello, Your IP address is \$REMOTE_ADDR</p>"
echo "<pre>"
env
echo "</pre>"
echo "</body>"
echo "</html>"

exit 0
EOF

Define owner and group for the created CGI script.

$ sudo chown www-data:www-data /usr/lib/cgi-bin/bashcgiscript.cgi

Set executable bit.

$ sudo chmod +x /usr/lib/cgi-bin/bashcgiscript.cgi

Copy default nginx configuration for the /cgi-bin/ location.

$ sudo cp /usr/share/doc/fcgiwrap/examples/nginx.conf /etc/nginx/fcgiwrap.conf

Prepare nginx virtual host configuration.

$ cat << EOF | sudo tee /etc/nginx/sites-available/cgi.example.org
server {
  listen 80 default_server;
  server_name default;

  include fcgiwrap.conf;

  location / {
    index index.html;
    root  /var/www/;
  }
}
EOF

Enable virtual host.

$ sudo ln -s /etc/nginx/sites-available/cgi.example.org /etc/nginx/sites-enabled/

Reload HTTP server configuration.

$ sudo systemctl reload nginx

Open web browser and point to the /cgi-bin/bashcgiscript.cgi CGI script on the configured HTTP server.

Additional notes

This is default configuration of the cgi-bin location used in the previous example.

$ cat /usr/share/doc/fcgiwrap/examples/nginx.conf
# Include this file on your nginx.conf to support debian cgi-bin scripts using
# fcgiwrap
location /cgi-bin/ { 
  # Disable gzip (it makes scripts feel slower since they have to complete
  # before getting gzipped)
  gzip off;

  # Set the root to /usr/lib (inside this location this means that we are
  # giving access to the files under /usr/lib/cgi-bin)
  root	/usr/lib;

  # Fastcgi socket
  fastcgi_pass  unix:/var/run/fcgiwrap.socket;

  # Fastcgi parameters, include the standard ones
  include /etc/nginx/fastcgi_params;

  # Adjust non standard parameters (SCRIPT_FILENAME)
  fastcgi_param SCRIPT_FILENAME  /usr/lib$fastcgi_script_name;
}

References

Milosz Galazka's Picture

About Milosz Galazka

Milosz is a Linux Foundation Certified Engineer working for a successful Polish company as a system administrator and a long time supporter of Free Software Foundation and Debian operating system.

Gdansk, Poland https://sleeplessbeastie.eu