How to Deploy Laravel Applications to AWS with Nanobox

Laravel, "the PHP framework for web artisans", has dominated the PHP world in recent years with its expressive, elegant syntax, rich feature-set, and extensibility. Amazon Web Services (AWS) is a juggernaut in the cloud computing industry and is the most widely-used cloud hosting platform.

In this article, I'm going to walk through deploying a Laravel application to AWS using Nanobox. Nanobox uses Docker to build local development and staging environments, as well as scalable, highly-available production environments on AWS.

Download Nanobox

Go ahead and create a Nanobox account and download Nanobox Desktop, the Nanobox CLI.

Setup Your Laravel Project

Whether you have an existing Laravel project or are starting the scratch, the process of configuring it for Nanobox is the same.

Add a boxfile.yml

Nanobox uses the boxfile.yml to build and configure your app's environment both locally and in production. Create a boxfile.yml in the root of your project with the following:

  engine: php
    runtime: php-7.1
    webserver: nginx
    document_root: public
      - pdo
      - mbstring
      - tokenizer
      - session
      - zip
      - dom
      - xml
      - ctype
      - xmlwriter
      - pdo_mysql

      - mkdir -p storage/{app,framework/{sessions,cache,views},logs,public}
      - php artisan migrate --force
    php: start-php
    nginx: start-nginx
    - bootstrap/cache
      - storage
    laravel[error]: /app/storage/logs/laravel.log

  image: nanobox/mysql:5.7
  image: nanobox/unfs:0.9

