Repository Tokens: Create One and Authenticate
A repository token is the credential your build tools send to CloudRepo. Other tools call the same thing an access token or an API token. You create it in the admin portal, choose which repositories it reaches and whether it can publish, and paste it into Maven, Gradle, npm, pip, twine or Docker in place of a password.
Every repository token:
reaches only the repositories you tick when you create it;
is Read only (download) or Read + write (download, publish and delete);
expires: the default is 90 days and the maximum is 90 days;
is shown once, when you create it, and starts with
crp_v1_;can be revoked on its own, without changing your password or your other tokens.
This page uses four placeholders. [org-id] is your organization’s name, the first part of your
repository host: for acme.mycloudrepo.io it is acme. [repo-name] is the repository’s
name as it appears in the admin portal. you@example.com stands for your email address, and
YOUR_REPOSITORY_TOKEN for the token. Never commit a real token to version control.
The Credential Every Client Sends
Client |
Username |
Password or token |
|---|---|---|
Maven, Gradle, sbt, Leiningen, deps.edn, pip, twine, Poetry, uv, curl |
Your email address, in lower case: the email of the account that created the token |
The repository token |
npm (and pnpm, which reads |
None |
The repository token, as |
Docker ( |
Your email address (Docker does not check it) |
The repository token |
The username is your email address, not the token’s name and not a placeholder. Type it in lower
case. For the clients that send a username (Maven, Gradle, sbt, Leiningen, deps.edn, pip, twine,
Poetry, uv, curl and npm _auth), a username of __token__, token, an email with a capital
letter, or anything other than the email of the account that created the token is refused with
401 Unauthorized. (__token__ is the convention on pypi.org; CloudRepo does not use it.)
Docker does not check the username; use your email address there anyway.
Important
Create the token while signed in as a user of your organization, not as the organization
owner. Maven, Gradle, pip, twine and the other clients that send a username do not yet
reliably accept a token created by the owner account. npm (_authToken) and Docker do. If your builds have no user yet, add
one under Users (see Create Your First User), sign in to the admin portal as that user,
and create the token there. That user’s email address is then the username.
Create a Token in the Admin Portal
Sign in to the CloudRepo Admin Portal as the user whose builds will use the token, and in the sidebar, click Repository Tokens.
Expected: the Repository Tokens page. If you have no tokens yet, it shows No repository tokens yet.
Click Create token, or Create your first token if you have none.
Expected: the Create repository token form, with Name, Scope, Repositories and Expires. If it shows No repositories available instead, your organization has no repositories yet: create one first (see Create Your First Repository).
In Name, type a name that says where the token will be used, such as
ci-mavenorlaptop-npm.Expected: the field holds the name. The name is a label for the token list; it is never the username.
Under Scope, choose Read only to download, or Read + write to download, publish and delete.
Expected: one option is selected.
Under Repositories, tick each repository the token may reach.
Expected: the repositories you need are ticked. This choice is permanent: to reach different repositories later, create a new token.
Under Expires, keep the default or pick an earlier date. The token stops working at the start of that date (00:00 UTC), so pick a date after the last day you need it.
Expected: the form reads Default 90 days. Maximum 90 days from today. When the token expires, builds that use it stop authenticating, and you create a new one.
Click Create token.
Expected: a green Token created banner and the token value. If you have not confirmed your identity in the last 15 minutes, a Confirm Your Identity dialog comes first: enter your password and click Confirm. If the form says Your account is read-only and cannot create a write-enabled token., your user has read only access: choose Read only, or ask your organization owner for write access.
Click Copy next to the token, and store it where your build tool will read it, such as a CI secret.
Expected: the button reads Copied!. CloudRepo shows the token only this once. If you lose it, rotate the token from the Repository Tokens page to get a new value.
Maven (settings.xml)
Put the credential in ~/.m2/settings.xml. The <id> is any name you choose; it must match
the <id> of the repository in your pom.xml.
<settings>
<servers>
<server>
<id>cloudrepo</id>
<username>you@example.com</username>
<password>${env.CLOUDREPO_TOKEN}</password>
</server>
</servers>
</settings>
${env.CLOUDREPO_TOKEN} reads the token from an environment variable, which keeps it out of the
file. You can paste the token there instead.
<repositories>
<repository>
<id>cloudrepo</id>
<url>https://[org-id].mycloudrepo.io/repositories/[repo-name]</url>
</repository>
</repositories>
<distributionManagement>
<repository>
<id>cloudrepo</id>
<url>https://[org-id].mycloudrepo.io/repositories/[repo-name]</url>
</repository>
</distributionManagement>
More: Maven Repositories.
Gradle
Keep the credential in ~/.gradle/gradle.properties, outside your project:
cloudrepoUsername=you@example.com
cloudrepoToken=YOUR_REPOSITORY_TOKEN
Then read it in the build script.
repositories {
maven {
url = uri("https://[org-id].mycloudrepo.io/repositories/[repo-name]")
credentials {
username = providers.gradleProperty("cloudrepoUsername").get()
password = providers.gradleProperty("cloudrepoToken").get()
}
}
}
repositories {
maven {
url = "https://[org-id].mycloudrepo.io/repositories/[repo-name]"
credentials {
username = findProperty("cloudrepoUsername")
password = findProperty("cloudrepoToken")
}
}
}
To publish, use the same maven { ... } block under publishing { repositories { ... } }.
More: Gradle Repositories.
npm (.npmrc)
npm sends the token on its own, with no username. Put it in the project’s .npmrc, or in
~/.npmrc:
registry=https://[org-id].mycloudrepo.io/repositories/[repo-name]/
//[org-id].mycloudrepo.io/repositories/[repo-name]/:_authToken=${CLOUDREPO_TOKEN}
npm replaces ${CLOUDREPO_TOKEN} with the environment variable of that name, so the file can be
committed without the token in it. Keep the trailing / on both lines, and keep the
//[org-id]... line identical to the registry URL without https:.
npm loginalso works, for a local npm repository: it opens the admin portal in your browser and writes a token to.npmrcfor you. That token starts withcrn_v1_and works only on the local npm repository you rannpm loginagainst. A proxy npm repository refuses it with403(npm_token_not_supported_on_proxy), even thoughnpm loginagainst the proxy succeeds; use a token from Repository Tokens there.An
npm logintoken is read-only unless you choose Read-write when you authorize it and your user has write access, sonpm publishanswers403with a read-only one. A token created under Repository Tokens works on every npm repository it reaches, local or proxy.npm token createis not supported: create tokens in the admin portal.
More: npm Repositories and npm Client.
pip (pip.conf or --index-url)
pip takes the credential inside the index URL. Write the @ in your email address as %40:
[global]
index-url = https://you%40example.com:YOUR_REPOSITORY_TOKEN@[org-id].mycloudrepo.io/repositories/[repo-name]/simple/
The same URL works for a single command:
pip install my-package \
--index-url "https://you%40example.com:${CLOUDREPO_TOKEN}@[org-id].mycloudrepo.io/repositories/[repo-name]/simple/"
In CI, set PIP_INDEX_URL to that URL from a secret instead of writing a file. More, including
keeping the token in your system keyring: Basic Configuration Examples.
twine (.pypirc)
twine uploads to the repository URL without /simple/. Its username is a plain field, so the
@ needs no encoding:
[distutils]
index-servers = cloudrepo
[cloudrepo]
repository = https://[org-id].mycloudrepo.io/repositories/[repo-name]
username = you@example.com
password = YOUR_REPOSITORY_TOKEN
twine upload --repository cloudrepo dist/*
In CI, skip the file and set the environment instead:
export TWINE_USERNAME="you@example.com"
export TWINE_PASSWORD="$CLOUDREPO_TOKEN"
twine upload --repository-url https://[org-id].mycloudrepo.io/repositories/[repo-name] dist/*
The username is your email address, not __token__. More:
Python Repositories, and for Poetry, uv, pixi and conda the
pages under Python.
Docker (docker login)
Log in to the host alone, with your email address and the token:
echo "$CLOUDREPO_TOKEN" | docker login [org-id].mycloudrepo.io \
--username you@example.com \
--password-stdin
Expected: Login Succeeded. Then push and pull with the repository in the image reference:
docker tag my-app:1.0.0 [org-id].mycloudrepo.io/repositories/[repo-name]/my-app:1.0.0
docker push [org-id].mycloudrepo.io/repositories/[repo-name]/my-app:1.0.0
The password is the token, not the password you sign in to the admin portal with. docker login
can also accept a user’s portal password, but use a token: it reaches only the repositories you
tick, can be read only, expires, and can be revoked without changing anyone’s password. More:
Docker Repositories.
When a Client Answers 401, 403 or 404
A refused credential answers 401 Unauthorized; a credential that may not do what was asked
answers 403 Forbidden. A proxy repository answers 404 Not Found instead of 403, with
one exception: it refuses an npm login token with 403 (see the npm item below).
npm is different for a bad token. npm sends _authToken as a Bearer token, and a token that is
mistyped, expired, revoked or from another organization answers 404 Not Found, not 401. npm
then prints 404 Not Found for the package. If npm reports 404 for a package you know
exists, check the token first.
Check these in order:
The username. It must be the email address of the account that created the token, typed in lower case. Not
__token__, not the token’s name, not your organization name.Who created the token. Maven, Gradle, pip, twine and the other clients that send a username do not yet reliably accept a token created by the organization owner account. Create one as a user of your organization (see the note above).
The token. Paste it whole, starting at
crp_v1_. Check on the Repository Tokens page that it has not expired or been revoked. With npm, a bad token shows as404.The repository. The token reaches only the repositories ticked when it was created. A different repository needs a token that includes it.
Publishing. A Read only token downloads but cannot publish; create a Read + write token for the build that publishes.
An npm token elsewhere. A token from
npm login(crn_v1_) works only on the local npm repository it was created for, and publishes only if you chose Read-write and your user has write access. A proxy npm repository refuses it with403. Use a token from Repository Tokens for a proxy npm repository, every other npm repository, Maven, Python and Docker.The expiry date. A token stops working at 00:00 UTC on its expiry date.