Red Hat Enterprise Linux

You have been asked to create a LAMP stack, whether you're thinking "Lamp stack, as in lights and bulbs" or "Ok let’s build a web server" this guide will help get you working quickly.

First for those that do not know a LAMP stack, also known simply as LAMP, is an acronym for a Linux/UNIX server with Apache as the server engine, MySQL/MariaDB as the database engine and PHP as the primary server-side script language.

These steps are based on RHEL 7.2/7.3 but should work for all versions of RHEL with minimal changes.

Just a couple things that you will need to be ready:

  • A decent Internet connection.
  • A non-production server to use with this guide.
    • This guide assumes that the server was installed with minimal options and is properly registered with a Red Hat subscription.
  • Access to the server that allows you Sudo (admin) access.

Depending on your organizational needs your server may have a graphical user interface (GUI) or you may simply have terminal access. With either option, it is suggested that you go through this guide first on a non-production server in case you need to go through it a couple times.

If you have a GUI, go to the “Applications” menu, then within the “Utilities” sub-menu find the “Terminal” application and open it.

Within Terminal (whether in the GUI or through SSH) follow these steps, to make things easier you can copy and paste the commands into the Terminal window.

NOTE:
With the yum commands below, this guide does not automatically install any piece of the LAMP stack. After you understand what you are doing, you can use the “-y” command to automatically install.

# Will not automatically update
sudo yum update
# Will not automatically install Apache/HTTPD
sudo yum install httpd
# Will automatically update
sudo yum -y update
# Will automatically install Apache/HTTPD
sudo yum -y install httpd

