An advanced Laravel integration for Bref, including Octane support.

Overview

Bref Laravel Bridge

An advanced Laravel integration for Bref, including Octane support.

This project is largely based on code from PHP Runtimes, Laravel Vapor and Bref's Laravel Bridge.

Background

Why does this exist and why not just use Laravel Vapor? Vapor is fantastic, easy to use and the better choice for situations, its $399/year pay for itself not having to maintain your own infrastructure.

For Relay's API however we needed something that 1) is open source (Vapor's API is a black box), 2) is secure (Vapor has admin access to databases and environment variables) and 3) doesn't leave us at the mercy of a support team (Vapor has no enterprise support). We also didn't want to be forced to use CloudFront on top of Cloudflare, but that's just nerdy preference.

We needed an open source solution that gives us more fine-grained control and is secure.

Bref + Serverless Framework is exactly that, however Bref's Laravel integration is rather basic, it easily exposes SSM secrets and it doesn't support Laravel Octane.

So we built this.

Installation

First, be sure to familiarize yourself with Bref and its guide to Serverless Laravel applications.

Next, install the package and publish the custom Bref runtime:

composer require cachewerk/bref-laravel-bridge

php artisan vendor:publish --tag=bref-runtime

By default the runtime is published to php/ where Bref's PHP configuration resides, but it can be move anywhere.

Next, we need to set up in the AWS_ACCOUNT_ID environment variable in your serverless.yml:

provider:
  environment:
    AWS_ACCOUNT_ID: ${aws:accountId}

Then set up your functions:

functions:
  web:
    handler: php/runtime.php
    environment:
      APP_RUNTIME: octane
      BREF_LOOP_MAX: 250
    layers:
      - ${bref:layer.php-81}
    events:
      - httpApi: '*'

  queue:
    handler: php/runtime.php
    timeout: 59
    environment:
      APP_RUNTIME: queue
    layers:
      - ${bref:layer.php-81}
    events:
      - sqs:
          arn: !GetAtt Queue.Arn
          batchSize: 1
          maximumBatchingWindow: 60

  cli:
    handler: php/runtime.php
    timeout: 720
    environment:
      APP_RUNTIME: cli
    layers:
      - ${bref:layer.php-81}
      - ${bref:layer.console}
    events:
      - schedule:
          rate: rate(1 minute)
          input: '"schedule:run"'

If you don't want to use Octane, simply remove APP_RUNTIME and BREF_LOOP_MAX from the web function.

To avoid setting secrets as environment variables on your Lambda functions, you can inject them directly into the Lambda runtime:

provider:
  environment:
    APP_SSM_PREFIX: /${self:service}-${sls:stage}/
    APP_SSM_PARAMETERS: "APP_KEY, DATABASE_URL"

This will inject APP_KEY and DATABASE_URL using your service name and stage, for example from /myapp-staging/APP_KEY.

Finally, deploy your app:

sls deploy --stage=staging

Check out some more comprehensive examples.

Configuration

Serving static assets

If you want to serve some static assets from your app's public directory, you can use the ServeStaticAssets middleware.

First, publish the configuration:

php artisan vendor:publish --tag=bref-config

Then define the files you want to serve in bref.assets.

Lastly tell Bref to support binary responses on your web function:

functions:
  web:
    handler: php/runtime.php
    environment:
      BREF_BINARY_RESPONSES: 1

Persistent database sessions

If you're using PostgreSQL 9.6 or newer, you can take advantage of persistent database sessions.

First set idle_in_transaction_session_timeout either in your RDS database's parameter group, or on a specific database itself.

ALTER DATABASE SET idle_in_transaction_session_timeout = '10000' -- 10 seconds in ms

Lastly, set the OCTANE_PERSIST_DATABASE_SESSIONS environment variable.

functions:
  web:
    handler: php/runtime.php
    environment:
      APP_RUNTIME: octane
      BREF_LOOP_MAX: 250
      OCTANE_PERSIST_DATABASE_SESSIONS: 1

Usage

Artisan Console

Just like with Bref, you may execute console commands.

vendor/bin/bref cli --cli -- route:list

vendor/bin/bref cli example-staging-cli -- route:list

Maintenance mode

Similar to the php artisan down command, you may put your app into maintenance mode. All that's required is setting the MAINTENANCE_MODE environment variable:

