Lando has an advanced plugin system that allows developers to add and extend Lando's core functionality. Here are a few examples of things you can do with plugins:

  1. Create CLI commands like lando danceparty
  2. Add services like solr, redis or ruby
  3. Add additional configuration options and functionality to .lando.yml
  4. Hook into various Lando runtime events to provide additional functionality.
  5. Print "A British tar is a soaring soul!" after every app is started.

Plugin Basics

Plugins give you access to the Lando API so that you can modify and/or extend Lando. Here is the main entrypoint of the engine plugin that adds the lando.engine module and handles engine config.

'use strict';

module.exports = function(lando) {

  // Modules
  var _ = lando.node._;
  var env = require('./lib/env.js');
  var fs = lando.node.fs;
  var ip = require('ip');
  var path = require('path');
  var url = require('url');

  // Add some config for the engine'post-bootstrap', 1, function(lando) {

    // Log'Configuring engine plugin');

    // Engine script directory
    var esd = path.join(lando.config.userConfRoot, 'engine', 'scripts');
    var host = (process.platform === 'linux') ? ip.address() : 'host.docker.internal';

    // Build the default config object
    var defaultEngineConfig = {
      composeBin: env.getComposeExecutable(),
      composeVersion: '3.2',
      containerGlobalEnv: {},
      dockerBin: env.getDockerExecutable(),
      dockerBinDir: env.getDockerBinPath(),
      engineId: lando.user.getUid(),
      engineGid: lando.user.getGid(),
      engineScriptsDir: esd

    // Merge defaults over the config, this allows users to set their own things
    lando.config = lando.utils.config.merge(defaultEngineConfig, lando.config);

    // Strip all DOCKER_ and COMPOSE_ envvars
    lando.config.env = lando.utils.config.stripEnv('DOCKER_');
    lando.config.env = lando.utils.config.stripEnv('COMPOSE_');

    // Set up the default engine config if needed
    if (!_.has(lando.config, 'engineConfig')) {

      // Set the defaults
      lando.config.engineConfig = {
        socketPath: '/var/run/docker.sock',
        host: '',
        port: 2376

      // Slight deviation on Windows due to npipe://
      if (process.platform === 'win32') {
        lando.config.engineConfig.socketPath = '//./pipe/docker_engine';


    // Set the docker host if its non-standard
    if ( !== '') {
      lando.config.env.DOCKER_HOST = url.format({
        protocol: 'tcp',
        slashes: true,
        port: lando.config.engineConfig.port || 2376

    // Set the TLS/cert things if needed
    if (_.has(lando.config.engineConfig, 'certPath')) {
      var certPath = lando.config.engineConfig.certPath;
      lando.config.env.DOCKER_CERT_PATH = certPath;
      lando.config.env.DOCKER_TLS_VERIFY = 1; = fs.readFileSync(path.join(certPath, 'ca.pem'));
      lando.config.engineConfig.cert = fs.readFileSync(path.join(certPath, 'cert.pem'));
      lando.config.engineConfig.key = fs.readFileSync(path.join(certPath, 'key.pem'));

    // Set the ENV
    lando.config.env.LANDO_ENGINE_CONF = lando.config.userConfRoot;
    lando.config.env.LANDO_ENGINE_ID = lando.config.engineId;
    lando.config.env.LANDO_ENGINE_GID = lando.config.engineGid;
    lando.config.env.LANDO_ENGINE_HOME = lando.config.home;
    lando.config.env.LANDO_ENGINE_IP =;
    lando.config.env.LANDO_ENGINE_REMOTE_IP = host;
    lando.config.env.LANDO_ENGINE_SCRIPTS_DIR = lando.config.engineScriptsDir;

    // Add some docker compose protection on windows
    if (process.platform === 'win32') {
      lando.config.env.COMPOSE_CONVERT_WINDOWS_PATHS = 1;

    // Log it
    lando.log.verbose('Engine plugin configured with %j', lando.config);

    // Add utilities
    lando.utils.engine = require('./lib/utils');

    // Move our scripts over and set useful ENV we can use
    var scriptFrom = path.join(__dirname, 'scripts');
    var scriptTo = lando.config.engineScriptsDir;
    lando.log.verbose('Copying config from %s to %s', scriptFrom, scriptTo);
    lando.utils.engine.moveConfig(scriptFrom, scriptTo);


  // Add some config for the engine'post-bootstrap', 2, function(lando) {

    // Log'Initializing engine plugin');

    // Add the engine
    lando.engine = require('./engine')(lando);



Running your own plugins

You can add plugins either globally or in individual apps by adding your plugin to the global config.yml or an individual app's .lando.yml.

  - my-plugin

In the above example Lando looks for a plugin in a folder called my-plugin in either the node_modules or plugins folders. For app plugins these locations will be relative to the app root directory. For global plugins the locations specified in pluginDirs in lando config will be scanned.

If there are multiple occurences of the same-named plugin, Lando will use the one "closest to your app". This means that lando will priortize in-app plugins and then priortize the locations in pluginDirs from last to first.

A powerful corollary to this is that indiviual apps can implement plugins that override global plugin behavior.

Where is config.yml?

Check out the global config docs if you are unclear where to change this file.

Plugin Examples

Check out some of our core plugins for motivation in creating your own.

results matching ""

    No results matching ""