Configure Nginx to Read PHP on Ubuntu 16.04

Nginx is an open source Linux web server that accelerates content while utilizing low resources. Known for its performance and stability Nginx has many other uses such as load balancing, reverse proxy, mail proxy, and HTTP cache. Nginx, by default, does not execute PHP scripts and must be configured to do so.  In this tutorial, we will show you how to enable and test PHP capabilities with your server.

Pre-Flight Check

  • This article assumes you are logged in as root and using Ubuntu 16.04 LTS server. If not logged in as root, please add sudo before each command or login as root user.
  • This article also assumes you have installed Nginx. If you have not yet installed Nginx or are unsure how to do so, please reference this easy to follow article
  • This article is tested using NGINX 1.10.3+,  older versions should work, but it’s a good idea to update to the latest version if available before you try to configure PHP.
  • This article will be running php7.0-fpm or later  (as of Dec 31, 2018, PHP 5.6 will be approaching “end of life” and no longer supported.)

 

Step 1a: Give Me the Packages!

First, we want to make sure our manager is up-to-date. Run the following command
sudo apt-get update && apt-get upgrade
You also want to make sure that your Nginx is up-to-date. You can check the current version by running this command. nginx -v
The result should return something like this.

Running the command nginx -v allows you to see which NGINX version you are currently using.

Note
Note: This article is using Nginx 1.10.3. If you need to update your Nginx version make sure you backup your configuration BEFORE you make any changes.

sudo cp /etc/nginx/nginx.conf   / etc/nginx/nginx.conf.1.x.x.backup

This article will NOT cover updating your Ngnix as its focus is for PHP configuration.

You can test your NGINX configuration file for syntax errors with the following command

nginx -t

If successful you should get something similar to the following
Test a NGINX configuration file for syntax errors using the nginx -t command.Using nginx -t should also give you a starting point to look for errors if for some reason this was unsuccessful it will return an error.

Note
Note: Ngnix should have started on its own after install. However, here are a couple of commands to keep on hand.

sudo systemctl stop nginx.service

sudo systemctl start nginx.service

sudo systemctl enable nginx.service

sudo systemctl restart nginx.service

Step 1b: PHP Version Check

Now it is time to check that your PHP version is running and using the correct version. You can do so with the following:

sudo systemctl status php7.0-fpm
You will see something similar to this if working properly:Check your PHP version is running and using the correct version.

Note
Note: If you need to install PHP you can run the following line :

sudo apt-get -y install php7.0 php7.0-fpm

Replace 7.0 with whatever version of PHP is the most recent. You can check for updates here.

Alternatively, if you need to update PHP to the latest version, please be sure you make a backup BEFORE any changes then run the following:

sudo apt-get upgrade

Step 2:Time for Some NGINX Configuration

Once you have verified that both PHP and Nginx are running on your system, it’s time to configure your PHP settings!

From home cd into your NGINX folder

cd ~

cd /etc/nginx
To configure your NGINX PHP settings. Cd into the etc/php folder.
cd etc/php/
Depending on which PHP version you are using the following folders may differ. This article is using PHP 7.0. You can replace the 7.0 with the version of PHP you are using. We are looking for a file called the php.ini file.

On PHP 7.0 and 7.1 that is located at :
vim 7.0/fpm/php.ini

Or
vim 7.1/fpm/php.ini
The php.ini  is a giant file but it’s where you can customize your environment. If this is your first time, it might be a good idea to make a copy of this file BEFORE you make any changes.
cp php.ini php.ini_copy
However, if you are pro and just like to read articles for the warm fuzzies you feel inside, then go ahead and edit away!

Note
First time using vim?  Use the I command to insert, Esc to exit and :wq to save the file. If you need to leave the file without saving that command is :q. Feel free to use whatever file editor you most comfortable with.
Here are a couple of the recommended values for the php.ini file.

max_execution_time = 300

max_input_time = 60

memory_limit = 256M

upload_max_filesize = 100M

Simply find these variables in the file and update the values.

Before Edit :Set the max_execution_time to 300 in the php.ini file.

After edit:Setting the max_execution_time to 300 in the php.ini file allows more processing time.

Step 2b: Default Sites Configuration

We are almost done!  Now it is time to set your default sites environment. Open your sites configuration file. It should be stored by default at the following path.

/etc/nginx/sites-available/default

You can cd there or open it right up with vim.

You want to remove the following commented out lines. Here is an example for both PHP7.0 and PHP 7.1

PHP 7.0
#
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
     location ~ \.php$ {
include snippets/fastcgi-php.conf;

#
#     # With php7.0-cgi alone:
#     fastcgi_pass 127.0.0.1:9000;
#     # With php7.0-fpm:
            fastcgi_pass unix:/run/php/php7.0-fpm.sock;
}

 

