You can watch my video on setting up a Ubuntu 18.04.1 LTS Server on Microsoft Azure
https://www.youtube.com/watch?v=y9RQirmC_pk
This is my video of this post but with out really explaination of why I do some things. It is just a start to finish this is how you setup the server.
https://www.youtube.com/watch?v=qszvUjjL-ZI
With our server already setup via Azure or even on our localhost though Hyper-V or KVM login into your server and update and upgrade any missing packages.
- Install Apache2
sudo apt install apache2Once that is complete then we are going to install Mariadb
2. Install Mariadb
Add MariaDB Keyapt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
Add MariaDB Repo
add-apt-repository 'deb [arch=amd64] http://mirror.nodesdirect.com/mariadb/repo/10.3/ubuntu bionic main'
update
sudo apt-get install mariadb-server mariadb-client
sudo mysql_secure_installation
Enter current password for root (enter for none): Just press the Enter
Set root password? [Y/n]: Y
New password: $password
Re-enter new password: $password
Remove anonymous users? [Y/n]: Y
Disallow root login remotely? [Y/n]: Y
Remove test database and access to it? [Y/n]: Y
Reload privilege tables now? [Y/n]: Y
sudo mysql -u root -p
$password
3. Create The Joomla Database
CREATE DATABASE $DBNAME;
Now here I would recommend creating a new user for the database we just created.
Create the User
create user $DBUSER
Grant privileges while assigning the password
grant all on $DBNAME.* to ‘$DBUSER’@’localhost’ identified by ‘$DBUSER_PASSWORD’
Note: The localhost field usually doesn’t have to be edited, but you can set it to the specific address. The above example grants all privileges, obviously. But you may want to limit privileges.
exit
4. Install Unzip
Install Unzipsudo apt-get install unzip
5. Install PHP
Install PHPsudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php7.2 libapache2-mod-php7.2 php7.2-common php7.2-mbstring php7.2-xmlrpc php7.2-soap php7.2-gd php7.2-xml php7.2-intl php7.2-mysql php7.2-cli php7.2-zip php7.2-curl
if libzip error
vi /etc/apt/sources.list and add the following repositories
deb http://archive.ubuntu.com/ubuntu bionic universe multiverse
deb-src http://archive.ubuntu.com/ubuntu bionic universe multiverse
deb http://us.archive.ubuntu.com/ubuntu/ bionic universe
deb-src http://us.archive.ubuntu.com/ubuntu/ bionic universe
deb http://us.archive.ubuntu.com/ubuntu/ bionic-updates universe
deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-updates universe
deb http://us.archive.ubuntu.com/ubuntu/ bionic multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ bionic multiverse
deb http://us.archive.ubuntu.com/ubuntu/ bionic-updates multiverse
deb-src http://us.archive.ubuntu.com/ubuntu/ bionic-updates multiverse
deb http://security.ubuntu.com/ubuntu bionic-security universe
deb-src http://security.ubuntu.com/ubuntu bionic-security universe
deb http://security.ubuntu.com/ubuntu bionic-security multiverse
deb-src http://security.ubuntu.com/ubuntu bionic-security multiverse
Then edit and make the following changes to the PHP INI File
sudo vi /etc/php/7.2/apache2/php.ini
file_uploads = On
allow_url_fopen = On
memory_limit = 256M
upload_max_filesize = 25M
max_execution_time = 360
date.timezone = America/Edmonton
Restart Apache
sudo systemctl restart apache2.service
Create the file phpinfo.php
sudo vi /var/www/html/phpinfo.php
<?php
sudo vi /etc/php/7.2/apache2/php.ini
file_uploads = On
allow_url_fopen = On
memory_limit = 256M
upload_max_filesize = 25M
max_execution_time = 360
date.timezone = America/Edmonton
Restart Apache
sudo systemctl restart apache2.service
Create the file phpinfo.php
sudo vi /var/www/html/phpinfo.php
<?php
phpinfo();
?>
Now that we have our apache server, mysql and php setup now we want to enable virtualhosts so we can host multiple websites on the same server.
In this configuration our default site configuration is located in /etc/apache2/sites-available we want to copy the default virtual host file called 000-default.conf contents to the new virtual host files like below.
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/$myvirtualdomain.ca.conf
you would do this for however many sites you need, but I would recommend getting one setup first then copying the finished config as may times as you need using the command above. Then edit and change the settings highlighted in yellow to suit what you need as many times as you need it.
Edit the virtual host file (sudo vi $myvirtualdomain.ca.conf)
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin demoadmin@domain.ca
ServerName webserver.domain.ca
ServerAlias www.domain.ca
DocumentRoot /var/www/html/domain.ca/public_html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
Now disable the default config and enable your virtual host configuration files.
sudo a2dissite 000-default.conf - disables this config file
sudo a2ensite domain.ca.conf - enables config file of your virtual host you just setup.
you will have to restart apache for your setting to take effect.
sudo service apache2 restart
***NOTE it is very important that the ServerAlias matches the DNS otherwise the virtual host will not redirect the browser properly.
If your working locally, you can make changes to your local hosts file. Once you've gotten everything setup you can make changes to the DNS for Production.
SCP /path-to-file/file.zip $username@$HOST:/path-to-destination-folder/
in this case I typically use just the home directory
SCP /path-to-file/file.zip $username@$HOST:/~/file.zip
Then copy and paste the zip file to the virtual host directory we created for the site.
sudo cp Joomla_X.X.X-Stable-Full_Package.zip /Path/To/Virtual/Site
Once copied to the server move it to the /var/www/html/$site virtual directory we just enabled and unzip the file.
Run unzip sudo unzip Joomla_X.X.X-Stable-Full_Package.zip
The default settings in Joomla are a little different from what however before we do that you will want to fix a couple settings in your php.ini file.
There are 2 things we need to fix. Now for Joomla, recommended settings are to disable output buffering, to do that we need to edit the php.ini file
sudo vi /etc/php/7.2/apache2
Find
output_buffering = 4096
and change it to Off
output_buffering = Off
while were here we are going to increase the max file upload size
Save your changes restart apache
With the file now unzipped we are going to add our user/owner to the www-data group so we can properly run and execute Joomla.
By default the www-data user and group are unprivileged; however Joomla requires the www-data group to have certain permissions. So we are going to add the owner of the files to the www-data group so that Joomla can install modules, run updates, etc. We don't want to set ownership of any files to the www-data user. The whole point of the www-data user is that it is an unprivileged user, not able to write to any files. Server daemons accessible from the outside network (such as the web server) typically run as an unprivileged user so that in the event that they are hacked due to a vulnerability, the possible things the attacker can do is minimal. In these cases you should set ownership to www-data ONLY for those files, keeping the number of files writable by www-data at a minimum it's the same reason, don't set any files to be world-writable. You need to give www-data write permission to the joomla directory files. We don't want to give www-data ownership because of the security implications. So to do this we are going to add our user to the www-data group, which will give Joomla the permissions we need for it to run.
add $USER to www-data
sudo usermod -a -G www-data $USER
sudo chgrp -R www-data /var/www/html/$Site
sudo chown -R www-data:$USER /var/www/html/$Site
Do this for the setup then change your files and folders for
If you want to re-verify the proper permissions on the files and folders run the following commands
find /var/www/html/$Site -type d -exec chmod 755 {} \;
find /var/www/html/$Site -type f -exec chmod 644 {} \;
Logout and log back into to verify the changes were made. Now you should be able to run the Joomla installer without any write or execute permission issues.
Now open your browser and run though the Joomla setup. http://yournewjoomlasite/index.php
To enable .htaccess and security headers you will need to add the following to your Site Config file located in /etc/apache2/sites-available called $Site-Domain.conf
Add the following just under the tag
Options Indexes FollowSymLinks
Options FollowSymLinks
AllowOverride ALL
Require all granted
6. Setup Virtual Hosts
Now that we have our apache server, mysql and php setup now we want to enable virtualhosts so we can host multiple websites on the same server.
In this configuration our default site configuration is located in /etc/apache2/sites-available we want to copy the default virtual host file called 000-default.conf contents to the new virtual host files like below.
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/$myvirtualdomain.ca.conf
you would do this for however many sites you need, but I would recommend getting one setup first then copying the finished config as may times as you need using the command above. Then edit and change the settings highlighted in yellow to suit what you need as many times as you need it.
Edit the virtual host file (sudo vi $myvirtualdomain.ca.conf)
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin demoadmin@domain.ca
ServerName webserver.domain.ca
ServerAlias www.domain.ca
DocumentRoot /var/www/html/domain.ca/public_html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
Now disable the default config and enable your virtual host configuration files.
sudo a2dissite 000-default.conf - disables this config file
sudo a2ensite domain.ca.conf - enables config file of your virtual host you just setup.
you will have to restart apache for your setting to take effect.
sudo service apache2 restart
***NOTE it is very important that the ServerAlias matches the DNS otherwise the virtual host will not redirect the browser properly.
If your working locally, you can make changes to your local hosts file. Once you've gotten everything setup you can make changes to the DNS for Production.
7. Copy Joomla to the Webserver
Now upload the latest version of Joomla to the server via SCP. Make sure you have a writable directory you can save to if you don't make one.SCP /path-to-file/file.zip $username@$HOST:/path-to-destination-folder/
in this case I typically use just the home directory
SCP /path-to-file/file.zip $username@$HOST:/~/file.zip
Then copy and paste the zip file to the virtual host directory we created for the site.
sudo cp Joomla_X.X.X-Stable-Full_Package.zip /Path/To/Virtual/Site
Once copied to the server move it to the /var/www/html/$site virtual directory we just enabled and unzip the file.
Run unzip sudo unzip Joomla_X.X.X-Stable-Full_Package.zip
The default settings in Joomla are a little different from what however before we do that you will want to fix a couple settings in your php.ini file.
There are 2 things we need to fix. Now for Joomla, recommended settings are to disable output buffering, to do that we need to edit the php.ini file
sudo vi /etc/php/7.2/apache2
Find
output_buffering = 4096
and change it to Off
output_buffering = Off
while were here we are going to increase the max file upload size
Save your changes restart apache
By default the www-data user and group are unprivileged; however Joomla requires the www-data group to have certain permissions. So we are going to add the owner of the files to the www-data group so that Joomla can install modules, run updates, etc. We don't want to set ownership of any files to the www-data user. The whole point of the www-data user is that it is an unprivileged user, not able to write to any files. Server daemons accessible from the outside network (such as the web server) typically run as an unprivileged user so that in the event that they are hacked due to a vulnerability, the possible things the attacker can do is minimal. In these cases you should set ownership to www-data ONLY for those files, keeping the number of files writable by www-data at a minimum it's the same reason, don't set any files to be world-writable. You need to give www-data write permission to the joomla directory files. We don't want to give www-data ownership because of the security implications. So to do this we are going to add our user to the www-data group, which will give Joomla the permissions we need for it to run.
add $USER to www-data
sudo usermod -a -G www-data $USER
sudo chgrp -R www-data /var/www/html/$Site
sudo chown -R www-data:$USER /var/www/html/$Site
Do this for the setup then change your files and folders for
If you want to re-verify the proper permissions on the files and folders run the following commands
find /var/www/html/$Site -type d -exec chmod 755 {} \;
find /var/www/html/$Site -type f -exec chmod 644 {} \;
Logout and log back into to verify the changes were made. Now you should be able to run the Joomla installer without any write or execute permission issues.
Now open your browser and run though the Joomla setup. http://yournewjoomlasite/index.php
Enable .htaccess and security headers
Options FollowSymLinks
AllowOverride ALL
Require all granted
Save the config file then eneable a2enmod by
sudo a2enmod rewrite
then restart apache
sudo systemctl restart apache2
Securing The Webserver
enable module headers
sudo a2enmod headers
Now edit the security.conf file typically localed in /etc/apache2/conf-available/security.conf
Header unset X-Powered-By
Header always unset X-Powered-By
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure - Enable once you have ssl setup.
Header set X-Permitted-Cross-Domain-Policies "none"
Header always set X-XSS-Protection "1; mode=block"
Header always set x-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Feature-Policy "microphone 'none'; payment 'none'; sync-xhr 'self' Header always set Referrer-Policy "strict-origin"
<!--very secure policy--!>
Header always set Content-Security-Policy "default-src 'self'; font-src *;img-src * data:; script-src *; style-src *;"
Very Insecure policy if your going to be using several different joomla extensions.
Header always set Content-Security-Policy "default-src 'self'; connect-src *; font-src *; frame-src *; img-src * data:; media-src *; object-src *; script-src * 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline';"
So if you want a copy paste security headers
Header unset X-Powered-By
Header always unset X-Powered-By
#Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
Header set X-Permitted-Cross-Domain-Policies "none"
Header always set X-XSS-Protection "1; mode=block"
Header always set x-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Feature-Policy "microphone 'none'; payment 'none'; sync-xhr 'self' Header always set Referrer-Policy "strict-origin"
then restart apache
sudo systemctl restart apache2
sudo a2enmod headers
Now edit the security.conf file typically localed in /etc/apache2/conf-available/security.conf
Header unset X-Powered-By
Header always unset X-Powered-By
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure - Enable once you have ssl setup.
Header set X-Permitted-Cross-Domain-Policies "none"
Header always set X-XSS-Protection "1; mode=block"
Header always set x-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Feature-Policy "microphone 'none'; payment 'none'; sync-xhr 'self' Header always set Referrer-Policy "strict-origin"
<!--very secure policy--!>
Header always set Content-Security-Policy "default-src 'self'; font-src *;img-src * data:; script-src *; style-src *;"
Very Insecure policy if your going to be using several different joomla extensions.
Header always set Content-Security-Policy "default-src 'self'; connect-src *; font-src *; frame-src *; img-src * data:; media-src *; object-src *; script-src * 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline';"
So if you want a copy paste security headers
Header unset X-Powered-By
Header always unset X-Powered-By
#Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
Header set X-Permitted-Cross-Domain-Policies "none"
Header always set X-XSS-Protection "1; mode=block"
Header always set x-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Feature-Policy "microphone 'none'; payment 'none'; sync-xhr 'self' Header always set Referrer-Policy "strict-origin"
Header always set Content-Security-Policy "default-src 'self'; connect-src *; font-src *; frame-src *; img-src * data:; media-src *; object-src *; script-src * 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline';"
then restart apache
sudo systemctl restart apache2
Disable Expose PHP
sudo vi /etc/php/7.2/apache2/php.ini
expose_php = Off
expose_php = Off
Setup your domains and DNS
Now before we setup our SSL Cert, we need to setup our DNS. For my DNS I needed to setup both an A record.
Now once the DNS resolves we can setup our SSL Certificate using Let's Encrypt.
Setup the SSL Certificate
Digital Ocean has a great post on setting up Let's Encrypt on Ubuntu. You can get the source link in the resources.Step 1 - Add the repository and install Certbot
sudo add-apt-repository ppa:certbot/certbot
Install Certbot's Apache package with apt:
sudo apt install python-certbot-apache
Step 2 - Set Up the SSL Certificate
Verify that the Server name matches the domain name your going to use. If it doesn't change it so it matches.
sudo vi /etc/apache2/sites-available/$SITE.conf
Your server name should match the domain your setting up with lets encrypt.
ServerName YOURDOMAIN.CA;
You can verify the syntax of your configuration edits:
sudo apache2ctl configtest
If you get an error, reopen the virtual host file and check for any typos or missing characters. Once your configuration file's syntax is correct, reload Apache to load the new configuration:
sudo systemctl reload apache2
Certbot can now find the correct VirtualHost block and update it.
Step 3 - Allowing HTTPS and SSH Through the Firewall
You can see the current setting by typing:
sudo ufw status
sudo ufw allow 'ssh'
sudo ufw allow 'Apache Full'
sudo ufw delete allow 'Apache'
if it is disabled do a sudo ufw enable to enable the firewall
Your status should now look like this:
sudo ufw status
Output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Apache Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Apache Full (v6) ALLOW Anywhere (v6)
Step 4 - Obtaining an SSL Certificate
Certbot has an Apache plugin that will take care of reconfiguring Apache and reloading the config whenever necessary.
sudo certbot --apache -d domain.ca -d dev.domain.ca
This runs certbot with the --apache plugin, using -d to specify the names you'd like the certificate to be valid for.
The first time you run certbot, you will be prompted to enter an email address and agree to the terms of service. After doing so, certbot will communicate with the Let's Encrypt server, then run a challenge to verify that you control the domain you're requesting a certificate for.
If that's successful, certbot will ask how you'd like to configure your HTTPS settings:
Example:
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):
I would suggest selecting option 2. The configuration on you server will be updated, and Apache will reload to pick up the new settings. certbot will wrap up with a message telling you the process was successful and where your certificates are stored:
Example:
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/example.com/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/example.com/privkey.pem
Your cert will expire on 2018-07-23. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
Your certificates are downloaded, installed, and loaded. Try reloading your website using https:// and notice your browser's security indicator. It should indicate that the site is properly secured, usually with a green lock icon. If you test your server using the SSL Labs Server Test, it will get an A grade.
Let's finish by testing the renewal process.
Step 5 - Verifying Certbot Auto-Renewal
Let's Encrypt's certificates are only valid for ninety days. This is to encourage users to automate their certificate renewal process. The certbot package takes care of this for us by adding a renew script to /etc/cron.d. This script runs twice a day and will automatically renew any certificate that's within thirty days of expiration.
To test the renewal process, you can do a dry run with certbot:
sudo certbot renew --dry-run
If you see no errors, you're all set. When necessary, Certbot will renew your certificates and reload Apache to pick up the changes. If the automated renewal process ever fails, Let’s Encrypt will send a message to the email you specified, warning you when your certificate is about to expire.
Security Tests and Scanners
https://app.upguard.com
https://pentest-tools.com/
https://sitecheck.sucuri.net
https://hackertarget.com/
https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools
https://securityheaders.com/
https://tools.geekflare.com/report/header-security-test/
https://app.upguard.com/webscan#/
https://qualysguard.qg3.apps.qualys.com/fo/home/Dashboard.php?skip=1
https://pentest-tools.com/website-vulnerability-scanning/web-server-scanner#
https://observatory.mozilla.org/
https://addons.mozilla.org/en-US/firefox/addon/laboratory-by-mozilla/
https://websiteforstudents.com/installing-apache2-mariadb-on-ubuntu-16-04-17-10-18-04-with-php-7-2-support-lamp/
Configuring Virtual Hosts
https://www.ostechnix.com/configure-apache-virtual-hosts-ubuntu-part-1/
https://httpd.apache.org/docs/current/vhosts/
Server Hardening
https://askubuntu.com/questions/778463/www-data-vs-username
https://stackoverflow.com/questions/9133024/www-data-permissions/19620585#19620585
https://unix.stackexchange.com/questions/268905/is-giving-all-permissions-to-www-data-group-a-good-idea
https://www.tecmint.com/hide-apache-web-server-version-information/
.HTACCESS
https://www.opentechguides.com/how-to/article/apache/115/htaccess-file-dir-security.html
adding user to www-data group & Joomla Security Checklist
https://www.cyberciti.biz/faq/ubuntu-add-user-to-group-www-data/
https://docs.joomla.org/Security_Checklist/Joomla!_Setup
https://docs.joomla.org/Security_and_Performance_FAQs
Security Headers
https://kb.sucuri.net/warnings/hardening
https://www.ryadel.com/en/apache-setup-httpd-conf-file-send-http-security-headers-web-site/
https://jsblog.insiderattack.net/apache-security-configuring-secure-response-headers-e8a83b72ce5e
https://geekflare.com/apache-web-server-hardening-security/
https://geekflare.com/httponly-secure-cookie-apache/
Setup SSL
https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-18-04
https://pentest-tools.com/
https://sitecheck.sucuri.net
https://hackertarget.com/
https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools
https://securityheaders.com/
https://tools.geekflare.com/report/header-security-test/
https://app.upguard.com/webscan#/
https://qualysguard.qg3.apps.qualys.com/fo/home/Dashboard.php?skip=1
https://pentest-tools.com/website-vulnerability-scanning/web-server-scanner#
https://observatory.mozilla.org/
Browser addons
https://chrome.google.com/webstore/detail/csp-evaluator/fjohamlofnakbnbfjkohkbdigoodcejfhttps://addons.mozilla.org/en-US/firefox/addon/laboratory-by-mozilla/
References
Setting up a lampp serverhttps://websiteforstudents.com/installing-apache2-mariadb-on-ubuntu-16-04-17-10-18-04-with-php-7-2-support-lamp/
Configuring Virtual Hosts
https://www.ostechnix.com/configure-apache-virtual-hosts-ubuntu-part-1/
https://httpd.apache.org/docs/current/vhosts/
Server Hardening
https://askubuntu.com/questions/778463/www-data-vs-username
https://stackoverflow.com/questions/9133024/www-data-permissions/19620585#19620585
https://unix.stackexchange.com/questions/268905/is-giving-all-permissions-to-www-data-group-a-good-idea
https://www.tecmint.com/hide-apache-web-server-version-information/
.HTACCESS
https://www.opentechguides.com/how-to/article/apache/115/htaccess-file-dir-security.html
adding user to www-data group & Joomla Security Checklist
https://www.cyberciti.biz/faq/ubuntu-add-user-to-group-www-data/
https://docs.joomla.org/Security_Checklist/Joomla!_Setup
https://docs.joomla.org/Security_and_Performance_FAQs
Security Headers
https://kb.sucuri.net/warnings/hardening
https://www.ryadel.com/en/apache-setup-httpd-conf-file-send-http-security-headers-web-site/
https://jsblog.insiderattack.net/apache-security-configuring-secure-response-headers-e8a83b72ce5e
https://geekflare.com/apache-web-server-hardening-security/
https://geekflare.com/httponly-secure-cookie-apache/
https://www.digitalocean.com/community/tutorials/how-to-secure-apache-with-let-s-encrypt-on-ubuntu-18-04