Heroku上的NPM私有git模块

时间:2012-06-03 11:09:44

标签: node.js heroku npm

我正在尝试将我的应用程序部署到Heroku但是我依赖于使用一些私有git repos作为模块。我这样做是为了在项目之间重用代码,例如:我有一个我在多个应用程序中使用的自定义记录器。

"logger":"git+ssh://git@bitbucket.org..............#master"

问题是Heroku显然没有对此代码的ssh访问权限。我在这个问题上找不到任何东西。理想情况下,Heroku有一个我可以添加到模块中的公钥。

10 个答案:

答案 0 :(得分:65)

基本身份验证

GitHub支持基本身份验证:

"dependencies" : {
    "my-module" : "git+https://my_username:my_password@github.com/my_github_account/my_repo.git"
}

和BitBucket一样:

"dependencies" : {
    "my-module": "git+https://my_username:my_password@bitbucket.org/my_bitbucket_account/my_repo.git"
}

但可能不希望在package.json中使用普通密码。

个人访问令牌(GitHub)

为了使这个答案更新,我现在建议在GitHub上使用using a personal access token而不是用户名/密码组合。

您现在应该使用:

"dependencies" : {
    "my-module" : "git+https://<username>:<token>@github.com/my_github_account/my_repo.git"
}

对于Github,您可以在此处生成新令牌:

https://github.com/settings/tokens

应用密码(Bitbucket)

应用程序密码主要用于提供与不支持双因素身份验证的应用程序的兼容性,您也可以将它们用于此目的。首先,create an app password,然后像这样指定你的依赖:

"dependencies" : {
    "my-module": "git+https://<username>:<app-password>@bitbucket.org/my_bitbucket_account/my_repo.git"
}

[已弃用]团队的API密钥(Bitbucket)

对于BitBucket,您可以在Manage Team页面上生成API Key,然后使用以下URL:

"dependencies" : {
    "my-module" : "git+https://<teamname>:<api-key>@bitbucket.org/team_name/repo_name.git"
}

答案 1 :(得分:36)

更新2016-03-26

如果使用npm3,则描述的方法不再有效,因为npm3在运行package.json脚本之前获取preinstall中描述的所有模块。这has been confirmed as a bug

官方node.js Heroku buildpack现在包括heroku-prebuildheroku-postbuild,它们将分别在npm install之前和之后运行。在所有情况下,您应该使用这些脚本而不是preinstallpostinstall来支持npm2和npm3。

换句话说,您的package.json应该类似于:

 "scripts": {
      "heroku-prebuild": "bash preinstall.sh",
      "heroku-postbuild": "bash postinstall.sh"
    }

我已经想出了迈克尔答案的替代方案,保留了(IMO)有利的要求,即保持您的凭据不受源代码控制,同时不需要自定义构建包。这是因为buildpack linked by Michael过时而感到沮丧。

解决方案是在npm的preinstallpostinstall脚本中设置和拆除SSH环境,而不是在buildpack中。

请按照以下说明操作:

  • 在您的回购中创建两个脚本,我们称之为preinstall.shpostinstall.sh
  • 使它们可执行(chmod +x *.sh)。
  • 将以下内容添加到preinstall.sh
    #!/bin/bash
    # Generates an SSH config file for connections if a config var exists.

    if [ "$GIT_SSH_KEY" != "" ]; then
      echo "Detected SSH key for git. Adding SSH config" >&1
      echo "" >&1

      # Ensure we have an ssh folder
      if [ ! -d ~/.ssh ]; then
        mkdir -p ~/.ssh
        chmod 700 ~/.ssh
      fi

      # Load the private key into a file.
      echo $GIT_SSH_KEY | base64 --decode > ~/.ssh/deploy_key

      # Change the permissions on the file to
      # be read-only for this user.
      chmod 400 ~/.ssh/deploy_key

      # Setup the ssh config file.
      echo -e "Host github.com\n"\
              " IdentityFile ~/.ssh/deploy_key\n"\
              " IdentitiesOnly yes\n"\
              " UserKnownHostsFile=/dev/null\n"\
              " StrictHostKeyChecking no"\
              > ~/.ssh/config
    fi
  • 将以下内容添加到postinstall.sh
    #!/bin/bash

    if [ "$GIT_SSH_KEY" != "" ]; then
      echo "Cleaning up SSH config" >&1
      echo "" >&1

      # Now that npm has finished running, we shouldn't need the ssh key/config anymore.
      # Remove the files that we created.
      rm -f ~/.ssh/config
      rm -f ~/.ssh/deploy_key

      # Clear that sensitive key data from the environment
      export GIT_SSH_KEY=0
    fi
  • 将以下内容添加到package.json

    "scripts": {
      "preinstall": "bash preinstall.sh",
      "postinstall": "bash postinstall.sh"
    }
    
  • 使用ssh-agent生成私钥/公钥对。

  • 在Github上添加公钥作为部署密钥。
  • 创建私钥的base64编码版本,并将其设置为Heroku config var GIT_SSH_KEY
  • 提交并将您的应用推送到Github。

