Setting Up LAMP Stack On CentOS and RackSpace Cloud Server

The following is a step-by-step guide for setting up and configuring a LAMP Stack on a 1GB or 2GB RackSpace Cloud Server with the latest CentOS distribution.

The following is a step-by-step guide for setting up and configuring a LAMP Stack on a 1GB or 2GB RackSpace Cloud Server with the latest CentOS distribution. You will need root access to complete the following steps.

Please note that in these instructions I make the specific effort of installing PHP 5.2, which is still the most compatible/safest PHP version for running Drupal.

Linux Bootstrap

  • Log in as root
  • Set the hostname
    • sudo hostname yourdomain.com
    • Add entry into /etc/hosts:
    • _public ip address_ yourdomain.com
    • Edit /etc/sysconfig/network to set hostname
    • Check /proc/sys/kernel/hostname for hostname
    • A reboot might be necessary (might as well)
  • Set root password to something that is impossible to remember.
  • Setup sudo, if it is not already set up (typically it is)
  • sudo groupadd sudoers
  • sudo groupadd webmaster
  • In /etc/bashrc set umask to 0002
  • Create a local account (regular user with primary group set to webmaster and secondary group to sudoers)
    • useradd -m -s /bin/bash -g webmaster -G sudoers irakli
    • Set local account’s password:
    • passwd irakli
  • Log in as the local account (“irakli” in our examples).

The rest of the tutorial assumes you are working with the local account and sudo into root as necessary.

Configuring Yum

Yum is a popular package manager for CentOS and RedHat Linux distributions. Unfortunately, standard Yum repositories carry significantly outdated packages. Fortunately, there are third-party Yum repositories with more updated LAMP packages which we can use. One such repository is provided and hosted by RackSpace itself. Let’s set it up:

  • sudo rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/5/x86_64/epel-release-1-1.ius.el5.noarch.rpm
  • sudo rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/5/x86_64/ius-release-1.0-6.ius.el5.noarch.rpm

For more information about setting up Rackspace’s IUS Community repository, please refer to the following blog post: Reliable Yum Repo for Easy Upgrades to the Latest Packages, on RedHat and CentOS

Setting Up Packages

  • sudo yum install openssl-devel zlib-devel gcc gcc-c++ make autoconf readline-devel curl-devel expat-devel gettext-devel
  • sudo yum install libjpeg libpng telnet libxslt freetype freetype-devel
  • sudo yum install mysql51-server mysql51-devel
  • sudo yum install php52-devel httpd-devel apr-devel
  • sudo yum install php52-pear
  • sudo yum install mod_ssl
  • sudo yum install php52-mysql php52-gd php52-xml php52-mbstring php52-mcrypt
  • sudo yum install php52-pecl-apc edit /etc/php.d/apc.ini and enter:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    extension=apc.so
    apc.enabled=1
    apc.shm_segments=1
    apc.shm_size=64
    apc.ttl=7200
    apc.user_ttl=7200
    apc.num_files_hint=1024
    apc.mmap_file_mask=/tmp/apc.XXXXXX
    apc.enable_cli=1
  • sudo yum install bind bind-utils bind-devel
  • sudo yum install postfix openssl

