Skip to content

bostontrader/lemp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Introduction

The purpose of this directory is to provide/document a build process that can build from source code a LEMP stack, for Ubuntu 15.10, composed of Nginx, MySQL, PHP, and php-fpm.

We will optionally install xdebug with PHP.

More specifically, we're going to download the source code and build from scratch, the following packages and versions:

PackageVersion
MySQL5.7.11
PHP5.6.18
Nginx1.9.12

This directory contains not merely this README file, but also a handful of initial configuration files. Hence the version control.

Any installation starts with this directory. During the build, we'll download, unzip, and otherwise create lots of new files in this directory. But even though this directory is under git version control, we don't want to add these new files.

Rebuild from Source Code

This process will use .tar.gz (or similar) files containing the source code for all of the above. We want to be able to very carefully rebuild the same stack, every time, starting from exactly the same source code. Attempting to do this using the SCM repos of the various programs is needlessly complicated because these programs use several different systems. And attempting to do this using whatever package manager is available on a specific system is troublesome because the different packages will likely contain subtle differences that will likely cause grief.

This Stack is Not Entwined With The Rest Of The System

All of the installation is contained within this directory and uses non-standard ports and user names. This stack may thus be easily deleted and rebuilt without affecting other packages on the system. One reason for using non-standard ports, in additional to a minor security boost, is to ensure that we really are dealing with this software and not pre-existing instances that may have been installed previously.

Install/Execute as Ordinary User

This installation my be built and executed as an "ordinary" user, ie. not root, and can be placed anywhere said user has sufficient access rights, such as in his HOME directory. This will however require that we use certain non-standard ports. For example, an ordinary user cannot run a process to bind to port 80.

Prerequisites

Although Nginx, MySQL, PHP, and php-fpm can all be installed and executed by an ordinary user, the host system still needs a variety of build tools. You will most conveniently need to sudo or root access to install these tools, if they are not already installed.

Starting from a fresh install of Ubuntu 15.10, I needed to install the following extra packages to get all this to work:

MySQL
Package nameWhy?
cmakeMySQL
libncurses5-devMySQL
libxml2-devPHP
libssl-devPHP
libpcre3-devnginx

Unfortunately, installing all this is outside the scope of this document, so you're on your own with this.

Rebuild

Ok, here we go...

I. Wipe the Slate

  1. Determine a file-system location for this installation. Let's refer to that location as STACK_ROOT. In fact, let's export that as an environment variable.

    export STACK_ROOT=/home/myhome/lemp

    Warning: If STACK_ROOT is in a user's home directory, you might be tempted to use the ~ as part of the path. Resist the urge because subsequent make install apparently don't like that.

  2. p>rm -rf $STACK_ROOT

    Remove any prior installation.

  3. mkdir $STACK_ROOT

  4. cd $STACK_ROOT

  5. git clone https://github.com/bostontrader/lemp.git .

    Be sure to include the trailing 'dot' That says to clone the repository into 'this' directory.

II. Install MySQL 5.6.22

Let's install MySQL first. This is the most complicated part and if you can get this working then the rest of the installation will be easier. Also, the PHP installation needs MySQL so we need to install this first.

Since our goal is specifically to build from source code, we'll neglect to use any easier installation methods such as package managers. A good starting point for building from source is http://dev.mysql.com/doc/refman/5.7/en/source-installation.html

There are a few issues to consider when installing MySQL:

  • Which directory will contain the database files? Not the binaries or configuration, but the database files themselves.
  • How do we carefully control where configuration information comes from? This can be confusing because MySQL will routinely look in several places and we can easily mix in config from other installations.
  • Which user and group should be the owner of the database files?

