How to use a private npm registry on Elastic Beanstalk?
Asked Answered
S

7

22

We have a nodejs project running on Amazon Elastic Beanstalk that uses private modules that we host using nodejitsu's private npm registry.

However getting access to the private npm registry from the elastic instances hasn't been straightforward and is not documented well.

What is the best way to get this access set up?

Surreptitious answered 28/7, 2014 at 10:18 Comment(0)
W
23

None of the other answers were working for me. After hours of hair pulling, we finally figured it out. The solution that worked is almost the same as the other answers but with a very minor tweak.

  1. Set an NPM_TOKEN environment variable on Elastic Beanstalk under Configuration > Software Configuration > Environment Properties.
  2. Create a .ebextensions/npm.config file. (The name does not have to be 'npm'.)
  3. Put this content into the file:

    files:
      "/tmp/.npmrc":
        content: |
          //registry.npmjs.org/:_authToken=${NPM_TOKEN}
    

Note that it uses ${NPM_TOKEN} and not $NPM_TOKEN. This is vital. Using $NPM_TOKEN will not work; it must have the curly braces: ${NPM_TOKEN}.

Why are the curly braces needed? No idea. In shell/POSIX languages, ${VAR} and $VAR are synonymous. However, in .npmrc files (at the time of this writing), variables without the curly brackets are not recognized as variables, so npm must be using a slightly different syntax standard.

UPDATE

Also, this has worked for us only on new or cloned environments. For whatever reason, environments which were not initialized with a /tmp/.npmrc will not read it in any future deployments before running npm install --production. We've tried countless methods on 4 different apps, but cloning and replacing an environment has been the only method which has worked.

Wilone answered 14/10, 2016 at 21:26 Comment(6)
${NPM_TOKEN} never gets replaced by its value. It is set in the environment variable. Is there which neds to be done?Iou
/tmp/.npmrc will not contain the real token string literally, just ${NPM_TOKEN}. The environment variable NPM_TOKEN will hold the real token string. The ${...} syntax tells npm to look up the value of the environment variable. So, as long as the EB environment has an environment variable whose name is NPM_TOKEN and whose value is the npm token, and the file created by the ebextension (/tmp/.npmrc) includes ..._authToken=${NPM_TOKEN}, npm will be able to make the connection. Hopefully that helps.Wilone
This one works for me as I'm using private packages from NPM registry.Shushan
Can't seem to get this to work. Is the // intentionally commenting this out? @WiloneSecluded
No, the // isn't supposed to be a comment. It's the beginning of a url with the protocol unspecified. Replacing it with https:// would also work and is probably a good idea anyway.Wilone
In my last comment, I said that // could be replaced with https://. I was wrong; I am encountering issues if I use https:// instead of //.Wilone
S
10

So, we managed to get this working by using the npm userconfig file. See the doc page for npmrc for more info.

When a nodejs application is being deployed to Elastic Beanstalk, the root user runs npm install. So you will need to write the root's npm userconfig file, which is at /tmp/.npmrc.

So if you add a file called private_npm.config (or whatever name you choose) to your .ebextensions folder with all the information needed, you will be good to go. See Customizing and Configuring AWS Elastic Beanstalk Environments for more info.

So here is what my file looks like to use nodejitsu private registry.

.ebextensions/private_npm.config:

files:
  #this is the npm user config file path
  "/tmp/.npmrc":
    mode: "000777"
    owner: root
    group: root
    content: |
      _auth = <MY_AUTH_KEY>
      always-auth = true
      registry = <PATH_TO_MY_REGISTRY>
      strict-ssl = true
      email = <NPM_USER_EMAIL>
Surreptitious answered 28/7, 2014 at 10:18 Comment(2)
A trivial addendum: nodejs is the user that runs npm... but the home dir. is correct : /tmp .... root's home is /rootOdele
Late to see this, but thanks! I'd add that can use _authToken as well. Generate a token using npm login and retrieve the token from ~/.npmrc.Vesperal
M
3

Using an .npmrc within the project also works. For example...

.npmrc

registry=https://npm.mydomain.com

You may want to .gitignore this file if you include an _authToken line but make sure you don't .ebignore it so it's correctly bundled up with each deployment. After trying a few things unsuccessfully, I came across this post which made me realize specifying it locally in a project is possible.

