env-master

Quickstart

Five minutes from a fresh account to a service that reads its own database password.

1. Create an account

The service runs at https://env.aistastudio.ru — there is nothing to install or operate. Sign up, confirm your email through the link, and create an organisation: it owns the projects, the members and the plan.

The API lives on the same domain under /api:

export ENVMASTER_URL=https://env.aistastudio.ru

Examples below use $ENVMASTER_URL.

2. Create a project and a secret

Through the dashboard it's three screens; through the API, three requests:

BASE=$ENVMASTER_URL/api/v1
TOKEN=$(curl -s $BASE/auth/login -H 'content-type: application/json' \
  -d '{"email":"you@example.com","password":"..."}' | jq -r .tokens.accessToken)

ORG=$(curl -s $BASE/orgs -H "authorization: Bearer $TOKEN" | jq -r .items[0].id)
PROJECT=$(curl -s $BASE/projects -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d "{\"orgId\":\"$ORG\",\"name\":\"Billing API\",\"slug\":\"billing-api\"}" | jq -r .id)

curl -s $BASE/projects/$PROJECT/environments/production/entries \
  -H "authorization: Bearer $TOKEN" -H 'content-type: application/json' \
  -d '{"key":"DB_PASSWORD","kind":"secret","visibility":"masked","value":"..."}'

3. Issue an identity to the service

curl -s $BASE/services/$SERVICE/identities -H "authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{"name":"prod worker","environmentId":"...","mode":"universal","allowedKeys":["DB_*"]}'

The response contains a clientSecret — it is shown exactly once. Only its hash is kept in the database, so a lost secret is not recovered but re-issued.

4. Connect the service

import { EnvMasterClient } from "@env-master/sdk";

const em = new EnvMasterClient({
  baseUrl: process.env.ENVMASTER_URL!,
  project: "billing-api",
  environment: "production",
});

await em.loginMachine({
  clientId: process.env.ENVMASTER_CLIENT_ID!,
  clientSecret: process.env.ENVMASTER_CLIENT_SECRET!,
});

const password = await em.get("DB_PASSWORD");

Done. From here the value can be changed in the dashboard — the service picks up the current one on its next start, and with rotation it doesn't even need a restart.

Migrating an existing .env

ENVMASTER_TOKEN=... envmaster import .env \
  --project billing-api --env production --dry-run

The command decides what looks like a secret on its own and shows the plan before writing anything.