That said, let's doit...

  1. Earlier I referenced the starting point in the MySQL docs for building the source code. A more specific reference for our purposes now can be found at:
    http://dev.mysql.com/doc/refman/5.7/en/installing-source-distribution.html

  2. export MYSQL_DEFAULT_PORT=3307

    Determine a port for the configuration to listen to. The MySQL default port = 3306 so let's secure by obscurity and use a different port:

  3. export MYSQL_USER=batman
    export MYSQL_GROUP=catwoman

    The access rights for the various files are customarily set according to a user=mysql and a group=mysql. As with the port, let's again thwart our determined nemeses and use different names.

  4. groupadd $MYSQL_GROUP
    useradd -r -g $MYSQL_GROUP -s /bin/false $MYSQL_USER
    Add the group and user, if necessary.

  5. cd $STACK_ROOT
    Ensure that you're in the STACK_ROOT directory.

  6. wget http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-boost-5.7.11.tar.gz

    This downloads the source code, including some c++ boost source/headers.

  7. tar xvf mysql-boost-5.7.11.tar.gz

  8. cd $STACK_ROOT/mysql-5.7.11

  9. cmake -L
    Optional. Gives a brief overview of important configuration parameters. You can change their values by using the -D option. See supra for example.

  10. cmake . -DCMAKE_INSTALL_PREFIX=$STACK_ROOT/mysql -DMYSQL_DATADIR=$STACK_ROOT/mysql/data -DWITH_BOOST=$STACK_ROOT/mysql-5.7.11/boost

  11. If you want to start over with cmake, then do rm CMakeCache.txt

  12. make

  13. make test

  14. make install

Post installation

  1. cd $STACK_ROOT/mysql

  2. sudo chown -R $MYSQL_USER .

  3. sudo chgrp -R $MYSQL_GROUP .

  4. sudo bin/mysqld --initialize --user=$MYSQL_USER

    This may take a few moments, so please be patient.

  5. The output from the prior step includes a temporary password for root@localhost. Be sure to write this down!

  6. cd $STACK_ROOT/mysql

    sudo mkdir mysql-files

    sudo chmod 750 mysql-files

    sudo chown -R $MYSQL_USER .

    sudo chgrp -R $MYSQL_GROUP .

Post Installation and Initialization

At this point the MySQL daemon and various utilities are ready to run. Although the installation created a default conf file, we don't want to use it. Instead, we'll feed the binaries whatever options via command line. The following options are typically used for our application:

  • --no-defaults If we don't carefully suppress the use of any default configuration files, MySQL will diligently try to find some configuration and it may find and use configuration from some other installation. So we generally want to use this option to prevent that.

  • --user=$MYSQL_USER The actual db files are owned by this user. If we don't specify this then MySQL will typically use the currently logged in user.

  • --port=MYSQL_DEFAULT_PORT Which TCP/IP port will the program listen on?

  • --protocol=tcp Sometimes this is required. Sometimes the use of the --port option apparently implies this option as well.

  • --datadir=? Where are the datafiles?

  • --log-error=? Where is the error log?

That said... let's crank it up!


sudo $STACK_ROOT/mysql/bin/mysqld_safe --user=$MYSQL_USER --log-error=$STACK_ROOT/mysql.err --datadir=$STACK_ROOT/mysql/data --port=$MYSQL_DEFAULT_PORT

mysqld_safe is the preferred way to execute mysqld. This command will _not_ be daemonized and will consume your terminal window. So append the "&" character to daemonize or open another terminal window for subsequent work.

Verify basic installation and operation

sudo ps -A | grep mysqld
Verify that mysql is a process. You should see both "mysqld" and "mysqld_safe"

sudo netstat -lnp | grep mysql
Verify that mysql is listening on the expected port. Do you see $MYSQL_DEFAULT_PORT and "LISTEN" in there somewhere?

killall -r mysql
Stop the server, ending any processes it had.

Review the directory structure, relevant to MySQL

$STACK_ROOT/mysql-5.7.11.tar.gz - This is the original installation media.

$STACK_ROOT/mysql-5.7.11 - This is the installation source code as extracted from the above.

$STACK_ROOT/mysql - This contains the MySQL installation that was built from the above.