VirtualHost Configuration

  • sudo mkdir /var/www/vhosts
  • sudo mkdir /var/www/default
  • sudo vi /etc/httpd/conf.d/00_default.virtualhost.conf and in there enter:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    NameVirtualHost *:80
     
    <VirtualHost *:80>
        ServerAdmin webmaster@example.com
        DocumentRoot /var/www/default
        ServerName __default__
        ErrorLog logs/default-error_log
        CustomLog logs/default-access_log common
    </VirtualHost>
  • sudo vi /var/www/default/index.html
  • in there enter any text, e.g.: “RESTRICTED”.

  • in /etc/httpd/conf/httpd.conf replace all /var/www/html with var/www/vhosts
    • change “KeepAlive Off” to “KeepAlive On”
    • change “KeepAliveTimeout” from 15 to 5
    • Uncomment and Add ServerName yourdomain.com
  • type following:
    1
    2
    3
    
     cd /var/www/vhosts/
     sudo chown -R apache:apache .
     sudo chmod -R 775 /var/www/vhosts 
  • Make apache-owned files writable by your local user (“irakli” in our examples): sudo /usr/sbin/usermod -G sudoers,apache irakli
  • sudo mkdir -p /var/www/vhosts/yourdomain.com/html
  • sudo mkdir -p /var/www/vhosts/yourdomain.com/logs
  • sudo vi /etc/httpd/conf.d/yourdomain.com.conf
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    <VirtualHost *:80>
        ServerAdmin webmaster@yourdomain.com
        DocumentRoot /var/www/vhosts/yourdomain.com/html
        ServerName yourdomain.com
        ServerAlias subdomain.yourdomain.com
        ErrorLog /var/www/vhosts/yourdomain.com/logs/error_log
        CustomLog /var/www/vhosts/yourdomain.com/logs/access_log combined
     
        UseCanonicalName Off
     
       <Directory /var/www/vhosts/yourdomain.com/html>
            AllowOverride all
            Options all
            Order allow,deny
            Allow from all
            Deny from none
     
          # Insert filter
              SetOutputFilter DEFLATE
     
              # Netscape 4.x has some problems…
              BrowserMatch ^Mozilla/4 gzip-only-text/html
     
              # Netscape 4.06-4.08 have some more problems
              BrowserMatch ^Mozilla/4.0[678] no-gzip
     
              # NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48
              # the above regex won't work. You can use the following
              # workaround to get the desired effect:
              BrowserMatch bMSI[E] !no-gzip !gzip-only-text/html
     
              # Don't compress images, videos and audio
              SetEnvIfNoCase Request_URI
              .(?:gif|jpe?g|png|flv|mp4|m4v|mp3|zip|gz)$ no-gzip dont-vary
     
              # Make sure proxies don't deliver the wrong content
              Header append Vary User-Agent env=!dont-vary
     
     
       </Directory>
     
    FileETag none
     
    </VirtualHost>

    Please do not forget to replace “yourdomain.com” with the actual domain name you are setting up, in the above example code.

  • cd /var/www/vhosts
  • sudo chown -R apache:apache /var/www/vhosts
  • sudo chmod -R 775 /var/www/vhosts
  • sudo /etc/init.d/httpd configtest
  • sudo /etc/init.d/httpd restart

Apache Caching of Resources

If the website you are deploying is not a Drupal site, make sure to add the following inside the VirtualHost:

1
2
3
4
5
6
7
8
9
ExpiresActive On
ExpiresDefault "access plus 2 minutes"
ExpiresByType image/gif A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType image/png A2592000
ExpiresByType text/css A2592000
ExpiresByType application/x-javascript A2592000
ExpiresByType text/javascript A2592000
ExpiresByType application/x-shockwave-flash A2592000

You do not need to do this for Drupal. Drupal already does these in .htaccess, but Joomla, for instance, may not.

Configure Firewall

  • Edit /etc/sysconfig/iptables-config and make sure following variables are set to “yes”:
    • IPTABLES_SAVE_ON_STOP=“yes”
    • IPTABLES_SAVE_ON_RESTART=“yes”
    • Open Web ports:
    • sudo /sbin/iptables -I INPUT -p tcp -m state --state NEW,ESTABLISHED --dport 80 -j ACCEPT
    • sudo /sbin/iptables -I INPUT -p tcp -m state --state NEW,ESTABLISHED --dport 443 -j ACCEPT
  • Restart iptables with:

sudo /sbin/service iptables stopsudo /sbin/service iptables start

Recommended Settings for Performance Tuning

Performance and scalability tuning of a server is more of an art than science, in the sense that there’re no ready-to-use formulas. Optimal server settings depend on many unique factors: web-app code, traffic to the site, site’s information architecture among other things. It’s virtually impossible to really optimize server settings without thorough understanding of the web application and a lot of testing.

That said, you are not going to run newsweek.com or huffingtonpost.com on a 1GB or 2GB slice and the default settings are typically so off that it is possible to give you a much better starting point.

