In this guide we will set up a way to execute BASH scripts with Nginx & fastcgi. After that we will make it update itself without reloading the page by using HTMX.

Setting it up

This method is tested on Debian 12.

Step 1: Install nginx and fastcgi

# apt install nginx fcgiwrap -y

Step 2: Modify your server config file

Usually it is located at /etc/nginx/sites-available/default.

server {
    listen 8088;
    server_name NAME;

    root /var/www/html;
    index index.html;

    location /cgi-bin/ {
        alias /usr/lib/cgi-bin/; # Default path for cgi scripts.
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib$fastcgi_script_name;
    }
}

After that, test the nginx config with:

# nginx -t

On success, restart the nginx system service:

# systemctl restart nginx

Step 3: Write your BASH script

Create a file in /usr/lib/cgi-bin. If the directory does not exist yet, create it with mkdir.

# nano /usr/lib/cgi-bin/script.sh

Example BASH script:

#!/bin/sh
        
echo "Content-Type: text/html"
echo ""
echo "<!DOCTYPE html>"
echo "<html lang="de">"
echo "<head>"
echo "  <meta charset="UTF-8">"
echo "  <title>Monitoring</title>"
echo "  <link rel="icon" type="image/x-icon" href="/assets/favicon.png">"
echo "  <style>"
echo "    body { font-family: Arial, sans-serif; color: #ffffff; background-color: #000000; }"
echo "    .section { margin-bottom: 20px; }"
echo "    .section h2 { margin: 0; }"
echo "    pre { color: #ffffff; font-size: 14px; white-space: pre-wrap; }"
echo "  </style>"
echo "</head>"
echo "<body>"

# RAM Usage
echo "<div class='section'>"
echo "<h2>RAM Usage:</h2>"
echo "<pre>"
echo "$(awk '/MemTotal/ {total=\$2} /MemAvailable/ {available=\$2} END {usage=((total-available)/total)*100; printf \"Percent: %.2f%%\\n\", usage}' /proc/meminfo)"
echo "$(awk '/MemTotal/ {total=\$2} /MemAvailable/ {available=\$2} END {printf \"MiB: %d / %d MiB\\n\", (total-available)/1024, total/1024}' /proc/meminfo)"
echo "</pre>"
echo "</div>"

# Uptime
echo "<div class='section'>"
echo "<h2>Uptime:</h2>"
echo "<pre>$(uptime -p | sed 's/up //')</pre>"
echo "</div>"

echo "</body>"
echo "</html>"

# Removing temporary files.
rm /tmp/stat1 /tmp/stat2

Important

Step 4: Start & enable fcgiwrap

# systemctl start fcgiwrap && systemctl enable fcgiwrap

Step 5: Testing

If you now enter the IPv4 address of your webserver into your browser and add /cgi-bin/script.sh at the end, you should see your script output.

Automating live updates with HTMX

HTMX setup

Edit your /var/www/html/index.html and add the following lines:

<script src="https://unpkg.com/[email protected]"></script>

Adding the auto-update div

Add this snippet inside your index.html:

<div hx-get="/cgi-bin/script.sh" hx-swap="innerHTML" hx-trigger="every 1s">
<!-- Script Content -->
</div>

Notes

This will create a div that reloads its content from the CGI script every one second without refreshing the whole page. You can change the interval if you want.

Info on CSS, title, etc: To change the title, favicon and CSS, you might have to edit the CGI script instead of relying solely on your index.html stylesheets.