CLI in CI/CD
Use ass in your build pipelines to fetch secrets at runtime — no more storing 20+ secrets in GitHub Actions or GitLab CI variables.
The pattern
Store only ASS_AGENT_KEY in your CI/CD platform. Everything else is fetched from the vault at runtime. This reduces your CI/CD secret surface from dozens of entries to one — and gives you audit trails, rotation, and access control for free.
GitHub Actions
Add ASS_AGENT_KEY to your repository secrets (Settings → Secrets and variables → Actions), then reference it in your workflow:
Fetch individual secrets
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Agent Secret Store CLI
run: npm install -g @agentsecretstore/cli
- name: Fetch secrets from vault
env:
ASS_AGENT_KEY: ${{ secrets.ASS_AGENT_KEY }}
run: |
GEMINI_KEY=$(ass secrets get production/gemini/GEMINI_API_KEY --silent)
DB_URL=$(ass secrets get production/database/DATABASE_URL --silent)
# Write to GITHUB_ENV so downstream steps can use them
echo "GEMINI_API_KEY=$GEMINI_KEY" >> $GITHUB_ENV
echo "DATABASE_URL=$DB_URL" >> $GITHUB_ENV
- name: Run tests
run: npm test
# $GEMINI_API_KEY and $DATABASE_URL are now availableBulk export a namespace
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Agent Secret Store CLI
run: npm install -g @agentsecretstore/cli
- name: Export all production secrets
env:
ASS_AGENT_KEY: ${{ secrets.ASS_AGENT_KEY }}
run: |
# Export all secrets in the production namespace to a local .env
ass env export production --output .env.production
# Source the file to load all variables into the shell environment
set -a
source .env.production
set +a
- name: Build and deploy
run: ./deploy.shJSON output for scripting
- name: Get one secret as JSON for scripting
env:
ASS_AGENT_KEY: ${{ secrets.ASS_AGENT_KEY }}
run: |
# Parse JSON output with jq
STRIPE_JSON=$(ass secrets get production/stripe/STRIPE_SECRET_KEY --json)
STRIPE_KEY=$(echo "$STRIPE_JSON" | jq -r '.value')
echo "STRIPE_SECRET_KEY=$STRIPE_KEY" >> $GITHUB_ENVMask secret values
GitHub Actions automatically masks values set via $GITHUB_ENV, but values printed directly to stdout may appear in job logs. Always use --silent with ass secrets get in CI environments.
GitLab CI
Store ASS_AGENT_KEY as a masked CI/CD variable (Settings → CI/CD → Variables), then use the before_script anchor to fetch secrets before each job:
# .gitlab-ci.yml
variables:
# Store only ASS_AGENT_KEY in GitLab CI/CD Variables
# All other secrets fetched from vault at runtime
stages:
- test
- deploy
.fetch-secrets: &fetch-secrets
before_script:
- npm install -g @agentsecretstore/cli
- |
export GEMINI_API_KEY=$(ass secrets get production/gemini/GEMINI_API_KEY --silent)
export DATABASE_URL=$(ass secrets get production/database/DATABASE_URL --silent)
test:
stage: test
image: node:22
<<: *fetch-secrets
script:
- npm ci
- npm test
deploy:
stage: deploy
image: node:22
only:
- main
<<: *fetch-secrets
script:
- npm ci
- npm run build
- ./deploy.shCircleCI
Set ASS_AGENT_KEY as a project environment variable in CircleCI (Project Settings → Environment Variables), then use $BASH_ENV to pass secrets between run steps:
# .circleci/config.yml
version: 2.1
jobs:
deploy:
docker:
- image: cimg/node:22.12
steps:
- checkout
- run:
name: Install Agent Secret Store CLI
command: npm install -g @agentsecretstore/cli
- run:
name: Fetch secrets
command: |
# ASS_AGENT_KEY is set as a CircleCI environment variable
export GEMINI_KEY=$(ass secrets get production/gemini/GEMINI_API_KEY --silent)
export STRIPE_KEY=$(ass secrets get production/stripe/STRIPE_SECRET_KEY --silent)
# Write to BASH_ENV so they persist across run steps
echo "export GEMINI_API_KEY=$GEMINI_KEY" >> $BASH_ENV
echo "export STRIPE_SECRET_KEY=$STRIPE_KEY" >> $BASH_ENV
- run:
name: Run tests
command: npm test
workflows:
main:
jobs:
- deployDocker & Docker Compose
Fetch secrets at container startup via an entrypoint script — never bake them into image layers:
Never fetch secrets at build time
Secrets fetched during docker build are baked into image layers and visible in the image history. Always fetch at container startup (in the entrypoint or application boot), not during the build.
Dockerfile
# Dockerfile — fetch secrets at container startup, not build time
FROM node:22-alpine
RUN npm install -g @agentsecretstore/cli
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Use an entrypoint script to fetch secrets at runtime
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["node", "server.js"]entrypoint.sh
#!/bin/sh
# entrypoint.sh — fetch secrets from vault before starting the app
set -e
echo "Fetching secrets from Agent Secret Store..."
# ASS_AGENT_KEY must be set in the container environment
export GEMINI_API_KEY=$(ass secrets get production/gemini/GEMINI_API_KEY --silent)
export DATABASE_URL=$(ass secrets get production/database/DATABASE_URL --silent)
export STRIPE_SECRET_KEY=$(ass secrets get production/stripe/STRIPE_SECRET_KEY --silent)
echo "✓ Secrets loaded"
# Execute the main process
exec "$@"docker-compose.yml
# docker-compose.yml
version: '3.9'
services:
api:
build: .
environment:
# Only the vault key — all others fetched at startup
ASS_AGENT_KEY: ${ASS_AGENT_KEY}
ports:
- "3000:3000"
worker:
build: .
command: node worker.js
environment:
ASS_AGENT_KEY: ${ASS_AGENT_KEY}