当Heroku构建你的应用程序时,在npm安装依赖项之前,运行preinstall.sh脚本。这将根据GIT_SSH_KEY环境变量的已解码内容创建私钥文件,并创建SSH配置文件以告知SSH在连接到github.com时使用此文件。 (如果您要连接到Bitbucket,请将Host中的preinstall.sh条目更新为bitbucket.org)。然后npm使用此SSH配置安装模块。安装后,将删除私钥并擦除配置。

这允许Heroku通过SSH下载您的私有模块,同时将私钥保留在代码库之外。如果您的私钥被泄露,因为它只是部署密钥的一半,您可以撤销GitHub中的公钥并重新生成密钥对。

顺便说一句,由于GitHub部署密钥具有读/写权限,如果您在GitHub组织中托管该模块,您可以创建一个只读团队并为其分配一个“部署”用户。然后,可以使用密钥对的公共一半配置部署用户。这为您的模块增加了额外的安全层。

答案 2 :(得分:13)

在你的git repo中使用纯文本密码是一个非常糟糕的主意,使用访问令牌会更好,但你仍然需要非常小心。

"my_module": "git+https://ACCESS_TOKEN:x-oauth-basic@github.com/me/my_module.git"

答案 3 :(得分:13)

我创建了一个自定义nodeJS buildpack,它允许您指定一个使用ssh-agent注册的SSH密钥,并在首次设置dynos时由npm使用。它可以无缝地允许您将模块指定为package.json中的ssh网址,如下所示:

"private_module": "git+ssh://git@github.com:me/my_module.git"

要设置您的应用以使用您的私钥:

  • 生成密钥:ssh-keygen -t rsa -C "your_email@example.com"(输入无密码.build包不支持带密码的密钥)
  • 将公钥添加到github:pbcopy < ~/.ssh/id_rsa.pub(在OS X中)并将结果粘贴到github admin
  • 将私钥添加到heroku应用的配置中:cat id_rsa | base64 | pbcopy,然后heroku config:set GIT_SSH_KEY=<paste_here> --app your-app-name
  • 设置您的应用以使用buildpack,如项目中包含的heroku nodeJS buildpack README中所述。总之,最简单的方法是使用heroku config设置一个特殊的配置值:设置为包含所需buildpack的存储库的github url。我建议分支我的版本并链接到你自己的github fork,因为我不承诺不改变我的buildpack。

我的自定义buildpack可以在这里找到:https://github.com/thirdiron/heroku-buildpack-nodejs它适用于我的系统。评论和拉取请求非常受欢迎。

答案 4 :(得分:6)

