Automatic Website Configuration in NginX

The simple life of simple websites on an NginX server.

After apache refused to start 1000+ sites, I decided to switch to nginx and do the same thing.

Same conditions as before: the client was asked to upload sites to the server over ftp and name the folders after the full site names. On the server side, pure-ftpd with a virtual user was configured. After logging in, the client lands in the /var/www/html folder, where they create a folder named after the site and upload the files into it.

After that, new server-side magic kicks in and the site becomes available by the will of magical bash.

For this, a template was created in the /etc/nginx folder:

/etc/nginx/templatenginx
server {
  listen 80;
  server_name websiterepl www.websiterepl;

  root /var/www/html/websiterepl;

  index index.php;

  if ($host ~ !^(websiterepl|www.websiterepl)$) {
    rewrite ^ http://www.websiterepl$request_uri? permanent;
  }

  # Limit methods, allowed on server to GET, HEAD and POST
  if ($request_method !~ ^(GET|HEAD|POST)$ ) {
    return 444;
  }

  location ~* \.(ico|gif|jpeg|jpg|png|eot|ttf|swf|woff)$ {
    root /var/www/html/websiterepl;
    expires 30d;
    access_log off;
  }

  location ~* \.(css|js)$ {
    root /var/www/html/websiterepl;
    expires 7h;
    access_log off;
  }

  location / {
    try_files $uri $uri/ /index.php;
  }

  location ~ \.(php|html)$ {
    root /var/www/html/websiterepl;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
  }
}

After that, the following script processes the contents of /var/www/html/ and creates virtual hosts in the nginx config for every folder.

  <div class="spoiler-wrap">
    <div class="spoiler-head folded">
      /usr/local/bin/make_vhosts_nginx
    </div>

    <div class="spoiler-body">
#!/bin/bash
do_websites () {
for f in $(ls /var/www/html/);
do
    sed 's/websiterepl/'"$f"'/g' /etc/nginx/templatenginx >> /etc/nginx/conf.d/websites.conf
    echo "" >> /etc/nginx/conf.d/websites.conf
done
}

if [ "$1" == "force" ]
then
    echo "[Forced] Building new websites' configuration";
    rm -f /etc/nginx/conf.d/websites.conf
    do_websites
    /bin/systemctl restart nginx.service
else

servernames=$(grep server_name /etc/nginx/conf.d/websites.conf |wc -l);
folders=$(ls /var/www/html |wc -l);

if [ "$folders" != "$servernames" ]
then
    echo "[General] Building new websites' configuration";
    rm -f /etc/nginx/conf.d/websites.conf
    do_websites
    /bin/systemctl restart nginx.service
else
    echo "No new websites found";
fi
fi

</div> </div>

Using crontab to make the script run every 15 minutes.

*/15 * * * * /usr/local/bin/make_vhosts_nginx 2>&1 >> /dev/null

In principle, the script itself already checks the number of virtual hosts against the number of folders in /var/www/html, so it could just as well run every 5 minutes.

The script can be forced to run using the force flag.

Categories:

Updated: