Automated multi region deployments using Github Actions, Laravel Vapor and Cloudflare
Tom Hatzer • December 13, 2020
laravel vapor cloudflare awsATTN: I'm writing this as a brain dump so some places may be missing information. If you find a mistake or would love to get more information, please get in touch with me on twitter. Thanks!
Today I would like to show you how to get automated multi region deployments working with Github Actions, Laravel Vapor and Cloudflare.
Ingredients
- 1 Laravel Vapor account
- 1 Cloudflare account
- 1 AWS account
- 1 Domain (also added to Vapor including certificates)
- 1 Github account
- 1 Source repository on Github
- 4 tbsp love and affection
- 2+ Regions
Difficulty
Low to mid
Duration
About 30 minutes to 1 hour
Temperature
Your body temperature and heart rate should stay at the usual levels.
Contents
- Project setup in Vapor
- Project setup for other regions in Vapor
- Environment setup in Vapor
- Vapor configuration files
- Vapor API access token
- Github repository secrets
- Github action auto deploy
- Cloudflare Load Balancer setup
- Final step
Introduction
We will start with the base, a working Laravel Vapor account. I won't go into details as this is already covered in the docs here. After you've set up your Laravel Vapor account, let's create our project in the regions we want to deploy it.
In my case we will use the following regions for our project:
- US North Virginia (us-east-1)
- EU Frankfurt (eu-central-1)
- ASIA Singapore (ap-southeast-1)
Steps
Step 1 - Project setup in Vapor
Log into Laravel Vapor, select your Team
and in your Dashboard
click on the Create Project
button.
Fill the modal windows input fields with your desired project name and select the first region eg.
After creating your project, a modal window will appear with an example vapor.yml
file. Copy the content from this window into a temporary file on your local disk as we will need this later on.
Laravel Vapor will create 2 environments for you: Production
and Staging
. For simplicity we will only keep production here and delete the Staging
environment.
Step 2 - Project setup for other regions in Vapor
Repeat Step 1
for the other regions you have. In my case it would be eu-central-1
and ap-southeast-1
.
Step 3 - Environment setup in Vapor
Now add/edit the environment variables (content of your .env file) for each environment in each project.
A single global database is a nice to have. AWS offers Aurora Global Databases with active/active sync, but they are pretty expensive when deployed in multiple regions. For 3 regions with high availability you would have to pay around 2.4k USD per month for a single global cluster.
You can also create databases in Laravel Vapor and use them for your project if you don't need active synchronisation.
Step 4 - Vapor configuration files
Create vapor-<region>.yml
(replace <region>
with your custom region) files with the content that you received earlier in the Vapor Dashboard after creating the projects.
In my case there would be 3 .yml
files:
- vapor-us-east-1.yml
- vapor-eu-central-1.yml
- vapor-ap-southeast-1.yml
Your files could look like this one here:
id: 1234
name: global-demo-project-ap-southeast-1
environments:
production:
domain: mydomain.com
gateway-version: 2
memory: 512
cli-memory: 512
cli-timeout: 15
runtime: 'php-7.4'
build:
- 'COMPOSER_MIRROR_PATH_REPOS=1 composer install --no-ansi --no-dev --no-interaction --no-suggest --optimize-autoloader'
- 'php artisan event:cache'
- 'yarn && yarn prod && rm -rf node_modules'
deploy:
- 'php artisan migrate --force'
Please be aware that you have to enter your own id
depending on your project.
Step 5 - Vapor API access token
Now create a Vapor API access token by clicking your name in the upper right corner of the Vapor Dashboard
, selecting My Profile
and then clicking on API
below the Account Settings
headline.
Enter your tokens name and submit the form by clicking on the Add
button. A modal window will appear with your token. Copy the content from this window into a temporary file on your local disk as we will need this later on.
Step 6 - Github repository secrets
Head over to github.com and into the settings of your repository. Select Secrets
from the menu and click the New repository secret
button on the right side. (Can't find it? The github docs will guide you the way.)
Enter the following details:
- Name:
VAPOR_API_TOKEN
- Value: Enter the token you copied/saved in Step 5 into this field
Now click on Add secret
to store the secret inside your repository.
Step 7 - Github action auto deploy
Let's set up our automatic deployment using Github actions.
For this, we will create the file .github/workflows/multi-region-deployment.yml
in the repository with the following content:
name: Laravel
on:
push:
branches: [ "main" ]
jobs:
vapor:
name: Check out, build and deploy using Vapor
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Setup PHP (w/ extensions) & Composer
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
tools: pecl
extensions: bcmath, bz2, ctype, curl, fileinfo, gd, gmp, iconv, intl, json, mbstring, mysqli, openssl, pdo, pdo_mysql, pdo_sqlite, sodium, sqlite3, tokenizer, xml, zip
coverage: none
- name: Obtain Composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
- name: Cache Composer dependencies
uses: actions/cache@v1
with:
path: ${{ steps.composer-cache.outputs.dir }}
# Use composer.json for key, if composer.lock is not committed.
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install Vapor CLI Globally
run: composer global require laravel/vapor-cli
- name: Install Composer dependencies
run: composer install --no-progress --no-suggest --prefer-dist --optimize-autoloader
- name: Obtain NPM Cache directory (used by Laravel Mix)
id: node-cache-dir
run: echo "::set-output name=dir::$(yarn cache dir)" # Use $(yarn cache dir) for yarn
- name: Cache NPM dependencies (used by Laravel Mix)
uses: actions/cache@v1
with:
path: ${{ steps.node-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }} # Use '**/yarn.lock' for yarn
restore-keys: ${{ runner.os }}-node-
- name: Rename vapor.yml file
run: mv vapor-eu-central-1.yml vapor.yml
- name: Deploy using Laravel Vapor
env:
VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }}
run: /home/runner/.composer/vendor/bin/vapor deploy production
- name: Remove vapor.yml file
run: rm vapor.yml
- name: Rename vapor.yml file
run: mv vapor-ap-southeast-1.yml vapor.yml
- name: Deploy using Laravel Vapor
env:
VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }}
run: /home/runner/.composer/vendor/bin/vapor deploy production
- name: Remove vapor.yml file
run: rm vapor.yml
- name: Rename vapor.yml file
run: mv vapor-us-east-1.yml vapor.yml
- name: Deploy using Laravel Vapor
env:
VAPOR_API_TOKEN: ${{ secrets.VAPOR_API_TOKEN }}
run: /home/runner/.composer/vendor/bin/vapor deploy production
Quick explanation:
- Checkout the repository code
- Set up php 7.4 and composer
- Obtain composer cache directory and cache dependencies
- Install Vapor CLI
- Install project dependencies using composer
- Obtain npm/yarn cache directory and cache dependencies
- Rename vapor.yml file and deploy to desired stage (3x)
- Done!
After you've done this, Github should trigger your first deployment and set up your first environments on AWS.
Step 8 - Cloudflare Load Balancer setup
Like in the description we will be using Cloudflare for the regional load balancing. The whole process is also described in the Cloudflare docs including screenshots.
So first, you will have to point the nameservers of your domain to cloudflare. To do this, follow these steps:
- Log into your Cloudflare account.
- Add your domain if you haven't done this already.
- Cloudflare will show you the nameservers you have to point your domain to. Set your nameservers for your domain accordingly.
- Wait a little bit until Cloudflare was able to resolve your domain using their nameservers. This can take up to 48 hours, but most of the time it takes only a few minutes or more.
- The first thing afterwards should be, setting your SSL settings to
Full
. Do not set it toFull (strict)
as this will cause problems with monitoring for the load balancer. - Then click on the
Traffic
item in the top menu. - The submenu has the
Load Balancing
item for you available to select. Click on it. - Create a new Load Balancer of type
Dynamic steering
to be able to useGeo steering
. - Set your
Hostname
for the Load Balancer. This can be a subdomain or your main domain (eg. www.mydomain.com or mydomain.com). - Activate
Session Affinity
as you may encounter problems with sessions or likewise if you use multiple regions. - Click on
Next
. - Now we are going to add the Origin Pools. These are the
API Gateway
domains you will find in your Vapor environments. For every region you have, add one Origin Pool.- Go back to your Vapor Dashboard, select the Production environment for the first region. I'll be using the domain directly without subdomain, so I'm copying the hostname without www like
d-kx24nowri2.execute-api.ap-southeast-1.amazonaws.com
. Pay attention to copy the correct hostname as this will otherwise cause problems later on. - Repeat the previous step for every region you have on your list. Also assign them a speaking name so you can differentiate them later on.
- You can also add monitoring to your Origin Pools. We'll do this right below.
- Go back to your Vapor Dashboard, select the Production environment for the first region. I'll be using the domain directly without subdomain, so I'm copying the hostname without www like
- Click on
Next
. - Let's add a Health Check to our Origin Pools.
- Type: https
- Path: /
- Method: GET
- Expected Codes: 2xx
- Header Name:
- Host: mydomain.com
- You can now add that Health Check to all of your Origin Pools.
- Click on
Next
. - Now we're going to configure the Geo Routing:
- Select the Region where you want to bind the Origin Pool to. Do this for every region that you want to support and every Origin Pool you have.
- Click on
Next
. - Review your settings and check if your Origin Pools are
Healthy
. Everything should be green andHealthy
. If not, you can send me a message on twitter if you need assistance. - Click on
Done
.
Step 9 - Final step
Now check your domain, you should be able to view your deployed website, delivered from the Origin Pool you selected for your region.
Notes
- If there are parts of information missing, send me a quick message on twitter (link on top of this article).
- Please use the docs of the specific products you are using if you need any further help or want to implement additional features.