LAMP is one of the most common web systems we find today. Letters L A M P stands for Linux , Apache, MySQL & PHP.
We now already have our first objective ‘L’, i.e. Linux or in our case its Ubuntu. Therefore, let’s see how to install the other three and then into some security hardening.
Login to the vm via ssh. change to root user
$sudo su
Give your password
Before you get started, make sure you set up your server so that it correctly resolves its hostname to fully qualified domain name (FQDN). This will be necessary in order for your certificates to be validated by clients.
check FQDN by
hostname -f
Apache is a web server application that is widely used in the internet for more than 20 years and it is a well-documented piece of Free and Open Source Software managed by Apache Foundation. (https://httpd.apache.org/)
Before installing we need to update our repositories.
sudo apt-get update
Once the repo lists are updated run,
sudo apt-get install apache2
When asked press Y and hit Enter to continue, and the installation will proceed.
Check installed apache version details by issuing,
$ apache2 -v
NOTE: if you had installed apache2 while installing Ubuntu OS then we should update it to the latest by,
sudo apt-get --only-upgrade install apache2 -y
Now go to your browser and type http://www.yourdomain and check whether you are able to access the apache test page.
Once the webserver is installed and running we need to install a database management system to host our dynamic data. For that, we use MySQL database as another popular FOSS.
So to install MYSQL run,
sudo apt-get install mysql-server
Again you will be asked to press Y to continue. During the installation process, you will be asked to type in and confirm a root password for your MySQL system. Please keep in mind that MySQL root is also similar to root access of your server and therefore choose a strong and unique password, never leave it blank.
As the installation completes let’s tighten some security in MySQL by running,
sudo mysql_secure_installation
Enter your MySQL root password when asked. As the first step, it will ask
VALIDATE PASSWORD PLUGIN
where this will make your passwords associated with databases much stronger by enforcing password restrictions. Once you click y it will give three options LOW, MEDIUM, STRONG. Then select a level of password validation. Make sure to keep in mind that if you enter 1, for the medium level, you will receive errors when attempting to set any password which does not contain numbers, upper and lowercase letters, and special characters.
Then there will be several questions asked, please enter Y for every answer and enter.
Once the script ends running we can test our MySQL instance by login into it.
mysql –u root –p
Enter your MySQL root password when requested.
As the last option of LAMP lets install PHP.
type in,
sudo apt-get -y install php libapache2-mod-php
the switch –y will automatically put yes on the installation process when it is prompted.
Once the installation is finished restart apache.
sudo service apache2 restart
To check php, lets create a test php file.
sudo vi /var/www/html/info.php
Note: /var/www/html/ is the default document root for apache in Ubuntu unless you have changed it in apache configuration.
Enter the following in info.php
<?php phpinfo(); ?>
Now let us call that file in a browser (e.g. http://www.yourdomain/info.php)
If your PHP is working you will see all your php server settings in one single place.
For the security of your server make sure you delete info.php after testing
Create two directories on /var/www/ to host two separate web sites.
sudo mkdir /var/www/web1 sudo mkdir /var/www/web2
Create index pages on each directories containing following.
sudo vi /var/www/web1/index.php
You may change the content as appropriate.
<html> <head> <title>Web 1</title> </head> <body> <h1> <?php Echo "Hello, I’m Web1"; ?> </h1> </body> </html>
Default host configuration is located in /etc/apache2/sites-available/000-default.conf which serves any requests coming to its domain name or IP address. To make other two domains work, lets create virtual host files for each domain names;
sudo vi /etc/apache2/sites-available/web1.conf
with the following content,
<VirtualHost *:80> ServerAdmin admin@yourdomain ServerName yourdomain ServerAlias web1.yourdomain DocumentRoot /var/www/web1 ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Then create the virtual host for web2 as web2.conf on the same directory as web1.conf with the following.
<VirtualHost *:80> ServerAdmin admin@yourdomain ServerName yourdomain ServerAlias web2.yourdomain DocumentRoot /var/www/web2 ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
Once both files are written these needs to be enabled by,
sudo a2ensite web1.conf sudo a2ensite web2.conf
Now restart the apache.
Do a nslookup for www.yourdomain.ws.learn.ac.lk and find the IP Address of your web server and edit your pc host file and include following.(assume your IP is 192.168.X.X)
192.168.X.X web1.yourdomain 192.168.X.X web2.yourdomain
Note: For Linux:host file is /etc/hosts , edit with nano as sudo For Windows:host file is %!SystemRoot%\System32\drivers\etc\hosts, open with Notepad in Run As Admin mode.
and restart your pc’s….
check your browsers for following and see how three websites are hosted in one server.
CGI stands for Common Gateway Interface are useful for creating dynamic content on web page by transferring data from server to client. These scripts can be written in many languages such as bash, c, java, perl, python etc. First we need to create a script firstbash.cgi in following location /usr/local/cgi-bin/ , you may need to create it as sudo.
#!/bin/bash echo "Content-type: text/html" echo "" echo "My first CGI script"
Give the script file execute permissions
sudo chmod 705 /usr/local/cgi-bin/firstbash.cgi
Now to add this CGI on our web2 virtual host, edit /etc/apache2/sites-available/web2.conf as follows.
<VirtualHost *:80> ServerAdmin admin@yourdomain ServerName yourdomain ServerAlias web2.yourdomain DocumentRoot /var/www/web2 <Directory /var/www/web2> Require all granted </Directory> ScriptAlias /cgi-bin/ "/usr/local/cgi-bin/" <Directory "/usr/local/cgi-bin/"> Options +ExecCGI AddHandler cgi-script .cgi Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost>
After editing web2.conf lets enable CGI apache module and restart the server.
sudo a2enmod cgi sudo systemctl reload apache2
Visit following link and check-out your script.
- Hide Apache version details: By default, Apache displays the version of Apache web server installed with the name of the operating system. To hide this information, you need to edit /etc/apache2/conf-enabled/security.conf
sudo nano /etc/apache2/conf-enabled/security.conf
Add/edit the following line:
ServerSignature Off ServerTokens Prod TraceEnable Off
- Stop Directory Browsing Rename index.html in /var/www/html as index2.html and try to access the web server from outside. You will see the directory Listing as now we don’t have an Index. But better stop displaying a directory listing. Therefore, edit /etc/apache2/apache.conf and remove Indexes keyword from any Directory listing such as,
<Directory /var/www/> # Options Indexes FollowSymLinks Options -FollowSymLinks AllowOverride None Require all granted </Directory>
and restart apache. Now go back to your default web portal and check the results.
When you create or modify documents under /var/www/ as sudo those files and directories will belong to root user and root group. Apache is usually run by a user www-data and www-data group in Ubuntu. Therefore, if any document belongs to root will also be published as root has higher precedence than www-data. But if some malicious content are hosted, they can also be run under root opening lot of vulnerabilities to the public.
To secure publically accessible areas we can change user permissions by,
sudo chown -R www-data:www-data /var/www
Also if we had directories that are open for users to upload content we can restrict access by modifying access modes.
sudo chmod 664 /var/www/uploads
That will change file permissions to rw-rw-r—
When securing a directory it is a common practice we use a password to enter that path. Also in apache2 we can specify a password by creating an apache user and using .htaccess as needed.
First install Apache Utilities;
sudo apt-get install apache2-utils
On your virtual host configuration file add or modify following inside the <Directory> … </Directory>.
AllowOverride AuthConfig
Next create an authenticate user.
sudo htpasswd -c /etc/apache2/.htpasswd yourname
This will ask you to enter a new password and conform it for the new user. If you want to add another user, try with the same command above with new username. You can view the contents of the .htpassword file by
sudo cat /etc/apache2/.htpasswd
next we need to grant permission to www-data user.
sudo chown www-data:www-data /etc/apache2/.htpasswd sudo chmod 0660 /etc/apache2/.htpasswd
After that create a directory called “mystuff” inside the directory web1, create an html page of your choice inside the directory as sudo and change ownership to www-data.
sudo mkdir /var/www/web1/mystuff sudo nano /var/www/web1/mystuff/index.html sudo chown –R www-data:www-data /var/www/web1/mystuff/*
Now create .htaccess file inside mystuff directory
sudo nano /var/www/web1/mystuff/.htaccess
Add following content
AuthType Basic AuthName "Restricted Content" AuthUserFile /etc/apache2/.htpasswd Require valid-user
Now restart apache and browse to the newly created directory from your browser and check what is changed.
Create self-signedCertificates on to a directory /etc/ssl using openssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache_prv.key -out /etc/ssl/certs/apache_crt.crt
You will be asked series of questions, answer them carefully
Country Name (2 letter code) [AU]:LK State or Province Name (full name) [Some-State]:Colombo Locality Name (eg, city) []:Galleface Organization Name (eg, company) [Internet Widgits Pty Ltd]:YourCompany Organizational Unit Name (eg, section) []:IT Team Common Name (e.g. server FQDN orYOUR name) []:www.yourdomain Email Address []:info@yourdomain
Once finished, it will create two files in /etc/ssl. Next create another apacheconfig fileas web1-ssl.conf and include
<IfModule mod_ssl.c> <VirtualHost _default_:443> ServerAdmin admin@yourdomain ServerName web1.yourdomain DocumentRoot /var/www/web1 <Directory /var/www/web1> Require all granted </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined SSLEngine on SSLCertificateFile /etc/ssl/certs/apache_crt.crt SSLCertificateKeyFile /etc/ssl/private/apache_prv.key <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> <Directory /usr/lib/cgi-bin> SSLOptions +StdEnvVars </Directory> </VirtualHost> </IfModule>
Now enable this site by
sudo a2enmod ssl sudo a2ensite web1-ssl.conf
Try browsing https://web1.yourdomain, you will be warned about the untrusted connection as it is a self-signed authentication.
Also as a best practice, it is better to disable port 80 or plain HTTP traffic to your server. But if you directly disable Port 80 and allow only 443 then we have to manually type https
before your exact URL in browsers. Therefore, better to redirect all HTTP traffic to port443 from your server configuration without disabling. So to do that we need to put a redirect in each virtual host conf. files.
Edit port 80 virtual host configuration files and add these in bottom just before the line </!VirtualHost>
RewriteEngine on RewriteCond %{SERVER_NAME} = web1.yourdomain RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent] </VirtualHost>
Then enable mod-rewrite in apache and restart..
sudo a2enmod rewrite sudo systemctl reload apache2
Now test your configuration by browsing to http://www.yourdomain and see how it redirects
HTTP/2 support is included in Apache 2.4.17 and upwards. Enable HTTP/2 module by executing,
sudo a2enmod http2
then add below to each individual ssl virtual host files to enable respectively.
Protocols h2 http/1.1
To enable http/2 globally you can add following to the apache.conf
Protocols h2 h2c http/1.1
Once those lines are added restart apache and visit https://tools.keycdn.com/http2-test to check http2 configuration.
systemctl status apache2.service journalctl –xe
Log files:
tail –f /var/log/syslog tail –f /var/log/apache2/access.log tail –f /var/log/apache2/error.log