LAMP Installation Steps

  1. Check Red Hat registration, the script below will help with that.
    If you are properly registered, you will receive a message "Properly Registered" otherwise you will receive prompts to type in the Red Hat username and password along with the hostname of the server.
    if [ "$(sudo subscription-manager status]; then
    clear
    echo "Properly Registered"
    else
    clear
     
    echo -e "\033[32mRed Hat Registration - Start\033[0m"
        if [ -z ${1+x} ]; then
            echo -e "\033[01m\e[4mType your username for RedHat.com, followed by [ENTER]:\e[0m\033[0m"
            read rhUser
        else
            declare rhUser=$1
        fi
        if [ -z ${2+x} ]; then
            echo -e "\033[01m\e[4mType your password for RedHat.com, followed by [ENTER]:\e[0m\033[0m"
            read -s rhPass
        else
            declare rhPass=$2
        fi
        clear
        echo -e "\033[32mSet Server Hostname - Start\033[0m"
        if [ -z ${3+x} ]; then
            echo -e "\033[01m\e[4mType your desired hostname for the server, followed by [ENTER]:\e[0m\033[0m"
            read hostname
            sudo hostnamectl set-hostname $hostname
        else
            declare hostname=$3
            sudo hostnamectl set-hostname $hostname
        fi
        echo -e "\033[32mSet Server Hostname - Stop\033[0m"
        # Register Red Hat Server - Start
        sudo subscription-manager register --username $rhUser --password $rhPass --auto-attach
        clear
        sudo subscription-manager refresh
        clear
        history -c
        sudo subscription-manager identity
        # Register Red Hat Server - Stop
        echo -e "\033[32mRed Hat Registration - Stop\033[0m"
     
    fi
    
  2. Update System first.
    # Update system first
    sudo yum update
  3. Install useful applications
    #Install useful applications
    # nano - text editor alternative to vi
    # curl / wget - terminal based downloaders
    # bind-utils / telnet - useful for testing domain and port problems
    
    sudo yum install nano curl wget bind-utils telnet
  4. Install LAMP components.
    # Install LAMP
    # httpd - Base Apache
    # mod_ssl & openssl - Needed for HTTPS/SSL secure websites
    # mariadb-server & mariadb - MariaDB Database (latest DB based on MySQL after Oracle bought MySQL)
    # php - Base PHP
    # php-mysql - Allow PHP to work with MariaDB/MySQL
    # php-gd - Allow PHP to create/manipulate images
    # php-mbstring - Allow PHP to work with multi-byte strings - http://php.net/manual/en/book.mbstring.php
    
    sudo yum install httpd mod_ssl openssl mariadb-server mariadb php php-mysql php-gd php-mbstring
  5. Enable Services to have them load at startup.
    # Enable Services to have them load at startup
    sudo systemctl enable httpd.service
    sudo systemctl enable mariadb.service
  6. Open Firewall for HTTP and HTTPS.
    # Open Firewall for HTTP and HTTPS
    sudo firewall-cmd --permanent --zone=public --add-service=http 
    sudo firewall-cmd --permanent --zone=public --add-service=https
    sudo firewall-cmd --reload
  7. Create simple PHP Info page to verify PHP is working in Apache.
    The main purpose of this file is to make sure that PHP is working in Apache but it is also a good file to review for each project to make sure you have all needed PHP modules/extensions installed.
    # Create simple PHP Info page to verify PHP is working in Apache
    sudo echo "" | sudo tee /var/www/html/info.php
    
    echo "<?PHP
    echo 'Server URL: ' . \$_SERVER['SERVER_NAME'] . '
    Document Root: ' . \$_SERVER['DOCUMENT_ROOT'];
    ?>" | sudo tee /var/www/html/index.php
    
    
  8. Add PHP configuration into Apache.
    This is a needed step in order to have PHP handled properly in Apache.
    # Create a backup of your original Apache configuration
    sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.original
    
    sudo sed -i -e 's/^[ \t]*//' /etc/httpd/conf/httpd.conf
    sudo sed -i "s|IncludeOptional|#IncludeOptional|" /etc/httpd/conf/httpd.conf
    sudo sed -i "s|#ServerName www.example.com:80|ServerName localhost|" /etc/httpd/conf/httpd.conf
    sudo sed -i "s|DirectoryIndex index.html|DirectoryIndex index.html index.php|" /etc/httpd/conf/httpd.conf
    
    # Add PHP configuration into Apache
    echo "AddType application/x-httpd-php .php" | sudo tee -a /etc/httpd/conf/httpd.conf
  9. Secure MariaDB/MySQL.
    This is a needed step to protect your MariaDB/MySQL server. This command will first start the service then ask a series of questions, based on the needs of the project the answers will vary.
    # Secure MariaDB/MySQL
    sudo systemctl start mariadb.service
    clear
    sudo /usr/bin/mysql_secure_installation

    This is what you will see

    $ sudo /usr/bin/mysql_secure_installation
    
    NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
          SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!
    
    In order to log into MariaDB to secure it, we'll need the current
    password for the root user.  If you've just installed MariaDB, and
    you haven't set the root password yet, the password will be blank,
    so you should just press enter here.
    
    Enter current password for root (enter for none):

    At this point, tap enter/return, as you shouldn't have a root password at this point

    Enter current password for root (enter for none): 
    OK, successfully used password, moving on...
    
    Setting the root password ensures that nobody can log into the MariaDB
    root user without the proper authorisation.
    
    Set root password? [Y/n]

    At this point, type Y (case can be lower or upper) and tap enter/return

    You will need to type in a password then confirm the password. NOTE: This is your "god" password over all of your MariaDB system so it should be a difficult to guess password

    Set root password? [Y/n] y
    New password: 
    Re-enter new password: 
    Password updated successfully!
    Reloading privilege tables..
     ... Success!
    
    
    By default, a MariaDB installation has an anonymous user, allowing anyone
    to log into MariaDB without having to have a user account created for
    them.  This is intended only for testing, and to make the installation
    go a bit smoother.  You should remove them before moving into a
    production environment.
    
    Remove anonymous users? [Y/n]

    In most cases, you want to remove unauthenticated users so type Y (case can be lower or upper) and tap enter/return

    Remove anonymous users? [Y/n] y
     ... Success!
    
    Normally, root should only be allowed to connect from 'localhost'.  This
    ensures that someone cannot guess at the root password from the network.
    
    Disallow root login remotely? [Y/n]

    In most cases you want to remove remote "god" root access so type Y (case can be lower or upper) and tap enter/return

    Disallow root login remotely? [Y/n] y
     ... Success!
    
    By default, MariaDB comes with a database named 'test' that anyone can
    access.  This is also intended only for testing, and should be removed
    before moving into a production environment.
    
    Remove test database and access to it? [Y/n]

    If this is a development box to start learning how to do things with MariaDB/MySQL you could say no to this but in most cases type Y (case can be lower or upper) and tap enter/return

    Remove test database and access to it? [Y/n] y
     - Dropping test database...
     ... Success!
     - Removing privileges on test database...
     ... Success!
    
    Reloading the privilege tables will ensure that all changes made so far
    will take effect immediately.
    
    Reload privilege tables now? [Y/n]

    In most cases type Y (case can be lower or upper) and tap enter/return

    You are now done and will see something like this

    Reload privilege tables now? [Y/n] y
     ... Success!
    
    Cleaning up...
    
    All done!  If you've completed all of the above steps, your MariaDB
    installation should now be secure.
    
    Thanks for using MariaDB!
  10. Start Apache.
    # Start Apache
    sudo systemctl start httpd.service
  11. Load your site, if you are in a GUI, depending you may or may not have an internet browser on your machine, if you have a browser you can open it and simply go to http://localhost/info.phpIf you are in SSH/Terminal, the code below should load HTML of the default site for you if everything is working
    curl http://localhost/info.php
    

At this point, you should have a working HTTP LAMP stack but it will only run one website.

Multi-Site Installation Steps

Very few LAMP stacks are set up specifically to run only one website. The steps below will help you get your server serving multiple websites, again with little effort on your part.

  1. For multi-site to work we need to change SELinux to run in permissive mode.
    NOTE: Check with your company's IT security, some companies may have a problem with this where others may have no problem with it.Running the below script will change the setting for you and then restart the server.
    clear
    sudo cp /etc/selinux/config /etc/selinux/config.original
    sudo sed -i '/^#/d' /etc/selinux/config
    sudo sed -i '/^$/d' /etc/selinux/config
    SELinuxStatus=$(cat /etc/selinux/config | grep SELINUX=|cut -d'=' -f2)
    echo "Current Status: $SELinuxStatus"
    sudo sed -i "s|SELINUX=$SELinuxStatus|SELINUX=permissive|" /etc/selinux/config
    SELinuxStatus=$(cat /etc/selinux/config | grep SELINUX=|cut -d'=' -f2)
    echo "New Status: $SELinuxStatus"
    sudo shutdown -r now
    
  2. Create a file "websites.csv", within this file we will define the additional sites for the server.
    DomainName, HTTP_Port, HTTPS_Port,SSLCertificateFile,SSLCertificateKeyFile
    

    This websites.csv file has some logic tied to it in that if you do not define the HTTPS_Port, SSLCertificateFile, and SSLCertificateKeyFile your site will simply be HTTP and not a secure site (HTTPS)

    This script below will create the header of the CSV for you and then load the file in the nano text editor.

    Type in the values remembering to add a comma as the delimiter (make sure not to add spacing).

    When you are done hold down the Control/Ctrl key and type the X key to close the file, the system will ask you if you want to save, type Y for yes or type N for no then tap the Enter/Return key.

    echo -e "DomainName, HTTP_Port, HTTPS_Port,SSLCertificateFile,SSLCertificateKeyFile\n" | sudo tee /var/www/websites.csv
    sudo nano /var/www/websites.csv
    

    Here is an example of what the final file could look like

    DomainName, HTTP_Port, HTTPS_Port,SSLCertificateFile,SSLCertificateKeyFile
    test.someurl.local,80,443,/etc/httpd/ssl/SSLCRT.crt,/etc/httpd/ssl/SSLKey.key
    test2.someurl.local,80
    
  3. SSL CertificatesWhere you put your SSL certificate files may differ than this guide. The guide will focus on the location of the files as /etc/httpd/sslMake sure you have the crt and key files both in the /etc/httpd/ssl directory (or the directory you choose).
  4. Set some basic variables for the following steps
    # Declare main variables - start
    declare netAdapter=$(nmcli device status | grep en | cut -d " " -f1)
    if [ -z "$netAdapter" ]; then
    netAdapter=$(nmcli device status | grep eth | cut -d " " -f1)
    fi
    declare netIP=$(/sbin/ip -o -4 addr list $netAdapter | awk '{print $4}' | cut -d/ -f1)
    #declare netCIDR=$(/sbin/ip -o -4 addr list $netAdapter | cut -d ' ' -f7)
    declare netMask=$(ipcalc -m $netIP | cut -d '=' -f2)
    declare netCIDR=$(ipcalc -p $netIP $netMask | cut -d '=' -f2)
    declare netWork=$(ipcalc -n $netIP $netMask | cut -d '=' -f2)
    echo -e "Hostname: $(hostname)\n$netAdapter: $netIP\nNetmask: $netMask\nCIDR: $netWork/$netCIDR"
    declare AzureServer=$(awk -v address="$netIP" -f /opt/DSP/checkIP.awk /opt/DSP/AzureIPRange.txt)
    LoggedInUser=$(whoami)
    echo $LoggedInUser
    # Declare main variables - stop
    
  5. OPTIONAL - Remove GUI Desktop
    sudo yum remove gnome-desktop*
    
  6. Create Web Developer Group
    In the situation that you have multiple web developers a web developer group is helpful.
    # Create Web Developer Group
    sudo groupadd webdev
    
    # Add users to Web Developer Group
    sudo usermod -G webdev -a $LoggedInUser
    sudo usermod -G webdev -a apache
    sudo usermod -G webdev -a root
    
    # Create webdev User and add it to the Web Developer Group
    sudo useradd -g webdev -m webdev
    USR=webdev
    # This will generate a random, 8-character password:
    PASS=`tr -dc A-Za-z0-9_ < /dev/urandom | head -c8` echo $PASS > ~/webdev_temp_password.txt
    # This will actually set the password:
    echo "$USR:$PASS" | sudo chpasswd
    # List all users in webdev group
    sudo lid -g webdev | cut -f1 -d'('
    
    
  7. Configure Apache to handle multiple sites
    sudo mkdir /etc/httpd/sites-available
    sudo mkdir /etc/httpd/sites-enabled
    
    sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.original
    
    sudo sed -i -e 's/^[ \t]*//' /etc/httpd/conf/httpd.conf
    sudo sed -i "s|IncludeOptional|#IncludeOptional|" /etc/httpd/conf/httpd.conf
    sudo sed -i "s|#ServerName www.example.com:80|ServerName localhost|" /etc/httpd/conf/httpd.conf
    sudo sed -i "s|DirectoryIndex index.html|DirectoryIndex index.html index.php|" /etc/httpd/conf/httpd.conf
    
    echo "IncludeOptional /etc/httpd/sites-available/*.conf"  | sudo tee -a  /etc/httpd/conf/httpd.conf
    
    cat /etc/httpd/conf/httpd.conf | grep IncludeOptional
    cat /etc/httpd/conf/httpd.conf | grep DirectoryIndex
    
  8. Let the CSV define the additional sites
    # Read websites.csv file and create virtual host for each site - start
    sed 1d /var/www/websites.csv | while IFS=$’,’ read -r -a site
    do
    echo "Reading CSV File"
    echo "Domain Name: ${site[0]}"
    echo "HTTP Port: ${site[1]}"
    echo "HTTPS Port: ${site[2]}"
    echo "SSL CRT File: ${site[3]}"
    echo "SSL Key File: ${site[4]}"
    if [ -n "${site[1]}" ]; then
    echo "Configuring HTTP for ${site[0]}"
    echo -e "\n"\
    "ServerName ${site[0]}\n"\
    "DocumentRoot /var/www/${site[0]}/public_html\n"\
    "ErrorLog /var/www/${site[0]}/error.log\n"\
    "CustomLog /var/www/${site[0]}/requests.log combined\n"\
    "\n"\
    "Options All\n"\
    "AllowOverride All\n"\
    "Require all granted\n"\
    "\n"\
    ""  | sudo tee /etc/httpd/sites-available/${site[0]}.conf
    fi
    if [ -n "${site[2]}" ]; then
    if [ -z "${site[3]}" ] || [ -z "${site[4]}" ]; then
        echo "HTTPS Requested but SSL Parameters are not filled"
        exit 0
    fi
    echo "Configuring HTTPS for ${site[0]}"
    echo -e "\n"\
    "ServerName ${site[0]}\n"\
    "DocumentRoot /var/www/${site[0]}/public_html\n"\
    "ErrorLog /var/www/${site[0]}/error.log\n"\
    "CustomLog /var/www/${site[0]}/requests.log combined\n"\
    "\n"\
    "Options All\n"\
    "AllowOverride All\n"\
    "Require all granted\n"\
    "\n"\
    "SSLEngine on\n"\
    "SSLCertificateFile ${site[3]}\n"\
    "SSLCertificateKeyFile ${site[4]}\n"\
    ""  | sudo tee /etc/httpd/sites-available/${site[0]}_secure.conf
    fi
    sudo ln -s /etc/httpd/sites-available/${site[0]}.conf /etc/httpd/sites-enabled/${site[0]}.conf
    sudo mkdir -p /var/www/${site[0]}/public_html
    echo "$ip ${site[0]}"   | sudo tee -a  /etc/hosts
    # Download Test index.php file in place
    cd /var/www/${site[0]}/public_html
    echo "<?PHP
    echo 'Server URL: ' . \$_SERVER['SERVER_NAME'] . '
    Document Root: ' . \$_SERVER['DOCUMENT_ROOT'];
    ?>" | sudo tee /var/www/${site[0]}/public_html/index.php
    # Test SSL
    openssl s_client -connect ${site[0]}:443
    done
    # Read websites.csv file and create virtual host for each site - stop
    
    sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.bk
    sudo sed -i '/^#/d' /etc/httpd/conf/httpd.conf
    sudo sed -i '/^$/d' /etc/httpd/conf/httpd.conf
    
    
  9. Reassign permissions to the /var/www/ directory to allow the webdev group read and write access
    clear
    sudo chown -cR apache:webdev /var/www/
    sudo chgrp -cRv webdev /var/www/
    sudo chmod g+w -Rv /var/www/
    sudo chmod -Rv 774 /var/www/
    
  10. Test Configuration
    apachectl configtest
    httpd -D DUMP_VHOSTS
    
  11. Restart Apache Service
    sudo apachectl restart
    
Last updated: October 18, 2018