PHP 5.5, MySQL, Postfix, Nginx and WordPress on Ubuntu

easyengine (ee) note: If you are using easyengine, you can accomplish everything in this article using following command:

ee stack install --all

A complete WordPress-Nginx setup will involve PHP, MySQL, Nginx stack and on the top of it WordPress itself.

If you already have PHP, MySQL & Nginx up & running then you may jump to next part i.e Nginx configuration for different WordPress

Assumption:

I am assuming few things before you start.

  1. You have a Ubuntu server up and running. This guide may work on other Debian based distros but this is tested on Ubuntu 12.04 LTS only.
  2. You have shell access to your Ubuntu server with sudo privilege or you have direct root-user access.

Installing PHP 5.6

We are going to use latest PHP 5.6 as it is much faster & better than PHP 5.3 and PHP 5.4.

As official repo for Ubuntu 12.04 LTS contains PHP version 5.3 only, we will use a launchpad repo maintained by Ondřej Surý

Run following codes to add launchpad repo to apt-sources:

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:ondrej/php

Press “enter” key whenever asked!

Update apt-cache…

This is must, otherwise next command may end up installing PHP 5.3!

sudo apt-get update

Now, run following to install PHP itself

sudo apt-get install php5-common php5-mysqlnd php5-xmlrpc php5-curl php5-gd php5-cli php5-fpm php-pear php5-dev php5-imap php5-mcrypt

Check PHP Version

Run following command…

php -v

You will see following output…

PHP 5.6.29-1+deb.sury.org~xenial+1 (cli)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
 with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

Installing MySQL

We use Percona-MySQL everywhere for extra features and up-to-date Ubunut builds they maintain.

Add Percona Repo

Execute following commands:

apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A

echo "deb http://repo.percona.com/apt `lsb_release -cs` main" >> /etc/apt/sources.list.d/percona.list
echo "deb-src http://repo.percona.com/apt `lsb_release -cs` main" >> /etc/apt/sources.list.d/percona.list

apt-get update

Installing percona-mysql server

sudo apt-get install percona-server-server-5.6 percona-server-client-5.6

Above wizard should ask you to enter a mysql password for user root. If it doesn’t, then run the following command to change MySQL password.

sudo mysqladmin -u root password NEWPASSWORD

Please note that above command will not help you in case you forget your mysql root password in future.

Installing Postfix

If you want to send mails from your WordPress, you will need a SMTP server. You can use a remote SMTP server like gmail.com for this. But I prefer using postfix package to run a SMTP server locally.

In simple words, if you skip this step and do not configure remote SMTP server with WordPress either, your WordPress will not be send email notifications for comments, etc.

sudo apt-get install postfix

It will take you through few steps. The important one are:

  1. Select option – Internet Site
  2. Hostname – generally your main domain i.e example.com. Recommended – a FQDN like mail.example.com 

You no need to touch other options. Just restart mail service to be safe.

/etc/init.d/postfix restart

Testing your mail config:

Run following PHP code with [email protected] replaced by your mail id:

php -a
mail ('[email protected]', "Hello from nginx!", "My email setup works!");
exit ();

Alternatively you can use check-mail WordPress Plugin after your WordPress setup completes to be sure that your WordPress can send emails.

Installing Nginx

Ubuntu official repos come with a Nginx package but I prefer using launchpad repo maintained by Nginx team.

sudo add-apt-repository ppa:nginx/stable
sudo apt-get update 
sudo apt-get install nginx

If you prefer to use Nginx package in Ubuntu repo, you can simply run following command:

sudo apt-get install nginx-full

What’s Next?

At this point, we are done with installing prerequisite for WordPress.

Changelog:

As technology evolves, we keep upgrading our installation. This article is “how” we work here at rtCamp. So this article need to be changed over time.

Oct 15, 2013

  • Replaced PHP 5.4 with PHP 5.5
  • Removed APC
  • Using PHP’s built-in zend-opcache for opcode-cache.
  • Using memcache for user/data-cache requirement
  • Switched to mysql native driver for PHP (php-mysqlnd package)
  • Replaced oracle-mysql with percona-mysql. Mysql 5.6 at the time of writing this article.

 

