GitLab CI/CD - Manual Setup

Manually configure GitLab CI/CD with SikkerKey secrets.

For a faster setup experience, use the automated setup which handles everything from the dashboard.

Pipeline Configuration

stages:
  - secrets
  - build

sikkerkey:
  stage: secrets
  image: node:20
  script:
    - npm install -g sikkerkey 2>/dev/null
    - VAULT_DIR="$HOME/.sikkerkey/vaults/$SIKKERKEY_VAULT_ID"
    - mkdir -p "$VAULT_DIR"
    - chmod 700 "$HOME/.sikkerkey" "$HOME/.sikkerkey/vaults" "$VAULT_DIR"
    - cp "$SIKKERKEY_PRIVATE_KEY" "$VAULT_DIR/private.pem"
    - chmod 600 "$VAULT_DIR/private.pem"
    - printf '{"machineId":"%s","machineName":"gitlab-ci","vaultId":"%s","apiUrl":"https://api.sikkerkey.com","privateKeyPath":"%s/private.pem"}' "$SIKKERKEY_MACHINE_ID" "$SIKKERKEY_VAULT_ID" "$VAULT_DIR" > "$VAULT_DIR/identity.json"
    - chmod 600 "$VAULT_DIR/identity.json"
    - sikkerkey connect $SIKKERKEY_VAULT_ID
    - sikkerkey unlock $SIKKERKEY_PROJECT_ID
    - sikkerkey export --project $SIKKERKEY_PROJECT_ID > sikkerkey.env
  artifacts:
    reports:
      dotenv: sikkerkey.env

build:
  stage: build
  needs: [sikkerkey]
  script:
    - echo "Secrets are available as environment variables"

The sikkerkey stage installs the CLI, configures the machine identity, fetches secrets, and exports them as a dotenv artifact. All downstream jobs in later stages receive the secrets as environment variables automatically.

Setup

1. Bootstrap a CI machine

From the dashboard, go to Machines and click + Validate. Select the CI/CD tab and run the command:

curl -sSL https://api.sikkerkey.com/v1/bootstrap/YOUR_TOKEN/ci | sh

This generates a keypair locally, registers the public key with SikkerKey, and prints the credentials:

SIKKERKEY_VAULT_ID=vault_abc123
SIKKERKEY_MACHINE_ID=9daae125-1f61-4eca-bde6-70aaa40db018

SIKKERKEY_PRIVATE_KEY:
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIHN...
-----END PRIVATE KEY-----

2. Add CI/CD variables

In your GitLab project, go to Settings > CI/CD > Variables and add:

VariableTypeMaskedValue
SIKKERKEY_VAULT_IDVariableYesThe vault ID from the output
SIKKERKEY_PROJECT_IDVariableYesYour project ID (from the dashboard sidebar)
SIKKERKEY_MACHINE_IDVariableYesThe machine ID from the output
SIKKERKEY_PRIVATE_KEYFileNoThe full PEM private key including headers

Set the private key as a File type variable. Set Visibility to Visible -- masked variables cannot contain whitespace, and PEM keys contain newlines. File type variables write the content to a temporary file, so the key never appears in job logs.

3. Approve and grant access

The machine appears as pending in the dashboard. Approve it, add it to your project, and grant it access to the secrets your pipeline needs.

Examples

Inject and run

deploy:
  image: node:20
  script:
    # ... CLI install + identity setup ...
    - sikkerkey run --all -- ./deploy.sh

Fetch individual secrets

deploy:
  script:
    # ... CLI install + identity setup ...
    - export DB_PASSWORD=$(sikkerkey get sk_db_prod password)
    - export API_KEY=$(sikkerkey get sk_api_key)
    - ./deploy.sh

Reusable template

Create a template in your group for reuse across projects:

# .gitlab/ci/sikkerkey.yml
.sikkerkey-setup:
  image: node:20
  before_script:
    - npm install -g sikkerkey 2>/dev/null
    - VAULT_DIR="$HOME/.sikkerkey/vaults/$SIKKERKEY_VAULT_ID"
    - mkdir -p "$VAULT_DIR"
    - chmod 700 "$HOME/.sikkerkey" "$HOME/.sikkerkey/vaults" "$VAULT_DIR"
    - cp "$SIKKERKEY_PRIVATE_KEY" "$VAULT_DIR/private.pem"
    - chmod 600 "$VAULT_DIR/private.pem"
    - printf '{"machineId":"%s","machineName":"gitlab-ci","vaultId":"%s","apiUrl":"https://api.sikkerkey.com","privateKeyPath":"%s/private.pem"}' "$SIKKERKEY_MACHINE_ID" "$SIKKERKEY_VAULT_ID" "$VAULT_DIR" > "$VAULT_DIR/identity.json"
    - chmod 600 "$VAULT_DIR/identity.json"
    - sikkerkey connect $SIKKERKEY_VAULT_ID
    - sikkerkey unlock $SIKKERKEY_PROJECT_ID

Then use it:

include:
  - local: .gitlab/ci/sikkerkey.yml

deploy:
  extends: .sikkerkey-setup
  script:
    - sikkerkey run --all -- ./deploy.sh

Security Notes

  • The private key is stored as a file type CI/CD variable and never printed to logs
  • The identity is created in the runner's home directory and discarded when the job ends
  • Every secret read is authenticated with Ed25519 signatures and recorded in the SikkerKey audit log
  • Each pipeline run uses the same machine identity, so all reads are logged with the same machine ID