Step 3: Scripting an Nginx Site

Objective: Create an Nginx site using a script.

Creating shell scripts are easy and useful! Let’s demonstrate how.

Note

These commands are from Nginx Quick References

Setting up the Script

  1. First, let’s create a scripts directory in our home folder. We can use this directory to store all of our scripts.

mkdir ~/scripts
  1. Next, we’ll create the file.

touch ~/scripts/create-nginx-reverse-proxy.sh
  1. Edit the file and add the shebang.

#!/bin/bash
  1. Let’s add a welcome message to the user. Not necessary, but a nice touch.

echo ""
echo "-----------------------------------"
echo "Welcome to our Nginx Site Builder!"
echo "-----------------------------------"
echo ""
  1. Execute the file to verify that it runs without errors.

Prompt the User

  1. Now, let’s prompt the user for some information.

    • Use your own domain name to personalize it.

Note

As a personal preference, I capitalize variables to identify them easily.

# Default values
FQD=sub.jj8i.cc
PORT=8888

#[] denotes the default value
read -r -p "Please enter the fully qualified name of the site [$FQD]: " RESPONSE
if [ -n "$RESPONSE" ]; then
    FQD=$RESPONSE
fi

read -r -p "Enter the port of the reverse proxy [$PORT]: " RESPONSE
if [ -n "$RESPONSE" ]; then
    PORT=$RESPONSE
fi

# Display output
echo ""
echo "Creating reverse proxy for $FQD -> localhost:$PORT"
echo ""
  1. Run the script to verify that it operates correctly before continuing.

Expected Output
----------------------------------
Welcome to our Nginx Site Builder!
----------------------------------

Please enter the fully qualified name of the site [sub.jj8i.cc]: test.jj8i.cc
Enter the port of the reverse proxy [8888]: 8901

Creating reverse proxy for test.jj8i.cc -> localhost:8901

root@vps298933:~/scripts#

Write the Site Data

  1. Now, let’s write the site to the configurations file and enable it.

Note

We have to escape the $ characters that are used in the Nginx config. Otherwise, Bash treats them as variables.

echo "
server {
    listen 80;

    server_name $FQD;

    location / {
        proxy_pass http://localhost:$PORT;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    }
}" > /etc/nginx/sites-available/$FQD

# Enable the site
ln -s /etc/nginx/sites-available/$FQD /etc/nginx/sites-enabled
  1. Next, we should ask the user to verify the config for errors before restarting Nginx.

    Note

    The if condition is true for any character except n or N.

echo ""
echo "Verifying config..."
echo ""

nginx -t

echo ""

read -r -p "Restart Nginx? ?[Y/n] " RESPONSE
if [[ ! $RESPONSE =~ ^[Nn]$ ]]
then
    systemctl restart nginx
else
    # Exit the script if "n" or "N".
    exit;
fi
  1. Prompt the user to encrypt the with SSL.

echo ""

read -r -p "Create SSL certificate? ?[Y/n] " RESPONSE
if [[ ! $RESPONSE =~ ^[Nn]$ ]]
then
    echo ""
    certbot --nginx -d $FQD
fi
  1. Lastly, we can verify that the site works.

echo ""
echo "Verifying site using curl --head http://$FQD"
echo ""
curl --head http://$FQD

Expected Output

-----------------------------------------------------------
Welcome to our Nginx Site Builder!
-----------------------------------------------------------

Please enter the fully qualified name of the site [sub.jj8i.cc]: test.jj8i.cc
Enter the port of the reverse proxy [8888]: 8899

Creating reverse proxy for test.jj8i.cc -> localhost:8899


Verifying config...

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Restart Nginx to enable config? ?[Y/n]

Create SSL certificate? ?[Y/n] n

Verifying site using curl --head http://test.jj8i.cc

HTTP/1.1 502 Bad Gateway
Server: nginx/1.14.0 (Ubuntu)
Date: Sat, 27 Apr 2019 03:28:42 GMT
Content-Type: text/html
Content-Length: 182
Connection: keep-alive

Wrap up

This script does most of the work for us and provides some user interaction. There are other tweaks that we could add to improve it.

This script adds complexity by prompting the user for input and providing some status output. That additional information is not necessary. You could omit the menu and use command-line arguments for the domain name and port.

A simpler script would accept the arguments from the command line, run the commands, and provide minimal output.

#!/bin/bash

# Verify that there are two arguments
if [[ $# -ne 2 ]]
then
    echo "Please provide two arguments: <domain name> <port>"
    exit
else
    FQD=$1
    PORT=$2
fi

echo "
server {
    listen 80;

    server_name $FQD;

    location / {
        proxy_pass http://localhost:$PORT;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
    }
}" > /etc/nginx/sites-available/$FQD

# Enable the site and restart
ln -s /etc/nginx/sites-available/$FQD /etc/nginx/sites-enabled
systemctl restart nginx

echo "Verifying site using curl --head http://$FQD"
curl --head http://$FQD
Output
root@vps298933:~/scripts# bash create-site.sh demo.jj8i.cc 8844
Verifying site using curl --head http://demo.jj8i.cc
HTTP/1.1 502 Bad Gateway
Server: nginx/1.14.0 (Ubuntu)
Date: Sat, 27 Apr 2019 03:51:29 GMT
Content-Type: text/html
Content-Length: 182
Connection: keep-alive