Setup Notes for Serverless PHP 8.0 Laravel on AWS Lambda using Bref

Serverless framework have piqued my interest since 2019. And since then I have followed PHP developers and communities to check if there is already an available package that can ship it as a "serverless" build. As far as I know the only available options back then are OpenWhisk and Bref.

For this post, I am sharing my setup notes on how to get started on deploying a simple Laravel PHP application using the Serverless Framework and the Bref plugin.

Just like with any project, you will need to prepare to install some software to build your project.

  1. NodeJS
  2. Serverless Framework
  3. AWS Account
  4. Laravel PHP Project

Each software installation is broken down into steps and has screenshots for it be more helpful as the AWS UI can be confusing sometimes. (or maybe its just me)

💡 I am sharing some gotchas along the way while I was using this framework extensively. I hope you can find it helpful on your workflows too.

👣 NodeJS Installation

Verify that you have installed this by typing this in the terminal

node -v
//should output a version
v16.3.1

npm -v
//should output a version
8.1.2

👣 Serverless Framework Installation

Serverless Framework will be our wrapper to do the hard lifting of orchestrating everything in AWS. You will need to install this via terminal, npm install -g serverless if there is an error about permission, try sudo npm install -g serverless .

serverless -v
//should output like this

Framework Core: 2.69.0
Plugin: 5.5.1
SDK: 4.3.0
Components: 3.18.1

👇 there is also a shorthand command for "serverless"

sls -v
//should output the same

Framework Core: 2.69.0
Plugin: 5.5.1
SDK: 4.3.0
Components: 3.18.1

👣 AWS Keys generation

If you haven't signed up on AWS, you can create an free account here https://aws.amazon.com/console/ .

Step 1

You will need to generate AWS Keys to deploy services automatically. Head on to IAM and create a new user. Ensure that you are giving the programmatic access a turned on checkmark.

Step 2

We will need to attach permissions to the user we are creating.

First, on the "Set permissions" choose the "Attach existing policies directly.

Edit: Removed ec2FullAccess (ty to @smknstd for taking the time to notice it 🎄)

Do these steps for the following permissions:

  • IAMFullAccess, AmazonS3FullAccess, CloudWatchFullAccess, CloudFrontAccess, AmazonAPIGatewayAdministrator, AWSCloudFormationFullAccess, AWSLambda_FullAccess.*

Step 3

Click Next: Tags, Tags are optional so just click on next.

Step 4

This review page should show something similar to this. The permissions 💡 **If the logs are still returning an error, read it carefully and check if you still lack additional permissions.

Step 5

Upon creating the user, download the .csv file as you will not be seeing the aws secret keys anymore. Store it where it is safe and accessible to you.

Open that .csv file you just downloaded because you will be copying some of its fields in a bit.

👣 Setup the AWS Keys to Serverless Framework

Copy and paste the needed AWS keys to the serverless cli (without the < or > symbols)

serverless config credentials --provider aws --key <key> --secret <secret>

👣 Create a Laravel Project

I use the following commands to create a fresh laravel project. If you already have an existing project then just add the bref/bref package.

composer create-project laravel/laravel serverless-template
cd serverless-template
composer require bref/bref

👣 Setup your PHP Laravel project with a serverless.yml

Create a serverless.yml on the root directory of your project using this template.

As of this writing, that template uses a PHP 8.0 and is compatible to Laravel 8.x

Add also install the needed plugin mentioned in the serverless.yml

npm install
npm install serverless-prune-plugin

💡 My gotchas on the serverless.yml

💡 reservedConcurrency is not like provisionedConcurrency

💡 reservedConcurrency is the maximum number of concurrency your lambda can scale to. If this has no limit, your lambda concurrency can go as high as 1,000 instances.💸💸

💡 provisionedConcurrency is the minimum number of readily available lambda, or as the word itself, already provisioned. So even though you are not using it, there is already that number of provisioned lambda turned on and running.

💡 AWS Code storage limited to 75GB. I had a project that happen to reach that limit and as we did not need any old version of our lambda code, we instead pruned every old code version. That is why I added the serverless-prune-plugin this will automatically just retain the latest code version in S3 bucket.

Deploying 🚀🚀🚀

For a Laravel framework, you will need to add these on your .env file. In a normal server, the cache driver can be installed locally but for a lambda, you will need to outsource that, you can use AWS RDS or AWS Redis / Memcached with a public endpoint or a separate VPC but for this demo, we can put it as an array.

CACHE_DRIVER=array
VIEW_COMPILED_PATH=/tmp/storage/framework/views
SESSION_DRIVER=array
LOG_CHANNEL=stderr

And on the app/Providers/AppServiceProvider.php we will need to add this

public function boot()
{
    //ensures the directory for compiled views exist
    if (! is_dir(config('view.compiled'))) {
        mkdir(config('view.compiled'), 0755, true);
    }
}

And finally, you will need to invoke serverless deploy or sls deploy This will communicate with AWS to automate stuff on the background. Check the logs if we missed any permissions. This is how it should look like. You should be able to access a URL endpoint and see the default landing page.

/users/path/to/my/project/serverless-template % sls deploy
Serverless: Running "serverless" installed locally (in service node_modules)
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Ensuring that deployment bucket exists
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service template-serverless-service-sample.zip file to S3 (14.19 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..........................................
Serverless: Stack update finished...
Service Information
service: template-serverless-service-sample
stage: dev
region: us-east-1
stack: template-serverless-service-sample-dev
resources: 15
api keys:
  None
endpoints:
  ANY - https://wtv6mun227.execute-api.us-east-1.amazonaws.com/dev
  ANY - https://wtv6mun227.execute-api.us-east-1.amazonaws.com/dev/{proxy+}
functions:
  web: template-serverless-service-sample-dev-web
  artisan: template-serverless-service-sample-dev-artisan
layers:
  None
Serverless: Prune: Running post-deployment pruning
Serverless: Prune: Querying for deployed function versions
Serverless: Prune: template-serverless-service-sample-dev-web has 1 additional version published and 0 aliases, 0 versions selected for deletion
Serverless: Prune: template-serverless-service-sample-dev-artisan has 1 additional version published and 0 aliases, 0 versions selected for deletion
Serverless: Prune: Pruning complete.

And that's just about it! let me know if this worked out for ya!

32