Following are some recommended settings that help maximize the utilization of the resources on a multi-core server of 1-2GB RAM size (like that on RackSpace cloud). Please note that these settings are just snippets from the respective configuration files and not the entire configuration file. Do not replace existing files with just these setting, rather edit the new settings into the files already created by previous installation steps.

In /etc/php.ini:

; Some of the larger CMSes are more memory-hungry than others. Set memory_limit to 128M for Drupal, you may need to bump it to 192M.<br>; More lightweight CMSes like WordPress may be fine at 64M<br>memory_limit = 128M<br>max_execution_time = 120<br>max_input_time =120.<br>realpath_cache_ttl=300<br>realpath_cache_size=1M

In /etc/my.cnf (warning: a snippet, not a full configuration):

skip-external-locking           = 1<br>skip-name-resolve<br>open-files-limit                = 20000<br><br>## Cache<br>thread-cache-size               = 16<br>table-open-cache                = 2048<br>table-definition-cache          = 512<br>query-cache-size                = 92M<br>query-cache-limit               = 8M<br><br>## Per-thread Buffers<br>sort-buffer-size                = 4M<br>read-buffer-size                = 2M<br>read-rnd-buffer-size            = 8M<br>join-buffer-size                = 4M<br><br>## Temp Tables<br>tmp-table-size                  = 64M<br>max-heap-table-size             = 64M<br><br>## Networking<br>back-log                        = 100<br>#max-connections                = 200<br>max-connect-errors              = 10000<br>max-allowed-packet              = 16M<br>interactive-timeout             = 600<br>wait-timeout                    = 600<br>skip-character-set-client-handshake<br>collation_server                = utf8_unicode_ci<br>character_set_server            = utf8<br><br>### Storage Engines<br>default-storage-engine         = InnoDB<br>innodb                          = FORCE<br><br>## MyISAM<br>key-buffer-size                 = 8M<br>myisam-sort-buffer-size         = 8M<br><br>## InnoDB<br>innodb-buffer-pool-size         = 16M<br>innodb-additional-mem-pool-size= 16M<br>innodb_log_files_in_group       = 2<br>innodb-log-buffer-size          = 4M<br>#innodb-flush-method            = O_DIRECT<br>innodb-file-per-table          = 1<br>#innodb-open-files              = 300<br>#innodb-thread-concurrency      = 16<br>#innodb-support-xa              = 0

In /etc/httpd/conf/httpd.conf

KeepAlive On<br>MaxKeepAliveRequests 100<br>KeepAliveTimeout 3

Disabling Swapping

Another thing that can adversely affect performance is if a server decides to start using swap partition for memory. On Linux, swap space is there to prevent running out of memory. However, Linux is somewhat frivolous in swapping, in that it may use swap even in the cases when it would not have ran out of memory. When linux uses swap for MySQL or Apache/PHP performance degrades significantly.

If you want to be absolutely sure that swapping never happens you can disable swap. This is dangerous because if you don’t properly project your maximum memory allocation you may run out of space and server will crash. But sometimes the risk is worth the benefit of running the server at top speed. To disable swap: edit the /etc/fstab file and find a record that looks like:

/dev/sda2               swap                    swap    defaults        0 0

The first column shows the partition used for swap: /dev/sda2. It may be different in your case. To disable swap put a comment character (”#” pound character) in front of that line and run the following command as root:

swapoff /dev/sda2

where the argument of “swapoff” should be the partition which swap was mounted on.

Static Cache

Another thing that could be a great idea for a small server is to put it behind a static-HTTP-cache like Varnish. That can really boost your scalability. Configuring Varnish is a complex and large topic that requires its own blog post, however.

Add Startup Scripts

  • HTTPD
    • sudo /sbin/chkconfig —add httpd
    • sudo /sbin/chkconfig —level 2345 httpd on
  • sudo /sbin/chkconfig —list httpd
  • MySQL
    • sudo /sbin/chkconfig —add mysqld
    • sudo /sbin/chkconfig —level 2345 mysqld on
  • sudo /sbin/chkconfig —list mysqld

Irakli Nadareishvili