Logo

dev-resources.site

for different kinds of informations.

Generate server block (virtual hosts) for nginx dynamically

Published at
1/17/2022
Categories
nginx
pm2
devops
Author
eichgi
Categories
3 categories in total
nginx
open
pm2
open
devops
open
Author
6 person written this
eichgi
open
Generate server block (virtual hosts) for nginx dynamically

Hey pals, I will show you how to create a basic shell script so you can dynamically generate nginx virtual hosts or "subdomains" for every site you want to put online. There are two examples, one for your node or whatever app that runs locally, the second is for static websites.

Reversed proxy subdomain example

If you are running a node app on a specific port this basic example will help you to create and connect your site. The following is the stub file we will use subdomain.stub:

server {
        listen 80;
        listen [::]:80;

        index index.html index.htm;

        server_name {{DOMAIN}}.yoursite.com;

        location / {
                proxy_pass http://localhost:{{PORT}};
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }
}
Enter fullscreen mode Exit fullscreen mode

Now let's create the generator.sh shell script:

#!/bin/bash

SED=$(which sed)
CURRENT_DIR=$(dirname $0)

# check the domain is valid!
PATTERN="^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$"
if [[ "$1" =~ $PATTERN ]]; then
  DOMAIN=$(echo $1 | tr '[A-Z]' '[a-z]')
  echo "Creating hosting for:" $DOMAIN
else
  echo "invalid domain name"
  exit 1
fi

CONFIG="$CURRENT_DIR/$DOMAIN.yoursite.com"
cp $CURRENT_DIR/subdomain.stub $CONFIG
$SED -i "s/{{DOMAIN}}/$DOMAIN/g" $CONFIG
$SED -i "s/{{PORT}}/$2/g" $CONFIG

echo "The subdomain has been successfully generated"

cp $CONFIG "/etc/nginx/sites-available"
ln -s "/etc/nginx/sites-available/$DOMAIN.yoursite.com" "/etc/nginx/sites-enabled"

echo "The subdomain has been moved to nginx to sites-available and symlinked to sites-enabled"
Enter fullscreen mode Exit fullscreen mode

In your terminal you run the command as follows: ./generator.sh DOMAIN PORT

In order to run this script you have to make it executable with this command: chmod u+x generator.sh otherwise you won't be able to execute it.

Now it's ready to run, let me explain what it does:

  • Stores SED as a variable
  • Stores the current location
  • Creates a domain pattern and the compares it with the 1st parameter (DOMAIN)
  • Defines CONFIG location, then clones the subdomain.stub file into the previous definition
  • Replaces the {{DOMAIN}} value inside the cloned configuration
  • Replaces the {{PORT}} value inside the cloned configuration

At this point our virtual host is ready to be published

  • Copies the new virtual host file into "/etc/nginx/sites-available" which is the folder for every available site in nginx
  • Then creates a symlink from the previous location to /etc/nginx/sites-enabled which is the folder for every enabled site in nginx

Once this is done you need to ensure virtual hosts definitions are valid. You can do this by running nginx -t in your terminal. If everything went well now you only need to reload/restart nginx so changes can be applied. nginx service reload/restart.

Static site subdomain example

This example is for static websites (not SSR)

subdmain.stub:

server {
        listen 80;
        listen [::]:80;

        root /var/www/{{DOMAIN}};
        index index.html index.htm index.nginx-debian.html;

        server_name {{DOMAIN}}.yoursite.com;

        location / {
                try_files $uri $uri/ /index.html = 404; #This line redirects to index for correct react router usage
        }
}
Enter fullscreen mode Exit fullscreen mode

Then we use basically the same generator.sh script than before:

#!/bin/bash

SED=$(which sed)
CURRENT_DIR=$(dirname $0)

# check the domain is valid!
PATTERN="^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$"
if [[ "$1" =~ $PATTERN ]]; then
  DOMAIN=$(echo $1 | tr '[A-Z]' '[a-z]')
  echo "Creating hosting for:" $DOMAIN