Marciamarciano answered 1/4, 2019 at 20:8 Comment(1)
Just wanted to add that this worked perfectly for me and helped me when I was barking up the wrong tree looking for a solution. I have a CI/CD solution where CodeBuild runs tests, lints and creates the artifact for Elastic Beanstalk. In this case it was much better to let the build step create an .npmrc file and add it to the root of the zip artifact than write one during the Elastic Beanstalk deployment.Dichroscope
C
2

The answer above as a step in the right direction, but the permissions and owner did not work for me. Managed to get it to work with the following combination:

files:
  #this is the npm user config file path
  "/tmp/.npmrc":
    mode: "000600"
    owner: nodejs
    group: nodejs
    content: |
      _auth = <MY_AUTH_KEY>
      always-auth = true
      registry = <PATH_TO_MY_REGISTRY>
      strict-ssl = true
      email = <NPM_USER_EMAIL>
Circuit answered 21/4, 2016 at 12:19 Comment(0)
C
2

Place the below within your .ebextensions/app.config.

files:
  "/tmp/.npmrc":
    mode: "000777"
    owner: root
    group: root
    content: |
      //registry.npmjs.org/:_authToken=$NPM_TOKEN

Where NPM_TOKEN is an environment variable with the value of your actual npmjs auth token.

Note that environment variables within elasticbeanstalk can and should be set from within the AWS console Elasticbeanstalk software configuration tab.

AWS Elasticbeanstalk Configuration

Crayon answered 20/9, 2016 at 20:46 Comment(0)
L
1

In new Elastic Beanstalk Linux 2 Platforms, none of these solutions work (apart from the .npmrc file solution that works but has its issues when using them in development evironments due to the requirements that all developers have their ${NPM_TOKEN} Env Var defined in their own environments).

The reason is that the /tmp/.npmrc location no longer works.

Option 1

You have to change the .ebextensions/npm.config file to this new format:

files:
  #this is the npm user config file path
  "/root/.npmrc":
    mode: "000777"
    owner: root
    group: root
    content: |
      _auth= ${NPM_TOKEN}
      registry = https://{yourprivatenpmrepository.com}/

Option 2 Add a custom .npmrc_{any-suffix} to the root of your app and create a prebuild hook to rename it before Beanstalk executes the npm install so that it can use your private repository configuration:

  1. Add the following file (path from your app root) .platform/hooks/prebuild/01_set_npmrc.sh with the following content:
    #!/bin/bash
    
    #Copy and rename .npmrc_beanstalk to .npmrc
    mv .npmrc_beanstalk .npmrc
  1. Create an .npmrc_beanstalk file in your root with the following content (modify it depending on your private npm config):
    _auth= ${NPM_TOKEN}
    registry = https://{yourprivatenpmrepository.com}/
  1. Chmod the hook file so that it has the necessary exec permissions when uploaded to EB: chmod +x .platform/hooks/prebuild/01_set_npmrc.sh

Re-deploy using EB CLI and you are done!

Lombardo answered 21/9, 2021 at 21:53 Comment(2)
The NPM_TOKEN defined in the beanstalk config is only passed to the app, not at build time so it would still fail to install. What did you do to solve this?Echeverria
It should work in build time as well. Have you tried both approaches defined here and none of them worked?Lombardo
O
0

With modern platforms, you no longer need to do this via .ebextensions

You can simply create a .npmrc file at the root of your deployment package, alongside your package.json with the following line:

//registry.npmjs.org/:_authToken=${NPM_TOKEN}

Using this method, you can create an environment variable named NPM_TOKEN in your AWS console so you don't have to store the token in your repo.

Structure:

~/your-app/
|-- package.json
|-- .npmrc
Opal answered 17/5, 2020 at 19:47 Comment(1)
I can verify this works fine. I had two related issues I had to solve: (1) The zip file I was creating for EBS did not include hidden files, including .npmrc (2) When I went to add NPM_TOKEN to the EBS env, it caused a re-deploy, which failed because of the aforementioned problem. When a deploy fails, EBS rolls back the config changes. Catch-22!Dominicdominica

© 2022 - 2024 — McMap. All rights reserved.