npm Repositories

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

Hosted at CloudRepo. See private npm registry hosting for plans and pricing.

Note

For a setup-focused walkthrough, see the npm Client quick-start. This page covers the full reference: scoped packages, multi-registry config, package-size limits, unpublishing, and token-based authentication.

Prerequisites

  • Node.js and npm installed (npm --version to verify; npm v10.9.4 or later recommended)

  • A CloudRepo account with an npm repository created

  • Membership in the org as a full-access member (owners cannot mint package-client tokens; see npm Client for details)

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 (interactive, recommended)

npm login

What happens: npm CLI opens https://admin.cloudrepo.io/npm-login?session=<id> in your browser. Sign in with your CloudRepo email and password (or reuse an existing portal session), confirm “Authorize npm CLI for repo X,” and the CLI captures the token and writes it to ~/.npmrc. The minted token is repo-id-scoped: it authenticates only against the repo you ran npm login against.

If you don’t already have a registry configured, run npm config set registry=... first (see Step 1). Without it, npm login won’t know which CloudRepo registry to authenticate against.

Option B: API Token in .npmrc (for CI/CD)

For non-interactive environments, mint a bearer token with the npm CLI and reference it from .npmrc:

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

To mint a token, authenticate as a repository user (admin portal: Users → Create a Repository User) and run:

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

List and revoke tokens with npm token list and npm token revoke <id> against the same --registry. Tokens are revocable independently of the user’s password.

Option C: Legacy Basic auth in .npmrc

For older CI tooling that requires Basic auth, the _auth=base64(user:pass) form is still supported:

# Generate base64 credentials
echo -n 'username:password' | base64
registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
//[org-id].mycloudrepo.io/repositories/[repo-name]/:_auth=BASE64_ENCODED_CREDENTIALS
always-auth=true

Prefer Option B (_authToken). It scopes the credential to one repo, rotates independently from your portal password, and is the canonical npm pattern.

Important

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

Note

The legacy --auth-type=legacy flag is no longer supported. Modern npm CLI (v10.9.4+) rejects email addresses as usernames at validation time, and CloudRepo’s user model is email-keyed. Attempts to use the deprecated path receive 410 Gone with steering toward the modern flow. See npm Client for full details.

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.

npm login browser opens but the terminal hangs

Symptom: npm login opens the browser, you authorize successfully, but the terminal command never returns.

Possible cause: the session expired (5-minute TTL) before authorization completed, or the browser sign-in took longer than the polling timeout.

Fix: re-run npm login to start a fresh session. The expired session ID is no longer valid.

npm login rejects owner accounts

Symptom: the admin portal shows “Owner accounts cannot mint package-client tokens. Sign in as a member to authorize npm CLI.”

Cause: you’re signed in as the org owner, not as a full-access member. Owner accounts cannot mint package-client tokens by design.

Fix: sign in as a member in the admin portal first, then retry npm login. If you don’t have a member account, create one via Members → Invite Member.

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 bearer tokens are minted by the npm login web flow (see npm Client), which writes a repository-scoped token into your .npmrc. Each token is independently revocable from the admin portal without affecting your login or your other credentials.

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