OIDC for CI

OIDC lets an authorized GitHub Actions or GitLab.com CI job pull one environment from a personal Pro or organization project. CI stores no long-lived Registry token.

This flow is an explicit exception to ordinary end-to-end encrypted cloud sync. LPM.dev Registry decrypts the selected environment on the server after verifying the workflow identity and policy.

The supported workflow requires:

  • A personal Pro project or an organization project on an active Organization or Enterprise plan.
  • GitHub Actions or GitLab.com CI.
  • A repository checkout that contains the project's lpm.json and vault ID.

Organization projects require an explicit owner or admin opt-in for server decryption. OIDC here authorizes CI workloads. It does not configure organization SSO.

Push the Personal Vault First

Create the local vault, sign in, and upload its encrypted cloud copy:

lpm env set --env=production API_TOKEN=secret
lpm login
lpm env push

OIDC escrow cannot be enabled before that personal cloud vault exists.

Authorize a Workflow

Run this on the LPM CLI installation that holds the personal wrapping key:

lpm env oidc allow \
  --provider=github \
  --repo=owner/repository \
  --workflow=.github/workflows/deploy.yml \
  --branch=main \
  --env=production \
  --events=push

The command creates the policy and then uploads protected escrow material that lets LPM.dev Registry decrypt this vault for an authorized CI pull.

After the command succeeds, it prints a server-issued policy ID. Copy this UUID into the CI configuration as LPM_OIDC_POLICY_ID.

The policy ID is a selector, not a bearer credential. It cannot authorize a pull without a valid CI identity token. Protect its integrity because a changed value can select the wrong policy.

By default, LPM CLI gets the immutable numeric repository ID from the GitHub API. Public repository requests do not need GitHub authentication.

If the repository is private, set GITHUB_TOKEN or GH_TOKEN. You can also pass --repository-id=<numeric-id> directly.

The policy binds the repository name and numeric ID. Both values must match during the OIDC exchange and the CI pull.

If a repository is renamed or transferred, run lpm env oidc allow again with its current name. A different repository cannot reuse the old policy.

Existing GitHub policies without a repository ID fail closed. If lpm env oidc list reports a missing ID, run lpm env oidc allow again.

Continue only when LPM CLI reports that CI escrow is enabled. If the escrow upload fails, the command exits with an error.

The policy can already exist after this error, but the CI pull is not ready. Correct the error and run the same command again.

List the vault's current policies with:

lpm env oidc list

The current LPM CLI can create and list policies, but it does not yet provide an oidc revoke command.

Authorize an Organization Workflow

An owner or admin must first share or pull the current organization revision. Run the complete policy command with an explicit decryption opt-in:

lpm env pull --org=acme
lpm env oidc allow \
  --org=acme \
  --allow-server-decryption \
  --provider=github \
  --repo=owner/repository \
  --workflow=.github/workflows/deploy.yml \
  --branch=main \
  --env=production \
  --events=push
lpm env oidc list --org=acme

The command transfers only this project's current content key over TLS. The Registry encrypts the key before storage. Your sharing private key and personal wrapping key stay on your machine.

The organization owns the policy and CI credentials. Access does not depend on the original policy creator remaining an admin. Each pull checks current billing, policy restrictions, token validity, and content-key state.

Owners and admins can add, replace, or delete policies from the project's Access page. They can also disable CI decryption there or through the CLI:

lpm env oidc disable --org=acme

Disabling decryption revokes issued credentials. Enabling it again does not restore those credentials. Disabling remains available when organization billing lapses.

Content-key rotation or membership key invalidation clears CI escrow and revokes issued credentials. After the new key is shared, run the complete oidc allow command again.

The CI pull command is the same for personal and organization projects. Its policy ID selects the ownership scope. The CI job does not need --org.

Policy Controls

ControlCLI OptionMeaning
Repository--repo=owner/repositoryGitHub repository allowed to request access
Repository ID--repository-id=123456789This option sets an explicit immutable ID. LPM CLI gets the ID from GitHub by default
Workflow--workflow=.github/workflows/deploy.ymlExact workflow file allowed to request access
Branch--branch=mainThis option sets an allowed branch. It accepts a comma-separated list
Environment--env=productionThis option selects the env that the job receives. It accepts a comma-separated list
Event--events=pushThis option sets allowed GitHub event names. The default is push
Forks--allow-forksThis option permits eligible fork-originated runs. Fork access is disabled by default

