Back to Course |
Deploy Laravel Project to AWS EC2: Step-By-Step

Install PHP with Dependencies

We're getting closer to actually installing our Laravel project. But Laravel is a PHP framework, and guess what - we don't have PHP installed on the server yet. Let's fix this.

  1. Time to review our requirements once again, and determine which Ubuntu packages we need to install:

As per Laravel requirements:

  • BCMath PHP Extension - php8.1-bcmath - provides arbitrary-precision arithmetic
  • Ctype PHP Extension - php8.1-common - checks whether a character or string falls into a certain character class according to the current locale
  • cURL PHP Extension - php8.1-curl - allows you to connect and communicate to many different types of servers with many different types of protocols
  • DOM PHP Extension - php8.1-xml - allows you to operate on XML documents through the DOM API with PHP
  • Fileinfo PHP extension - php8.1-common - functions in this module try to guess the content type and encoding of a file
  • JSON PHP Extension - Always available - implements the JavaScript Object Notation (JSON) data-interchange format
  • Mbstring PHP Extension - php8.1-mbstring - provides multibyte specific string functions that help you deal with multibyte encodings
  • OpenSSL PHP Extension - openssl - library for symmetric and asymmetric encryption and decryption
  • PCRE PHP Extension - Always available - PHP Core library with JIT support
  • PDO PHP Extension - php8.1-common - defines a lightweight, consistent interface for accessing databases
  • Tokenizer PHP Extension - php8.1-common - interface to the PHP tokenizer
  • XML PHP Extension - php8.1-xml - implements support for DOM, SimpleXML, XML, and XSL

And additional dependencies for our demo project:

  • PHP-FPM - php8.1-fpm - server-side, FastCGI implementation (FPM-CGI binary), high performance interface between Web Server and PHP programs, allowing a server to handle more web page requests per unit of time
  • Zip PHP Extension - php8.1-zip - this will be useful if you plan to have ability to work with archives
  • GD PHP Extension - php8.1-gd - library for working with images, if you plan to use Laravel package like spatie/laravel-medialibrary
  • PHP cli - php8.1-cli - PHP command-line interpreter if you plan to have some scripts you want to in command line
  • Composer - composer - dependency manager for PHP
  • MySQL PHP Extension - php8.1-mysql - MySQL Native Driver, provides mysqli, mysqlnd and pdo_mysql PHP modules

Optional:

  • Redis PHP Extension - php8.1-redis - extension for interfacing with Redis, in-memory storage, used for cache and queues. Used in combination with Laravel Horizon and redis-server
  1. Install all dependencies:
root@ip-172-31-44-101:~# apt-get install --no-install-recommends php8.1 php8.1-{bcmath,cli,common,curl,fpm,gd,mbstring,mysql,xml,zip} openssl composer

Note that --no-install-recommends flag tells to install only required packages and ignore other recommended packages like Apache web server which we do not intend to use

  1. Verify PHP is installed and check the version:
root@ip-172-31-44-101:~# php -v
PHP 8.1.2-1ubuntu2.8 (cli) (built: Nov 2 2022 13:35:25) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.2, Copyright (c) Zend Technologies
with Zend OPcache v8.1.2-1ubuntu2.8, Copyright (c), by Zend Technologies
  1. Verify composer is installed and check the version:

Do not run Composer as a root/super user! See https://getcomposer.org/root for details

ubuntu@ip-172-31-44-101:~$ composer --version
Composer 2.2.6 2022-02-04 17:00:38
  1. Optionally you can check which modules are enabled for your php installation:
