This website uses Google Analytics and Advertising cookies, used to generate statistical data on how visitors uses this website (with IP anonymization) and to deliver personalized ads based on user prior visits to this website or other websites. [read more]
These cookies are disabled by default until your Accept/Reject Consent.
The Consent can be changed at any time by accesing the ePrivacy button located at the bottom of every page. Enjoy your visit!

WebH-NL - a quick do it yourself web hosting solution

A half hour from zero to a fast, secure and reliable Debian 9 web hosting stack

The WebH-NL stack objectives:

timer fast loading time for the websites pages
slow_motion_video light server resource consumption
bug_report stable server software
crop_square easy maintenance

The WebH-NL on GitHub:

The WebH-NL stack components:1)

 - Debian9
 - NGINX (light)
 - PHP7+ (php-fpm)
 - Apache 2.4+
 - PostgreSQL 9.6+ (other databases also supported)
 - NodeJS 6+
1)Disclaimer: the web hosting stack does not contain email hosting software; for any email communication needs inside the WebH-NL stack, a Postfix configured with a SMTP relay should suffice (
Remember this
- all websites files will reside inside /var/www server location, easy to identify by corresponding FQDN; /var/www/fqdn/[logs/public]
- all websites configuration files (php,nginx,apache) will reside inside /etc/www location, easy to identify by corresponding FQDN; /etc/www/fqdn-(nginx|apache|php).conf
You may need this files for backup/transfer procedures
Debian9 use systemd as the process manager, so all processes will be managed by systemctl.
systemctl start|stop|restart|reload|status service_name

Step1: power on a new server with Debian9

We gonna use a 5 USD Google Compute Engine from Google Cloud but the stack will fit in any physical or virtual servers with at least 1 (v)CPU and 512MB of RAM.
Login to (300 USD to be used over 12 months are also provided by Google in a trial plan for their Google Cloud services testing) - (00:00:00:00). Create a new project and a new VPS (Compute Engine) inside this project (00:01:55:28). Check above video for this part.

Step2: gain SSH access to VPS, using Putty (00:04:58:17) Command used to generate SSH Keys, from the local computer terminal:
ssh-keygen -t rsa -f ~/.ssh/b247 -C b247@Ubuntu-Desktop
puttygen ~/.ssh/b247 -o ~/.ssh/b247.ppk -C "b247"
cat ~/.ssh/
From now on, we will work remotely on the VPS using the Putty SSH connection

Step3: cleaning and updating the server

sudo apt remove --purge google-cloud-sdk
sudo apt update && sudo apt upgrade

Step4: install some prerequisites needed for the webh-nl helper

sudo apt-get install python-pip && sudo pip install pexpect
sudo apt-get install acl git htop

Step5: clone the WebH-NL GIT project

git clone
cd WebH-NL
From now on, we will work from within the WebH-NL folder

Step6: install server software

echo 'Installing, cleaning and set defaults for NGINX: used for proxy, static files, SSL, SSL Offloading'
sudo apt-get install nginx-light
sudo rm -R {/etc/nginx/sites-enabled/*,/etc/nginx/sites-available/*,/var/www/*}
sudo cp files/configs/nginx/nginx.conf /etc/nginx/

echo 'Creating the /etc/www location for our server config storage'
sudo mkdir /etc/www
sudo chown root:www-data /etc/www/
sudo chmod 0750 /etc/www/

echo 'Configuring the /var/www location used for websites storage'
sudo chown root:www-data /var/www/
sudo chmod 0770 /var/www/
sudo chmod g+s /var/www/
sudo setfacl -d -m u::rwX,g::rwX,o::- /var/www/

echo 'Changing logged user default group to www-data'
sudo usermod -g www-data $(whoami)

echo 'Installing, cleaning and set defaults for Apache: used for PHP, mod_security, .htaccess'
echo "don't worry about the Failed to start The Apache HTTP Server info, this is because the standard http 80 port is already used by NGINX. We will gonna change this soon (run Apache on port 8080)"
sudo apt-get install apache2
sudo rm -R /var/www/html && sudo rm -R {/etc/apache2/sites-available/*,/etc/apache2/sites-enabled/*}
sudo rm -R {/etc/apache2/conf-enabled/*,/etc/apache2/conf-available/*}
sudo cp files/configs/apache2/apache2.conf /etc/apache2/
sudo cp files/configs/apache2/mods-available/remoteip.conf  /etc/apache2/mods-available/remoteip.conf
sudo a2enmod headers
sudo a2enmod remoteip
sudo a2enmod proxy_fcgi

echo "Installing apache mod_security as a WAF (Web Application Firewall), OWASP CRS Included ("
sudo apt-get install libapache2-mod-security2
sudo cp files/configs/modsecurity/modsecurity.conf /etc/modsecurity/modsecurity.conf

echo "Installing fail2ban"
sudo apt-get install fail2ban
sudo cp files/configs/fail2ban/jail.d-modsec.conf /etc/fail2ban/jail.d/modsec.conf
sudo cp files/configs/fail2ban/filter.d-modsec.conf /etc/fail2ban/filter.d/modsec.conf

echo "Installing, cleaning and set defaults for PHP"
sudo apt-get install php-fpm php-pgsql php-mysql php-memcache php-mcrypt php-intl php-curl php-xml php-pear php-zip php-mbstring
sudo rm -R /etc/php/7.0/fpm/pool.d/
sudo cp files/configs/php/{php-fpm.conf,php.ini} /etc/php/7.0/fpm/

echo "Installing Memcached"
sudo apt-get install memcached

echo "Installing PostgreSQL"
sudo apt-get install postgresql

echo "Installing NodeJS"
curl -sL | sudo -E bash -
sudo apt-get install -y nodejs

echo "Installing Let's Encrypt, SSL requirements"
sudo wget && sudo chmod a+x certbot-auto && sudo mv certbot-auto /usr/local/bin/
echo "Executing certbot-auto (when asked for domain name just cancel, press c)"
sudo certbot-auto 
sudo apt-get install haveged
sudo openssl dhparam -dsaparam -out /etc/letsencrypt/dhparam.pem 4096

We need to scale Apache and PHP in accordance with server system power (CPU and RAM). Following configuration are available:
You must choose one configuration closest to the server CPUs and RAM
Find CPU and RAM of the server system
sudo echo $(nproc) cpu && sudo dmidecode -t 17 | grep  Size: | sed -e 's/Size: //g'
Declare MYSERVERSCALECONF variable according. Be aware of not using spaces when declaring a shell variable.
sudo cp files/configs/apache2/conf-available/$MYSERVERSCALECONF /etc/apache2/conf-available/server-scale.conf
sudo a2enconf server-scale
sudo cp files/configs/php/$MYSERVERSCALECONF /etc/php/7.0/fpm/load.conf
sudo systemctl restart apache2
sudo systemctl restart php7.0-fpm

Remember this
Re run above code if server system CPUs or RAM changes

sudo systemctl reload fail2ban

Step7: setup automatic Let's Encrypt SSL certificates renewal (00:16:59:27)

sudo crontab -e
and append this lines
# Let's Encrypt automatic certificates renewal, Nginx reload/restart after a successful certificate renewal.
59 23 * * 0          /usr/local/bin/certbot-auto renew --renew-hook "systemctl reload nginx"

Step8: change default postgres password

sudo su - postgres

Step9: use the WebH-NL provided helper for adding and manage new sites (00:17:33:15)

chmod +x
sudo ./
Don't forget to add necessary DNS entries for every new FQDN activated through WebH-NL helper, before adding a "new site". This is a requirement for validating Let's Encrypt free SSL certificates.

some final words

If you prefer MySQL (or required, let's say by Wordpress) instead of PostgreSQL, you can add MariaDB to the stack
sudo apt-get install mariadb-server
sudo mysql_secure_installation
sudo mysql
> create database escaped_fqdn default character set utf8 default collate utf8_bin;
> GRANT ALL PRIVILEGES ON escaped_fqdn.* to escaped_fqdn@'localhost' IDENTIFIED BY 'a_strong_password_here';

Server monitoring. At this stage, no monitoring solution provided. You can use Monitorix or a new modern monitoring stack based on Grafana, InfluxDB and Telegraf. I have tested this stack and yes, it's something cool but not for a 1vcpu 512MB f1-micro Google Compute Instance (at least when another website already running and under hight load). I may provide the stack installation procedure in another article, but for now I'm just waiting for the announced free tier from Grafana.


Share this post on your favorite networks.
© Copyright 2017 | Just another information technology blog - All Rights Reserved