The workflow file is mandatory. Keep production access restricted to the smallest repository, workflow, branch, event, and environment set that needs it.

GitHub Actions

The job needs id-token: write so GitHub can issue its signed identity token:

name: Deploy

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install LPM CLI
        run: npm install -g @lpm-registry/cli

      - name: Pull production environment
        run: lpm env pull --oidc --env=production --output=.env
        env:
          LPM_OIDC_POLICY_ID: ${{ vars.LPM_OIDC_POLICY_ID }}

      - name: Run the deployment
        run: node --env-file=.env ./scripts/deploy.mjs

--output accepts a file path and writes a plaintext dotenv file. Without --output, LPM CLI reports how many values were returned but does not inject them into later workflow steps. --output=- creates a file named -; it is not stdout.

Use a deployment command that explicitly loads the generated file. The file is set to owner-only permissions where the runner supports POSIX file modes.

The checked-out lpm.json must contain the vault ID used when the policy was created.

Create LPM_OIDC_POLICY_ID as a GitHub repository variable for this job. If you use an environment variable, add environment: <name> to the job. GitHub does not expose an environment variable to a job that does not target that environment.

You can pass --policy-id=<uuid> instead. The command flag takes precedence over LPM_OIDC_POLICY_ID.

GitLab.com CI

Authorize the numeric GitLab project ID from a logged-in development machine:

lpm env oidc allow \
  --provider=gitlab \
  --project-id=12345 \
  --branch=main \
  --env=production

Create LPM_OIDC_POLICY_ID as a GitLab CI/CD variable. Mark it protected only when every branch or tag allowed by the OIDC policy is also protected. GitLab does not expose protected variables to unprotected refs.

deploy:
  id_tokens:
    LPM_OIDC_TOKEN:
      aud: https://lpm.dev
  script:
    - npm install -g @lpm-registry/cli
    - lpm env pull --oidc --env=production --output=.env
    - node --env-file=.env ./scripts/deploy.mjs

Trust Boundary

The CI job obtains an OIDC identity token at run time. LPM CLI sends that token, the policy ID, the vault ID, and the requested environment.

LPM.dev Registry then:

  1. Verifies the OIDC token's signature, issuer, audience, and current claims.
  2. Selects the exact server-issued policy ID.
  3. Matches the provider identity, repository or project ID, workflow, branch, event, environment, and fork status against the policy.
  4. Issues access scoped to that vault and environment.
  5. Uses the escrowed key to decrypt the project.
  6. Returns only the authorized environment as plaintext over TLS.
OperationCan LPM.dev Registry read vault values?
Ordinary lpm env push or developer-machine pullNo
lpm env oidc allow escrow uploadReceives protected key material for later server decryption
Authorized lpm env pull --oidcYes

If server-side decryption is outside the project's security requirements, do not enable OIDC escrow.

Escrow Errors

If a CI pull reports a stale escrow key, repeat setup on the machine that holds the current project key. Organization setup also requires --org=<slug> and --allow-server-decryption.

If a CI pull reports an unavailable escrow key version, the Registry configuration needs operator action. The pull fails and returns no secret values.

The Registry protects escrow material with a versioned server key. A server-key rotation does not change the policy or require a new escrow upload.

Current Limitations

  • OIDC env pull requires a personal Pro project or an approved organization project.
  • Initial organization decryption setup requires an owner or admin with the current shared key.
  • GitLab.com policies use the stable numeric project ID. Self-managed GitLab issuers are not supported.
  • The dashboard does not provide personal env OIDC policy management.

For detailed CLI behavior, see the LPM CLI environment reference.

See Also

  • Cloud Sync — Understand the personal encrypted vault and escrow exception.
  • Organization Sharing — Review the separate organization key model.
  • CI/CD — Configure package installation and publishing in CI.