LAMP (Linux, Apache, MySQL, PHP) server from the scratch in an virtualized environment. There are many articles, but neither of them cover all the required steps. So far after each I had to troubleshoot many issues that weren’t even mentioned in the articles and that involves lot of searching and playing around. One of many issues came from SElinux security contexts. That supports my personal believe that many people just turn SElinux off when run into troubles and don’t care much about security, since those how-tos were aimed for development / sandbox servers for just playing and not real production usage. Otherwise there would be a troubleshooting info included, or not?
My motivation to write down this article is because I think I reinvented the wheel many times and sometimes running into same issues again. So I decided to compile all the information all-together into this one bulletproof how-to, so i can return to it and improve it over time and to prevent repeating mistakes in future. I see the clear benefits from sharing my know-how here, because you will definitely come up with some comments and bright ideas which could help me to improve it over time and maybe introduce new features inside installation. Also writing it down forces me to think about the correct order of the commands and include every change as it will come.
I want to have a production, enterprise grade, free, fast and secure linux. In other words I want to keep SElinux enabled and I would like to have it as minimal as possible and install only what is necessary. In my case webserver is virtualized in VMware vSphere Hypervisor (ESXi) environment – at the time of writing of this article HP’s customized ver4.1 hosted on an HP ProLiant DL380 G7 rack server HW with 16GB RAM, 6x146GB SAS/6G 15000rpm drives in RAID10 array. I’m preparing for an upgrade to version 5.0 and will share an how-to do it after that.
The designation of this system is to run custom developed PHP/MySQL CRM server and accounting software. Therefore there is some specific optimization for my environment included and I will especially mention those steps trough this how-to.
The requirements for the target system state are these:
- Free but enterprise-grade linux (done)
- httpd (Apache) including configuration:
- SSL support (done)
- targeting to /home/webroot directory (needs improvement)
- ServerName FDQN (needs insertion)
- http auto redirecting to https (needs improvement)
- PHP (done)
- MySQL (done)
- MySQL security hardening (needs improvement according to the script)
- vsftpd (FTP sever) including SFTP support and passive mode transfers, MySQL login/password authentication (needs improvement, currently missing SFTP and passive mode support)
- phpMyAdmin accessible trough HTTPS (needs improvement, allow access only trough https)
- midnight commander accessible trough SSH (done)
- SElinux enabled and security hardening performed, possibility to put the system into DMZ or directly on internet (done, needs testing)
- firewall enabled and configured (done)
- SSH enabled for remote administration via putty (done)
- Optimized performance (needs improvement)
- Scalable solution (done)
- Easy to maintain, support, backup trough cron and restore (needs improvement – I will provide backup scripts and cron part)
- Tested (needs more testing to claim it stable and secure)
Now let’s get to the thing:
I assume that you have up and running HW or virtual machine for this. I recommend you to allocate at least these specs. And remember – more is better!
- Production server:
- 4GB of RAM (8GB recommended)
- Dual-Core CPU (Quad-Core recommended especially if server is running in virtual environment)
- 40GB of storage (100GB recommended)
- stable and fast internet connectivity with low latency and no lags
- Development/testing server
- 2GB RAM should be enough
- 20GB of storage or more
- internet connectivity
- Sandbox with minimal configuration
- 512MB RAM
- 20GB of storage
- internet connectivity
First we have to do a netinstall CentOS v6.0 x86_64. I’m always performing this with a netinstall and choose minimal installation during setup wizard. This allow me to always quickly download the actual version of CentOS in minutes and perform basic installation very fast. It usually takes around 15-45 minutes depending on HW and internet connection speed. My choice of 64-bit architecture comes from that system will operate above 4GB RAM and probably more over the time. I also believe that x64 is slightly improving performance but it depends on the application. My favorite Linux distros are RHEL, CentOS, Fedora and Debian, but last year I always ended up with CentOS since it’s free and equal to RHEL. I use RHEL for middle and large enterprise deployments with high-availability and standardization demands, where 3rd level vendor support is crucial. But for many and many deployments the CentOS is a perfect free solution that will get the job done.
- Download an iso image with netinstall version of CentOS 6.0 according to the server architecture (can be found at mirror.centos.org). I’ve used this one.
- Burn the iso onto CD/DVD, write it to USB drive, or mount it trough remote management of the server (iLO for HP or DRAC for Dell). If you use VMware you can mount it via VMware vSphere client.
- Setup your computer system’s BIOS to boot from media where you stored the image or use the boot menu feature. In VMware vCenter client, you can press Escape key during BIOS POST boot-up sequence – and you have to be very fast 😉 otherwise it will take more than one try…
- Boot into installation
- Select “Install or upgrade an existing system” (first choice) by just pressing enter.
- You can test you iso downloaded media if it is not corrupted. I prefer to test.
- Choose URL as Installation Method
- Configure TCP/IP (DHCP or manual)
- During URL setup you will have to enter the path to server, where installation files resides. This can be any from CentOS mirrors. I use this path, because it’s easy to remember: http://mirror.centos.org/centos/6.0/os/x86_64. Be sure to check the processor architecture, this one is for Intel/AMD 64 bit.
- The setup will download necessary files and proceed onto welcome screen
- Then you can proceed trough installation steps according to this article, starting up with step 5 and ending up with step 22 from that article and returning back here. No need to reinvent the wheel ;).
- That’s it, we have minimal CentOS 6 installation up and running
- Now we can proceed into LAMP installation and configuration:
- Be sure you’ve issued update command as a root user before continuing, it will update whole system and load patches since the iso initial release:
yum -y update
- Install required packages (be sure to copy the whole line):
yum -y install mc httpd mysql-server php php-mysql mysql php-mbstring php-pear php-pecl-apc php-xml php-imap yum-priorities php-pecl-zip php-gd php-ldap mod_ssl openssl vsftpd pam_mysql
- Install the support for EPEL repository:
rpm -hUv http://download.fedora.redhat.com/pub/epel/6/x86_64/epel-release-6-5.noarch.rpm
- Generate private key for Apache:
openssl genrsa -out ca.key 1024
- Generate CSR for Apache:
openssl req -new -key ca.key -out ca.csr
- Generate Self Signed Key:
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
- Copy the files to the correct locations:
cp ca.crt /etc/pki/tls/certs cp ca.key /etc/pki/tls/private/ca.key cp ca.csr /etc/pki/tls/private/ca.csr
- Then we need to update the Apache SSL configuration file:
vi /etc/httpd/conf.d/ssl.conf
# Change the paths to match where the Key file is stored. If you've # used the method above it will be: SSLCertificateFile /etc/pki/tls/certs/ca.crt # Then set the correct path for the Certificate Key File a few lines # below. If you've followed the instructions above it is: SSLCertificateKeyFile /etc/pki/tls/private/ca.key # Quit and save
- Enable MySQL daemon auto start-up with system:
chkconfig mysqld on
- Start MySQL daemon:
service mysqld start
- Connect locally to MySQL CLI:
mysql -h 127.0.0.1 -u root
- List all users in MySQL. You should perform the root password setting for each line as described below:
select user,host,password from mysql.user;
- Set the MySQL root password for localhost connections. Remember to use only sensible SAFE passwords! Most of people will use the same password for all three steps:
set password for root@localhost=password('desiredmysqlrootpassword');
- Set the MySQL root password for 127.0.0.1 loopback connections:
set password for root@'127.0.0.1'=password('desiredmysqlrootpassword');
- Set the MySQL root password for your hostname loopback connections. Remeber to replace hostname for the one you have entered during CentOS installation. In the future, you should perform this security step for each internet realm/domain name you will need to be accessed from:
set password for root@'hostname'=password('desiredmysqlrootpassword');
- Delete anonymous users:
delete from mysql.user where user='';
- Print the final MySQL user table:
select user,host,password from mysql.user;
- Exit the MySQL CLI:
exit;
- Start the MySQL CLI (be sure to use -h 127.0.0.1, because MySQL from CentOS rpm repository doesnt support IPv6, although localhost is mapped to an IPv6 address:
mysql -h 127.0.0.1 -u root –p
# Perform these commands onto MySQL CLI: CREATE DATABASE vsftpd; USE vsftpd; GRANT SELECT ON vsftpd.* TO 'vsftpd'@'127.0.0.1' IDENTIFIED BY 'vsftpdpassword'; FLUSH PRIVILEGES; CREATE TABLE `accounts` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `username` VARCHAR( 30 ) NOT NULL , `pass` VARCHAR( 50 ) NOT NULL , UNIQUE (`username`) ) ENGINE = MYISAM ; INSERT INTO accounts (username, pass) VALUES('ftpdesiredusername', md5('ftpdesiredpassword')); exit;
- Add vsftpd system account:
useradd -G users -s /bin/false -d /home/vsftpd vsftpd
- Backup the vsftpd backup file content:
cp -v /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf-orig
- Empty the config file:
> /etc/vsftpd/vsftpd.conf
- Edit the vsftpd config file:
vi /etc/vsftpd/vsftpd.conf
# Enter this into vsftpd.conf file: # No ANONYMOUS users allowed anonymous_enable=NO # Allow 'local' users with WRITE permissions (0755) local_enable=YES write_enable=YES local_umask=022 dirmessage_enable=YES xferlog_enable=YES # if you want to LOG vsftpd activity then uncomment this log_ftp_protocol # log_ftp_protocol=YES connect_from_port_20=YES # uncomment xferlog_file and xferlog_std_format if you DIDN'T use the line above # with log_ftp_protocol - it must be excluding each other # The name of log file when xferlog_enable=YES and xferlog_std_format=YES # WARNING - changing this filename affects /etc/logrotate.d/vsftpd.log #xferlog_file=/var/log/xferlog # # xferlog_std_format Switches between logging into vsftpd_log_file and xferlog_file files. # NO writes to vsftpd_log_file, YES to xferlog_file # xferlog_std_format=YES # # You may change the default value for timing out an idle session (in seconds). #idle_session_timeout=600 # # You may change the default value for timing out a data connection (in seconds). #data_connection_timeout=120 # # define a unique user on your system which the # ftp server can use as a totally isolated and unprivileged user. nopriv_user=vsftpd chroot_local_user=YES listen=YES # here we use the authentication module for vsftpd to check users name and passw pam_service_name=vsftpd userlist_enable=YES tcp_wrappers=YES # here the vsftpd will allow the 'vsftpd' user to login into the # '/home/vsftpd/$USER' directory guest_enable=YES guest_username=vsftpd local_root=/home/vsftpd/$USER user_sub_token=$USER virtual_use_local_privs=YES user_config_dir=/etc/vsftpd/vsftpd_user_conf
- Create directory with user configuration files:
mkdir /etc/vsftpd/vsftpd_user_conf
- Edit ftp user configuration:
vi /etc/vsftpd/vsftpd_user_conf/ftpusername
dirlist_enable=YES download_enable=YES # full path to the directory where 'ftpusername' will have access, change to your needs local_root=/home/webroot write_enable=YES
- Create webroot directory:
mkdir /home/webroot
- Allow full permissions for owner:
chmod 700 /home/webroot
- Change owner:
chown vsftpd:users /home/webroot
- Backup pam.d vsftpd authentication profile file:
cp /etc/pam.d/vsftpd /etc/pam.d/vsftpd-orig
- Erase vsftpd pam.d auth config file:
cat /dev/null > /etc/pam.d/vsftpd
- Edit file /etc/pam.d/vsftpd:
vi /etc/pam.d/vsftpd
# Insert the lines below into the file: #%PAM-1.0 session optional pam_keyinit.so force revoke auth required pam_mysql.so user=vsftpd passwd=vsftpdpassword host=127.0.0.1 db=vsftpd table=accounts usercolumn=username passwdcolumn=pass crypt=3 account required pam_mysql.so user=vsftpd passwd=vsftpdpassword host=127.0.0.1 db=vsftpd table=accounts usercolumn=username passwdcolumn=pass crypt=3
- SElinux: Allow ftp daemon to connect to database to obtain user logins and passwords:
setsebool -P ftpd_connect_db 1
- SElinux: Change security context to webroot directory:
chcon -R -t public_content_rw_t /home/webroot
- SElinux: Change security context to webroot to be accessible for Apache
setsebool -P allow_httpd_anon_write 1
- SElinux: Allow ftp daemon to access webroot
setsebool -P ftp_home_dir 1
setsebool -P allow_ftpd_anon_write 1
- Edit the firewall settings so you can get onto desired ports:
vi /etc/sysconfig/iptables
# You should end up with iptables file something like this. You will have to add lines if you wanna enable more ports, or on the contrary remove the ports not needed: *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [2:516] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT # SSH -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT # HTTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT # HTTPS -A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT # FTP -A INPUT -p tcp -m state --state NEW -m tcp --dport 20 -j ACCEPT # SFTP -A INPUT -j REJECT --reject-with icmp-host-prohibited # reject all other traffic (its important to have this line at the end of the port opening rules, otherwise firewall will drop the packets before they even got to the rule -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMIT
- Start Apache daemon:
service httpd start
- Restart affected services:
service iptables restart service vsftpd restart
- Reboot the system
reboot
- Test the apache/php
Resources used to develop this article:
http://techspotting.org/how-to-install-centos-6-linux-for-servers-desktops
http://www.chrisgountanis.com/technical/45-centos-netinstall.html
http://wiki.centos.org/HowTos/VirtualVsFtpd
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
http://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-autotasks-cron-configuring.html
http://www.server-world.info/en/note?os=CentOS_6&p=mysql
Recent Comments