Cubicle

Sign in and API keys

How people sign in to Cubicle (email and password, Google, cubicle login device flow) and reset a password, how programs authenticate with service account API keys (cbk_), which routes read and write keys can call, how to create, expire, revoke and use keys, and what happens to Boxes when a key, service account or member is removed.

Cubicle has two kinds of credentials. People sign in, and get a sign-in session. Programs, such as the SDK, CI jobs and agents, use an API key that belongs to a service account.

Sign-in sessionService account API key
Who uses itA personA program
How you get oneSign in to the Dashboard, or run cubicle loginAn organization owner or admin creates it with cubicle api-keys create or in the Dashboard
Lifetime30 days from sign-inUntil it is revoked, or until its expiry if it was created with one (1 to 3650 days)
What it can callThe routes your roles and grants allowBox, snapshot and operation routes in its own organization
Token prefixjvs_cbk_

Both are sent the same way, as Authorization: Bearer <token>. HTTP API authentication covers the header and authentication errors.

Sign in as a person

Cubicle is invite-only: a Cubicle operator creates your account for your email address and sends you an invitation. Sign in to the Dashboard at https://app.cubicle.sh in one of these ways:

  • Email and password. The invitation email has a single-use link, valid for 72 hours, that opens the Dashboard so you can set a password of at least 12 characters. Then sign in with your email address and that password.
  • Google. When the sign-in page shows Continue with Google, you can sign in with a Google account whose verified email address is the one on your invitation. The first Google sign-in links that Google account to your Cubicle account; a different Google account cannot sign in to it later.

A Google account with any other email address gets no Cubicle account for <email>; ask an administrator for an invitation.

To give a colleague access to your organization, see Add a person.

Reset your password

Choose Forgot password? on the sign-in page and enter your email address. If it has an account, Cubicle emails a single-use link that expires after 1 hour; asking again within 5 minutes sends no second email. This also works when your invitation link has expired. Setting a new password signs out all your other sessions, including CLI logins.

Log in to the CLI

cubicle login uses a device flow: the CLI shows a code, and you approve it in the Dashboard. Nothing connects back to your computer, so it also works over SSH and behind NAT.

  1. Run cubicle login. It prints a link and a code:

    To log in, open:
      https://app.cubicle.sh/device?user_code=WDJB-MJHT
    and confirm the code WDJB-MJHT.
    Press Enter to open the browser…
  2. Press Enter to open the link, with open on macOS or xdg-open on Linux, or open it yourself. The prompt appears only on a terminal and without --no-browser. The CLI checks for your approval every 2 s, whether or not you press Enter.

  3. Sign in if needed, check that the page shows the same code and choose Authorize.

  4. The CLI stores the session and prints Logged in as <your email>.

The code expires after 10 minutes; run cubicle login again if it does. Choosing Deny ends the login with login was denied in the browser. cubicle whoami prints your identity and your role in each organization.

The CLI keeps one login at a time, and logging in again replaces it. Files the CLI writes lists where it stores the token.

Sessions and signing out

  • cubicle sessions list lists your Dashboard and CLI sign-ins, and cubicle sessions revoke ID ends one. In the Dashboard, they are under Account → Sessions.
  • cubicle logout disconnects the private network, ends the session and removes the stored login.
  • After 30 days, or once the session is revoked, the CLI prints login expired; run `cubicle login`.

Service accounts and API keys

A service account is a non-interactive member of one organization, named ORG/NAME, such as acme/ci. It never signs in and cannot join other organizations. Its API keys authenticate as the service account.

Only an owner or admin of the organization can manage service accounts and keys, and only while signed in: API keys can never manage service accounts or keys.

Create a service account and a key

  1. Create the service account:

    cubicle service-accounts create --org acme ci

    It prints created acme/ci (<ID>). Its role is member. Pass --role admin to let it start, stop, hibernate, delete, snapshot and restore every Box in the organization; running commands still needs a grant. It gets one on every Box it creates, and an owner or admin grants it other Boxes with its ID.

  2. Create an API key for it:

    cubicle api-keys create --org acme ci github-actions --scope write --expires-days 90

    It prints the key, then Store this key now; it is not shown again.

  3. Store the key in your secret manager or your CI system's secrets.