69 responses to “PHP 5.5, MySQL, Postfix, Nginx and WordPress on Ubuntu”

  1. HI,

    Got into bit of trouble here..
    I have tried to install APC for my current server ( aleady nginx, running on Centos)
    Now it seems APC is conflicting with Zend Optimizer
    If i enable APC extension on php.in then nginx will get me a 502 Error.

    Any idea to solve it.

    • If you are not using any application that uses Zend Optimizer, you can disable it.
      In my opinion WordPress will benefit from APC more rather than Zend Optimizer.

  2. I don’t like this line:

    sudo mysqladmin -u root password NEWPASSWORD

    because you’ll have the password in you bash history.

    For me the better way is to use the

    mysql_secure_installation

    script.

    • Thanks for your feedback. 🙂

      I am aware of mysql_secure_installation and bash history concern but if I can read your bash history then I will be able to read other files as well. 😉

      Goal of this chapter is to get all needed software up and running quickly. This is part of a large on-going wordpress-nginx series tutorials. I will be covering security in-depth towards end where I will revisit this and few more things.

  3. I think you’ll should explain the configuration of php-fpm too. The default options are quite good, but not for best performance. I’m using this one for my pool nginx

    [nginx]    
    listen = /var/lock/php5-fpm.sock    
    user = nginx    
    group = www-data    
    
    request_slowlog_timeout = 5s
    slowlog = /var/log/php5-fpm/www-slowlog.log
    
    listen.owner = nginx
    listen.group = www-data
    listen.mode = 0666
    listen.backlog = -1
    
    pm = dynamic
    pm.max_children = 9
    pm.start_servers =3
    pm.min_spare_servers = 2
    pm.max_spare_servers = 4
    pm.max_requests = 200
    pm.status_path = /status
    
    request_terminate_timeout = 120s
    
    rlimit_files = 131072
    rlimit_core = unlimited
    
    catch_workers_output = yes
    
    env[HOSTNAME] = $HOSTNAME
    env[TMP] = /tmp
    env[TMPDIR] = /tmp
    env[TEMP] = /tmp
    
    • What you are using is quite customised. In real-life people don’t need to make these many changes to their config. As explained earlier this article is part of a large series. If I cover everything here itself, then this article will become too big to be useful!

      I covered php slowlog in details here. It’s not good to keep slowlog always on as it itself slows-down PHP scripts. I will recommend turning it off when you are done with debugging.

      request_terminate_timeout is commented by default and it takes value of max_execution_time from php.ini file. Only when your php scripts fails to terminate after max_execution_time elapses (most likely because of some bug) you need to set value for request_terminate_timeout explicitly.

      I explained this in more details here.

      You can find all articles in this series here. More will be added soon. 🙂

  4. if I give APC say 1GB for caching, does it share that space between all vhosts even though they are running with different users?

  5. I am not sure but I think APC will “allocate” 1 GB for every PHP’s linux-user. Still, OS may not complain as long as that much memory is not “used” by all processes together.

    You can simply do following:

    1. Start with 256MB memory for APC. Copy apc.php file under different vhosts.
    2. Check what results apc.php shows from browser.
    3. If all vhosts’ apc.php shows same amount of memory consumption then memory may be shared among all.
    4. Also, if you see low free memory in apc.php output in any-case, you can increase memory allocated to APC.
  6. Doesn’t really work. I tried that before. The reason is that each vhost runs the webserver under its own user so apc.php within one vhost sees only stuff it has access to.

    i.e. apc.php within site a) show i.e. 60MB out of 256M in use while apc.php within site b) shows 58MB out of 256MB in use.

    I think that is because they run as different users so they only see their usage?
    The reason for my question was: i.e. if I know each of my ten wordpress sites needs 60MB, do I assign 60MB to apc.ini and since each vhost runs its own settings each uses 60MB or should I assign 600MB to apc.ini?

    • Sorry for delayed reply.

      You can try 60MB and if you see apc.php is using 100% of memory, you can start increasing it gradually.

      As every vhost is having separate memory segment, small segments can be used.

  7. php -a puts me in interactive mode rather than interactive shell, what do I need to do to get interactive shell. I am following your tutorial step by step.

    Thanks

  8. My wordpress can not send email, i has install postfix. Why it happen? how to fix this problem?

  9. Great series.. one detail I couldn’t find though off the bat:
    Do I use Ubuntu 12.04 x32 server or 12.04 x64 server?

    Many thanks.

    • @KC

      We mostly use 64-bit servers but these articles should work on 32-bit variants without any problem.

      If you face any issues, please let me know. We will sort it out! 🙂

  10. Thanks for the great blog series. It has helped me out tremendously.

    Unfortunately, I’ve hit a snag here with my nginx configuration. I am trying to deploy my blog at sudofoo.net, but I am getting a 403 error.

    Here is my /etc/nginx/sites-enables/sudofoo config file:

    server {
        listen 80;
        server_name sudofoo.net www.sudofoo.net;
    
        access_log   /var/log/nginx/sudofoo.access.log;
        error_log    /var/log/nginx/sudofoo.error.log;
    
        root /usr/share/nginx/www/sudofoo;
        index index.php;
    
        location / {
                try_files $uri $uri/ /index.php?$args; 
        }
        location ~ .php$ {
                include fastcgi_params;
                fastcgi_pass unix:/var/run/php5-fpm.sock;
        }
    }
    

    (I’m not sure why the text is the same color as the background, but highlighting the code should reveal it)

    I gave ownership of the following directories and sub-directories to the www-data user: /var/log/nginx/ and /usr/share/nginx/www/sudofoo/.

    Also, if I change the root and index to /usr/share/nginx/www and index.html respectively, I do get the default nginx welcome page.

    Does anyone have any tips on how to troubleshoot this issue?

  11. Awesome Tutorial Rahul,
    I also changed ‘cgi.fix_pathinfo=0’ in ‘/etc/php5/fpm/php.ini’ because i had it written down in my own notes as security issue.
    “If this number is kept as 1, the php interpreter will do its best to process the file that is as near to the requested file as possible. This is a possible security risk. If this number is set to 0, conversely, the interpreter will only process the exact file path—a much safer alternative. ”

    Is this necessary Rahul, what do you think?

    • Sorry for delayed reply.

      Using try_files in nginx will eliminate security risk without changing cgi.fix_pathinfo.

      I prefer try_files as it is efficient and takes care of security without any edit to php.ini

  12. Hi Rahul,

    This series has been tremendously helpful for a newbie such as myself that is new to linux and setting up dedicated websites. I largely followed your guide with some other additions and I wanted to ask you about security.

    1. Is it ok for www-data to have write permissions over /var/www ? Some discussions say that it is not safe to do so, whats your take on it? For me, I changed it to give ubuntu user/group ownership over /var/www because I wanted to be able to sftp in and change files.

    2. In /etc/php5/fpm/pool.d/www.conf and /etc/nginx/nginx.conf I changed the user/group to ubuntu from www-data. Will this open me up to hacking by doing this and if so, what is the best way to keep it www-data and be able to sftp in to the server with the ubuntu user?

    Any other security tips you or anyone here may have will be appreciated. As I said, I’m very new to all this and just trying to get a grasp of it so I can run my own site on Amazon EC2.

    Thanks.

    • Its hard to answer what should be the way but I will tell you what we do…

      #1. I make sure /var/www is owned by user & group www-data . Though I do not use sftp (I use scp/rsync for file transfer), I think a linux-user should be owner of his own home. If you create a new linux-user using adduser command, linux will make that user/group owner for his home directory.

      #2. I also use same www-data linux-user to run nginx and php processes. This makes things easy. But for shared-hosting scenarios, where 2-people are hosting on same machine and cannot trust each other, we prefer creating php-fpm pools per linux-user to run their sites’ php files. In this case they share `www-data` which is added to different php-fpm pools. Nginx, with `www-data` can read-only all website files.

      You can create separate php-fpm pools for different sites owned by same user as well. php-fpm pool with open_basedir restriction can prevent one sites php-files from accessing other-sites php-files.

      Apart from this, security itself is a big topic and I intend to write about it in-depth someday. Since its a senstive subject, I should post any “tip” without proper testing.

      You may subscribe here for future nginx-related updates.

  13. Dear. Very thank you about this article.

    I just have one problem that after install postfix, my WordPress site still can not send email.
    Do you have any site that work with WordPress email on Digital Ocean?

    Thak you very much,
    Tien Nguyen

        • By the way, I recently became fan of DO for their hostname > reverse-PTR mapping.

          They are one of very few companies to get this right! 🙂

          Yep, adding a notice like: “Hostname will be used as domain for all outgoing email’s” then a read more link for detailed explanation.

  14. Hi Rahul, for some reason I cannot make my setup pass the postfix php mail test… How would you advise to debug? Thanks 🙂

  15. As of today, this guide will install PHP 5.5.4-1+debphp.org~precise+1 (cli) (built: Sep 27 2013 11:36:42).

  16. Rahul, what can we use instead of APC with W3TC? I used your W3TC config for one of my servers. If you have an alternate suggestion, could you put up a tutorial for it?

    Thx.

  17. I have witnessed a solid sober man driven perfectly mad at the moment by two associated with so-called
    rum, supplied to him at one of these simple shanties.
    –LINK REMOVED –>Grammy Nominations 2011<. Neighbours were few in number, where there were only three other women living inside the neighbourhood – all lived in both bark huts or tents using their young children.

  18. Installing Python Software Properties, Please Wait…
    Reading package lists…
    Building dependency tree…
    Reading state information…
    python-software-properties is already the newest version.
    0 upgraded, 0 newly installed, 0 to remove and 108 not upgraded.
    Adding Brianmercer Nginx Launchpad Repository, Please Wait…
    Adding Ondrej PHP5 Launchpad Repository, Please Wait…
    Updating APT Cache, Please Wait…
    [ Thu Jan 30 14:19:58 UTC 2014 ] Unable To Update APT Cache

  19. Hey Rahul great tutorials! I have a small issue when installing the percona repository. Somehow the permission is denied for both echo’s.

    echo "deb http://repo.percona.com/apt `lsb_release -cs` main" >> /etc/apt/sources.list.d/percona.list

    -bash: /etc/apt/sources.list.d/percona.list: Permission denied

    I’m using an account with sudo priviledge, not root. What am I doing wrong? Thnx

  20. Hello,

    I’m new to VPS hosting. I always use shared hosting with my website. I followed all you instructions setting a wordpress website here
    https://rtcamp.com/tutorials/linux/ubuntu-php-mysql-nginx-postfix/
    https://rtcamp.com/wordpress-nginx/tutorials/

    It was working fine but I have one problem, My server eat lots of RAM. Here’s the screenshot:

    Last week I tried webuzo and installed LEMP stack on their panel. My ram consumes 120 – 190MB only.
    I’m so confuse now why my server eats a lot of RAM by following your tutorial.

    Can you please help me find what’s the problem?

    Here’s my VPS specs:
    Operating System Ubuntu 12.04 32-bit
    Memory 512 MB
    VSwap 512 MB
    CPU 1x 3.7GHz Core

    • Run free -m command from command line to get correct usage. There is a chance that memory usage reported by that tool includes “buffers/cache” memory. OS will always try to use maximum memory and will try to buffers/cache as much content as possible.

      Also, if you are setting up a new system, it will be better to use http://rtcamp.com/easyengine . It automates everything!

    • Not for now. You can continue with mysql.

      We will be soon adding percona-support and at that time easyengine will have update script to make a switch.

      We use percona-mysql internally.

      When we started EasyEngine percona-mysql 5.6 GA release wasn’t available.

  21. I found out what the problem was. It was the Percona-mysql that was eating a lot of RAM. Thanks!

  22. If i already have ee on my server.. Is ee running on percona?
    I want to try percona for my server..

  23. Hi Rahul,

    After following this tutorial, I want to make an email like for example [email protected] and access it through thunderbird. How do I do it? I have already installed postfix. Thanks!

  24. Also one more thing Sir. I want to use cloudflare on my website. Does ppa:nginx/stable includes httprealipmodule? Thanks.