Onboard a new service
You have a new service called api. By the end of this page it has a project,
a staging and a production environment, its secrets loaded, and it starts with
prk run.
Before you begin
- A deployed prick server, and
prk logindone. - Admin at the scope you are creating in.
prk whoamishould print a role, or an administrator needs to grant you one.
1. Create the project
prk projects create "API service" --slug apiCreated project `API service` (api).The slug is what everything else addresses. Pass it explicitly when the
display name would not derive the one you want — here "API service" would have
become api-service.
2. Create the environments
prk env create Production --slug production --project apiCreated environment `Production` (production).prk env create Staging --slug staging --project apiCreated environment `Staging` (staging).Check what you have:
prk env list --project apiproduction Production rev 0 0 secret(s)staging Staging rev 0 0 secret(s)3. Stop typing the flags
export PRK_PROJECT=apiexport PRK_ENV=stagingEvery command below now runs against api:staging until you change it. Put
these in a direnv file per repository if you switch between services often.
4. Add secrets
prk secrets set DATABASE_URLValue for DATABASE_URL:Paste the value at the prompt — it is masked, and it reads the terminal directly so nothing lands in your shell history.
Added `DATABASE_URL` (rev 1).Add a description while you are there, so the next person knows what they are looking at:
prk secrets set STRIPE_SECRET_KEY --description "Test mode, rotates quarterly"Added `STRIPE_SECRET_KEY` (rev 2).Descriptions are stored in plaintext beside the key name, so never put a value in one.
From a script or a password manager
op read "op://vault/stripe/test-key" | prk secrets set STRIPE_SECRET_KEY --stdinAnything that writes to stdout works — --stdin takes the value from the pipe.
5. Check your work
prk secrets listDATABASE_URL v1 you@example.comSTRIPE_SECRET_KEY v1 you@example.comValues never appear in a listing. To read one back:
prk secrets get DATABASE_URLpostgres://app:hunter2@db.staging.example.com:5432/appThat read is audited, as every reveal is.
6. Run the application
prk run -- npm startThe secrets land in the process’s environment block and nowhere else — no
temporary file, nothing on disk. prk then becomes your program, so its exit
code and signal handling are its own.
Confirm what was injected without printing any values:
prk run -vv -- node -e 'console.log("started")'injecting 2 secrets into the child environmentvariables: DATABASE_URL, STRIPE_SECRET_KEYstarted7. Copy the shape to production
Staging is set up and working. Export its keys as a template:
prk secrets download --format env --output template.envWrote 2 secrets to template.env.Edit template.env so it holds the production values, then load it:
prk secrets upload template.env --dry-run --env production2 added, 0 changed, 0 removed (dry run; nothing was written).The dry run says exactly what would happen. When it reads right:
prk secrets upload template.env --env production2 added, 0 changed, 0 removed.Then delete the file — it holds production secrets in plaintext:
rm template.envupload replaces by default
Keys the file does not name are deleted, because “upload this environment”
means the environment ends up matching the file. Pass --merge when you only
mean to add.
8. Let your team in
Find out who has authenticated:
prk access identitiesyou@example.com useralice@example.com userGive Alice write access to staging, and read-only on production:
prk access grant alice@example.com --role writer --scope api:stagingGranted writer to `alice@example.com` on `api:staging`.prk access grant alice@example.com --role reader --scope api:productionGranted reader to `alice@example.com` on `api:production`.Confirm it reads the way you meant:
prk access explain alice@example.comalice@example.com usergroups noneapi:staging writer via a direct grant on `api:staging` -> writer a direct grant on `api:staging`api:production reader via a direct grant on `api:production` -> reader a direct grant on `api:production`Someone has to authenticate before you can grant to them
The server learns a subject exists the first time it authenticates. If Alice has
never signed in, have her run prk login once — she will get an empty world
rather than an error — and then grant.
What you have now
- A project
apiwithstagingandproduction. - Secrets in both, versioned, with every read and write audited.
- An application that starts with
prk runand never sees a.envfile. - One teammate with exactly the access she needs.
Next steps
- Give CI read-only access — the same thing for a deploy job.
- Using secrets — Docker, npm scripts, Workers, GitHub Actions.
prk secrets— every flag on the commands above.