This will also include instructions on how to configure the machine for Nginx.
These instructions are ideal for those who want to run PHP in production. This version of PHP lacks intrusive packages like Suhosin.
And added benefit, is you don't have install any packages like
php-json
, php-mysql
, php-common
, nor php-cli
Instead, you have 1 PHP binary, and a PHP FPM binary.
The PHP binaries will be installed in a bin
directory off of the user's
home directory.
mkdir -p ~/bin/
This will allow you to use type php
anywhere and the version of PHP we're
compiling will be first on the list - and the first one to be run
Open the file ~/.bashrc
and add the following to the end of it
cat >> ~/.bashrc
Now, paste the following into your terminal
# add local bin directory
if [ -d "$HOME/bin/php7/bin" ] ; then
PATH="$HOME/bin/php7/bin:$PATH"
fi
# press ctrl-c to exit cat
Install the following packages. These are needed for PHP to communicate with MySQL, Postgres, composer, and Nginx.
sudo apt-get install autoconf build-essential \
libssl-dev pkg-config zlib1g-dev libargon2-dev \
libsodium-dev libcurl4-openssl-dev sqlite3 libsqlite3-dev \
libonig-dev
If you want to use nginx instead of laravel's artisan serve
or PHP's local web
server
sudo apt-get install nginx
If you do not plan on installing MySQL, then skip this step
sudo apt-get install mariadb-server
If you don't plan on installing PostgreSQL then skip this step
# I like to add a postgres user (but, this is optional)
sudo adduser postgres
sudo apt-get install postgresql-9.6 postgresql-client-9.6 \
postgresql-contrib-9.6 libpq-dev
IF you installed the package pkg-config
skip this step
Debian based distros don't report the correct location of
openSSL headers. Without the pkg-config
package PHP looks in the wrong
location for the headers. This symlink fixes that.
sudo ln -s /usr/include/x86_64-linux-gnu/curl /usr/include/curl
As of the time of this, PHP 7.4.6 was the latest PHP available.
NOTE: this installs PHP in the user's local bin directory, not globally!
# create the Download directory
mkdir -p ~/Downloads/
# change to the Downloads directory and fetch the PHP 7.3 tarball
cd ~/Downloads;
wget https://www.php.net/distributions/php-7.4.6.tar.bz2 -O php-7.4.6.tar.bz2
tar -xf php-7.4.6.tar.bz2
cd php-7.4.6
This is our base build script. Create a file called build_php.sh
and paste
this snippet into it
#!/bin/sh
######################
# To build PHP
# STEP 1: sh build_php.sh
# STEP 2: make -j number_of_cores_or_processors_CPU_has
# STEP 3: make install
######################
INSTALL_DIR=$HOME/bin/php7
mkdir -p $INSTALL_DIR
./configure --prefix=$INSTALL_DIR \
--enable-bcmath \
--enable-fpm \
--with-fpm-user=www-data \
--with-fpm-group=www-data \
--disable-cgi \
--enable-mbstring \
--enable-shmop \
--enable-sockets \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--with-zlib \
--with-curl \
--without-pear \
--with-openssl \
--enable-pcntl \
--with-password-argon2 \
--with-sodium \
--disable-libxml \
--disable-simplexml \
--disable-xml \
--disable-xmlreader \
--disable-xmlwriter \
--disable-dom \
--without-libxml
# to add additional compile options to PHP, add " \" after the last
# element. You *must* put a space and then a backslash so the configure
# script knows that the there is more to the build script
--enable-mysqlnd \
--with-pdo-mysql=mysqlnd
--with-pdo-pgsql=/usr/bin/pg_config
Install the ZIP libraries if you need to work with .zip file
Earlier we installed the package zlib1g-dev
, this allows us to work with
compressed files, like tar.gz and .tgz, but not .zip files.
sudo apt-get install libzip-dev libzip5
And, add this to the build PHP build script below
--with-zip \
sudo apt-get install libreadline-dev
And, add the following to the PHP build script below
--with-readline \
sudo apt-get install libxml2-dev
remove the following lines from the PHP build script below
--disable-libxml \
--disable-simplexml \
--disable-xml \
--disable-xmlreader \
--disable-xmlwriter \
--disable-dom
The next three commands create a Makefile so the make
command knows how to
build PHP, where to install the binaries at, what options PHP should be built
with
The variable number_of_cores_or_processors_CPU_has
should be at least 3 unless
you are building on a small box, or a VM, however, this increases the time
greatly
sh build_php.sh
make -j number_of_cores_or_processors_CPU_has
make install
Copy the php-7.3.4/php.ini-development file from the source directory to the ~/bin/php7/lib/ directory, and rename the file to php.ini
cp php.ini-development ~/bin/php7/lib/php.ini
cd ~/bin/php7/lib;
You'll need to set your timezone to one of the following values from here: http://php.net/manual/en/timezones.php
For example, if you are in the US Central timezone, your timezone will be
America/Chicago
If you are in the US Pacific Timezone, your timezone will be America/Los_Angeles
If you are in Zurich, Switzerland, your timezone will be Europe/Zurich
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone=America/Chicago
The MySQL socket PDO connects to (if MySQL is running locally)
; Default socket name for local MySQL connects. If empty, uses the built-in
; MySQL defaults.
; http://php.net/pdo_mysql.default-socket
pdo_mysql.default_socket=/var/run/mysqld/mysqld.sock
The PHP-FPM fix
cgi.fix_pathinfo=0:
You need to create a php-fpm.conf file to use Nginx.
cd ~/bin/php7/etc/; mv php-fpm.conf.default php-fpm.conf
cd ~/bin/php7/etc/php-fpm.d/; mv www.conf.default www.conf
In your favorite editor, open the www.conf file, and change the user and group from nobody to www-data (the user for nginx). THIS SHOULD BE DONE FOR YOU JUST DOUBLE CHECK TO MAKE SURE IT'S SET
...
user = www-data
group = www-data
...
Sockets are faster then using TCP ports, but are limited in the number of connections they support.
If you want to use sockets, though, you'll need to make the following changes
to the www.conf
file
change listen
from
listen = 127.0.0.1:9000
to
listen = /var/run/php-fpm.sock
also, uncomment out the listen.owner
, listen.group
, & listen.mode
variables
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
Edit your .bashrc file and add the PHP 7 bin directories to your path
if [ -d "$HOME/bin/php7" ] ; then
PATH="$HOME/bin/php7/bin:$HOME/bin/php7/sbin:$PATH"
fi
cd ~/bin
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
ln -s composer.phar composer
Do this for local development, and for testing servers
To run the PHP-FPM process whenever the server reboots run the following command
sudo crontab -eu root
Then add the following line to the crontab
@reboot /home/me/bin/php-fpm
DO NOT install XDebug on a production server!
wget https://xdebug.org/files/xdebug-2.9.6.tgz -O xdebug-2.9.6.tgz
tar -xzf xdebug-2.9.6.tgz
The variable number_of_cores_or_processors_CPU_has should be at least 3. Most modern computers have quad core processors. This significantly speeds up the time taken to compile the PHP binary and its shared libraries
cd xdebug-2.9.6/
phpize
./configure --enable-xdebug
make -j number_of_cores_or_processors_CPU_has
make install
The XDebug installation script should install xdebug.so in the correct location which is $HOME/bin/php7/lib/php/extensions/no-debug-non-zts-20190902/
Test if the file exists
ls -l $HOME/bin/php7/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
If you get an error stating no such file or directory, then, you need to move the shared object to the PHP extension directory manually
cp modules/xdebug.so $HOME/bin/php7/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
You need to tell PHP where to find the xdebug
library. Append this snippet
to the end of the php.ini file located at $HOME/bin/php7/lib/php.ini
[xdebug]
zend_extension=/home/{USER NAME}/bin/php7/lib/php/extensions/no-debug-non-zts-20190902/xdebug.so
xdebug.remote_enable=1
xdebug.remote_autostart=1
xdebug.remote_connect_back=1
xdebug.remote_host=127.0.0.1
xdebug.remote_port=9000
You'll have to start php-fpm manually to get it working with Nginx
sudo $HOME/bin/php7/sbin/php-fpm
To run the PHP-FPM process whenever the server reboots run the following command
sudo crontab -eu root
Then add the following line to the crontab
@reboot /home/me/bin/php-fpm
You need to modify Nginx's configuration to start using PHP-FPM
cd /etc/nginx/sites-available
Open default and change the root directory to where your code is
root /path/to/your_PHP_project;
Add index.php to the index list
index index.php;
Remove the location section and make the following changes in the FastCGI section
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# If you want to use a TCP port, un-comment this
# fastcgi_pass 127.0.0.1:9000;
# ...OR
# If you want to use Unix sockets, un-comment this
# fastcgi_pass unix:/var/run/php-fpm.sock;
}
So, your conf file should look like this:
server {
listen 80 default_server;
listen [::]:80 default_server;
# path to code (index.php should be in this directory)
root /path/to/PHPCODE;
index index.php;
server_name phpdevbox;
location / {
try_files $uri $uri/ /index.php?query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# use this if you want to use TCP:
# fastcgi_pass 127.0.0.1:9000;
# use this if you want to use sockets
# fastcgi_pass unix:/var/run/php-fpm.sock;
}
location ~ /\.ht {
# deny access to .htaccess files
deny all;
}
}
Nginx should now be serving your files
There are multiple ways to use PHP for development.
If you're using Laravel 5.5 this is how you start the built in PHP server
php artisan serve --host=your.ip.of.vm --port=8000
If you want to use the built in PHP web-server
php -S ip.of.your.machine:port_number
While, you can use Nginx for testing, it's not the best alternative. One of the issue you will find is that Nginx times out.
Follow the instructions found in the section Using PHP with Nginx (production mode) on how to setup Nginx to serve PHP files from your VM
You'll need to edit /etc/nginx/nginx.conf
and change the line
sendfile on;
to sendfile off;
What will happen is changes to static files (CSS and Javascript) files won't be updated. Turning off sendfile will cause Nginx to serve the file via a different method and the new file's changes will be displayed immediately.
These step are if you want to develop [write code] on Windows or Mac, but run the code on a VM.
I prefer Ubuntu Server because it lacks a window manager and only needs about 256 MB RAM
Every step in the below instructions has been tailored specifically for Ubuntu Server on Virtualbox.
After installing Ubuntu Server (20.04) in a virtual machine, install the following packages
nfs-kernel-server
NFS (Network File System) is targeted at *NIX based systems. Originally developed by Sun MicroSystems in the 1980s, NFS allows the file system of one *NIX computer to be accessed by another *NIX system.
First create a directory to be shared. It's best to use a directory with no assigned user by default
mkdir -p /mnt/shared_dir
Each folder to be shared via NFS must have an entry in the file /etc/exports
# NOTE: NO SPACE AFTER THE IP ADDRESS!
/mtn/shared_dir client_ip(permissions)
- The first arguement is pretty simple: the directory to share.
- The second argument is the client's IP or IP range: e.g. 192.168.1.1/24. That IP address means anyone from 192.168.1.1 - 192.168.1.255. If you want anyone to be able to connect, change the IP Address to *
- The third arguement is the permissions
Here's the list of permissions that work on Mac/Ubuntu to an Ubuntu server
- rw
- sync
- no_subtree_check
- insecure
- all_squash - tells NFS that for any user connecting,ignore their actual user & group ID and treat them as if user ID = anonuid and group ID = anonguid
- anonuid=1000
- anonguid=1000
IF anonuid and anonguid are 0,then that user IS GIVEN ROOT PERMISSION
The anonuid and anonuid of 1000 is the user and group of the user on my Ubuntu Server
Now that we have a shared dir, allow others to connect to it
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
systemctl start rpc-statd
Using MacOS Catalina (10.15) this is one way to connect
cd # change to the home directory
mkdir -p nfs_mount # create a new directory called "nfs_mount"
sudo mount 192.168.1.184:/mnt/shared_dir /Users/{my mac user}/nfs_mount
If you are using VSCode this launch.json will allow you to write code locally and debug remotely
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for XDebug",
"type": "php",
"request": "launch",
"port": 9000,
"pathMappings": {
"/home/phpuser/cifs_share": "${workspaceRoot}"
}
}
]
}