provider:
  environment:
    MAINTENANCE_MODE: ${param:maintenance, null}

You can then quickly put all functions into maintenance without running a full build and CloudFormation deploy:

serverless deploy function --function=web --update-config --param="maintenance=1"
serverless deploy function --function=cli --update-config --param="maintenance=1"
serverless deploy function --function=queue --update-config --param="maintenance=1"

To take your app out of maintenance mode, simply omit the parameter:

serverless deploy function --function=web --update-config
serverless deploy function --function=cli --update-config
serverless deploy function --function=queue --update-config

One caveat with the --update-config flag is that it doesn't objects in environment variables in the serverless.yml:

provider:
  environment:
    SQS_QUEUE: ${self:service}-${sls:stage}    # good
    SQS_QUEUE: !Ref QueueName                  # bad
    SQS_QUEUE:                                 # bad
      Ref: QueueName
Comments
  • Switch to Laravels own queue worker

    Switch to Laravels own queue worker

    This PR adds a more native queue handler. It tries to utilise as many internal Laravel components as possible, to stay as close to the other queue implementations as possible.

    It's worth noticing that due to the way Lambda timeouts and SQS's integration with Lambda works, it's probably best to run with a batchSize of 1. If you want a larger batch size, make sure your jobs are designed in such a way that it won't break things if they are run more than once.

    This package will add a timeout value (calculated for each job by subtracting a safety margin from the remaining invocation time) that will trigger a job timeout exception if the job is configured to do so.

    Configuring a job to raise a failed exception on timeout can be done by adding the following to the job class:

    public $failOnTimeout = true;
    
    // or
    
    public function shouldFailOnTimeout()
    {
        return true;
    }
    

    When is this is set, the handler will catch the timeout, flag the job as failed and push it back onto the queue with it's attempts incremented with 1.

    If the above is not set, the worker will not catch the timeout, and after SQS's visibility timeout expires, the job will be retried with the attempts NOT incremented.


    Closes #6

    Tested by hand using a test project deployed using sls.

    opened by georgeboot 4
  • Default nonbreaking log driver.

    Default nonbreaking log driver.

    Yesterday I had the pleasure of using this Laravel bridge for the first time, and the overall experience was very good. I only had a minor issue with the initial setup I got some chmod errors. The issue was regarding the logging which used the default Laravel settings. So I was curious if it could make sense to override the default logging setting to something more compatible with AWS such as stderr. I think this is something that is also done in the Briefs Laravel bridge, or maybe change the default path to /tmp instead of Laravel's default logging path. If you believe it is a good idea, I would like to make a PR.

    Bref is doing something similar https://github.com/brefphp/laravel-bridge/blob/master/src/BrefServiceProvider.php#L58

    opened by kris914g 3
  • Check for content type starting with application/x-www-form-urlencoded

    Check for content type starting with application/x-www-form-urlencoded

    Because content type could be application/x-www-form-urlencoded;charset=UTF-8.

    It currently doesn't recognise the request as an url encoded form, and hence the form data is not available inside Laravel.

    This should probably be fixed upstream as its also in Brefs PSR-7 bridge (which inspired this code).

    Lastly, shouldn't we use something like https://symfony.com/doc/current/components/psr7.html#converting-objects-implementing-psr-7-interfaces-to-httpfoundation to convert the request from PSR-7 to Symfony instead?

    opened by georgeboot 2
  • Support maintenance mode

    Support maintenance mode

    Looks like Vapor does a full deployment and sets VAPOR_MAINTENANCE_MODE.

    Let's see if we can set an environment variable without a full build, or re-use the last built package.

    https://github.com/serverless/serverless/discussions/11089

    enhancement help wanted 
    opened by tillkruss 1
  • FPM can't write to stdout

    FPM can't write to stdout

    The secrets injector and the storage directories helper, both write to stdout. This however doesn't work in PHP-FTP and results in a crash.

    https://github.com/cachewerk/bref-laravel-bridge/blob/33c1fe09ce00d5c67bc20e1f4c9dad34f35e0ac0/src/Secrets.php#L37 https://github.com/cachewerk/bref-laravel-bridge/blob/33c1fe09ce00d5c67bc20e1f4c9dad34f35e0ac0/src/StorageDirectories.php#L31

    Ideally we attempt to write to stderr, but wrapped in a try/catch block.

    opened by georgeboot 0
  • Make package configurable

    Make package configurable

    The package is quite opinionated, let's make it configurable.

    • [x] Make ServeStaticAssets optional
    • [x] Make ServeStaticAssets assets configurable
    • [x] Document usage including the need for BREF_BINARY_RESPONSES
    • [x] Make Log::shareContext() configurable
    enhancement help wanted 
    opened by tillkruss 0
  • Support persistent database connection

    Support persistent database connection

    Let's focus on PostgreSQL, but why would ANYONE use something else.

    PostgreSQL 9.6 upwards supports idle_in_transaction_session_timeout.

    SET SESSION idle_in_transaction_session_timeout = '5min';
    

    https://stackoverflow.com/a/41818410

    It's fairly straight forward: https://github.com/laravel/vapor-core/blob/7ea7c0001795768a0fcb43d89524a7ac1cfef533/src/Runtime/Octane/Octane.php#L60-L125

    enhancement help wanted 
    opened by tillkruss 0
  • Provide a default `serverless.yml` with FPM by default

    Provide a default `serverless.yml` with FPM by default

    This PR follows up on the following threads:

    • https://github.com/brefphp/laravel-bridge/discussions/79#discussioncomment-4177668
    • https://github.com/brefphp/laravel-bridge/discussions/79#discussioncomment-4177671

    It changes the following:

    • Add a default serverless.yml so that users can quickly get started without having to create it manually
    • Switches to PHP-FPM by default (instead of Octane) so that all Laravel apps work out of the box (they don't have to be compatible with Octane)
    opened by mnapoli 0
  • Resolve SSM parameters using lambda extension

    Resolve SSM parameters using lambda extension

    Todo:

    • [x] Add docs
    • [x] Update changelog

    How to get it to work:

    • Add the required layer to your function(s)
    • Ensure your functions have access to ssm:GetParameter
    • Add APP_SSM_PREFIX and APP_SSM_PARAMETERS as usual

    Minimal serverless.yml example:

    service: my-app
    
    provider:
      name: aws
      region: eu-central-1
      stage: staging
      runtime: provided.al2
      environment:
        APP_SSM_PREFIX: /${self:service}-${sls:stage}/
        APP_SSM_PARAMETERS: "APP_KEY, WORKERLESS_LICENSE_KEY, TEST_NON_EXISTING_KEY"
      iam:
        role:
          statements:
            - Effect: Allow
              Resource: arn:aws:ssm:${aws:region}:${aws:accountId}:parameter/${self:service}-${sls:stage}/*
              Action: [ ssm:GetParameter, ssm:GetParameters ] # singular for extension, plural for sdk
    
    plugins:
      - ./vendor/bref/bref
    
    functions:
      web:
        handler: php/runtime.php
        environment:
          APP_RUNTIME: octane
          BREF_LOOP_MAX: 250
        layers:
          - ${bref:layer.php-81}
          - arn:aws:lambda:eu-central-1:187925254637:layer:AWS-Parameters-and-Secrets-Lambda-Extension:2
        events:
          - httpApi: "*"
    
    opened by georgeboot 1
  • Consider using KMS for secrets

    Consider using KMS for secrets

    Encrypting secrets in a during artifact building and loading them from a file might be a better approach for scale. Requires PHP 8.1. Hat tip @GrahamCampbell.

    https://github.com/GrahamCampbell/Envelope-Encryption

    enhancement help wanted 
    opened by tillkruss 7
Releases(v0.3.0)
Owner
CacheWerk
CacheWerk
Export Laravel Octane metrics using this Prometheus exporter.

Laravel Octane Prometheus Exporter Export Laravel Octane metrics using this Prometheus exporter. ?? Supporting If you are using one or more Renoki Co.

Renoki Co. 19 Dec 26, 2022
A High-Level Overview of Laravel Octane

This is the source code behind the Laracasts Larabit: A High-Level Overview of Laravel Octane, and features all of the files and code available in that video.

Andrew Schmelyun 1 Feb 10, 2022
Live Helper Chat - live support for your website. Featuring web and mobile apps, Voice & Video & ScreenShare. Supports Telegram, Twilio (whatsapp), Facebook messenger including building a bot.

Live helper chat It's an open-source powered application, which brings simplicity and usability in one place. With live helper chat you can bring live

Live Helper Chat 1.7k Dec 29, 2022
Provide all attributes (including irregular patterns) to Laravel Blade class components.

blade-wants-attributes blade-wants-attributes offers you the ability to use Blade/HTML-defined attributes within the constructors of Laravel Blade cla

Stephan Casas 4 Sep 15, 2022
Get estimated read time of an article. Similar to medium.com's "x min read". Multilingual including right-to-left written languages. Supports JSON, Array and String output.

Read Time Calculates the read time of an article. Output string e.g: x min read or 5 minutes read. Features Multilingual translations support. Static

Waqar Ahmed 8 Dec 9, 2022
Advanced Laravel models filtering capabilities

Advanced Laravel models filtering capabilities Installation You can install the package via composer: composer require pricecurrent/laravel-eloquent-f

Andrew Malinnikov 162 Oct 30, 2022
Thunder is an advanced Laravel tool to track user consumption using Cashier's Metered Billing for Stripe. ⚡

⚡ Thunder Thunder is an advanced Laravel tool to track user consumption using Cashier's Metered Billing for Stripe. ⚡ ?? Supporting If you are using o

Renoki Co. 10 Nov 21, 2022
⚡ PowerGrid generates Advanced Datatables using Laravel Livewire.

?? Documentation | ?? Features | ⌨️ Get started Livewire ⚡ PowerGrid ⚡ PowerGrid creates modern, powerful and easy to customize Datatables based on La

Power Components ⚡ 962 Jan 2, 2023
An advanced datatable component for Laravel Livewire.

Livewire Smart Table An advanced, dynamic datatable component with pagination, sorting, and searching including json data. Installation You can instal

Turan Karatuğ 87 Oct 13, 2022
Worlds (soon to be) most advanced Anime site! Featuring Administration features and everything you need for users and yourself. The successor of aniZero.

/**********************************************************************\ | _____ H33Tx & xHENAI __ 31.01.2022| |

HENAI.eu 40 Jan 3, 2023
This package provides an integration with FFmpeg for Laravel. Laravel's Filesystem handles the storage of the files.

Laravel FFMpeg This package provides an integration with FFmpeg for Laravel 6.0 and higher. Laravel's Filesystem handles the storage of the files. Lau

Protone Media 1.3k Jan 1, 2023
Laravel-OvalFi helps you Set up, test, and manage your OvalFi integration directly in your Laravel App.

OvalFi Laravel Package Laravel-OvalFi helps you Set up, test, and manage your OvalFi integration directly in your Laravel App. Installation You can in

Paul Adams 2 Sep 8, 2022
Razorpay payment gateway integration in laravel with submit form and storing details in payment table.

Integrating razorpay payment gateway in laravel with submit form and storing payment details in payment table. How to settup the project in your local

Mohammed-Thamnees 3 Apr 15, 2021
Laravel Echo library for beautiful Pusher and Ably integration.

Introduction In many modern web applications, WebSockets are used to implement realtime, live-updating user interfaces. When some data is updated on t

The Laravel Framework 980 Dec 31, 2022
Laravel basic repository integration

WekodeRepository This is a package to easely integrate a repository pattern with the needed service provider and all the necessary basic functions Ins

ZakariaDehaba 3 Oct 11, 2022
Official Mollie integration for Laravel Cashier

Subscription billing with Laravel Cashier for Mollie Laravel Cashier provides an expressive, fluent interface to subscriptions using Mollie's billing

Mollie 80 Dec 31, 2022
Chrome extension to generate Laravel integration tests while using your app.

Laravel TestTools Check out the introduction post about the chrome extension. Installation git clone [email protected]:mpociot/laravel-testtools.git # i

Marcel Pociot 473 Nov 1, 2022
A Laravel Livewire integration for Statamics antlers engine

Statamic Livewire A third-party Laravel Livewire integration for Statamic. It's as easy as it get's to get stared with Livewire if using Statamic 3. I

Jonas Siewertsen 55 Nov 19, 2022
This package is the official Laravel integration for Pirsch Analytics

Laravel Pirsch This package is the official Laravel integration for Pirsch Analytics. Installation Install this package. composer require pirsch-analy

Pirsch Analytics 13 Nov 10, 2022