PHP 7.1
server {
listen 80;
listen [::]:80;
root /var/www/html;
index  index.php index.html index.htm;
server_name  example.com www.example.com;
location / {
try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
     location ~ \.php$ {
             include snippets/fastcgi-php.conf;
  #
#     # With php-fpm (or other unix sockets):
            fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
#     # With php-cgi (or other tcp sockets):
#     fastcgi_pass 127.0.0.1:9000;
}
}

Step 3: Testing PHP on NGINX

Once you have made the necessary edits go ahead and restart NGINX and PHP with the following lines.
sudo systemctl restart nginx.service
To test your PHP configuration by creating a  phpinfo.php file in the /var/www/html file path.
sudo vim /var/www/html/phpinfo.phpAdd the following inside the file and save :
<?php phpinfo( ); ?>
To test your setup go to your server IP followed by /phpinfo.php in your web browser.

http://localhost/phpinfo.php

If you see the following then kick back and relax because you are all done! Congrats you deserve it!Set up a PHP info page to ensure PHP is enabled on your NGINX server.

How to Use Ansible

Ansible symbolAnsible is an easy to use automation software that can update a server, configure tasks, manage daily server functions and deploys jobs as needed on a schedule of your choosing. It is usually administered from a single location or control server and uses SSH to connect to the remote servers. Because it employs SSH to connect, it is very secure and, there is no software to install on the servers being managed. It can be run from your desktop, laptop or other platforms to assist with automating the tedious tasks which every server owner faces.

Once it is configured, Ansible performs tasks based on an ordered list of assignments in what is called a Playbook. The Playbook outlines what tasks need to be run on the remote server and in what order. Once this is configured, Ansible acts like a bash for-loop command that allows a section of code to be repeated over and over again. The difference between using a bash command and Ansible is that Ansible is idempotent. The term Idempotent sounds a little scary, but it merely means that you can make the same type of request over and over again and unless something has changed, you will get the same result.

Pre-flight: Server Requirements

Source Server Requirements

Ansible requires the installation of Python 2.7 or Python 3.5 on the source server. The source server is where you will be running the tasks in the playbook for the remote servers. The remote servers receive commands defined in the playbook.  A playbook is a file which defines the scripts that will be run on the remote servers.

Note:
Unfortunately, Windows is unsupported as a source server. Certain Ansible plugins and/or modules will have other needs or requirements. Usually, these plugins or modules are installed on the same server of the Ansible installation.

Let’s start by installing Python on the source server.
root@test:~# apt-get install python

 

Target Server Requirements

The only requirement from the target server is an open SSH port. Access can also be granted for scp (secure copy) and/or SFTP connections if configured in the /etc/ansible/ansible.cfg file.

Install Ansible On Ubuntu 16.04

To install Ansible on a source Ubuntu server, let’s follow these steps:

Note:
The PPA for Ansible is here: https://launchpad.net/~ansible/+archive/ubuntu/ansible if you would like to review the versions available for your variant of Ubuntu.

root@test:~# apt-get update
root@test:~# apt-get install software-properties-common
root@test:~# apt-add-repository ppa:ansible/ansible
root@test:~# apt-get update
root@test:~# apt-get install ansible
(install text)After this operation, 42.0 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Answer “Y” to the prompt. The install will complete and take you back to the command prompt. Now, let’s check the version of Ansible installed.

Check Ansible Version

root@test:~# ansible --version
ansible 2.7.0
 config file = /etc/ansible/ansible.cfg
 configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
 ansible python module location = /usr/lib/python2.7/dist-packages/ansible
 executable location = /usr/bin/ansible
 python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]

As an alternative, you can also install Ansible on your CentOS 7 server.
Ansible also can be installed on RedHat, Debian, MacOS, and any of the BSD flavors!

Install Ansible on CentOS 7

In order to install Ansible on a source CentOS 7 server, follow these steps.
First, we need to make sure that the CentOS 7 EPEL repository is added:

[root@test ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)

[root@test ~]# yum install epel-release
Loaded plugins: fastestmirror, priorities, universal-hooks
Loading mirror speeds from cached hostfile

...
Resolving Dependencies
--> Running transaction check
---> Package epel-release.noarch 0:7-11 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
==========================================================================================================
Package Arch Version Repository Size
==========================================================================================================
Installing:
epel-release noarch 7-11 system-extras 15 k
Transaction Summary
==========================================================================================================
Install 1 Package
Total download size: 15 k
Installed size: 24 k
Is this ok [y/d/N]: y
Downloading packages:
epel-release-7-11.noarch.rpm | 15 kB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : epel-release-7-11.noarch 1/1
Verifying : epel-release-7-11.noarch 1/1
Installed:
epel-release.noarch 0:7-11
Complete!

Select “y”. The EPEL repo will then be added. Once the repository is enabled, we can install Ansible with yum:

