How to setup a Centos 6/7 LAMP server correctly (or at least how I do it, needs work).
To check the centos version and system info, do this:
hostnamectl
To check the full release version, do this:
rpm --query centos-release
I would suggest you secure SSH first, if you mess up here you won't waste hours of setup if your provider needs to reset the server.
- Apache
/var/www
permissions and ACL- EPEL, Remi & MariaDB repositories & yum utils
- PHP 7.1, modules & composer
- phpMyAdmin
- MariaDB
- Fail2ban
- Ssh securing
- Sftp users
- Backups (rsync/rsnapshot)
- SSL certificates
- Virus scans
- Mailx
- Security (making a start)
As simple as:
yum install httpd
To modify the config:
/etc/httpd/conf/httpd.conf
To start the server:
sudo systemctl start httpd
To load it on boot:
sudo systemctl enable httpd
<VirtualHost *:80>
ServerAdmin admin@example.com
ServerName www.example.com
ServerAlias example.com
DocumentRoot /var/www/example.com/public_html
ErrorLog /var/log/httpd/example_com_error.log
CustomLog /var/log/httpd/example_com_requests.log combined
<Directory "/var/www/example.com/public_html">
AllowOverride All
php_value session.save_path "/var/www/example.com/phpsessions"
</Directory>
</VirtualHost>
Alias /appname /var/www/appname/public
<Directory "/var/www/appname/public">
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Set the parent folder to:
chmod 755 /var/www
chown root:apache /var/www
This is done to allow additional SFTP users.
Set contents to:
chmod -R 775 /var/www/*
chown -R apache:apache /var/www/*
Make sure selinux is on:
selinux 1
For details of settings see here:
sudo chcon -t httpd_sys_content_t /var/www -R
This will be required for folders like uploads or cache, allows httpd to read and write to files/directories.
sudo chcon -t httpd_sys_rw_content_t /var/www/[site-required-writes] -R
These are required to install PHP 7, fail2ban and other useful tools.
For CentOS 7:
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
For CentOS 6:
yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
yum install http://rpms.remirepo.net/enterprise/remi-release-6.rpm
yum install yum-utils
Create the repo file:
vi /etc/yum.repos.d/MariaDB.repo
Put this in the file for CentOS 7:
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
Put this in the file for CentOS 6:
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/centos6-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
INSTALL REMI & EPEL FIRST
To install:
yum-config-manager --enable remi-php71
yum install php php-mysql php-common php-devel php-enchant php-intl php-gd php-zip php-mcrypt php-posix php-fpm php-opcache php-mbstring php-pdo php-pspell php-soap php-xml php-xmlrpc php-pecl-ssh2 php-sqlite3 php-sodium
Alternatively, for 7.2 on Ubuntu (my dev machine):
sudo apt install php7.2 php7.2-mysql php7.2-common php7.2-enchant php7.2-intl php7.2-gd php7.2-zip php7.2-posix php7.2-fpm php7.2-opcache php7.2-mbstring php7.2-pdo php7.2-pspell php7.2-soap php7.2-xml php7.2-xmlrpc php7.2-pear php7.2-curl php7.2-sqlite3
Check the version:
php -v
Edit the .ini:
sudo vi /etc/php.ini
To install composer:
yum install composer
This should be loaded from the epel repo, in order to get the latest version.
phpMyAdmin needs installing from remi to work with PHP 7.
To enable Remi and install phpMyAdmin, run this:
yum --enablerepo=remi install phpmyadmin
To secure, first open the config file:
sudo vi /etc/httpd/conf.d/phpMyAdmin.conf
Set the alias by modifying this line:
Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /phpmyadmin /usr/share/phpMyAdmin
Generate a random string from https://passwordsgenerator.net/
Modify those lines as follows (replacing [RANDOM STRING] with your generated string):
#Alias /phpMyAdmin /usr/share/phpMyAdmin
Alias /[RANDOM STRING] /usr/share/phpMyAdmin
Make a note of the string, this will be used to access phpMyAdmin.
To allow external access, modify these lines:
<IfModule mod_authz_core.c>
# Apache 2.4
Require local
</IfModule>
<IfModule !mod_authz_core.c>
# Apache 2.2
Order Deny,Allow
Deny from All
Allow from 127.0.0.1
Allow from ::1
</IfModule>
Replace
Require local
With:
Order allow,deny
Allow from all
Require all granted
Replace:
Order Deny,Allow
Deny from All
Allow from 127.0.0.1
Allow from ::1
With:
Order allow,deny
Allow from All
Save file, restart apache:
sudo service httpd restart
You should now be able to access phpMyAdmin externally.
Check if installed:
rpm -qa | grep mariadb
INSTALL MARIADB REPOSITORY FIRST
To Install:
yum install MariaDB-server MariaDB-client -y
To Enable:
service mysqld start
chkconfig --level 35 mysqld on
service mysqld status
To setup (MAKE SURE TO RUN AS SUDO):
sudo mysql_secure_installation
Check version:
mysql -V
mysql --print-defaults
mysql -u root -p
INSTALL REMI & EPEL FIRST
Install:
yum install fail2ban
Enable:
systemctl enable fail2ban
Configure:
vi /etc/fail2ban/jail.local
[DEFAULT]
# Ban hosts for one hour:
bantime = 3600
# Override /etc/fail2ban/jail.d/00-firewalld.conf:
banaction = iptables-multiport
[sshd]
enabled = true
Restart:
systemctl restart fail2ban
Status:
fail2ban-client status
First, create a new user for root, set the password and add it to the sudoers file:
DO NOT SKIP THIS STEP OR YOU WILL BE LOCKED OUT
adduser username
passwd username
Add it to the sudoers group:
usermod -aG wheel username
su - username
sudo ls -la /root
Try modifying the sudoers file:
sudo vi /etc/sudoers
Add this line somewhere:
username ALL=(ALL) ALL
Re-check the user has sudo priviliges.
Modify the ssh config:
sudo vi /etc/ssh/sshd_config
Modify the following line to prevent root login:
# Prevent root logins:
PermitRootLogin no
Add the following line to limit SSH to the new user you created:
AllowUsers username
Restart the ssh service:
service sshd restart
https://wiki.centos.org/HowTos/Network/SecuringSSH
Add and set a new users password:
adduser username
passwd username
Add this user to the Apache group:
usermod -a -G apache username
Set the users home to /var/www
:
usermod -m -d /var/www username
Add the new user to those allowed to connect via SSH:
sudo vi /etc/ssh/sshd_config
AllowUsers [USERS] username
Restart the ssh service:
service sshd restart
Not going to go through setup for a backup machine, only how to get the backup machine baking your server up.
To setup a backup machine see here - https://www.howtoforge.com/installing-rsnapshot-on-centos
yum install rsnapshot
Login to your backup machine and open the config file:
vi /etc/rsnapshot.conf
Place the following in your config file (replace spaces with tabs):
backup [USER]@[SERVERIP]:/var/www/ [BACKUP_FOLDER_NAME]/
Then, generate an SSH key for you local machine using the user you defined as [ROOTUSER].
This is so your backup machine can connect without a password.
Create a key pair for your backup machines root user, don't use a passphrase and accept defaults:
ssh-keygen -t rsa
Copy this to your local machine:
ssh-copy-id -i ~/.ssh/id_rsa.pub [USER]@[SERVERIP]
Test it works:
ssh [USER]@[SERVERIP]
Setup cron, un-comment the bottom few lines (should look like code sample when done):
vi /etc/cron.d/rsnapshot
# This is a sample cron file for rsnapshot.
# The values used correspond to the examples in /etc/rsnapshot.conf.
# There you can also set the backup points and many other things.
#
# To activate this cron file you have to uncomment the lines below.
# Feel free to adapt it to your needs.
0 */4 * * * root /usr/bin/rsnapshot hourly
30 3 * * * root /usr/bin/rsnapshot daily
0 3 * * 1 root /usr/bin/rsnapshot weekly
30 2 1 * * root /usr/bin/rsnapshot monthly
Check it works:
rsnapshot -t hourly
If it looks ok, run your first backup:
rsnapshot hourly
To create an SQL backup (using Connor's script), first create a user that can select, show view, trigger, lock and read databases on the target machine (not modify).
Make sure the user is only accessible from the backup machines IP address.
Append the following line to sql_list.sh
:
sudo sh $1'scripts/sql.sh' [SERVER_IP] [SQL_USER] [SQL_PASS] [DB_NAME] $1
Job done.
CentOS 7 - https://certbot.eff.org/lets-encrypt/centosrhel7-apache.html
CentOS 6 - https://certbot.eff.org/lets-encrypt/centos6-apache.html
Generate a CSR:
https://support.rackspace.com/how-to/generate-a-csr-with-openssl/
Send the CSR to the SSL signing thing, get the certificates back.
Install said certificates:
Open httpd.conf:
/etc/httpd/conf/httpd.conf
Modify and paste the following code into your VirtualHost (or just in this file for the whole server):
SSLEngine on
SSLCertificateFile /etc/ssl/example.com.crt
SSLCertificateKeyFile /etc/ssl/example.com.key
SSLCertificateChainFile /etc/ssl/example.com.crt
Restart apache and test:
sudo service httpd restart
Virus scans are handled by ClamAV at the moment (free and open source).
For clamd
see this link for now - https://www.hostinger.com/tutorials/how-to-install-clamav-centos7
To have the logs mailed to you, make sure to install mailx
yum install clamav-server clamav-data clamav-update clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib clamav-server-systemd
Comment out example text:
sed -i -e "s/^Example/#Example/" /etc/freshclam.conf
sed -i -e "s/^Example/#Example/" /etc/clamd.d/scan.conf
Update database:
freshclam
First scan (test on home):
clamscan -r /home
Update database:
freshclam
Scan entire system (only notify viruses, ring bell when found):
clamscan -r --bell -i /
First, we create the daily scan script (entire system, change DIRTOSCAN
to narrow focus):
vi /root/clamscan_daily.sh
#!/bin/bash
LOGFILE="/var/log/clamav/clamav-$(date +'%Y-%m-%d').log";
EMAIL_MSG="Please see the log file attached.";
EMAIL_FROM="servername@domainname.com";
EMAIL_TO="webmaster@domainname.co.uk";
DIRTOSCAN="/var/www";
for S in ${DIRTOSCAN}; do
DIRSIZE=$(du -sh "$S" 2>/dev/null | cut -f1);
echo "Starting a daily scan of "$S" directory.
Amount of data to be scanned is "$DIRSIZE".";
freshclam
clamscan -ri "$S" >> "$LOGFILE";
# get the value of "Infected lines"
MALWARE=$(tail "$LOGFILE"|grep Infected|cut -d" " -f3);
# if the value is not equal to zero, send an email with the log file attached
if [ "$MALWARE" -ne "0" ];then
# using heirloom-mailx below
echo "$EMAIL_MSG"|mail -a "$LOGFILE" -s "[sysnotif]Malware Found" -r "$EMAIL_FROM" "$EMAIL_TO";
fi
done
exit 0
Then we add the log file directory:
mkdir /var/log/clamav
chmod 755 /var/log/clamav
Change the script permissions:
chmod 0755 /root/clamscan_daily.sh
Add to crontab:
ln /root/clamscan_daily.sh /etc/cron.daily/clamscan_daily
Test the script:
/root/clamscan_daily.sh
yum install mailx
Then create a symbolic link for mail
:
ln -s /bin/mailx /bin/email
Enable httpd to send mail in selinux:
setsebool httpd_can_sendmail 1
Then edit the config file to your requirements:
vi /etc/mail.rc
echo "Your message" | mail -v -s "Message Subject" email@address
https://coderwall.com/p/ez1x2w/send-mail-like-a-boss
- XSS header - https://kb.sucuri.net/warnings/hardening/headers-x-xss-protection
- content type sniffing header - https://kb.sucuri.net/warnings/hardening/headers-x-content-type
- STS header - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
- server banners (version nums) - https://kb.sucuri.net/warnings/hardening/disable-server-banners
- PHP version visible (
expose_php = Off
in php.ini) - https://secure.php.net/manual/en/ini.core.php
can cause issues if HTTPS is disabled, or non-HTTPS subdomains
https://stackoverflow.com/questions/24144552/how-to-set-hsts-header-from-htaccess-only-on-https
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options nosniff
</IfModule>