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
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
  • Extend your Lando config by adding the database pull script

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

Run the following commands:

lando poweroff
docker system prune
lando start

Laravel Valet interferes with Lando

Valet services should be turned off when running a site through Lando. Turn off valet with:

valet stop

To turn Valet back on simply run

valet start

Statamic - Only the homepage loads

Statamic requires a .htaccess file to work correctly with Lando. Statamic comes with a sample .htaccess that should work without any additional setup as long as it is in the same directory as where your webroot key in the .lando.yml points to.

It’s important that we don’t commit the .htaccess to the repository since we don’t want that to affect our production servers. Make sure to include the .htaccess file in the .gitignore file.

An example command that would be added to your local:setup step would look something like this: cd public && cp sample.htaccess .htaccess. This command would go into the public directory and make a copy of sample.htaccess renamed to .htaccess. Note that depending on how the project is setup the public folder may be in a different location or have a different name.