III. Install PHP 5.6.18

Now install PHP 5.6.18. This release also includes php-fpm so that will be installed as well. We will however configure php-fpm separately.

  1. cd $STACK_ROOT
    Ensure that you're in the STACK_ROOT/ubuntu-nginx-php-mysql directory.

  2. wget http://hk1.php.net/distributions/php-5.6.18.tar.bz2

  3. tar xvf php-5.6.18.tar.bz2

  4. cd $STACK_ROOT/php-5.6.18

  5. ./configure --help
    This is optional but possibly useful. Possibly review the modules being loaded and exclude some of them.

  6. ./configure --prefix=$STACK_ROOT/php --enable-fpm --with-mysql=$STACK_ROOT/mysql

  7. We need fpm!

  8. make --help Optional.

  9. make

  10. make test This may reveal some minor errors. Don't worry about them.

  11. make install

Note: After installation, there is no initial php.ini. This will be added later.

Verify basic installation and operation of PHP

$STACK_ROOT/php/bin/php --version
Look for version or info about php. Does this say 5.6.18?

$STACK_ROOT/php/bin/php --info
Look at the info....

$STACK_ROOT/php/bin/php --info | grep "Loaded Configuration"
Narrow the search for "Loaded Configuration". Is php using the php.ini we expect? At this point, there should be none loaded at all.

$STACK_ROOT/php/bin/php --info | grep "configure"
This will tell you the exact configuration you used for this build. This is useful when you return to this later and need to configure new options.

Review the directory structure, relevant to PHP

$STACK_ROOT/php-5.6.5.tar.bz2 - This is the original installation media. Not under SCM.

$STACK_ROOT/php-5.6.5 - This is the installation source code as extracted from the above. Not under SCM.

$STACK_ROOT/php - This contains the PHP installation that was built from the above. Not under SCM.

IV. Install php-fpm.

php-fpm has already been installed via our installation of PHP. The versioning is not relevant because it's whatever version comes with PHP 5.6.18. We do however need to configure php-fpm and learn a bit about its ways and customs.

Determine a port for the initial configuration to listen to. By default it's port 9000. For this example let's use 9001.

PHPFMP_DEFAULT_PORT = 9001

Use a custom built configuration provided by this project.

The stock configuration is filled with commented out examples. This just confuses everything. The custom built config has nothing except things we specifically want. We'll otherwise just rely on the default operation of php-fpm until and unless we specifically decide otherwise.

ln -s $STACK_ROOT/php-fpm-conf/php-fpm.conf $STACK_ROOT/php/etc/php-fpm.conf

Verify basic installation and operation

Help, version, info.

$STACK_ROOT/php/sbin/php-fpm --help
$STACK_ROOT/php/sbin/php-fpm -v
$STACK_ROOT/php/sbin/php-fpm -i

$STACK_ROOT/php/sbin/php-fpm -t
Test the configuration file.

$STACK_ROOT/php/sbin/php-fpm
This will start the php-fpm server.

netstat -lnp | grep php-fpm
Verify that php-fpm is listening on the expected port.

Do you see "127.0.0.1:PHP-PFM_DEFAULT_PORT" and "LISTEN"?

ps -A | grep php-fpm
killall php-fpm

Stop the php-fpm server.

Review the directory structure, relevant to php-fpm

Recall that php-fpm was installed with PHP so therefore php-fpm will not have it's own original installation media or extracted source or installation directory.

$STACK_ROOT/php-fpm-conf
This contains the versioned configuration files that we develop.

$STACK_ROOT/php/sbin/php-fpm
This is the executable binary.

$STACK_ROOT/php/etc/php-fpm.conf
This is a link to the configuration file.

V. Install nginx 1.9.12

