npm Repositories

This guide covers using the npm CLI with CloudRepo private repositories.

Prerequisites

  • Node.js and npm installed (npm --version to verify)

  • A CloudRepo account with an npm repository created

  • Repository credentials (username and password)

Configuration

Step 1: Set the Registry URL

Configure npm to use your CloudRepo registry:

npm config set registry https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Important

Include the trailing slash on the registry URL. Without it, npm may fail to resolve packages correctly.

Step 2: Authenticate

Option A: npm login (recommended)

npm login --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
# Enter your CloudRepo username (email) and password

This generates a bearer token and stores it in ~/.npmrc.

Option B: Manual .npmrc configuration

For CI/CD or non-interactive environments:

# Generate base64 credentials
echo -n 'username:password' | base64

Add to your project’s .npmrc or ~/.npmrc:

registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
//[org-id].mycloudrepo.io/repositories/[repo-name]/:_auth=BASE64_ENCODED_CREDENTIALS
always-auth=true

Important

Always include always-auth=true when using private registries. Without this setting, npm install will return a 401 error on private repositories.

Step 3: Verify

npm whoami --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
# Should print your username

npm ping --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
# Should print: Ping success

Publishing Packages

Unscoped Package

mkdir my-package && cd my-package
npm init -y
# Edit package.json as needed
npm publish --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Scoped Package

mkdir my-scoped-package && cd my-scoped-package
npm init --scope=@yourorg -y
npm publish --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Note

CloudRepo supports both scoped (@scope/name) and unscoped packages. Unlike GitHub Packages or GitLab, you don’t need to use scoped packages.

Installing Packages

npm install package-name --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Or with a configured .npmrc, simply:

npm install package-name

Multi-Registry Configuration

To install private packages from CloudRepo while falling back to npmjs.org for public packages:

; .npmrc
@yourorg:registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
//[org-id].mycloudrepo.io/repositories/[repo-name]/:_authToken=YOUR_TOKEN
always-auth=true

This routes @yourorg/* packages to CloudRepo and everything else to the default npm registry.

Package Size Limit

CloudRepo supports npm packages up to 210 MB in size. This accommodates tarballs up to approximately 155 MB (base64 encoding adds ~33% overhead). This limit aligns with npmjs.org’s limits.

If you need to publish larger packages, consider splitting them into multiple packages or using a Raw repository for large binary assets.

About npm audit

When you run npm install, npm may attempt to check packages against a security advisory database. For packages hosted on CloudRepo:

  • Public packages from npmjs.org are audited normally against the npm advisory database

  • Private packages on CloudRepo skip audit checks because they aren’t listed in any public advisory database

This is expected behavior, not a limitation. Your private packages aren’t vulnerable to known public exploits because they’re not public packages. npm install will complete without audit warnings.

Troubleshooting

401 Unauthorized on npm install

Symptom: npm install returns a 401 error even though npm login succeeded.

Cause: The always-auth setting is missing from your .npmrc.

Fix: Add always-auth=true to your .npmrc:

always-auth=true

Without this, npm only sends credentials for publish operations, not install.

401 on npm login

Symptom: npm login returns 401.

Possible causes:

  • Incorrect username or password

  • Missing X-Forwarded-Proto: https header (if behind a non-standard proxy)

  • Rate limiting (more than 5 attempts per minute)

Fix: Verify your credentials and try again. If rate-limited, wait 60 seconds.

Missing Trailing Slash

Symptom: Various npm commands fail with 400 or 404.

Cause: The registry URL is missing a trailing slash.

Fix: Ensure your registry URL ends with /:

# Correct
npm config set registry https://[org-id].mycloudrepo.io/repositories/[repo-name]/

# Wrong (may cause issues)
npm config set registry https://[org-id].mycloudrepo.io/repositories/[repo-name]

npm publish Fails with “Version already exists”

Symptom: npm publish returns a 409 Conflict error.

Cause: A package with that version already exists and overwrite protection is enabled (the default).

Fix: Increment the version number in package.json before publishing.

Scoped Package 404

Symptom: npm install @scope/package returns 404.

Cause: npm is looking for the package on the default registry (npmjs.org) instead of CloudRepo.

Fix: Configure the scope to point to CloudRepo:

@yourscope:registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Unpublishing Packages

Remove a specific version:

npm unpublish my-package@1.0.0 --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Remove all versions of a package:

npm unpublish my-package --force --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Note

Unlike npmjs.org, which restricts unpublishing packages older than 72 hours, CloudRepo allows you to unpublish any package version at any time. You always have full control over your repository contents.

Important

Prefer removing specific versions over deleting an entire package. Removing all versions is irreversible and may break downstream consumers who depend on any version of the package.

API-Based Removal

You can also remove packages using the REST API directly. This is useful for scripting and automation.

Remove a specific version:

# First, get the current revision ID from the package metadata
REVISION=$(curl -s -u user@example.com:password \
  https://[org-id].mycloudrepo.io/repositories/[repo-name]/my-package/ \
  | jq -r '._rev')

# Delete the specific tarball
curl -X DELETE -u user@example.com:password \
  "https://[org-id].mycloudrepo.io/repositories/[repo-name]/my-package/-/my-package-1.0.0.tgz/-rev/$REVISION"

Remove an entire package (all versions):

REVISION=$(curl -s -u user@example.com:password \
  https://[org-id].mycloudrepo.io/repositories/[repo-name]/my-package/ \
  | jq -r '._rev')

curl -X DELETE -u user@example.com:password \
  "https://[org-id].mycloudrepo.io/repositories/[repo-name]/my-package/-rev/$REVISION"

Token Management

CloudRepo supports npm’s token management commands for creating, listing, and revoking bearer tokens.

Listing Tokens

View all active tokens for your account:

npm token list --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

This shows each token’s key (UUID), creation date, and whether it is read-only.

Creating Tokens

Create a new bearer token:

npm token create --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

Note

npm login also creates a bearer token. Use npm token create when you need additional tokens (for example, one per CI/CD pipeline or deployment environment).

Revoking Tokens

Revoke a token by its key (the UUID shown in npm token list):

npm token revoke <token-key> --registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/

You can only revoke tokens that belong to your own account.

Token Storage

After npm login or npm token create, npm stores the token in your .npmrc file:

//[org-id].mycloudrepo.io/repositories/[repo-name]/:_authToken=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

This token is sent as a Bearer header on all subsequent requests to the registry.

CI/CD Token Patterns

For CI/CD pipelines, set the token via environment variables instead of committing .npmrc files:

# Set the registry and token as environment variables
export NPM_CONFIG_REGISTRY=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
export NPM_CONFIG_//[org-id].mycloudrepo.io/repositories/[repo-name]/:_authToken=$CLOUDREPO_TOKEN

# npm commands will use these automatically
npm install
npm publish

Alternatively, generate .npmrc at build time:

echo "//[org-id].mycloudrepo.io/repositories/[repo-name]/:_authToken=${CLOUDREPO_TOKEN}" >> .npmrc
echo "always-auth=true" >> .npmrc

Important

Never commit tokens or credentials to version control. Use your CI/CD platform’s secret management (GitHub Actions secrets, GitLab CI variables, Jenkins credentials, etc.) to inject tokens at build time.

Next Steps