32
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.
- NodeJS
- Serverless Framework
- AWS Account
- 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 - https://nodejs.org/en/download/
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 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
If you haven't signed up on AWS, you can create an free account here https://aws.amazon.com/console/ .
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.
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.*
Click Next: Tags, Tags are optional so just click on next.
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.
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.
Copy and paste the needed AWS keys to the serverless cli (without the < or > symbols)
serverless config credentials --provider aws --key <key> --secret <secret>
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
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
💡 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.
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