The interlaken CLI
A small command that holds your credentials, keeps a token fresh, and makes authenticated calls.
interlaken does the token dance so you do not have to. It authenticates as an API
client, caches the token, refreshes it when it expires, and gives you a curl that
already knows the base URL and the Authorization header.
It has no interactive sign-in. The credential is always an API client, which is the right shape for a tool that lives in a terminal and in CI alike.
Signing in
Each profile is one zone. --api is that zone's host, not a shared endpoint.
interlaken login \
--api https://api.eu-par-1.interlaken.ai \
--client-id "$INTERLAKEN_CLIENT_ID" \
--client-secret "$INTERLAKEN_CLIENT_SECRET"The command proves the credentials with a real token request before saving anything, so a typo fails here rather than on your next call.
The commands
login --api URL --client-id ID --client-secret SECRET [--profile NAME]
token [--profile NAME] print a valid bearer token
api [--profile NAME] METHOD PATH [-d BODY|@file] [-H 'K: V']...
whoami [--profile NAME]
profiles list saved profiles
logout [--profile NAME] revoke the token, forget the secretMaking calls
interlaken api GET /api/v1/vms
interlaken api GET "/api/v1/vms?status=running&limit=100"
interlaken api POST /api/v1/vms -d '{"name":"web-1", …}'
interlaken api POST /api/v1/vms -d @vm.json
interlaken api DELETE /api/v1/vms/0f7c1e1e-…-d @file reads the body from a file, which saves fighting your shell over quoting.
-H adds a header and can be repeated. The response goes to stdout as JSON, so jq
works as you would expect:
interlaken api GET /api/v1/vms | jq -r '.items[] | "\(.id) \(.name) \(.status)"'Borrowing the token
curl -s https://api.eu-par-1.interlaken.ai/api/v1/vms \
-H "Authorization: Bearer $(interlaken token)"token prints a valid bearer, fetching a new one first if the cached one has
expired. Useful when you want the CLI's credential handling and something else's HTTP
client.
Profiles, one per zone
A profile pairs one zone with one API client. Since zones are separate deployments, addressing two of them means two profiles, and an API client is per zone as well:
interlaken login --profile paris --api https://api.eu-par-1.interlaken.ai --client-id … --client-secret …
interlaken login --profile dev --api https://api.dev.example --client-id … --client-secret …
interlaken --profile dev api GET /api/v1/vms
interlaken profiles
interlaken whoamiwhoami prints the profile, the zone and the client. It is worth running before
anything destructive, because the only thing separating your development zone from
production is a flag you might have forgotten.
Environment variables
| Variable | Replaces |
|---|---|
INTERLAKEN_API | --api |
INTERLAKEN_CLIENT_ID | --client-id |
INTERLAKEN_CLIENT_SECRET | --client-secret |
INTERLAKEN_PROFILE | --profile |
In CI, set the three credential variables from your secret store and call
interlaken api directly. There is no need to login first if the environment
already carries everything.
Where state lives
$XDG_CONFIG_HOME/interlaken/config.json, or ~/.config/interlaken/config.json.
The file is created 0600 in a 0700 directory.
The client secret is stored in that file in the clear, because it is the credential:
there is nothing to encrypt it with that would not itself have to be stored beside
it. Treat the file as you would an SSH private key. On a shared or ephemeral machine,
prefer the environment variables and never run login.
Signing out
interlaken logout --profile devThis revokes the current token at the server and then deletes the profile, so the credential stops working immediately rather than when it would have expired.