Accounts and access
Arkvory knows four kinds of credentials. People sign in with a password. Their own tools use personal access tokens. CI systems and deployment agents use service keys. The installer creates one more key, the recovery key, for setup and emergencies. The server checks every request against the credential it came with.
Who can do what
| Credential | Made by | Lifetime | Administration | Repository access |
|---|---|---|---|---|
| Password session | Signing in | 12 hours | Users and groups, if the account is an administrator | Read or write per repository, through groups |
| Personal access token | You, from a password session | 90 days by default, 365 at most | Never | Your groups, optionally read only |
| Service key | The recovery key or a delegated operator | 90 days by default, 365 at most | Only what the owner delegated | The service account policy, narrowed by the key |
| Recovery key | The installer | Until you replace it | Users, groups, service accounts, backups | Read and write on releases |
Three things are easy to miss:
- An administrator account manages users and groups. It does not give access to files. Files are reached only through group grants.
- A service key is created by the recovery key or by an operator key, not by a password session. An administrator who signed in with a password cannot create service accounts.
- A personal token or a service key can never create users, groups or other tokens.
The owner and the recovery key
The first account is the owner. It is an administrator. The Windows setup wizard creates it. On Linux and Docker you create it in the console with the recovery key, as The web console describes.
The owner is a member of the group arkvory-owners, which has write access to the repository releases. For any other repository, give a group access yourself. See Groups and repository access.
The recovery key is the file config/bootstrap-token.txt in the installation directory. Only an administrator of the server can read it. Do not copy it to CI or to client machines. Installation and update tools read it, so do not delete it. See Security.
Create users
Only administrators create users. A name has 3 to 64 letters, digits, ., _ or -. A password has 12 to 128 characters. An installation holds at most 1000 accounts.
In the console:
- Sign in as an administrator and open Users and access.
- Expand Create user.
- Enter Username and Password. Tick Administrator only for people who manage users.
- Select Create user.
The table Accounts lists the accounts. Disable blocks an account: its sessions end at once and its personal tokens stop working until you select Enable. To set a new password for someone, expand Reset password. This ends the account's sessions and revokes all its personal tokens.
With the API, an administrator session or the recovery key calls these operations: createUser, updateUser and listUsers.
curl -X POST "$ARKVORY/api/v1/users" \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"anna","password":"a long password here","administrator":false}'await client.administration.users.create('anna', 'a long password here', false);arkvoryctl has no commands for accounts. Use the console or the API.
Self-registration is off by default. The server administrator turns it on with ARKVORY_ALLOW_REGISTRATION=true (see Environment variables). Then Sign up appears on the sign-in card. A new account has no access to any repository until an administrator adds it to a group. Self-registration stops at 900 accounts, so 100 places stay free for administrators.
Groups and repository access
People get access through groups. A group has members and, for each repository, one level of access:
| Level in the console | Meaning |
|---|---|
| Read | See and download |
| Read and write | Everything in read, and upload, publish, change metadata, promote and restore |
A repository has no separate create step. It exists as soon as a grant or a service policy names it. A name uses lowercase Latin letters, digits, - and _, starts with a letter or a digit and has at most 64 characters. See Repositories.
In the console, open Users and access:
- Expand Create group, enter an Access group name (2 to 64 letters, digits,
.,_or-) and select Create group. - Expand Manage group members, choose the group and the account, then select Add to group. Remove from group takes the account out of the group.
- Expand Manage repository access, choose the group, type the Repository name, choose the Access level and select Save access. Remove access takes the access away.
The table below the forms shows the Members and Grants of every group. Removing a member or a grant takes effect at the next request of the account. The files stay where they are.
An installation holds at most 100 groups, 10 000 memberships and 10 000 grants in total.
With the API, the operations are createAccessGroup, addGroupMember, removeGroupMember, setGroupGrant and removeGroupGrant:
curl -X PUT "$ARKVORY/api/v1/access-groups/$GROUP_ID/grants/builds" \
-H "Authorization: Bearer $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"access":"write"}'await client.administration.groups.setGrant(groupId, 'builds', 'write');Permissions
Behind the two levels read and write there are 24 repository actions. A service key names these actions one by one. arkvoryctl doctor and GET /api/v1/auth/permissions show the actions the current credential holds, per repository.
| Action | Console label | It allows |
|---|---|---|
repository.read | Discover repositories | List repositories and see your own rights. No file access. |
artifact.list | List artifacts | List and search artifacts, read the stage list and the promotion journal |
artifact.read | Read artifact details | Artifact details, stages and promotion history of one artifact |
content.read | Download files | Download bytes, create download links, resolve a package for download |
upload.create | Start uploads | Start an upload |
upload.read | Read upload progress | Read the state and the parts of your own upload |
upload.write | Upload bytes | Send the bytes of your own upload |
upload.complete | Finish uploads | Finish your own upload, start a completion job |
upload.cancel | Cancel uploads | Cancel your own upload |
job.read | Read jobs | Read your own completion job |
package.read | Read packages | List UPack packages and resolve a version |
package.publish | Publish packages | Register an uploaded archive as a package |
asset.read | Read file links | Read file paths, their history and revisions |
asset.write | Assign file links | Make an artifact the current content of a path |
asset.restore | Restore file history | Restore an earlier revision of a path |
annotation.read | Read metadata | Read labels, metadata, collections and attachments |
annotation.write | Edit metadata | Change labels, metadata, collections and attachments |
artifact.promote | Promote artifacts and manage stages | Add and remove stages, promote into the repository |
reference.write | Manage references | Add and remove your own external reference on an artifact |
audit.read | Read audit | Read the catalog audit of the repository |
artifact.delete | Delete artifacts | Check and delete artifacts, preview and apply retention |
storage.read | View storage policy and usage | Read the storage policy, usage and cleanup settings |
storage.manage | Manage storage policy | Change the storage policy and cleanup settings, run them |
diagnostics.read | Read diagnostics | Read storage events |
How the levels of a group map to actions:
- Read gives
repository.read,artifact.list,artifact.read,content.read,package.read,asset.readandannotation.read. - Write gives everything in read, and
upload.create,upload.read,upload.write,upload.complete,upload.cancel,job.read,package.publish,asset.write,asset.restore,annotation.write,artifact.promote,reference.writeandaudit.read. - No group level gives
artifact.delete,storage.read,storage.manageanddiagnostics.read. Deleting artifacts and managing storage are for service keys that name these actions. See Storage and retention.
A mirror is a read-only copy of another repository (Mirrors). Every action that changes it is refused with 409 mirror_read_only, whatever the grants say.
Passwords and sessions
Sign in with Username and Password in the Repository connection card. A session lasts 12 hours. Disconnect ends it.
To change your own password, use Change my password in the same card. Enter the Current password and the New password. All your sessions and personal tokens end, so you sign in again and create new tokens. An administrator can reset the password of another account without knowing the old one.
The server slows down guessing:
- One network address may try 10 sign-ins in a burst, then one more every 15 seconds.
- After many wrong passwords for one account, the account waits longer and longer, up to 2 minutes. Even the right password is refused during this wait. The answer is
429 rate_limitedwithRetry-After. - Behind a reverse proxy, the administrator lists the proxy in
ARKVORY_TRUSTED_PROXIES. Otherwise all people share one address.
With the API, login exchanges a name and a password for a bearer session, and changeOwnPassword changes the password:
curl -X POST "$ARKVORY/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"name":"anna","password":"a long password here"}'Personal access tokens
A personal access token is a key for your own tools: a script on your computer, arkvoryctl, or the SDK. It acts as you, with the repositories of your groups.
Only a password session creates tokens. A token cannot create another token and has no administrator rights.
- Sign in with your password.
- In the Repository connection card, expand Personal access tokens.
- Enter a Token name. Choose Expires after: 30 days, 90 days or 365 days.
- Choose Access: Read only or Read and write. A read token refuses every change with
403 read_only_token. - Select Generate token, then Copy token. The token is shown once. It starts with
pat_.
The table shows each token's Prefix, Created, Expires, Last used and Status: Active, Expired or Revoked. To stop a token, select Revoke token and confirm with Revoke. Clients that use it lose access at once.
An account may hold 50 active tokens. An administrator can list and revoke the tokens of any account with listAccountTokens and revokeAccountToken.
With the API, a token has a name and, optionally, an expiry (up to 365 days from now) and a scope:
curl -X POST "$ARKVORY/api/v1/auth/tokens" \
-H "Authorization: Bearer $SESSION" \
-H "Content-Type: application/json" \
-d '{"name":"laptop","scope":"read-write","expiresAt":"2027-01-31T00:00:00Z"}'const created = await client.identity.createToken('laptop', { scope: 'read-write' });
console.log(created.token); // shown onceThe API default scope is read-write. The console preselects Read only.
Give the token to arkvoryctl in a private file. See Command line.
Service accounts and keys for CI
A service account is an identity for a tool, not for a person. It has a policy: the repositories and actions it may use. A service account has keys. A key has its own list of repositories and actions too. The effective rights are the intersection of the two lists, action by action. An empty policy gives no access to files.
You manage service access with the recovery key, or with an operator key that the owner delegated rights to. In the console:
- Select Disconnect if you are signed in. Then open Connect with a service or automation key, paste the recovery key into Service key and select Connect.
- Open Service access. The section appears only for the recovery key and for operator keys.
Create an account and its policy
- In Service access, expand Create service account.
- Enter a Account name (3 to 64 letters, digits,
.,_or-). - Under Repository permissions select Add repository and type the Repository name.
- Fill in the permissions: Read preset and Publish preset set typical sets, Clear permissions clears them, and Individual permissions lists every action. Select Remove repository to drop a repository.
- Select Create service account.
The two presets are:
| Preset | Actions |
|---|---|
| Read preset | repository.read, artifact.read, artifact.list, content.read, package.read, asset.read, annotation.read |
| Publish preset | The read set, and upload.create, upload.read, upload.write, upload.complete, upload.cancel, job.read, package.publish, asset.write, annotation.write |
Neither preset includes promotion, restore or deletion. Add artifact.promote for a promotion job. A deployment agent that only downloads needs the read set for arkvoryctl. For a plain HTTP download of a package by name, content.read alone is enough.
A policy has at most 64 repositories and an installation at most 1000 service accounts. A saved policy has a version. If someone changes it meanwhile, the console shows a conflict and keeps your draft: select Reload account and apply your change again. Disable account blocks every key of the account. Transfers that already run may finish.
Issue, save and activate a key
- Open the account and its Service keys.
- Expand Issue key. Enter a Key name. Set the expiry in Expires at (local time, optional) or leave it empty for 90 days. The longest expiry is 365 days.
- Narrow the permissions if the key needs less than the account. Select Issue key.
- The window Save the new secret shows the secret once. Select Copy secret and store it in your CI secret store. The secret starts with
arkvory_. - Tick I have saved the secret and select Activate key.
A key that is not activated is useless and expires after 15 minutes. It shows as Pending activation until you activate it. An account may hold 3 active keys and 2 pending keys at a time. The states are Pending activation, Active, Revoked and Expired; Key details lists the id and the permissions of a key.
If the answer is lost before you copy the secret, the server cannot show it again. Revoke the key and issue another.
With the API, the recovery key creates the account, then issues the key. The header Idempotency-Key (1 to 128 letters, digits, ., _, : or -) makes a repeated request safe, but a repeat returns no secret. The key activates itself when it calls activateServiceKey:
curl -X POST "$ARKVORY/api/v1/service-accounts" \
-H "Authorization: Bearer $RECOVERY_KEY" -H "Content-Type: application/json" \
-d '{"name":"ci-prod","bindings":[{"resource":{"kind":"repository","id":"releases"},"actions":["repository.read","artifact.read","artifact.list","content.read","package.read","upload.create","upload.read","upload.write","upload.complete","job.read","package.publish","asset.read","asset.write"]}]}'
curl -X POST "$ARKVORY/api/v1/service-accounts/$ACCOUNT_ID/keys" \
-H "Authorization: Bearer $RECOVERY_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: ci-prod-2026-10" \
-d '{"name":"pipeline-2026","bindings":[{"resource":{"kind":"repository","id":"releases"},"actions":["content.read","package.read","artifact.read"]}]}'
curl -X POST "$ARKVORY/api/v1/auth/activate-key" -H "Authorization: Bearer $NEW_SECRET"The same steps in the SDK:
const account = await root.administration.services.create('ci-prod', bindings);
const issued = await root.administration.credentials.issue(account.id, requestId, {
name: 'pipeline-2026',
bindings,
});
if (!issued.secret) throw new Error('Lost response: revoke the key and issue another');
await saveToSecretStore(issued.secret);
await new ArkvoryClient(url, () => issued.secret ?? '').identity.activateKey();Give the activated key to the job as ARKVORY_TOKEN_FILE or ARKVORY_TOKEN. See the CI example.
Rotate and revoke
Rotate a key before it expires, without a gap:
- Next to the key select Rotate. The form is filled with the old key's permissions. You may only keep or reduce them.
- Issue the new key, save its secret and activate it.
- Switch your jobs to the new secret.
- Select Revoke on the old key.
Activating the new key limits the old one to at most 24 more hours, so a forgotten old key does not live on. Revoking is permanent and asks for the key name. New requests with the key are refused at once. Transfers that already run may finish. With the API the operations are rotateServiceKey and revokeServiceKey.
Activity log on the account shows who issued, activated, rotated and revoked keys, with the time. It keeps no secrets. The server keeps the latest 100 000 events of all accounts.
Delegated administration
Day to day, do not use the recovery key. The owner can hand parts of service administration to an operator key, and keep the recovery key offline.
- With the recovery key, create a service account for the operator with an empty policy, and issue and activate a key for it.
- Open Service keys of that account and select Delegated administration on the key.
- Expand New delegation. Enter the Target account ID, the account the operator will manage.
- Tick the Administrative actions and set the Maximum repository permissions, the most the operator may grant in repositories.
- Select Save delegation.
The seven actions are:
| Action | Console label | The operator may |
|---|---|---|
service-account.read | Read accounts | See the account |
service-account.manage | Enable or disable accounts | Enable and disable it |
policy.read | Read account policies | Read its policy |
policy.manage | Manage account policies | Replace its policy |
credential.read | Read key metadata | List its keys |
credential.manage | Issue, rotate and revoke keys | Issue, rotate and revoke its keys |
service-audit.read | Read service audit | Read its activity log |
Rules:
- Everything the operator sets must stay inside the ceiling. A key it issues expires no later than its own key.
- An operator may issue keys for the target account, so treat the delegation as trust in everything the ceiling allows.
- An operator cannot manage its own account, and cannot delegate further. An account cannot be both a target and an operator.
- Removing a delegation with Remove delegation does not revoke the keys the operator already activated. Revoke them yourself.
- The operator sees its own assignments in My administrative grants.
Only the recovery key sets delegations. The operations are listServiceDelegations, setServiceDelegation and removeServiceDelegation.
Audit
Administrators can read the security journal of the installation: sign-ins and failures, registrations, password changes and resets, user, group and grant changes, and token creation and revocation. Each entry has the time, the actor, the kind of credential, the client address, the target and the outcome (success, failure or denied). It holds no passwords or secrets. The server keeps entries for 365 days or 1 000 000 entries, whichever comes first.
The console has no screen for this journal. Read it with the API, with an administrator session or the recovery key. Pages hold 50 entries by default and 100 at most, newest first. Pass next as after for the next page.
curl -H "Authorization: Bearer $ADMIN_KEY" "$ARKVORY/api/v1/security/audit?limit=20"const page = await client.administration.security.audit({ limit: 20 });The activity log of a service account is separate. See Issue, save and activate a key.
If the owner is locked out
When nobody can sign in as an administrator, use the recovery key:
- Read the key on the server:
config/bootstrap-token.txtin the installation directory. Only a server administrator can do this. - In the console, open Connect with a service or automation key, paste the key into Service key and select Connect.
- Open Users and access. Expand Reset password, choose the account, enter a New password and select Reset password. If the account shows as disabled, select Enable.
- Sign in with the new password.
You can also create a new administrator with Create user and tick Administrator.
The form Create the first owner works only while the installation has no accounts. Later, use the recovery key to repair accounts, not to start over.
If the recovery key itself is lost, the server administrator replaces the key's SHA-256 in config/keys.json and restarts the API. See Security.