Deployment

Getting started

PM2 embeds a simple and powerful deployment system with revision tracing. Another step by step tutorial here

Please read the Considerations to use PM2 deploy

1- Generate a sample ecosystem.json file that list processes and deployment environment

$ pm2 ecosystem

In the current folder a ecosystem.json file will be created. It contains this:

{
  // Applications part
  "apps" : [{
    "name"      : "API",
    "script"    : "app.js",
    "env": {
      "COMMON_VARIABLE": "true"
    },
    // Environment variables injected when starting with --env production
    // http://pm2.keymetrics.io/docs/usage/application-declaration/#switching-to-different-environments
    "env_production" : {
      "NODE_ENV": "production"
    }
  },{
    "name"      : "WEB",
    "script"    : "web.js"
  }],
  // Deployment part
  // Here you describe each environment
  "deploy" : {
    "production" : {
      "user" : "node",
      // Multi host is possible, just by passing IPs/hostname as an array
      "host" : ["212.83.163.1", "212.83.163.2", "212.83.163.3"],
      // Branch
      "ref"  : "origin/master",
      // Git repository to clone
      "repo" : "git@github.com:repo.git",
      // Path of the application on target servers
      "path" : "/var/www/production",
      // Can be used to give options in the format used in the configura-
      // tion file.  This is useful for specifying options for which there
      // is no separate command-line flag, see 'man ssh' 
      // can be either a single string or an array of strings
      "ssh_options": "StrictHostKeyChecking=no",
      // To prepare the host by installing required software (eg: git) 
      // even before the setup process starts
      // can be multiple commands separated by the character ";"
      // or path to a script on your local machine
      "pre-setup" : "apt-get install git",
      // Commands / path to a script on the host machine
      // This will be executed on the host after cloning the repository
      // eg: placing configurations in the shared dir etc
      "post-setup": "ls -la",
      // Commands to execute locally (on the same machine you deploy things)
      // Can be multiple commands separated by the character ";"
      "pre-deploy-local" : "echo 'This is a local executed command'"
      // Commands to be executed on the server after the repo has been cloned
      "post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env production"
      // Environment variables that must be injected in all applications on this env
      "env"  : {
        "NODE_ENV": "production"
      }
    },
    "staging" : {
      "user" : "node",
      "host" : "212.83.163.1",
      "ref"  : "origin/master",
      "repo" : "git@github.com:repo.git",
      "path" : "/var/www/development",
      "ssh_options": ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env dev",
      "env"  : {
        "NODE_ENV": "staging"
      }
    }
  }
}

Edit the file according to your needs.

2- Be sure that you have the public ssh key on your local machine

$ ssh-keygen -t rsa
$ ssh-copy-id node@myserver.com

If you encounter any errors, see the troubleshooting section below.

3- Now initialize the remote folder with:

$ pm2 deploy <configuration_file> <environment> setup

E.g:

$ pm2 deploy ecosystem.json production setup

This command will create all the folders on your remote server.

4- Deploy your code

$ pm2 deploy ecosystem.json production

Now your code will be populated, installed and started with PM2

Deployment options

Display deploy help via pm2 deploy help:

$ pm2 deploy <configuration_file> <environment> <command>

  Commands:
    setup                run remote setup commands
    update               update deploy to the latest release
    revert [n]           revert to [n]th last deployment or 1
    curr[ent]            output current release commit
    prev[ious]           output previous release commit
    exec|run <cmd>       execute the given <cmd>
    list                 list previous deploy commits
    [ref]                deploy to [ref], the "ref" setting, or latest tag

Use different set of env variables

In the post-deploy attribute, you may have noticed the command pm2 startOrRestart ecosystem.json --env production. The --env <environment_name> allow to inject different set of environment variables.

Read more here

$ pm2 startOrRestart all.json            # Invoke restart on all apps in JSON
$ pm2 startOrReload all.json             # Invoke reload
$ pm2 startOrGracefulReload all.json     # Invoke gracefulReload

Multi host deployment

To deploy to multiple host in the same time, just declare each host in an array under the attribute host

{
  [...]
  "deploy" : {
    "production" : {
      "user" : "node",
      // Multi host in a js array
      "host" : ["212.83.163.1", "212.83.163.2", "212.83.163.3"],
      "ref"  : "origin/master",
      "repo" : "git@github.com:repo.git",
      "path" : "/var/www/production",
      "pre-setup" : "echo 'commands or local script path to be run on the host before the setup process starts'",
      "post-setup": "echo 'commands or a script path to be run on the host after cloning the repo'",
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env production",
      "pre-deploy-local" : "echo 'This is a local executed command'"
    }
  [...]
}

Using file key for authenticating

Just add the “key” attribute with file path to the .pem key within the attributes “user”, “hosts”…

    "production" : {
      "key"  : "/path/to/some.pem",
      "user" : "node",
      "host" : "212.83.163.1",
      "ref"  : "origin/master",
      "repo" : "git@github.com:repo.git",
      "path" : "/var/www/production",
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env production"
    },

Force deployment

You may get this message:

--> Deploying to dev environment
--> on host 192.168.1.XX

  push your changes before deploying

Deploy failed

If you want to deploy without pushing any data just append the --force option:

$ pm2 deploy ecosystem.json production --force

Considerations

  • You can use the option --force to skip local change detection
  • You might want to commit your node_modules folder (#622) or add the npm install command to the post-deploy section: "post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env production"
  • Verify that your remote server has the permission to git clone the repository
  • You can declare specific environment variable depending on the environment you want to deploy the code to. For instance to declare variables for the production environment, just add “env_production”: {} and declare that variables.
  • PM2 will look by default to ecosystem.json. So you can skip the options if it's the case
  • You can embed the “apps” & “deploy” section in the package.json
  • It deploys your code via ssh, you don’t need any dependencies
  • Process are initialized / started automatically depending on application name in ecosystem.json
  • PM2-deploy repository is there: pm2-deploy

Troubleshooting

##### SSH clone errors In most cases, these errors will be caused by pm2 not having the correct keys to clone your repository. You need to verify at every step that the keys are available.

Step 1 If you’re certain your keys work, first try running git clone your_repo.git on the target server. If it succeeds, move onto the next steps. If not, make sure your keys are stored both on the server and on your git account.

Step 2 By default ssh-copy-id copies the default identiy, usually named id_rsa. If that is not the appropriate key:

$ ssh-copy-id -i path/to/my/key your_username@server.com

This adds your public key to the ~/.ssh/authorized_keys file.

Step 3 If you get the following error: ``` –> Deploying to production environment –> on host mysite.com ○ hook pre-setup ○ running setup ○ cloning git@github.com:user/repo.git Cloning into ‘/var/www/app/source’… Permission denied (publickey). fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

failed to clone

Deploy failed ``` …you may want to create an ssh config file. This is a sure fire way to ensure that the correct ssh keys are used for any given repository you’re trying to clone. See this example:

# ~/.ssh/config
Host alias
    HostName myserver.com
    User username
    IdentityFile ~/.ssh/mykey
# Usage: `ssh alias` 
# Alternative: `ssh -i ~/.ssh/mykey username@myserver.com`

Host deployment
    HostName github.com
    User username
    IdentityFile ~/.ssh/github_rsa
# Usage:
# git@deployment:username/anyrepo.git 
# This is for cloning any repo that uses that IdentityFile. This is a good way to make sure that your remote cloning commands use the appropriate key

Contributing

The module is https://github.com/Unitech/pm2-deploy Feel free to PR for any changes or fix.