This boxfile.yml will:

  • Provide a PHP runtime with PHP 7.1.
  • Include and use Nginx as the webserver.
  • Set the Nginx document root to public.
  • Include PHP extensions required to install Laravel.
  • Provide a publicly accessible webserver when deployed.
  • Provide a persistent network filesystem when deployed.
  • Store the contents of storage in the network filesystem when deployed.
  • Create required subdirectories of storage on deploy (since they'll be obscured by the network mount).
  • Make bootstrap/cache writable.
  • Run migrations on deploy. You can't interact with the deploy process so you need to include the --force flag with the migration command.
  • Pipe Laravel logs into your app's aggregated log stream.
  • Provide a scalable MySQL 5.7 database.

Depending on packages and functionality in your app, you may need to add other extensions, PHP settings, etc. The following guides show how to modify PHP settings, add extensions, and modify other settings:

PHP Settings
PHP Extensions
PHP Webserver Config

Start the Local Dev Environment

With the boxfile.yml in place, you can fire up a virtualized local development environment. I recommend adding a DNS alias just so the app will be easier to access from a browser.

# Add a convenient way to access the app from a browser
nanobox dns add local laravel.local

# Start the dev environment
nanobox run

Nanobox will provision a local development environment, mount your local codebase into the VM, provision a containerized MySQL database, load your app's dependencies (if a composer.json is present), then drop you into a console inside the VM.

Generate a New Laravel Project

If you have an existing Laravel project, you can skip this section. To generate a new Laravel project from scratch, run the following from inside the Nanobox console:

# download the laravel installer
composer require "laravel/installer"

# create a new laravel app
laravel new

Your project's current working directory is mounted into the /app directory in the VM, so all the Laravel files written there will propagate back down to your machine's filesystem and vice versa.

Update the Database Connection

In this example, I'm using MySQL, but you can use any of the officially supported data services. When Nanobox spins up a data service, it generates environment variables for the necessary connection credentials. For MySQL, host, user, and password environment variables are provided. Also, Nanobox provides a default gonano database.

There are two approaches to using the provided environment variables:

  1. Update your .env file.
  2. Update the database connection in config/database.php.

The .env Method


The downside of this approach is that you'd either have to commit the .env to version control, which generally isn't recommended, or anyone else sharing your project would have to update their own .env files.

The database.php Method

'mysql' => [
    'driver' => 'mysql',
    'host' => $_ENV['DATA_DB_HOST'],
    'port' => '3306',
    'database' => 'gonano',
    'username' => $_ENV['DATA_DB_USER'],
    'password' => $_ENV['DATA_DB_PASS'],
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix' => '',
    'strict' => true,
    'engine' => null,

The downside of this approach is that it wouldn't work without using Nanobox. There is a way to use both the env() fallback functionality and the auto-generated environment variables, but it isn't pretty (nested env() functions), so I won't cover it here.

Adding Other Data Components

Note: The process for adding other data components such as Redis, Memcached, Postgres, etc. is the same:

  1. Add the data component to your boxfile.yml.
  2. Add the necessary PHP extensions.
  3. Update your connection config to use the auto-generated environment variables.
  4. nanobox build to apply the changes and provision the data component.

Run Laravel Locally

Ok, you should be ready to fire Laravel up locally. Nanobox's PHP engine includes a php-server helper script that starts your app using settings defined in the boxfile.yml. For this example, it'll start Nginx and PHP-FPM. Just run the following from the root of your project in the Nanobox console:


You'll then be able to access your running Laravel app at laravel.local.

Any changes you make to your codebase will be reflected in the running app. Once you're done hacking, exit out of the Nanobox console and your local dev environment will shutdown.

Custom Nginx Configs

The PHP engine generates a bare-bones nginx.conf for you. If you need to customize your Nginx configuration, the Custom Nginx Configs with the Nanobox PHP Engine article walks through how.

Alright! Now to the fun part!

Setup Your AWS Account

If you haven't already, create an AWS account. In your AWS Management Console, create an IAM account that has read/write access to EC2 instances, security groups, and ssh keys. You can also setup a custom EC2 policy and user for Nanobox if you'd like.

Once the new account is created, create a new Access Key and download the key file. You'll need this and the key ID later.

Add a New Provider to Your Nanobox Account

In your Nanobox dashboard, go to your Account Admin > Hosting Accounts and click the "Add Account" button.

Add New Provider Account

Select AWS and click "Proceed."

Select AWS

Nanobox needs your AWS Access Key ID and the Access Key token to authenticate with your AWS account. Paste those in and click "Verify & Proceed."

Enter your AWS auth credentials

Name your provider and choose a default region. The name is arbitrary and only meant to help you identify it in your list of provider accounts.

Name your provider and select a default region

Launch a New App

Go to the home page of your Nanobox dashboard and click the "Launch New App" button. Select your AWS provider from the dropdown and choose the region in which you'd like to deploy your app.

Select your AWS provider

Confirm and click "Let's Go!" Nanobox will order an EC2 server on AWS under your account. When the server is up, Nanobox will provision platform components necessary for your app to run:

  • Load-Balancer: The public endpoint for your application. Routes and load-balances requests to web nodes.
  • Monitor: Monitors the health of your server(s) and application components.
  • Logger: Streams and stores your app's aggregated log stream.
  • Message Bus: Sends app information to the Nanobox dashboard.
  • Warehouse: Storage used for deploy packages, backups, etc.

Once all the platform components are provisioned and running, you're ready to deploy your app.

Stage Your App Locally

Nanobox provides "dry-run" functionality that simulates a full production deploy on your local machine. This step is optional, but recommended. If the app deploys successfully in a dry-run environment, it will work when deployed to your live environment.

nanobox deploy dry-run

More information about dry-run environments is available in the Dry-Run documentation.


Add Your New App as a Remote

From the root of your project directory, add your newly created app as a remote.

nanobox remote add app-name

This connects your local codebase to your live app. More information about the remote command is available in the Nanobox Documentation.

Deploy to Your Live App

With your app added as a remote, you're ready to deploy.

nanobox deploy

Nanobox will compile and package your application code, send it up to your live app, provision all your app's components inside your live EC2 instance, network everything together, and voila! Your app will be live.

Manage & Scale

Once your app is deployed, Nanobox makes it easy to manage and scale your production infrastructure. In your Nanobox dashboard you'll find health metrics for all your app's instances/containers. Your application logs are streamed in your dashboard and can be streamed using the Nanobox CLI.

Although every app starts out on a single EC2 instance with containerized components, you can break components out into individual instances and/or scalable clusters through the Nanobox dashboard. Nanobox handles the deep DevOps stuff so you don't have to. Enjoy!

Posted in Laravel, PHP, AWS, Deployment