In the Dashboard, open Account and use Service accounts: enter a name and a role and choose Create, then choose New key next to the account. The key dialog has Name, Scope (which starts as read) and Expires after days. Choose Create key; the dialog shows the key once, with Copy key.

SettingValues
Service account nameLowercase letters, digits and dashes, up to 63 characters. See Names.
Key nameLowercase letters, digits, ., _ and -, up to 63 characters. See Names.
Scoperead or write
Expiry1 to 3650 days with --expires-days. Without it, the key never expires.

Routes that accept API keys

API keys work only on GET /v1/me and the Box, snapshot and operation routes, and only in their own organization: other organizations' resources return 404, and a read key can send only GET requests. Every other authenticated route returns 403 api_key_not_allowed, so a service account cannot SSH into a Box, join the private network or open the console; it runs commands with exec, and those commands cannot rely on sudo. HTTP API authentication lists the routes.

The key is shown once

Cubicle stores only a SHA-256 digest of the key and its first 12 characters, which listings show as a hint. A lost key cannot be recovered: create a new one and revoke the old one.

Revoke a key or delete a service account

cubicle service-accounts list --org acme
cubicle api-keys revoke --org acme ci KEY_ID
cubicle service-accounts rm --org acme ci
  • service-accounts list prints each account and its keys, with their IDs.
  • api-keys revoke revokes one key. In the Dashboard, choose Revoke next to the key.
  • service-accounts rm deletes the account and frees its name. In the Dashboard, choose Delete next to the account.

A key also stops working when it expires, or when its service account leaves the organization. A key that no longer works gets 401 unauthenticated with "API key is invalid, expired or revoked".

When a key, service account or member is removed

Boxes belong to the organization, not to whoever created them. Revoking a key, deleting a service account or removing a person never stops or deletes a Box.

  • A key is revoked or expires. Only that key stops working. The service account keeps its other keys, its grants and its Boxes.
  • A service account is deleted, with cubicle service-accounts rm or cubicle members rm. Its membership, keys and grants end, and its guest account in each Box is locked; its files stay in the Box. A new service account with the same name gets a new ID and none of the old grants.
  • A person is removed with cubicle members rm. Their grants in the organization stop working, which ends their exec, SSH, private network and console access to its Boxes. API keys they created keep working. If they are added back, their earlier grants apply again.

Boxes that the service account or person created stay as they were:

  • A running Box keeps running until it hibernates automatically. Stopped and hibernated Boxes keep their CPU, memory and disk reserved.
  • Owners and admins can still start, stop, hibernate, snapshot, restore and delete them.
  • Running commands in them needs a grant. Anyone else who holds one keeps it; otherwise an owner or admin adds one.

Before you delete a service account, delete the Boxes it no longer needs.

Use an API key

new Cubicle() reads CB_SDK_API_URL and CB_SDK_API_KEY. The apiUrl and apiKey options override them.

import { Cubicle } from "@cubicle/sdk"

const cubicle = new Cubicle({
  apiUrl: "https://api.cubicle.sh",
  apiKey: process.env.CB_SDK_API_KEY,
})
const me = await cubicle.me()
console.log(me.identity, me.apiKey?.scope) // => acme/ci write

All keys of one service account share its rate limits.

Keep keys secret

Keep API keys out of browsers and repositories

A write key can create Boxes, run commands in them and delete them, until it is revoked.

  • Never put a key in browser code or a front-end bundle. Call Cubicle from a server, a CI job or another trusted process. The API sends no CORS headers, so browsers cannot call it directly.
  • Never commit a key. Keep it in your CI system's secrets or a secret manager, pass it as CB_SDK_API_KEY, and keep .env files out of version control.
  • Give each program its own key, with the read scope when it only reads and an expiry, so that you can revoke one key without affecting others.
  • If a key leaks, revoke it with cubicle api-keys revoke and create a new one.

On this page