If your GitHub Actions job asks for interactive login, your CI auth model is wrong for automation. Use JWT-based headless auth so pipelines can authenticate and deploy without browser prompts.
This is a focused deep dive from the Salesforce CLI DevOps Playbook.
What is Salesforce CLI headless auth in CI/CD?
Headless auth means the pipeline logs into Salesforce with a connected app, username, and signed JWT, not a browser flow. It is the standard pattern for repeatable CI deploys.
Core command:
sf org login jwt \
--client-id "$SF_CLIENT_ID" \
--jwt-key-file "$SF_JWT_KEY_PATH" \
--username "$SF_USERNAME" \
--instance-url https://login.salesforce.com
What do I need before configuring GitHub Actions?
You need a connected app configured for JWT bearer flow, an integration user, and an RSA key pair. Missing any one of these causes invalid_grant or auth failures.
Preflight requirements:
- Connected app consumer key (
SF_CLIENT_ID). - Integration username (
SF_USERNAME). - Private key file available to the workflow (
server.key). - Correct login domain (
https://login.salesforce.comor sandbox URL).
How do I generate a key pair for JWT auth?
Generate the private/public key pair once, upload the certificate to the connected app, and keep the private key out of git.
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
Upload server.crt to your connected app. Store server.key as an encrypted GitHub secret or encrypted file in the workflow.
Which GitHub secrets should I create?
Store credentials as repository or environment secrets and reconstruct the key during workflow runtime. Never commit private key material to source control.
Recommended secrets:
SF_CLIENT_IDSF_USERNAMESF_JWT_KEY_BASE64(base64-encoded contents ofserver.key)SF_INSTANCE_URL(https://login.salesforce.comor sandbox endpoint)
What does a minimal GitHub Actions workflow look like?
Install Node and Salesforce CLI, restore the JWT key, authenticate with sf org login jwt, then validate deploy. Keep auth and deploy in the same job unless you intentionally split with artifacts.
name: Salesforce Validate Deploy
on:
pull_request:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install Salesforce CLI
run: npm install @salesforce/[email protected] --global
- name: Restore JWT key
run: |
echo "$SF_JWT_KEY_BASE64" | base64 --decode > server.key
chmod 600 server.key
env:
SF_JWT_KEY_BASE64: ${{ secrets.SF_JWT_KEY_BASE64 }}
- name: Authenticate to Salesforce
run: |
sf org login jwt \
--client-id "$SF_CLIENT_ID" \
--jwt-key-file server.key \
--username "$SF_USERNAME" \
--instance-url "$SF_INSTANCE_URL"
sf org display --target-org "$SF_USERNAME"
env:
SF_CLIENT_ID: ${{ secrets.SF_CLIENT_ID }}
SF_USERNAME: ${{ secrets.SF_USERNAME }}
SF_INSTANCE_URL: ${{ secrets.SF_INSTANCE_URL }}
- name: Validate deploy
run: |
sf project deploy validate \
--source-dir force-app \
--target-org "$SF_USERNAME" \
--test-level RunLocalTests \
--wait 60
env:
SF_USERNAME: ${{ secrets.SF_USERNAME }}
How do I fix common JWT auth failures in Actions?
Most failures are configuration mismatches, not Salesforce CLI bugs. Verify the username, connected app consumer key, certificate, and instance URL first.
Fast checks:
invalid_grant: wrong username, cert mismatch, or user not approved for connected app.audience is invalid: wrong--instance-urlfor target org type.- Intermittent failures: key formatting issues from secret decoding.
- “No auth found”: auth step ran in a different job or key file was not created.
How do I keep this secure in production pipelines?
Use a dedicated integration user with least privilege, isolate secrets in GitHub environments, and rotate certificates on a schedule. Treat JWT key handling as production credential management.
Security baseline:
- Restrict connected app policies to approved users.
- Use protected environments for production deployment secrets.
- Rotate cert/key pair periodically and after team changes.
- Add a pre-deploy
sf org displaycheck so failures happen before metadata operations.
For deployment command strategy after auth, continue with sf project deploy start vs sf project deploy validate: when to use each.