This is my entire setup process from start to finish. Although there are lots of guides on setting up a webserver with the basic software, they don't often cover the more practical decisions like where web files should be stored and how they are updated. Hopefully this guide should be of some help, if only to show how I have chosen to go.
EC2
I have used the official " CentOS 7 (x86_64) with Updates HVM" AMI. I will leave setting up and booting an EC2 image to other guides.
Initial
login as: centos
# Authenticating with public key...
sudo yum update
# Install your favourite text editor
sudo yum install nano
Root User
# Check that root login and password auth is disabled as using SSH keys
sudo nano /etc/ssh/sshd_config
# PermitRootLogin no
# PasswordAuthentication no
sudo nano /root/.ssh/authorized_keys
# Here you will find a message telling you to login with user 'centos' rather than root, followed by the SSH key
# Remove this whole line and paste in a secondary root SSH key
# The remaining guide will assume you are logged in as root
nano ~/.bashrc
export VISUAL=nano
export EDITOR="$VISUAL"
Swap Memory
# Small EC2 instances come with very limited memory, without a swap file everything will work fine until you run out of memory and then suddenly grind to a halt!
dd if=/dev/zero of=/var/swapfile bs=1M count=2048
chmod 600 /var/swapfile
mkswap /var/swapfile
echo /var/swapfile swap swap sw 0 0 | sudo tee -a /etc/fstab
swapon -a
swapon -s
# Filename Type Size Used Priority
# /var/swapfile file 2097148 4 -1
Apache
sudo yum install -y httpd
# Start and enable at boot
sudo systemctl enabme --now httpd.service
PHP 7.3
yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum install -y yum-utils
yum-config-manager --enable remi-php73
# ==== repo: remi-php73 ====
[remi-php73]
...
yum install php
php -v
# PHP 7.3...
MariaDB 10.4
# https://downloads.mariadb.org/mariadb/repositories/#mirror=digitalocean-lon&distro=CentOS&distro_release=centos7-amd64--centos7&version=10.0
nano /etc/yum.repos.d/mariadb10.repo
yum install MariaDB-server MariaDB-client
# Set the default encoding to utf8
nano /etc/my.cnf
[client]
default-character-set=utf8
[mysqld]
character-set-server=utf8
collation-server = utf8_unicode_ci
init-connect='SET NAMES utf8'
systemctl enable --now mariadb.service
# mysql.service is not a native service, redirecting to /sbin/chkconfig...
# Although it looks like an error it has worked!
# Run mariadb initial secure script to go through setting up root password etc. https://mariadb.com/blog/installing-mariadb-10-centos-7-rhel-7
mysql_secure_installation
# Test root login
mysql -u root -p
phpMyAdmin
yum-config-manager --enable remi
yum install phpMyAdmin
# allow remote access
nano /etc/httpd/conf.d/phpMyAdmin.conf
# Fill in your IP, if you do not have a static IP then you should use other methods of security, such as SSH access or htpasswd
<IfModule mod_authz_core.c>
# Apache 2.4
Require ip XXX.XXX.XXX.XXX
</IfModule>
systemctl reload httpd.service
# GoTo http://chrishewett.com/phpmyadmin/
Users
I like to use a new user for each site I host on the server. For this small site the development and production versions of the website will be hosted on the same server. This makes it necessary to do virtual sites (which I think you should always use from the beginning anyway)
mkdir /home/sites/
sudo useradd chrishewett_com -d /home/sites/chrishewett_com -m
# To remove the need to run an FTP server to update the files I will be using SFTP so users need an ssh key adding
sudo su -c "mkdir -p /home/sites/chrishewett_com/.ssh/" chrishewett_com
sudo su -c "nano /home/sites/chrishewett_com/.ssh/authorized_keys" chrishewett_com
# Paste in public key from puttygen etc.
# Set the correct rw permissions
sudo chmod go-w /home/sites/chrishewett_com/ /home/sites/chrishewett_com/.ssh/ /home/sites/chrishewett_com/.ssh/authorized_keys
# Set the correct SELINUX permissions
sudo chcon -v -R --type=ssh_home_t /home/sites/chrishewett_com/.ssh/
Folders
Although tempting, it is not a good idea to create the app folder structure in the root of the users directory. This contains linux user specific items e.g. .bashrc and .ssh/ which would have to be manually ignored when copying / adding to version control.
# Add app folder
sudo su -c "mkdir -p /home/sites/chrishewett_com/web/" chrishewett_com
# set SELinux permissions
sudo chcon -v --type=httpd_sys_content_t /home/sites/chrishewett_com/ /home/sites/chrishewett_com/web/
# set directory permissions
sudo chmod 755 /home/sites/chrishewett_com/ /home/sites/chrishewett_com/web/
# add test page to site
sudo su -c "nano /home/sites/chrishewett_com/web/index.php" chrishewett_com
# <?= 1; //add this line to the file - if it shows '1' as the output then php is parsing
httpd.conf
nano /etc/httpd/conf/httpd.conf
<VirtualHost *:80>
ServerName chrishewett.com
ServerAlias www.chrishewett.com
DocumentRoot /home/sites/chrishewett_com/web
DirectoryIndex index.php
<Directory /home/sites/chrishewett_com/web/>
AddType application/x-httpd-php .php
Options +ExecCGI +Indexes +IncludesNOEXEC +SymLinksIfOwnerMatch
AllowOverride All
Require all granted
#uncomment to restrict the site to a single ip until it is ready to go live
#<RequireAny>
# Require ip XXX.XXX.XXX.XXX
#</RequireAny>
</Directory>
</VirtualHost>
systemctl reload httpd.service
# Add the site to your hosts file with the correct IP and browse to chrishewett.com, you should see '1'
SSL
See my dedicated setup instructions here.
GIT
See my dedicated setup instructions here.
Edits
- January 2020: Removed outdated GIT push to production instruction
- December 2019: Update MariaDB to v10.4, PHP to v7.3
- December 2017: Update MariaDB to v10.2
- December 2017: Removed specific dev subdomain setup, added PHP 5.6 setup, added swap memory setup
Addendum
# Upgrading MariaDB 10.0 to 10.2
mysql -uroot -p -e"SET GLOBAL innodb_fast_shutdown = 0"
service mysql stop
yum remove MariaDB-server MariaDB-client
nano /etc/yum.repos.d/mariadb10.repo
# change repo to latest version
yum install MariaDB-server MariaDB-client
service mysql start
mysql_upgrade -p
service mysql restart