else
  echo "invalid domain name"
  exit 1
fi

CONFIG="$CURRENT_DIR/$DOMAIN.yoursite.com"
cp $CURRENT_DIR/subdomain.stub $CONFIG
$SED -i "s/{{DOMAIN}}/$DOMAIN/g" $CONFIG

echo "The subdomain has been successfully generated"

cp $CONFIG "/etc/nginx/sites-available"
ln -s "/etc/nginx/sites-available/$DOMAIN.yoursite.com" "/etc/nginx/sites-enabled"

echo "The subdomain has been moved to nginx to sites-available and symlinked to sites-enabled"
Enter fullscreen mode Exit fullscreen mode

The only difference is that we no longer require a PORT, so you will run the command like this: ./generator.sh ${DOMAIN} (Do not forget to make the script executable)

From here the sky is the limit my friend, you could easily create your own stubs/snippets with many variables as needed. Also they only contain the minimum requirements to be served by nginx, have fun adding more specifications.

BONUS!! ๐Ÿคฏ

If you read my previous post Easy node apps deployment with PM2 let me show you how you could integrate this virtual host generator to a pm2 deployment set up file ecosystem.config.js:

module.exports = {
  deploy: {
    production: {
      user: USER,
      host: HOST,
      ref: BRANCH,
      repo: REPO,
      path: PATH,
      'post-setup': `npm install && cd setup/ && chmod u+x generator.sh && ./generator.sh ${DOMAIN}`
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Now you only have to create a /setup folder inside your project with the subdomain stub as well as the generator script and that's it. Ready to be executed after setup.

pm2 Article's
30 articles in total
Favicon
Deploy NestJS and NextJS application in same server using pm2 and Nginx
Favicon
Guia de Comandos PM2
Favicon
๐Ÿš€ Deploying Node.js Application with PM2, NGINX, and SSL Configuration ๐Ÿš€
Favicon
Monitoring PM2 in production
Favicon
Mastering PM2: Optimizing Node.js and Next.js Applications for Performance and Scalability
Favicon
Setting Up PM2 for Multi-User Access on Ubuntu Instance
Favicon
Manual deployment of NestJS and Angular applications on a dedicated server via "Docker Compose" and "PM2"
Favicon
Build applications on NestJS and Angular and run them in two versions: via PM2 and via Docker Compose
Favicon
An example of a simple update of NestJS-mod libraries
Favicon
Using pm2 to Manage Node.js Applications
Favicon
Using Screen and PM2 for Deploying, Debugging, and Running NestJS in Production
Favicon
Host Multiple Node Apps with nginx, pm2 with SSL certificate
Favicon
Node.js PM2 Orchestration Explained
Favicon
Managing Logs with PM2 and pm2-logrotate
Favicon
Streamlining PM2 Startup for Node.js Applications: A Comprehensive Guide
Favicon
Managing Next.js and NestJS Applications in Production with PM2
Favicon
Deploy a Full Stack Web App to VPS Server with NGINX andย PM2!
Favicon
Como utilizar o PM2 para gerenciar aplicaรงรตes
Favicon
Guide to Running a Node Server in Nx Monorepo using PM2 Process Manager
Favicon
How to run old nodejs Project into new nodejs project
Favicon
CentOS 7 NodeJS Kurulumu
Favicon
How to start node.js app with pm2
Favicon
How to start node.js app with pm2
Favicon
Deploying Multiple NodeJS Servers on a Single DigitalOcean Droplet; Managed by PM2, Without Using an ecosystem.config.js file
Favicon
Automatic deploys with PM2, Caddy, and GitHub Actions
Favicon
Utilizando PM2 (Basico)
Favicon
Experience on PM2 Tricks to manage your NodeJs processes
Favicon
Deploy Nest JS App using PM2 on Linux (Ubuntu) Server
Favicon
Install PM2 (Process Manager 2)
Favicon
Generate server block (virtual hosts) for nginx dynamically

Featured ones: