Penv Cloud
Start free
Docs
Guidesince cloud@2026-09-10

GitLab CI

Exchange your GitLab CI id token for a fifteen-minute credential from us and run one job step with the values.

Your job exchanges a GitLab-signed id token for a credential we mint, bound to one project and one environment. See machine identity and values in a CI build.

Trust a GitLab project

Open Machine Identities then Connect a Platform and pick GitLab CI. We build the subject from your project path, branch, host and ref type, for example project_path:acme/api:ref_type:branch:ref:main. The GitLab CI trust reference lists every field and default.

ConstraintDetail
Subject matchExact, no wildcards. A tag job (ref_type:tag) or a second branch needs its own trust
Self-managed GitLabMust be reachable from the internet; we read signing keys from the issuer's origin
AudienceYour workspace id, shown in the console

Run penv in the job

.gitlab-ci.yml
deploy:
  id_tokens:
    ID_TOKEN:
      aud: YOUR_WORKSPACE_ID
  script:
    - curl -fsSL https://penv.cloud/install | sh
    - export PATH="$HOME/.penv/bin:$PATH"
    - penv run -- npm run deploy

id_tokens is GitLab's id token mechanism. penv run exchanges the token itself and passes values to the child process only.

penv looks for a credential in this order:

OrderSource
1PENV_TOKEN
2A login in the OS keychain (absent on a runner)
3An enrolled keypair
4A platform token: GitHub Actions' ACTIONS_ID_TOKEN_REQUEST_URL, then ID_TOKEN, then PENV_OIDC_TOKEN
5AWS credentials; see AWS workload

A runner has no keychain, so every run is online and nothing is cached on disk.

Exchange explicitly

Name the id token PENV_OIDC_TOKEN and penv run reads it too. For any other name, exchange it yourself:

.gitlab-ci.yml
deploy:
  id_tokens:
    PENV_ID_TOKEN:
      aud: YOUR_WORKSPACE_ID
  script:
    - |
      C=$(T="$PENV_ID_TOKEN" jq -n '{token:env.T}' | curl -sS "https://penv.cloud/api/v1/auth/oidc" \
        -H 'content-type: application/json' --data-binary @- | jq -r .credential)
      PENV_TOKEN="$C" penv run -- npm run deploy

The console prints a pull-secrets job of this shape that ends in PENV_TOKEN="$C" penv pull, writing a .env for your later jobs. penv pull is for a host that needs a file; penv run keeps values off disk. Copy the audience from the Connect page either way.

Credential scope

  • Your trust holds no secret.
  • The credential is bound to one project and one environment.
  • Fifteen minutes is a ceiling: a credential never outlives the trust's expiry.

Troubleshooting

AnswerMeaning
401 unauthorizedThe token's subject is not your trust's. Check the branch and project path
401 expiredThe trust's expiry has passed. Reissue it in the console
403 forbiddenThe credential is bound to another environment
503 unavailableWe could not read the GitLab signing keys. Retry once

All codes: our API answers.

Other CI platforms