root@ip-172-31-44-101:~# php -i | grep enabled
Zend Signal Handling => enabled
Zend Memory Manager => enabled
IPv6 Support => enabled
BCMath support => enabled
Calendar support => enabled
ctype functions => enabled
cURL support => enabled
date/time support => enabled
DOM/XML => enabled
HTML Support => enabled
XPath Support => enabled
XPointer Support => enabled
Schema Support => enabled
RelaxNG Support => enabled
EXIF Support => enabled
Multibyte decoding support using mbstring => enabled
FFI support => enabled
fileinfo support => enabled
Input Validation and Filtering => enabled
FTP support => enabled
FTPS support => enabled
GD Support => enabled
FreeType Support => enabled
GIF Read Support => enabled
GIF Create Support => enabled
JPEG Support => enabled
PNG Support => enabled
WBMP Support => enabled
XPM Support => enabled
XBM Support => enabled
WebP Support => enabled
BMP Support => enabled
TGA Read Support => enabled
GetText Support => enabled
hash support => enabled
iconv support => enabled
Internationalization support => enabled
json support => enabled
libXML streams => enabled
Multibyte Support => enabled
Multibyte (japanese) regex support => enabled
MysqlI Support => enabled
mysqlnd => enabled
OpenSSL support => enabled
pcntl support => enabled
PCRE (Perl Compatible Regular Expressions) Support => enabled
PCRE JIT Support => enabled
PDO support => enabled
PDO Driver for MySQL => enabled
Phar: PHP Archive support => enabled
Phar-based phar archives => enabled
Tar-based phar archives => enabled
ZIP-based phar archives => enabled
gzip compression => enabled
Native OpenSSL support => enabled
POSIX support => enabled
Readline Support => enabled
Reflection => enabled
Session Support => enabled
session.upload_progress.enabled => On => On
shmop support => enabled
SimpleXML support => enabled
Schema support => enabled
Sockets Support => enabled
sodium support => enabled
SPL support => enabled
Dynamic Library Support => enabled
sysvmsg support => enabled
sysvsem support => enabled
sysvshm support => enabled
Tokenizer Support => enabled
XMLReader => enabled
XMLWriter => enabled
XSL => enabled
EXSLT => enabled
Zip => enabled
ZLib Support => enabled
  1. Verify the status of PHP-FPM:
root@ip-172-31-44-101:~# systemctl status php8.1-fpm
php8.1-fpm.service - The PHP 8.1 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php8.1-fpm.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2022-11-09 16:27:55 UTC; 31s ago
Docs: man:php-fpm8.1(8)
Process: 36268 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/8.1/fpm/pool.d/www.conf 81 (code=exited, status=0/SUCCESS)
Main PID: 36265 (php-fpm8.1)
Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
Tasks: 3 (limit: 1143)
Memory: 10.2M
CPU: 54ms
CGroup: /system.slice/php8.1-fpm.service
├─36265 "php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
├─36266 "php-fpm: pool www" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""
└─36267 "php-fpm: pool www" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""

PHP-FPM service is enabled and running so no action is needed.

  1. Enable PHP on NginX

Let's create a PHP file with a random name in our document root /var/www/html/ and see if it is working.

root@ip-172-31-44-101:~# cd /var/www/html/
root@ip-172-31-44-101:/var/www/html# nano 1af3503416.php # pick different file name

Then enter PHP contents:

<?php
 
phpinfo();

phpinfo() function outputs a large amount of information about the current state of PHP.

and press ^X (CTRL+x) to exit. Caret ^ symbol means [control] key. Editor asks you to confirm changes, enter Y and press [enter] to exit the editor.

Save modified buffer? Y
Y Yes
N No ^C Cancel

Note we chose a random filename because often people forget to delete such files, and if the file is named test.php this could pose a potential leak of sensitive system data.

Now navigate to http://18.195.117.231/1af3503416.php and see what happens. Right, the browser just downloaded the file. This is because NginX doesn't know yet what to do with that PHP file. It needs to be passed to PHP FPM to php code to execute so NginX can return a proper response.

For it to work, we need to add one configuration block to the NginX site config.

Edit the/etc/nginx/sites-enabled/default file

root@ip-172-31-44-101:~# nano /etc/nginx/sites-enabled/default

To server section after location / {...} add:

location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}

It should look something like this:

server {
listen 80 default_server;
listen [::]:80 default_server;
 
# <...>
 
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;
}
 
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
 
# <...>
}

This is a very basic NginX setup just to check if PHP is working properly, and is not suitable for production. We will come back to the NginX configuration for Laravel later.

For changes to take effect you need to restart the NginX server. But before that, make sure you have no errors in config files. This can be checked with the nginx -t command.

root@ip-172-31-44-101:~# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If everything is ok restart NginX:

root@ip-172-31-44-101:~# systemctl restart nginx

Now navigate to http://18.195.117.231/1af3503416.php again, PHP should be working:

phpinfo

And now you can delete this test file.

root@ip-172-31-44-101:~# rm /var/www/html/1af3503416.php