How to setup a project for local development with Lando

Before Starting

Make sure you have all the prerequisite tooling installed:

Setting up a project to use Lando

Setting up a project to use Lando is relatively simple. Everything is configured from a .lando.yml file. Follow these steps to get started:

  • In the root of your project create a .lando.yml file
  • The minimum required fields to get a site is a name and recipe
    • Recipes: Laravel = laravel, WordPress = wordpress
  • Additional tooling can be added to the config file to provision the Docker box exactly as it would be on the server.
  • Example .lando.yml file (non-Statamic sites)
    1. name: projectname # Replace with the project name
      recipe: laravel # For Craft sites, `wordpress` for WordPress sites
      config:
        php: "7.3" # Match what we are using on the production server
        webroot: ./public # This can very depending on the project
      services:
          database:
              run_as_root:
                  - /helpers/sql-import.sh /app/database.tgz # database.tgz is the local backup in the root directory
    2. Extend your Lando config by adding the database pull script
  • Example .lando.yml file (Statamic sites)
  • name: projectname # Replace with the project name
    recipe: lamp
    config:
      webroot: public
      php: "8.2" # Match what we are using on the production server
    services:
      database: disabled
    

Update the .env secure note in 1Password

Every repo should have a secure note created in 1Password with the .env contents. We should consider this the one source of truth for the .env file. This should be named [PROJECTNAME] - Local Env (where PROJECTNAME is the name of the account/vault in 1Pass). After migrating a project to use Lando (or setting it up fresh), you will want to make sure that the database keys in the .env file match what Lando created.

Lando uses a simple naming scheme when creating the local database. Your local database will have the following credentials, using coversports as the example:

  • DB_SERVER="database.coversports.internal" - The coversports here is name you set in the .lando.yml file.
  • DB_PORT=3306 - Port 3306 is the default for Lando

The database name, username and password will all match the name of the recipe that was set in the .lando.yml file:

  • DB_DATABASE="laravel"
  • DB_USER="laravel"
  • DB_PASSWORD="laravel"

Ensure that all of these keys are updated in the env secure note on 1Password.

👀
Note: You can find all this info by running lando info command.

Adding the .env copy command to package.json

After adding the secure note env to 1Password, follow these steps to add the command to the package.json:

  • Find the ID of the note by running op item list --vault "PROJECTNAME" in the terminal
  • Add the bash command to get the .env from 1Pass to your package.json in the get:env command: op item get NOTEID --fields notesPlain --format json | jq -r '.value' > .env replace NOTEID with the ID from the previous step.
  • Add the get:env command to the local:setup command in package.json. For example:
"get:env": "op item get tzyvty4y6xlcfofqb2ksw2xtyu --fields notesPlain --format json | jq -r '.value' > .env",
"local:setup": "composer i && npm install && npm run get:env && npm run dev",
👀
Note: If you are outside of the Cantilever organization in 1Password request access to the ENV note in 1password by your manager and manually copy over the contents to the .env file.

Adding database pulling to your Lando project

  • Add Envoy.blade.php to the root of the project with the following content:
@setup
  $ssh = getenv('LP_SSH_CMD');
@endsetup

@servers(['web' => $ssh, 'localhost' => '127.0.0.1'])

@story('pull')
  dump
  getdb
@endstory

@task('dump', ['on' => 'web'])
  if [ -d "{{ getenv('LP_FILES_BACKUP_PATH') }}" ]
  then
      mysqldump -u {{ getenv('LP_DB_USERNAME') }} -p{{ getenv('LP_DB_PWD') }} {{ getenv('LP_DB') }} > {{ getenv('LP_FILES_BACKUP_PATH') }}/database.tgz
  else
      mkdir {{ getenv('LP_FILES_BACKUP_PATH') }}
      mysqldump -u {{ getenv('LP_DB_USERNAME') }} -p{{ getenv('LP_DB_PWD') }} {{ getenv('LP_DB') }} > {{ getenv('LP_FILES_BACKUP_PATH') }}/database.tgz
  fi
@endtask

@task('getdb', ['on' => 'localhost'])
  scp {{ getenv('LP_SSH_CMD') }}:{{ getenv('LP_FILES_BACKUP_PATH') }}/database.tgz database.tgz
@endtask
  • Run composer require laravel/envoy
  • Add the pull commands to the tooling section of your .lando.yml file:
env_file:
    - .env
tooling:
  envoy:
    service: appserver
  pull:
    service: appserver
    description: Pull and import the database from production.
    cmd:
      - appserver: envoy run pull
      - database: /helpers/sql-import.sh database.tgz
  • Add the following keys to the .env file. Make sure to update the .env secure note in 1Password as well!
# Lando Keys for Local Development
LP_DB_PWD=# The database password for the remote server, should be in 1Pass
LP_DB_USERNAME=forge # This is usually user 'forge' but can be something different, check in Forge
LP_DB=# The database name on the remote server
LP_FILES_BACKUP_PATH=/home/forge/backup # Where do you want the backup on the remote server to be saved?
LP_SSH_CMD=forge@134.209.122.105 # Replace with the @ IP address of the server
  • Rebuild Lando lando rebuild

Common Problems

The .test proxy does not work

Laravel Valet interferes with Lando

Statamic (≤v3.4) - Only the homepage loads

Statamic - Every page 404s