root@test:~# yum install ansible
Loaded plugins: fastestmirror, priorities, universal-hooks
Loading mirror speeds from cached hostfile
epel/x86_64/metalink                                                               | 18 kB 00:00:00
* EA4: 208.100.0.204
* cpanel-addons-production-feed: 208.100.0.204
* epel: mirrors.liquidweb.com
epel                                                                               | 3.2 kB 00:00:00
(1/3): epel/x86_64/group_gz                                                        | 88 kB 00:00:00
(2/3): epel/x86_64/updateinfo
(3/3): epel/x86_64/primary                                                         | 3.6 MB 00:00:00
epel                                                                                          12756/12756
Resolving Dependencies
… (dependencies check)
Dependencies Resolved
==========================================================================================================
Package                        Arch Version            Repository Size
==========================================================================================================
Installing:
ansible                        noarch 2.4.2.0-2.el7            system-extras 7.6 M
Installing for dependencies:
21 k
Transaction Summary
==========================================================================================================
Install  1 Package (+17 Dependent packages)
Total download size: 12 M
Installed size: 58 M
Is this ok [y/d/N]:


Select “y” to start the Ansible install:

Is this ok [y/d/N]: y
… Downloading 18 packages:
----------------------------------------------------------------------------------------------------------
Total                                                                      30 MB/s | 12 MB 00:00:00
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
… (installing 18 python related software)
...
Installed:
ansible.noarch 0:2.4.2.0-2.el7
Dependency Installed:
... (dependencies verified)
Complete!

Check Ansible Version on CentOS 7

Now, let’s verify the version installed:

root@test ~]# ansible --version
ansible 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Jul 13 2018, 13:06:57) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]

 

Setting Up Ansible Connections

Initially, we will be adding server names or IP’s to the /etc/ansible/hosts file to identify which “ungrouped” servers and “groups” of servers we are going to be connecting to. We mention ungrouped and grouped in this specific order because this is the way the Ansible hosts file is usually arranged.

We can use any name we like for the hosts file itself but typically it is just called hosts. Ansible also states that the hosts file can also be identified as an inventory file and, you can have multiple inventory files.

Let’s start by opening the hosts file with vim and inserting some entries into the file.

root@test:~vim /etc/ansible/hosts
Here is what the default hosts file will look like:

# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
# Example 1: Ungrouped hosts, specify before any group headers.
#green.example.com
#blue.example.com
#192.168.100.1
#192.168.100.10
# Example 2: A collection of hosts belonging to the 'webservers' group
#[webservers] #alpha.example.org
#beta.example.org
#192.168.1.100
#192.168.1.110
# If you have multiple hosts following a pattern you can specify
# them like this:
#www[001:006].example.com
# Example 3: A collection of database servers in the 'dbservers' group
#[dbservers] #
#db01.intranet.mydomain.net
#db02.intranet.mydomain.net
#10.25.1.56
#10.25.1.57
# Here's another example of host ranges, this time there are no
# leading 0s:
#db-[99:101]-node.example.com


As you can see, there are individual servers “#
green.example.com”, and groups like #[webservers] which have multiple servers under the group and, another section with multiple servers listed like #db-[99:101]-node.example.com which identifies all of the individual servers from 99-101; eg.

  • db-99-node.example.com
  • db-100-node.example.com
  • db-101-node.example.com

So, let’s quickly add another server to the #[webservers] group:

#[webserver1]
#alpha.example.org
#beta.example.org
#192.168.1.100
#192.168.1.110gamma.example.com

Now, simply save the file using :wq

Note:
Make sure you uncomment any ‘#’ entries you place in the file otherwise, the entry is excluded!

 

SSH Keys

You can set up public SSH keys from the control server to log in to those remote servers noted in the hosts file. In this case, you simply want to make sure your local SSH keys are located in the /root/.ssh/authorized_keys file on the remote systems. (Depending on your setup, you may wish to use Ansible’s –private-key option to specify a .pem file instead)

 

Verify Ansible Connections

The ansible inventory file (/etc/ansible/hosts) contains the server names you will have control over and can run tasks against. To verify Ansible’s connectivity, run:

ansible remote -m ping

 

Ansible Playbooks

