Skip to main content
Version: 7.0

CI/CD and infrastructure integrations

Overview

Passwork integrates with CI/CD platforms through passwork-cli. The typical pattern looks like:

CI/CD Runner ──► passwork-cli exec ──► Deploy script with secrets in ENV
PlatformIntegration method
GitLab CIDocker image passwork/passwork-cli as the job image
GitHub ActionsDocker container via docker run
Bitbucket PipelinesDocker image in a pipe
KubernetesInit container or sidecar

GitLab CI

Basic example

stages:
- deploy

deploy_prod:
stage: deploy
image: passwork/passwork-cli:latest
variables:
PASSWORK_HOST: $PASSWORK_HOST
PASSWORK_TOKEN: $PASSWORK_TOKEN
PASSWORK_MASTER_KEY: $PASSWORK_MASTER_KEY
script:
- passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" ./deploy.sh

Setting up variables

In Settings → CI/CD → Variables, add:

VariableTypeProtectedMasked
PASSWORK_HOSTVariableYesNo
PASSWORK_TOKENVariableYesYes
PASSWORK_MASTER_KEYVariableYesYes
SECRETS_FOLDER_IDVariableYesNo

Multiple environments

.deploy_template: &deploy_template
image: passwork/passwork-cli:latest
variables:
PASSWORK_HOST: $PASSWORK_HOST
PASSWORK_TOKEN: $PASSWORK_TOKEN
PASSWORK_MASTER_KEY: $PASSWORK_MASTER_KEY
script:
- passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" ./deploy.sh

deploy_staging:
<<: *deploy_template
stage: deploy
variables:
SECRETS_FOLDER_ID: $STAGING_SECRETS_FOLDER_ID
environment:
name: staging

deploy_production:
<<: *deploy_template
stage: deploy
variables:
SECRETS_FOLDER_ID: $PROD_SECRETS_FOLDER_ID
environment:
name: production
when: manual

GitHub Actions

Basic example

name: Deploy

on:
push:
branches: [main]

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

- name: Deploy with secrets
run: |
docker run --rm \
-e PASSWORK_HOST="${{ secrets.PASSWORK_HOST }}" \
-e PASSWORK_TOKEN="${{ secrets.PASSWORK_TOKEN }}" \
-e PASSWORK_MASTER_KEY="${{ secrets.PASSWORK_MASTER_KEY }}" \
-v ${{ github.workspace }}:/app \
-w /app \
passwork/passwork-cli:latest \
exec --folder-id "${{ vars.SECRETS_FOLDER_ID }}" ./deploy.sh

Setting up secrets

In Settings → Secrets and variables → Actions:

  • Secrets: PASSWORK_HOST, PASSWORK_TOKEN, PASSWORK_MASTER_KEY
  • Variables: SECRETS_FOLDER_ID

Multiple environments

jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
steps:
- uses: actions/checkout@v4

- name: Deploy
run: |
docker run --rm \
-e PASSWORK_HOST="${{ secrets.PASSWORK_HOST }}" \
-e PASSWORK_TOKEN="${{ secrets.PASSWORK_TOKEN }}" \
-e PASSWORK_MASTER_KEY="${{ secrets.PASSWORK_MASTER_KEY }}" \
-v ${{ github.workspace }}:/app \
-w /app \
passwork/passwork-cli:latest \
exec --folder-id "${{ vars.SECRETS_FOLDER_ID }}" ./deploy.sh

Bitbucket Pipelines

image: passwork/passwork-cli:latest

pipelines:
branches:
main:
- step:
name: Deploy to production
deployment: production
script:
- passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" ./deploy.sh

Configure variables in Repository settings → Pipelines → Repository variables.

Kubernetes

Init container

An init container fetches secrets before the main application starts:

apiVersion: v1
kind: Pod
metadata:
name: order-service
spec:
initContainers:
- name: fetch-secrets
image: passwork/passwork-cli:latest
env:
- name: PASSWORK_HOST
valueFrom:
secretKeyRef:
name: passwork-credentials
key: host
- name: PASSWORK_TOKEN
valueFrom:
secretKeyRef:
name: passwork-credentials
key: token
- name: PASSWORK_MASTER_KEY
valueFrom:
secretKeyRef:
name: passwork-credentials
key: master-key
command:
- sh
- -c
- |
passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" env > /secrets/.env
volumeMounts:
- name: secrets-volume
mountPath: /secrets

containers:
- name: app
image: order-service:latest
command:
- sh
- -c
- |
set -a && source /secrets/.env && set +a
exec ./app
volumeMounts:
- name: secrets-volume
mountPath: /secrets
readOnly: true

volumes:
- name: secrets-volume
emptyDir:
medium: Memory

Sidecar for periodic refresh

A sidecar refreshes secrets after rotation without restarting the pod:

apiVersion: v1
kind: Pod
metadata:
name: order-service-with-sidecar
spec:
containers:
- name: app
image: order-service:latest
# App reloads /secrets/.env when it changes

- name: secrets-sync
image: passwork/passwork-cli:latest
env:
- name: PASSWORK_HOST
valueFrom:
secretKeyRef:
name: passwork-credentials
key: host
# ... other variables
command:
- sh
- -c
- |
while true; do
passwork-cli exec --folder-id "$SECRETS_FOLDER_ID" env > /secrets/.env.new
mv /secrets/.env.new /secrets/.env
sleep 300 # refresh every 5 minutes
done
volumeMounts:
- name: secrets-volume
mountPath: /secrets

volumes:
- name: secrets-volume
emptyDir:
medium: Memory

Why centralize secrets

AspectWithout PassworkWith Passwork
StorageScattered across CI variablesCentralized in Passwork
RotationUpdate each system separatelyUpdate once in Passwork
AuditLogs spread across platformsSingle audit log in Passwork
Access controlConfigure in every systemRBAC in Passwork
tip

Keep only Passwork connection credentials (PASSWORK_HOST, PASSWORK_TOKEN, PASSWORK_MASTER_KEY) in your CI system. Store everything else in Passwork.