Now it's time to install nginx version 1.9.12.

  1. export NGINX_DEFAULT_PORT=3000

    Determine a port for the initial configuration to listen to. As an unprivileged user we cannot use port 80.

  2. cd $STACK_ROOT

  3. wget http://nginx.org/download/nginx-1.9.12.tar.gz

  4. tar xvf nginx-1.9.12.tar.gz

  5. cd $STACK_ROOT/nginx-1.9.12

  6. ./configure --help
    This is not strictly necessary, but it may be useful. Possibly review the modules being loaded and exclude some of them.

  7. ./configure --prefix=$STACK_ROOT/nginx --without-http_gzip_module
    Look at the output of configure. It will tell you that the binaries, the configuration, the logs, etc. are all found inside this directory.

    We don't need gzip compression right now, which requires zlib, and it's easier to omit gzip than to install zlib at this time.

  8. make --help
    Optional, but may be useful.

  9. make
    make install

Replace the installed configuration directory with a custom built config

  1. rm -rf $STACK_ROOT/nginx/conf/\*
    Remove the contents of the existing directory.

  2. ln -s $STACK_ROOT/nginx-conf/nginx.conf $STACK_ROOT/nginx/conf/nginx.conf
    Link to new config

    The stock configuration is filled with commented out examples. This just confuses everything. The custom built config has _nothing_ except things we specifically want. We'll just rely on the default operation of nginx until and unless we specifically decide otherwise.

Verify basic installation and operation

$STACK_ROOT/nginx/sbin/nginx -t
Test the configuration file.

$STACK_ROOT/nginx/sbin/nginx &
Start the server. Recall that the "&" symbol makes this command run as a daemon.

netstat -lnp | grep nginx
Verify that nginx is listening on the expected port. Do you see "0 0.0.0.0:NGINX_DEFAULT_PORT" and "LISTEN"?

From your browser of choice, view this server, using the NGINX_DEFAULT_PORT. For example, what's the IP address of the server? Browse to ip-address:NGINX_DEFAULT_PORT. Do you see the nginx welcome message? As an exercise, find this message and modify it in order to verify that you really understand where this is being served from.

$STACK_ROOT/nginx/sbin/nginx -s reload
Restart the server and reload the config.

ps -A | grep "nginx"
Display any processes running nginx. There should be two processes, unless some other nginx is running on this server.

$STACK_ROOT/nginx/sbin/nginx -s stop
Stop the server, ending any processes it had.

Review the directory structure, relevant to nginx

$STACK_ROOT/nginx-1.9.12.tar.gz - This is the original installation media. Not under SCM.

$STACK_ROOT/nginx-1.9.12 - This is the installation source code as extracted from the above. Not under SCM. Note: this also contains the original configuration.

$STACK_ROOT/nginx - This contains the nginx installation that was built from the above, which is the binaries, configuration, log files, and html to serve. Not under SCM.

$STACK_ROOT/nginx-conf - This contains the versioned configuration files that we develop, that are later copied into the STACK_ROOT/ubuntu-nginx-php-mysql/nginx/conf directory.

VI. phpinfo() via PHP & Nginx

Now it's time to modify our configuration so that we can view a .php file, that contains a call to phpinfo() and view this in the browser, via nginx. Since we're using php-fpm, we'll have to get that properly configured as well.

  1. Replace the installed nginx configuration directory with the custom built configuration provided by this project. Note: This is the 2nd custom config that we're using.

  2. ln -sf $STACK_ROOT/nginx-conf/nginx.conf2 $STACK_ROOT/nginx/conf/nginx.conf

    Link to new config. This time you'll want to force (f) the link to replace the existing link.

  3. Edit $STACK_ROOT/nginx/conf/nginx.conf to replace STACK_ROOT with the real value.

  4. Turn on (or reload) nginx.

  5. Turn on (or reload) php-fpm.

  6. From your browser of choice, navigate to localhost:NGINX_DEFAULT_PORT/phpinfo.php. Do you see the php info message? You do? Congrats! Time for a cold one, a fat one, or both!

About

A LEMP stack that plays well together.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published