Ansible playbooks (also called inventory files) define the tasks ran on the remote servers. You can have one playbook or multiple playbooks to accomplish different tasks on different servers.  To easily apply a task to all of the servers in a pool, use the ‘group’ name to apply the task for that group (using the example above, you would use the [webserver1] in the command.

 

Create a Playbook

Step 1: In order to create a playbook, let’s create a new file in the /etc/ansible/playbooks/ folder:

mkdir -p /etc/ansible/playbooks/ && touch /etc/ansible/playbooks/playbook.yml && vim /etc/ansible/playbooks/playbook.yml

 

Step 2: Let’s add a server and file entry into the playbook filer:

(Click the insert key to open VIM’s edit access on the file)

- hosts: gamma.example.com
 tasks:
     - name: Create file
       file:
           path: /tmp/test.txt
           state: touch


Once we have added the entry, let’s save the file using

:wq

Step 3: Now, to set up 0644 permissions on that file, we can reopen it and add another line defining the permission set:

- hosts: gamma.example.com
 tasks:
     - name: Create file
       file:
           path: /tmp/test.txt
           state: touch            mode: "u=rw,g=r,o=r"

Again, let’s save the file using

:wq

Step 4: Next, let’s create a folder and then place a text file in it using Ansible. We will add another section defining the element needed:

- hosts: gamma.example.com
 Tasks:       - name: Create folder
       path: /home/tmp/
           state: directory
           mode: 0755
     - name: Create file
       file:
           path: /home/tmp/test.txt
           state: touch            mode: "u=rw,g=r,o=r"

Once we have added this entry, save the file using

:wq

 

Running a Playbook

To start a playbook, simply run:

ansible-playbook /etc/ansible/playbooks/playbook.yml

or if you have multiple playbooks in a folder, can run a specific playbook using the -i <path> option from the command line:

ansible-playbook -i /etc/ansible/playbooks/playbook1.yml
In addition to .yaml files, Ansible can use .json files as well to control the playbook. It is also very easy to convert 
bash or shell scripts into playbooks as well!

Schedule a Playbook Using Cron

As an additional option, you can schedule a playbook to run at a specific time using your servers cron command! To accomplish this, log in to your server as root and run the following command:

crontab -e
This command opens a temporary cron file in your system’s 
default text editor and then simply add a line like so:

0 4 * * * /usr/bin/ansible-playbook /etc/ansible/playbooks/playbook.yml
this will run the
/etc/ansible/playbooks/playbook.yml file at 0400 a.m. using the ansible-playbook command.

 

Troubleshooting A Playbook

Sometimes, a set of commands in the playbook file may fail. If it does, you have several options to address this. Generally, playbooks will simply stop completing the commands in the playbook. If this occurs, you can define a follow-up task in the playbook to overlook the error by adding another section like so:

- name: ignore this error
 command: /bin/false
 ignore_errors: yes


Unreachable Hosts

this command will only work when the task is run but returns a “failed” value.

If Ansible fails to connect to a server, it will set the host as being ‘UNREACHABLE’. This effectively removes the server temporarily from the list of active hosts for that task. To correct this, we can use an entry to reactivate them and have all current hosts previously indicated as being unreachable cleared, so subsequent tasks can use the playbook again.

meta: clear_host_errors


Handlers and Failure

A handler is simply a specially named task that runs when told to by another task. Handlers are executed at the end of the playbook by default as opposed to other tasks, which are executed immediately when defined within the playbook. This behavior can be modified by using the

--force-handlerscommand-line option, or by including

force_handlers: Truein a playbook, or addingforce_handlers = Truein the ansible.cfg file.


If you want to force a handler to run in the middle of two separate tasks instead of at the end of the playbook, you will need to add this entry between the two tasks:

- meta: flush_handlers

When handlers are “forced” like this, they will run when notified even if a task fails on that host.

Note:
Certain errors can still prevent the handler from running, such as a host becoming unreachable.
Handlers will only be visible in the output if they have actually been executed. Also, handlers are only fired when there are changes made by a task. For example, a task may update a specific configuration file and then notify a handler to restart a service. If a task in the same playbook fails later on, the service will not be restarted despite the previous configuration change.

Overall, Ansible is an indispensable tool for managing and administrating a single server or an entire group of geographically diverse servers.

 

Troubleshooting: Cron Jobs

Cron is a service for Linux servers that automatically executes scheduled commands. A cron job can be a series of shell commands, scripts, or other programs. Cron tasks or jobs can perform a variety of functions and once ran can send out an e-mail message to inform you of its completion or errors. If you receive an error, there are many ways to troubleshoot the cron task.  Use this article for troubleshooting assistance or a tutorial on the basics of cron jobs. If you would like to learn more about creating a cron job check out our Knowledge Base tutorials on the subject.

Checking Configurations with Crontab

From the command line, you can review the scheduled cron jobs by listing the crontab for the user. This command outputs the contents of the user’s crontab to the terminal.

As the user you can run:
crontab -l

As root, you can see any user’s crontab, by specifying the username.
crontab -l -u username

You can find some detailed information about how to format the cron jobs in the /etc/crontab file.  Below is the example within that file.  Each asterisk can be replaced with a number or to its corresponding field.  Or you can leave the asterisk in place to represent all possible numbers for that position.  For example, if left with all asterisk this means that the cron job will run every minute, all the time.

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed

 

Altering the E-mail Address of a Cron

Once initiated, a cron sends a notification to an email address, set within the MAILTO line of the crontab.

MAILTO="user@domain.com"

To edit the crontab, you can run the following commands as the user:

crontab -e

Or if logged in as root, you can type in the username for any of your users to see a scheduled task that they have created.

crontab -e -u usernameThese open the crontab of the user in the default editor. Typically the vim or nano command will open the file. Be aware that this similar to opening any other text file where you’ll save before closing.

The MAILTO line indicates where the execution status of a cron should be sent. The sending address will typically be the cron task creator’s username along with the server’s hostname. So an email’s sender address would follow this syntax, unixuser@serverhostname.com. If you don’t see an email right away, it may be a good idea to check your spam box.

Silenced Crons

Sometimes cron jobs are configured to either produce no output or have its output silenced, even if set with a MAILTO address. If you see a cron job listed with any of the following on end, it is a sign that the cron has output has been silenced. These send any output to the null device (the black hole on a Linux server). In cases like this, you’ll need to remove the line from the cron job script to generate an output.

&> /dev/null

2>&1 /dev/nullSome cron jobs are disabled entirely. These will have a “#” in front of the command, resulting ignored lines when executed. Remove the “#” to re-activate the cron job.

Verifying the Crond Service

Once you’ve confirmed the correct settings, it’s time to verify that the cron system is enabled and running. The three following commands can each be used to verify if the crond (the cron service) is running.

/etc/init.d/crond status

service crond status

systemctl status crond

After running any of the above commands, if you find the crond service is not running, you can start it with one of the following.

/etc/init.d/crond start

service crond start

systemctl start crond

/var/log/cron

Once you know that the cron is enabled, not silenced, and crond is running, then it’s time to check the cron log, located in the path of /var/log/cron.

cat /var/log/cron

Example Output:

Oct 2 23:45:01 host CROND[3957]: (root) CMD (/usr/local/lp/apps/kernelupdate/lp-kernelupdate.pl > /dev/null 2>&1)
Oct 2 23:50:01 host CROND[4143]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Oct 2 23:50:01 host CROND[4144]: (root) CMD (/usr/local/maldetect/maldet --mkpubpaths >> /dev/null 2>&1)
In the log, you will see if, when and what user ran the cron. If initiated, you’ll see the date and time of execution followed by brackets of the individual cron number. This timestamp does not confirm that the script ran normally or at all, it only signifies when the cron system last ran the task. Beyond that, you may need to investigate the cron script itself or application-level configurations and their respective logs to ensure the code is executing correctly.

Other Cron Services

This article is merely an overview of the main crond service as there many other cron tasks services. The anacron system is a commonly used cron service that configures daily or hourly jobs, and can even be set to run at reboot. The logs for these kinds of tasks are within /var/log/cron, and are not executed by crond.

Other scheduled tasks, although also referred to as cron jobs, are not executed from the crond system. These cron jobs are often configured within the code or configuration of a website. To determine if executed, you’ll need to investigate other configurations and logs that the cron script interacts with.

As with all cron services, automated jobs can be manipulated to execute numerous daily tasks, so you don’t have to. Cron tasks can occasionally go awry even without altering them or years, but knowing where to look is half the battle in troubleshooting a cron job.

 

Apache Performance Tuning: Swap Memory

Before we get into the nitty-gritty of Apache tuning, we need to understand what happens when servers go unresponsive due to a poorly optimized configuration. An over-tuned server is one that is configured to allow more simultaneous requests (ServerLimit) than the server’s hardware can manage. Servers set in this manner have a tipping point, once reached, the server will become stuck in a perpetual swapping scenario. Meaning the Kernel is stuck rapidly reading and writing data to and from the system swap file. Swap files have read/write access speeds vastly slower than standard memory space. The swap files’ latency causes a bottleneck on the server as the Kernel attempts to read and write data faster than is physically possible or more commonly known as thrashing. If not caught immediately, thrashing spirals the system out of control leading to a system crash. If trashing is left running for too long, it has the potential of physically harming the hard drive itself by simulating decades of read/write activity over a short period. When optimizing Apache, we must be cautious not to create a thrashing scenario. We can accomplish this by calculating the thrashing point of the server based on several factors.

 

Pre-Flight Check

This article covers all Apache-based servers including but is not limited to, both traditional Dedicated servers and Cloud VPS servers running a variety of Linux distributions. We will include the primary locations where stored Apache configurations on the following Liquid Web system types:

Liquid Web Server Types

Calculating the estimated thrashing point or ServerLimit of a server uses a simple equation:

Caculating the Thrashing Point

  • buff/cache: The total memory used by the Kernel for buffers and cache.
  • Reserved: The amount of memory reserved for non-Apache processes.
  • Available: The difference between buff/cache and Reserved memory.
  • Avg.Apache: The average of all running Apache children during peak operational hours.

 

Important
Calculating the thrashing point/ServerLimit should be done during peak operational hours and periodically reassessed for optimal performance.

The thrashing point value is equal to the number Apache children the server can run; this applies to either threaded or non-thread children. When the number of children running in memory meets the calculated thrashing point, the server will begin to topple. The following example walks through a standard Liquid Web Fully Managed cPanel server to illustrate gathering the necessary details to calculate a system’s estimated thrashing point.

 

Buff/Cache Memory

On modern Linux systems, the buffer/cache can be derived using the /proc/meminfo file by adding the Buffers, Cached and Slab statistics. Using the free command, we can quickly grab this information, as in the example below:

free

Output:

Use the free command to get the buff/cache info

Don’t be fooled by the column labeled “available.” We are solely looking at the memory we can reappropriate, which is the buff/cache column (708436).

 

Reserved Memory

Reserved memory is a portion of memory held for other services aside from Apache. Some of the biggest contenders for additional memory outside of Apache are MySQL, Tomcat, Memcache, Varnish, and Nginx. It is necessary to examine these services configs to determine a valid reserved memory. These configs are outside the purview of this article. However, MySQL is the most commonly encountered service running with Apache. You can find tools online to help analyze and configure MySQL separate from this article.

 

Rule-of-Thumb:
Save 25% of the total buff/cache memory for any extra services ran on the server. Examples:

  • A standard cPanel server runs several services along with Apache and MySQL. A server with these services runs on the heavier side, needing 25% reserved for non-Apache services.
  • A pure Apache web node in a high capacity load balanced configuration does not need to reserve any additional ram for other services.

 

Average Apache Memory

Finding the average size of Apache processes is relatively simple using the ps command to list the RSS (Resident Set Size) of all running httpd processes. Note: some distributions use “apache” instead of “httpd” for process name.

This example uses a short awk script to print out the average instead of listing the sizes.

ps o rss= -C httpd|awk '{n+=$1}END{print n/NR}'

Output:

22200.6

 

This example is easy to average by hand, but larger servers will require more calculation.

ps o rss -C httpd

Output:

RSS
5092
27940
28196
27572

 

Calculate the Thrashing Point

Once collected divided the Available memory by Avg. Apache, rounding down to the nearest whole number. Available memory is the buff/cache memory minus the Reserved memory. Below is a summary of the calculation process in table form.

Thrashing point calculations

Conservative estimates are provided below for various memory configurations. These estimates can be used as a starting configuration but will require additional follow up performance assessments during peak hours to adjust directives by the servers.

General Thrashing Estimates

Remote Desktop Troubleshooting

Remote Desktop Protocol (or RDP) is the most common method of gaining administrative access to a Windows server. RDP is available on all versions of Windows server and a client (called Remote Desktop Connection) is included with all versions of Windows desktop operating systems. Clients are also available for Macintosh operating systems from Microsoft in the iTunes store and for Linux desktops with applications like FreeRDP. Connecting to your server via RDP allows you full control of the server desktop environment, just as if you were sitting in front of the server’s monitor and keyboard. Depending on your permissions and settings, you can copy and delete files, change file permissions or settings, and even print documents from the server.

Pre-Flight Check

Using Remote Desktop Protocol to manage a Windows server generally requires a few basic settings and information about the server.

  • First, the Remote Desktop Service must be running on the server to which you would like to connect (RDP uses port 3389 by default).
  • Second, you need to know the IP address of the server.  
  • Third, you must have a username and password that is allowed to connect to the server remotely (often, this is the primary administrator account, but can also be a secondary account set up specifically for remote access purposes).
  • Finally, the Windows firewall (and any other hardware or software firewalls) needs to be configured to allow Remote Connections from your location.

 

Once you have all of the correct settings enabled, IP address and user account details, you can connect RDP to your server! Just launch the RDP client, enter the IP address of the server and the user credentials, and log in to the server using what looks like the standard Windows desktop environment.

Image of Remote Desktop Connection

As helpful as the Remote Desktop Protocol can be when it comes to managing your Windows server, there are also times when the connection fails, which can be very frustrating as the error message is generally not very helpful (often just the window shown below).         

RDP Connection Error Pop Up

 

The error shown above means that for some reason, your client was unable to make a connection to the Windows server via the Remote Desktop Protocol. When you are experiencing connectivity issues, there are many items that you can check to try to resolve the problem.

 

  1. Ensure you can reach the server via ICMP (or Ping). Most desktop operating systems will allow you to send small bits of information to the computer to verify connectivity and connection speeds. Generally, you just need to open a terminal window (on a Windows desktop, press the Window key, then type cmd and press enter) and enter the following command: ping IP or ping domain.tld. Normally, you’ll receive an output that is similar:Ping Results
  2. This output shows the pings were successful to the destination and took between 50 ms and 150 ms to complete. These pings indicate a successful connection to the server as desired (at least over ICMP). If the output for the command shows a failure to respond, we know there is some network interference.
  3. If the ping test fails (indicated by repeating asterisks), check your internet connectivity to guarantee that you can reach other resources on the internet. If not, you may need to contact your local service provider to restore your internet access.
  4. Reaching other internet sites but not your server indicates your server is refusing connections from your IP address (due to security software or firewall settings). You may need to contact your hosting company to verify there is not an IP address blocked by your server. You can find your current public IP address by going to http://ip.liquidweb.com.
  5. Can you ping your server, but still can’t connect over RDP? It is likely an issue with the RDP service or your firewall. You’ll need to contact your hosting company to get assistance with the service or firewall.

Firewall Issues

Best practices in configuring a firewall is to allow the least amount of access necessary for the various connections to the server. Limiting the connections to a particular service like RDP is called “scoping” the access for that service. If your configured Windows firewall scopes traffic on RDP, it’s possible that a user may not be able to connect due to their IP address not being included in the rule. Access to the server via RDP from one user but another user is not, check the firewall; their IP address may not be included in the allowed list of IPs for Remote Desktop Access.

  1. Log in to the server, click on the Windows icon, and type Windows Firewall into the search bar.Firewall Settings
  2. Click on Windows Firewall with Advanced Security.
  3. Click on Inbound Rules
  4. Scroll down to find a rule labeled RDP (or using port 3389).
  5. Double-click on the rule, then click the Scope tab.Scope Tab
  6. Make sure the user’s current IP address is included in the list of allowed Remote IPs.

If you are unable to connect to the server from your location, contact your hosting company for help in checking the firewall rule for RDP access.

User Connectivity Problems

Can you connect to RDP using the administrator account, but one or more of the other accounts cannot? There may be a problem with the user account permissions.

  1. Make certain the user is a member of the Remote Desktop Users group. Log in to the server with the administrator account, then go to the Local Users and Groups control panel (Open Administrative Tools, then open Computer Management).Local Users and Groups
  2. Navigate to the Remote Desktop Users group and verify that the user is a member of the group. If they are not a member of the group, add them as a member of the group.
    remote desktop users group
  3. Go to the username under the Users tab. Make sure that the user account is not locked out. Accounts can get locked out due to too many attempts to log in with an incorrect password (either by the user or by a brute force attack on the server).
    account lockout screen
  4. Double check the firewall for the IP address of the user and add to the scope of the RDP rule.

No Available Connections/Sessions

By default, Windows server only allows two users to connect via RDP simultaneously. If both sessions are already in use, you will receive an error indicating that no additional users are allowed to connect at this time. Too Many Users Error

To resolve this issue, you will need to wait until one of the other users logs out or you’ll require to purchase additional RDP user licenses from your hosting provider (assuming that you regularly need access for more than two users at a time).

Failed login attempts during a brute force attack can sometimes take up RDP licenses, even though the session isn’t connecting. If you are experiencing unavailable sessions even when no one is logged in to the server, it’s possibly the result of a malicious login. The best remedy for this situation is to scope the firewall rule to prevent access attempts from unauthorized IP addresses.

Data Encryption Errors

If you are using an out of date Remote Desktop Client or are connecting to an older Windows server, you may receive an error that there is a problem with the TLS settings for the connection. Generally, you can resolve this issue by updating your RDP client software on your workstation. It may also be possible to set the client to ignore these errors, but that could leave your workstation and your server vulnerable to malicious attacks.

Sudden Disconnection

If you are using RDP and suddenly lose the connection, the issue is almost always related to your internet connection. Check to make sure that you can stay connected to other services (like running a ping command in the background). If you are not losing internet connectivity, it’s possible that the server is running out of memory or the RDP service may be experiencing an active attacked in a brute force attack. If you’ve confirmed that your internet connection is stable, contact your hosting company to make sure that the server is not the cause of the lost connection.

Slow Connection Issues

If the connection between your location and your server is slow your Remote Desktop Session may not function as smoothly as you would like. However, you may be able to adjust the Desktop Environment settings of the connection before you connect to simplify and speed up the connection.

  1. Open the Remote Desktop Client application (these directions are for the Windows built-in client, but most RDP clients have similar settings available).
  2. Click on the Experience tab to see the various items you can choose to enable or disable to improve your connection speeds. Change the drop-down to select a specific connection speed or select/deselect the various items to optimize performance.Remote Desktop Connection Settings

         

Windows 10 Update Issues

Oddly enough, Microsoft updates often cause problems with RDP connectivity. As recent as April 2018, an update on both the server operating system and the Windows 10 desktop operating system caused connectivity issues for many users. Generally, the best policy is to update both the server and workstation, as connectivity issues most often arise when the two systems are not on the same update cycle. You may be able to resolve a new connectivity issue by removing a recent Windows update (either on the server or the desktop). Many users also reported that disabling the Printer option from the local resources setting resolved the most recent connectivity issue.         

Local Resources

 

While RDP is a great tool for managing your Windows server, connectivity issues can be frustrating. By working through the possible causes of the connection problem, you will generally be able to get reconnected and working again in no time!

Configuring and Troubleshooting WHMCS Crons

Over the years WHMCS has made some changes to where it stores certain directories, specifically directories outside of public_html. The goal of this is to increase overall security by moving sensitive files to a more protected location. While this change does help to improve WHMCS security, it also adds a few steps of complexity.

This article is meant to help simplify this complexity, or at least provide a reference configuration that you can use to troubleshoot cron issues, or gain a better understanding of WHMCS crons in general. I used WHMCS 7.3 for this article, but the general concept and instructions should apply for any 7.0 version of WHMCS.
Continue reading “Configuring and Troubleshooting WHMCS Crons”

How To Modify an Existing Email Account in Thunderbird

Pre-Flight Check

  • These instructions are intended specifically for setting up an email account in Mozilla Thunderbird 38.3.0 on Mac OS X 10.11.1.
  • While the steps should be similar across platforms and operating systems, they may not necessarily apply to older versions of Thunderbird.
  • For help with general email account settings, see How to Set up Any Email Client.

You can edit an email account that already has been configured in Thunderbird, for example should you decide to switch between non-SSL and SSL settings or change the server’s connection port. You change the connection type between standard (non-SSL) and secure (SSL) by changing the hostname and port for the incoming and outgoing servers.

Note: You cannot edit an existing email account to switch its account type from POP3 to IMAP or vice versa. To change the account type, you must add a new account of the desired type (POP3 or IMAP). Adding a new account with a different connection type should not require you to delete the old one in most mail clients.

To avoid data loss, please use caution any time you change an email account’s connection type or delete an email account. Removing an email account from a mail client also will remove all messages associated with it on the device and, specifically in the case of POP accounts that are not configured to retain mail on the server, there may be no way to recover those messages. If you have any doubt or questions, please feel free to contact Heroic Support® for guidance.

Step #1: Edit Incoming Server Settings

  1. To edit the incoming server, select your email address in the left pane and then click on View settings for this account in the main window.
  2. In the account settings window, click on Server Settings to update the Server Name and Port.incomingedit
    • Server Name
      • SSL settings will use the server’s hostname (e.g., host.yourdomainname.com)
      • Standard non-SSL settings will use the domain name (yourdomainname.com or mail.yourdomainname.com).
    • Port
      • SSL settings will use Port 993 for IMAP and Port 995 for POP3.
      • Standard non-SSL settings will use Port 143 for IMAP and Port 110 for POP3.

Step #2: Edit Outgoing Server Settings

  1. To edit the outgoing server settings, click on Outgoing Server (SMTP) in the left pane, select your outgoing server and click the Edit button.editoutgoing
  2. You can edit the server name and port in the popup window.out2
    • Server Name
      • SSL settings will use the server’s hostname (e.g., host.yourdomainname.com)
      • Standard non-SSL settings will use the domain name (yourdomainname.com or mail.yourdomainname.com).
    • Port
      • SSL settings will use Port 465.
      • Standard non-SSL settings will use Port 587 (depending on your server configuration, you may be able to use Port 25 as well).
  3. Click on the OK button to save the outgoing server settings, then click on OK once more to exit the settings menu and begin using your email account with the new settings.

 

How to Install Logwatch on Fedora 21

Logwatch is a Perl-based log management tool for analyzing, summarizing, and reporting on a server’s log files. It is most often used to send a short digest of server’s log activity to a system administrator.

What are log files? Logs are application-generated files useful for tracking down and understanding what has happened in the past.

Pre-Flight Check

  • These instructions are intended specifically for installing the Logwatch on Fedora 21.
  • I’ll be working from a Liquid Web Self Managed Fedora 21 server, and I’ll be logged in as root.

Continue reading “How to Install Logwatch on Fedora 21”

How to Install Logwatch on Fedora 20

Logwatch is a Perl-based log management tool for analyzing, summarizing, and reporting on a server’s log files. It is most often used to send a short digest of server’s log activity to a system administrator.

What are log files? Logs are application-generated files useful for tracking down and understanding what has happened in the past.

Pre-Flight Check
  • These instructions are intended specifically for installing the Logwatch on Fedora 20.
  • I’ll be working from a Liquid Web Self Managed Fedora 20 server, and I’ll be logged in as root.

Continue reading “How to Install Logwatch on Fedora 20”

How to Install Logwatch on Ubuntu 14.04 LTS

Logwatch is a Perl-based log management tool for analyzing, summarizing, and reporting on a server’s log files. It is most often used to send a short digest of server’s log activity to a system administrator.

What are log files? Logs are application-generated files useful for tracking down and understanding what has happened in the past.

Pre-Flight Check
  • These instructions are intended specifically for installing the Logwatch on Ubuntu 12.04 LTS.
  • I’ll be working from a Liquid Web Core Managed Ubuntu 12.04 LTS server, and I’ll be logged in as root.

Continue reading “How to Install Logwatch on Ubuntu 14.04 LTS”