How to make an NGinx server block: manually, or with a shell script

NGinx is really nice server, it's light and fast. Here's how to make Server Block creation super easy and completely automated with a script.

Virtual Host, is an Apache term, in NGinx Virtual Hosts are called Server Blocks.

This is Ubuntu specific stuff, but it shouldn’t be so different from other linux distros.

Server Block creation flow

  1. Make directory structure: sudo mkdir -p /var/www/
    • mkdir makes the dir (it’s short for “make directory”)
    • -p means that create the specified subdirectories also public_html in this case
  2. Change owner and group: sudo chown -R yourusername:www-data /var/www/
    • chown short for change owner
    • -R recursive flag, means that all the sub directories are affected also
    • yourusername:www-data username and group, the group should be www-data, so that MySQL can use it
  3. Make www dir readable: sudo chmod 755 /var/www
  4. Create index page for your site: sudo nano /var/www/
    • Nano will pop up, just type hello in the file
      ctrl+x will exit the file and ask you if you want to save the file, answer y and enter
  5. Create new virtual host file: sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/
    • cp short for copy, will copy the default server block and rename it to, the default is like a starter template
    • Check below the contents of the file
    • Remove or rename the default, so that NGinx wont look server from it
  6. Symlink between sites-enabled and sites-available: sudo ln -s /etc/nginx/sites-available/ /etc/nginx/sites-enabled/
    • ln, short for link, it does what is says, links the files
    • This is done because, it’s easy take the site down, just break the link
  7. Restart nginx: sudo service nginx restart
  8. Make DNS for the domain
    • This you do either in your server or domain usually
    • DigitalOcean has a nice DNS controls in the backend

Now, if you go to, you should see the contents of the index.html.

Contents of the server block file

I’m using four different files here to create the server. Click the file names to see the file contents.

  1. Main conf file /etc/nginx/nginx.conf
    • Configurations that are common to every single server block
    • Loads in all files from /etc/nginx/sites-enabled
    • Basic HTTP server can function only with this file if needed
  2. More specific conf file /etc/nginx/clobal/common.conf
    • Usually common to all server blocks, but doesn’t have to be
    • Far expiring headers and other fairly common ‘tricks’ are defined in this file
    • Port is defined here, i.e. Varnish needs to listen to another port than 80
  3. Server Block file /etc/nginx/sites-available/
    • Only the stuff that is mandatory for this domain
    • Include WordPress configuration if it’s a WP install
    • Loads in /etc/nginx/clobal/common.conf usually always, but there may be case where it’s not needed
    • Loads in WordPress config
  4. WordPress specific configurations /etc/nginx/clobal/wordpress.conf
    • Fastcgi rules and WP specific stuff
    • This is of course loaded only on WP installs

Shell script to do it for you

Bill Gates famously said:

I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.

I’m that lazy person, and here’s a shell script to do all the boring bits.

#!/usr/bin/env bash
# Nginx - new server block

# Functions
ok() { echo -e '\e[32m'$1'\e[m'; } # Green
die() { echo -e '\e[1;31m'$1'\e[m'; exit 1; }

# Variables

# Sanity check
[ $(id -g) != "0" ] && die "Script must be run as root."
[ $# != "1" ] && die "Usage: $(basename $0) domainName"

# Create nginx config file
# www to non-www
server {
    # If user goes to www direc them to non www
    server_name *.$1;
    return 301 $NGINX_SCHEME://$1$NGINX_REQUEST_URI;
server {
    # Just the server name
    server_name $1;
    root        /var/www/$1/public_html;

    # Logs
    access_log $WEB_DIR/$1/logs/access.log;
    error_log  $WEB_DIR/$1/logs/error.log;

    # Includes
    include global/common.conf;
    include global/wordpress.conf;

    # Listen to port 8080, cause of Varnis
    # Must be defined after the common.conf include

# Creating {public,log} directories
mkdir -p $WEB_DIR/$1/{public_html,logs}

# Creating index.html file
cat > $WEB_DIR/$1/public_html/index.html <<EOF
<!DOCTYPE html>
<html lang="en">
        <meta charset="utf-8" />
<body class="container">
        <div id="wrapper">

Hello World
        <footer>© $(date +%Y)</footer>

# Changing permissions
chown -R $USER:$WEB_USER $WEB_DIR/$1

# Enable site by creating symbolic link

# Restart
echo "Do you wish to restart nginx?"
select yn in "Yes" "No"; do
    case $yn in
        Yes ) /etc/init.d/nginx restart ; break;;
        No ) exit;;

ok "Site Created for $1"


How to use it:

  • Name it something like:
  • Make it executable: sudo chmod 755
  • Run it: sudo ./

Did I miss something? Drop a comment below :)


Club-Mate, the beverage →