You bought a new dedicated server or vps and want to avoid the hassle of setting it up to host Drupal sites, I done the work for you, I kept a history of all commands I used to setup a newly installed CentOS-5.5-x86 server.

In a few minutes you will get your server ready with all packages needed for Drupal.

IMPORTANT:

  1. Some code snippets need to be run in your local machine, other in the server, some with root account and some with "yourusername" account, so pay attention to lines before code snippets explaining how to run them.
  2. First lines of code snippets contain variable declarations, so before pasting the code snippet to your terminal, paste it in your text editor and modify the variables according to your needs. It is advisable to use a text editor with syntax highlighting for bash.
  3. The drupal.org site formatting turns web addresses automatically to links and trims long ones, so pay attention to this and correct links before pasting to your terminal.

Notes:

  1. Lines in code end with "\" , this way you can copy all snippet commands at once instead of copying each command individually.
  2. Code snippets contain inline comments (starting with #) to help you understand some commands, don't worry about them, they'll be ignored in code execution.

So let's start:

On local machine:

edit the SSH known_hosts file and remove any entries that point to your server IP address if any. It is easier to clear everything using:

echo "" > ~/.ssh/known_hosts


On server as root:

`# Please ensure that the following settings are set correctly:`;\
USER='admin' `# choose a username`; SSH_PORT='7326' `# choose a port to replace the default 22 for better security`;\
TIME_ZONE='Africa/Algiers' `# find your time zone here /usr/share/zoneinfo/`; SUDO_PASSWD_TIMEOUT='20';\
\
useradd $USER; passwd $USER; usermod -a -G wheel,apache $USER;\
rm -f /etc/localtime; ln -s /usr/share/zoneinfo/$TIME_ZONE /etc/localtime;\
yum -y remove sendmail `# we'll install postfix later`; yum -y update `# update system`;\
sed -i 's/^#\s*\(%wheel\s*ALL=(ALL)\s*ALL\)$/\1/' /etc/sudoers `# allow wheel group members to run all commands`;\
echo -e "\n# Set sudo timeout\nDefaults passwd_timeout=$SUDO_PASSWD_TIMEOUT\n" >> /etc/sudoers;\
sed -i "s/^#\s*\(Port\s*\)22$/\1 $SSH_PORT/" /etc/ssh/sshd_config;\
sed -i 's/^#\s*\(PermitRootLogin\s*\)yes$/\1no/' /etc/ssh/sshd_config `# forbid root ssh login`;\
echo -e "\n# Prevent timeout\nClientAliveInterval 60\n" >> /etc/ssh/sshd_config `# for better security don't use this if you often login from public stations` ;\
/etc/init.d/sshd reload;\


On local machine:

USER='admin' `# your server username`; HOST='yourdomain.com'; SSH_PORT='7326' `# ssh port you have set on the server`;\
ssh-copy-id "-p $SSH_PORT ${USER}@${HOST}"; ssh -p $SSH_PORT ${USER}@${HOST} `#on success you can close server root connection` ;\


On server logged in with your username:

USER='admin' `# your server username`; HOST='yourdomain.com' ;\
\
`# REPOSITORIES:`;\
sudo chown -R $USER:root /etc/yum.repos.d/ ;\
\
`# c5-testing repo:`; if [ ! -f "/etc/yum.repos.d/CentOS-Testing.repo" ]; then sudo echo -e "\
# CentOS-Testing:\n\
# !!!! CAUTION !!!!\n\
# This repository is a proving grounds for packages on their way to CentOSPlus and CentOS Extras.\n\
# They may or may not replace core CentOS packages, and are not guaranteed to function properly.\n\
# These packages build and install, but are waiting for feedback from testers as to\n\
# functionality and stability. Packages in this repository will come and go during the\n\
# development period, so it should not be left enabled or used on production systems without due\n\
# consideration.\n\
[c5-testing]\n\
name=CentOS-5 Testing\n\
baseurl=http://dev.centos.org/centos/\$releasever/testing/\$basearch/\n\
enabled=0\n\
gpgcheck=1\n\
gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing\n\
includepkgs=php*\n\
" > /etc/yum.repos.d/CentOS-Testing.repo; fi ;\
\
`# epel repo:`;\
sudo rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/`uname -i`/epel-release-5-4.noarch.rpm;\
`# disable epel repo:`; sudo sed -i 's/^\s*enabled\s*=\s*1\s*$/enabled=0/' /etc/yum.repos.d/epel.repo;\
\
`# set repo priorities:`;\
sudo yum -y install yum-priorities;\
sudo sed -i 's/^\s*\(enabled.*\)\s*$/\1\npriority=1/' /etc/yum.repos.d/CentOS-Base.repo;\
sudo sed -i 's/^\s*\(enabled.*\)\s*$/\1\npriority=21/' /etc/yum.repos.d/epel.repo;\
\
sudo chown -R root:root /etc/yum.repos.d/ ;\
\
`# INSTALLATION`;\
`# install from default repos:`; sudo yum -y install mysql-server postfix gcc httpd-devel patch curl ;\
`# install with testing repo enabled:`; sudo yum -y --enablerepo="c5-testing" install php php-mysql php-devel php-gd php-pear php-mbstring php-xml php-xmlrpc php-pdo php-mcrypt ;\
`# install with epel repo enabled:`; sudo yum -y --enablerepo="epel" install git mod_security phpmyadmin php-geshi ;\
`# install with pecl:`; echo -e "yes\n" | sudo pecl install apc uploadprogress; sudo chown -R $USER:root /etc/php.d/ ;\
sudo echo "extension=apc.so" > /etc/php.d/apc.ini; sudo echo "extension=uploadprogress.so" > /etc/php.d/uploadprogress.ini;\
\
`# CONFIGURATION`;\
`# php:`;\
sudo echo -e "memory_limit = 60M\nmax_execution_time = 100\nmax_upload_size = 50M\npost_max_size = 50M\nupload_max_filesize = 50M\nexpose_php = Off" > /etc/php.d/custom-php-settings.ini ;\
sudo chown -R root:root /etc/php.d/ ;\
\
`# apache:`;\
`# you can later edit /etc/httpd/conf.d/zzz-custom.conf and adjust prefork settings according to your server resources (RAM and CPU)`;\
`# we will specify a virtualhost to access /var/www , access will be limited to connections from inside the server only for security, you'll be able to browse it from your local machine via ssh tunnelling (explained later)`;\
sudo chown -R $USER:root /etc/httpd/conf.d/ ;\
sudo echo -e "ServerSignature Off\nServerTokens Prod\n\nTimeout 45\nMaxKeepAliveRequests 100\nKeepAliveTimeout 10\n\n<IfModule prefork.c>\n  StartServers 6\n  MinSpareServers 4\n  MaxSpareServers 10\n  ServerLimit 100\n  MaxClients 100\n  MaxRequestsPerChild 2000\n</IfModule>\n\n" > /etc/httpd/conf.d/zzz-custom.conf ;\
sudo echo -e "<IfModule mod_deflate.c>\n  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript\n</IfModule>\n\n\
<IfModule mod_expires.c>\n\
  ExpiresActive On\n\
  ExpiresByType application/x-javascript 'access plus 2 month'\n\
  ExpiresByType text/css 'access plus 2 months'\n\
\n\
  ExpiresByType image/gif 'access plus 3 months'\n\
  ExpiresByType image/png 'access plus 3 months'\n\
  ExpiresByType image/jpg 'access plus 3 months'\n\
  ExpiresByType image/jpeg 'access plus 3 months'\n\
  ExpiresByType image/x-icon 'access plus 3 months'\n\
  ExpiresByType application/x-shockwave-flash 'access plus 3 months'\n\
\n\
  ExpiresByType application/pdf 'access plus 3 months'\n\
\n\
  ExpiresByType audio/x-wav 'access plus 6 months'\n\
  ExpiresByType audio/mpeg 'access plus 6 months'\n\
  ExpiresByType video/mpeg 'access plus 6 months'\n\
  ExpiresByType video/mp4 'access plus 6 months'\n\
  ExpiresByType video/quicktime 'access plus 6 months'\n\
  ExpiresByType video/avi 'access plus 6 months'\n\
</IfModule>" >> /etc/httpd/conf.d/zzz-custom.conf ;\
sudo echo -e "ErrorDocument 403 /error/403.php\nErrorDocument 404 \"Not Found\"\n\n\
<Directory />\n\
  Order Allow,Deny\n\
</Directory>\n\n\
NameVirtualHost *:80\n\n\
<VirtualHost *:80>\n\
  ServerName localhost\n\n\
  DocumentRoot /var/www\n\
  <Directory /var/www>\n\
    Options Indexes FollowSymLinks\n\
    Order Allow,Deny\n\
    Allow from 127.0.0.1\n\
  </Directory>\n\
</VirtualHost>\n\n" >> /etc/httpd/conf.d/zzz-custom.conf ;\
sudo mkdir -p /etc/httpd/conf.d/custom/sites ;\
sudo echo -e "Include conf.d/custom/sites/*.conf\nInclude conf.d/custom/*.conf\n\n" >> /etc/httpd/conf.d/zzz-custom.conf ;\
sudo mv /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.bkp ;\
sudo chown -R $USER:apache /var/www ; find /var/www/ -type d -exec sudo chmod u=rwx,g=rxs,o= {} \; ; find /var/www/ -type f -exec sudo chmod u=rw,g=r,o= {} \; ;\
sudo echo -e "Site is currently under maintenance. Sorry for any inconvenience." > /var/www/html/index.html ;\
sudo echo -e "<?php sleep(30); // to slow down spambots ?>\n\
<html><head><meta name=\"robots\" content=\"nofollow\" /></head><body>\n\
<div><a href=http://english-205167422955.spampoison.com></a><a href=http://www.spamhelp.org/harvesterkiller/></a>\n\
<a href=http://www.searchbliss.com/spambot/spambot-stopper.asp></a><div>Forbidden</div><a href=http://zzzy.freeshell.org/guestbook/></a>\n\
</div></body></html>" > /var/www/error/403.php ;\
sudo chown -R root:root /etc/httpd/conf.d/ ;\
\
`# modsecurity:`;\
sudo mkdir -p /var/log/httpd/modsecurity/data ; sudo chmod -R u=rwx,g=,o= /var/log/httpd/modsecurity ; sudo chown  apache /var/log/httpd/modsecurity/data ;\
sudo chown -R $USER:root /etc/httpd/ ;\
sudo rm -rf /etc/httpd/modsecurity.d ;\
sudo wget -O /etc/httpd/modsecurity.d.tar.gz http://space.dl.sourceforge.net/project/mod-security/modsecurity-crs/0-CURRENT/modsecurity-crs_2.0.8.tar.gz `# change with current version`;\
sudo tar xzf /etc/httpd/modsecurity.d.tar.gz -C /etc/httpd ; find /etc/httpd/ -maxdepth 1 -type d -name modsecurity-crs* -exec sudo mv {} /etc/httpd/modsecurity.d \; ; sudo chown -R $USER:root /etc/httpd/modsecurity.d ; sudo rm -f /etc/httpd/modsecurity.d.tar.gz ;\
`# uncomment 'SecAuditEngine On' and increase debug level to get more detailed logs,  but be aware it will consume system resources and slow the server so use on a temporary basis`;\
sudo echo -e "\n# Drop your local rules in here.\n\n\
#SecAuditEngine On\n\
SecAuditLog /var/log/httpd/modsecurity/audit.log\n\
SecDebugLogLevel 0\n\
SecDebugLog /var/log/httpd/modsecurity/debug.log\n\
SecDataDir /var/log/httpd/modsecurity/data\n\n\
SecRuleEngine On\n\
SecDefaultAction phase:2,log,auditlog,deny,status:403\n\n\
SecServerSignature \" \"\n" > /etc/httpd/modsecurity.d/modsecurity_localrules.conf ;\
sudo chown -R root:root /etc/httpd/ ;\
sudo /etc/init.d/httpd restart ;\
\
`# logrotate: (limiting apache log files size for better handling)`;\
sudo sed -i 's/^\s*\(\/var\/log\/httpd\/\*log\s*{\)\s*$/\1\n    size 100k\n    rotate 50/' /etc/logrotate.d/httpd ;\
\
`# mysql:`;\
`# enable query cache:`; sudo sed -i 's/^\(\[mysqld\]\)$/\1\n\nquery_cache_type=1\nquery_cache_size=32M\nquery_cache_limit=1M\n/' /etc/my.cnf ;\
sudo /etc/init.d/mysqld start ; sudo mysql_secure_installation ;\
\
`# generating keys:`; ssh-keygen -t rsa ;\
\
`# add contents of "bashrc-custom-settings.txt" to ".bashrc"`;\
nano ~/.bashrc;source ~/.bashrc;\
\
`# Drupal installation:`;\
sudo mkdir /etc/httpd/conf.d/custom/drupal;\
sudo chown -R $USER:root /etc/httpd/conf.d/ ;\
sudo echo -e "\
<Directory /var/www/live/drupal/d6>\n\
  # Loading Drupal's .htaccess into memory gives better performance\n\
  AllowOverride None\n\
  Include /var/www/live/drupal/d6/.htaccess\n\
</Directory>\n\n\
# Allow the .htaccess files to be used in the sites folder where /files are stored\n\
<Directory /var/www/live/drupal/d6/sites>\n\
  AllowOverride All\n\
</Directory>\n\n\
<IfModule mod_security2.c>\n\
  SecRuleRemoveByMsg \"Too many arguments in request\"\n\
</IfModule>\n\n" > /etc/httpd/conf.d/custom/drupal/d6.conf ;\
sudo echo -e "\
<Directory /var/www/live/drupal/d7>\n\
  # Loading Drupal's .htaccess into memory gives better performance\n\
  AllowOverride None\n\
  Include /var/www/live/drupal/d7/.htaccess\n\
</Directory>\n\n\
# Allow the .htaccess files to be used in the sites folder where /files are stored\n\
<Directory /var/www/live/drupal/d7/sites>\n\
  AllowOverride All\n\
</Directory>\n\n\
<IfModule mod_security2.c>\n\
  SecRuleRemoveByMsg \"Too many arguments in request\"\n\
</IfModule>\n\n" > /etc/httpd/conf.d/custom/drupal/d7.conf ;\
\
sudo echo -e "<VirtualHost *:80>\n\
  ServerName $HOST\n\
  ServerAlias www.$HOST\n\n\
  DocumentRoot /var/www/live/drupal/d6\n\
  <Directory /var/www/live/drupal/d6>\n\
    Order Allow,Deny\n\
    Allow from all\n\
  </Directory>\n\n\
  # Rewrite the www\n\
  RewriteEngine on\n\
  RewriteCond %{HTTP_HOST} ^www\.${HOST//\./\\\.}$ [NC]\n\
  RewriteRule ^(.*)$ http://$HOST$1 [L,R=301]\n\n\
  Include conf.d/custom/drupal/d6.conf\n\
</VirtualHost>\n" > /etc/httpd/conf.d/custom/sites/$HOST.conf ;\
sudo chown -R root:root /etc/httpd/conf.d/ ;\
sudo mkdir -p /var/www/live/drupal ;\
sudo wget -O /var/www/live/drupal/d6.tar.gz http://ftp.drupal.org/files/projects/drupal-6.19.tar.gz `# change with current drupal version`;\
sudo tar xzf /var/www/live/drupal/d6.tar.gz -C /var/www/live/drupal ; find /var/www/live/drupal/ -maxdepth 1 -type d -name drupal-6* -exec sudo mv {} /var/www/live/drupal/d6 \; ; sudo rm -f /var/www/live/drupal/d6.tar.gz ;\
sudo wget -O /var/www/live/drupal/d7.tar.gz http://ftp.drupal.org/files/projects/drupal-7.0-beta2.tar.gz `# change with current drupal version`;\
sudo tar xzf /var/www/live/drupal/d7.tar.gz -C /var/www/live/drupal ; find /var/www/live/drupal/ -maxdepth 1 -type d -name drupal-7* -exec sudo mv {} /var/www/live/drupal/d7 \; ; sudo rm -f /var/www/live/drupal/d7.tar.gz ;\
sudo chown -R $USER:apache /var/www ; find /var/www/ -type d -exec sudo chmod u=rwx,g=rxs,o= {} \; ; find /var/www/ -type f -exec sudo chmod u=rw,g=r,o= {} \; ;\
\
`# Drush installation:`;\
sudo wget -O ~/drush.tar.gz http://ftp.drupal.org/files/projects/drush-6.x-3.3.tar.gz `# change with current drush version`;\
sudo tar xzf ~/drush.tar.gz  -C ~ ; sudo rm -f ~/drush.tar.gz ; sudo chown -R $USER:$USER ~/drush ;\
sudo chown $USER /usr/local/bin ; sudo chmod u+x  ~/drush/drush ; ln -s ~/drush/drush /usr/local/bin/drush ; sudo chown -R root:root /usr/local/bin ;\
sudo pear channel-update pear.php.net ; sudo pear install -a Console_Table ;\
\


On server logged in with your username:

edit "/etc/httpd/conf.d/zzz-custom.conf" to adjust prefork settings according to your server resources (RAM and CPU) see here

sudo nano /etc/httpd/conf.d/zzz-custom.conf ;\


On server as root:

(use su - to gain root privileges)
The following will make MySql start automatically at boot

chkconfig mysqld on ;\


All done! now reboot the server.

Note:

As mentioned in code above we will explain how to use ssh tunnelling to browse locations in your webserver, it is advisable not to expose sensitive locations in your server ( like "phpMyAdmin" ) to the outside world, instead allow access to them only from inside the server (localhost, 127.0.0.1) and use ssh tunnelling to access them, to do this just ssh to your server with "-L" option:
example: ssh -L 15112:localhost:80 -p 7326 yourusername@yourdomain.com (change 7326 with your server ssh port)
then point your web browser to http://localhost:15112 (15112 is an example, you can choose another port)




Feedback is highly appreciated

Comments

real_ate’s picture

you mention a line:

# add contents of "bashrc-custom-settings.txt" to ".bashrc"

which opens up nano on .bashrc what exactly are you supposed to put in .bashrc at this stage?

ahwebd’s picture

Oh thank you, I should've removed that line from code above, I used it for myself to add my custom bash settings ( like aliases ... ) but because you asked, here are my custom bash settings :

#=======================
# custom settings: BEGIN
#=======================
# Settings for history function
export HISTFILESIZE=50000
export HISTSIZE=50000
export HISTCONTROL=ignoreboth:erasedups
export HISTIGNORE='\&:e:c:l:ca:cd:cd -'

# Make history work well with multiple shells
# append to the history file, don't overwrite it
shopt -s histappend

# Bind up/down arrow to history search
bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'

# custom aliases
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias .....='cd ../../../..'
alias .....='cd ../../../../..'
alias cd..='cd ..'
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias l='ls -lhaF'
alias ll='ls -lhaF | less'
alias lt='ls -lhatF'
alias llt='ls -lhatF | less'
alias c='clear'
alias e='exit'
alias tx='tar -xvzf'
alias tc='tar -cvzf'

alias cdl='cd /var/www/live'
alias cdd='cd /var/www/dev'

# git
alias g='git'

# drush
alias d='drush'

#yum
alias y='sudo yum'

#=====================
# custom settings: END
#=====================

I hope you find it useful

bwynants’s picture

very welcome instructions.

most of it is working fine, surfing to the server via the ssh tunneling works. but i'm not able to surf to the system without the tunnel and using http://www.server.local as url

I always end up on the 'Forbidden' page. When I disable the mod_security I land on the drupal 6 install page when I type http://www.server.local

Any pointer on what could be wrong with my mod_security setup? ( I explicit installed mod_security 2.0.8)

bwynants’s picture

apc will not compile on centos 5

pcre-devel needs to be installed before compilation of apc

http://www.accella.net/installing-apc-on-centos-5/

So I changed

`# install from default repos:`; sudo yum -y install mysql-server postfix gcc httpd-devel patch curl pcre-devel;\