基于@fiznool的答案,我使用存储为环境变量的自定义ssh密钥创建了一个buildpack来解决这个问题。由于buildpack与技术无关,因此可以使用任何工具来下载依赖项,例如用于php的composer,用于ruby的bundler,用于javascript的npm等等:https://github.com/simon0191/custom-ssh-key-buildpack

  1. 将buildpack添加到您的应用中:

    $ heroku buildpacks:add --index 1 https://github.com/simon0191/custom-ssh-key-buildpack
    
  2. 生成没有密码短语的新SSH密钥(假设您将其命名为deploy_key)

  3. 将公钥添加到您的私人存储库帐户。例如:

  4. 将私钥编码为base64字符串,并将其添加为heroku应用程序的CUSTOM_SSH_KEY环境变量。

  5. 以逗号分隔的主机列表,为其应使用ssh密钥,并将其添加为heroku应用程序的CUSTOM_SSH_KEY_HOSTS环境变量。

    # MacOS
    $ heroku config:set CUSTOM_SSH_KEY=$(base64 --input ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
    # Ubuntu
    $ heroku config:set CUSTOM_SSH_KEY=$(base64 ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
    
  6. 部署您的应用并享受:)

答案 5 :(得分:2)

这个答案很好https://stackoverflow.com/a/29677091/6135922,但我更改了一些preinstall脚本。希望这会对某人有所帮助。

#!/bin/bash
# Generates an SSH config file for connections if a config var exists.

echo "Preinstall"

if [ "$GIT_SSH_KEY" != "" ]; then
  echo "Detected SSH key for git. Adding SSH config" >&1
  echo "" >&1

  # Ensure we have an ssh folder
  if [ ! -d ~/.ssh ]; then
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh
  fi

  # Load the private key into a file.
  echo $GIT_SSH_KEY | base64 --decode > ~/.ssh/deploy_key

  # Change the permissions on the file to
  # be read-only for this user.
  chmod o-w ~/
  chmod 700 ~/.ssh
  chmod 600 ~/.ssh/deploy_key

  # Setup the ssh config file.
  echo -e "Host bitbucket.org\n"\
          " IdentityFile ~/.ssh/deploy_key\n"\
          " HostName bitbucket.org\n" \
          " IdentitiesOnly yes\n"\
          " UserKnownHostsFile=/dev/null\n"\
          " StrictHostKeyChecking no"\
          > ~/.ssh/config

  echo "eval `ssh-agent -s`"
  eval `ssh-agent -s`

  echo "ssh-add -l"
  ssh-add -l

  echo "ssh-add ~/.ssh/deploy_key"
  ssh-add ~/.ssh/deploy_key

  # uncomment to check that everything works just fine
  # ssh -v git@bitbucket.org
fi

答案 6 :(得分:1)

我能够通过个人访问令牌在Heroku构建中设置Github私有存储库的解析。

  • 在此处生成Github访问令牌:https://github.com/settings/tokens
  • 将访问令牌设置为Heroku配置var:heroku config:set GITHUB_TOKEN=<paste_here> --app your-app-name或通过Heroku Dashboard
  • 添加heroku-prebuild.sh脚本:

    #!/bin/bash
    if [ "$GITHUB_TOKEN" != "" ]; then
        echo "Detected GITHUB_TOKEN. Setting git config to use the security token" >&1
        git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf git@github.com:
    fi
    
  • 将预建脚本添加到package.json

    "scripts": {
        "heroku-prebuild": "bash heroku-prebuild.sh"
    }
    

对于本地环境,我们也可以使用git config ...,或者我们可以将访问令牌添加到~/.netrc文件中:

machine github.com
  login PASTE_GITHUB_USERNAME_HERE
  password PASTE_GITHUB_TOKEN_HERE

并且安装私有github repos应该可以工作。

npm install OWNER/REPO --save将在package.json中显示为:"REPO": "github:OWNER/REPO"

并在Heroku构建中解析私有回购也应该有效。 您可以选择设置postbuild脚本来取消设置GITHUB_TOKEN

答案 7 :(得分:-2)

您可以在package.json私有存储库中使用以下身份验证示例:

https://usernamegit:passwordgit@github.com/reponame/web/tarball/branchname

答案 8 :(得分:-3)

简而言之,这是不可能的。我想出的这个问题的最佳解决方案是使用新的git subtree。在撰写本文时,它们不在官方git源代码中,因此需要手动安装,但它们将包含在v1.7.11中。目前它可以在自制软件和apt-get上使用。这是一个做的事情

git subtree add -P /node_modules/someprivatemodue git@github.......someprivatemodule {master|tag|commit}

这会使回购邮件大小变大,但是通过gitsubtree pull执行上述命令可以轻松进行更新。

答案 9 :(得分:-4)

我之前用github的模块做过这个。 Npm目前接受包的名称或包含包的tar.gz文件的链接。

例如,如果您想直接从Github使用express.js(通过下载部分获取链接),您可以这样做:

"dependencies" : {
  "express"   :  "https://github.com/visionmedia/express/tarball/2.5.9"
}

因此,您需要找到一种方法,通过http(s)将您的存储库作为tar.gz文件进行访问。