CircleCI
Cloud-native continuous integration and delivery platform
Overview
CircleCI is a cloud-hosted continuous integration and continuous delivery (CI/CD) platform founded in 2011. It automates the build, test, and deployment pipeline for software teams. CircleCI's key differentiators are speed (Docker layer caching, test parallelism, powerful executor fleet), a rich orbs ecosystem for reusable configuration, and multi-platform support (Linux, macOS, Windows, ARM). It is platform-agnostic, integrating with GitHub, GitLab, and Bitbucket as source code providers.
Cloud CircleCI Cloud
The primary SaaS offering. Fully managed — no infrastructure to maintain. Automatic scaling, managed executors, and a generous free tier (30,000 credits/month for up to 5 users). Paid tiers (Performance, Scale, Custom) add more concurrency, resource classes, and features like Docker layer caching.
Self-Hosted CircleCI Server
A self-hosted version of CircleCI for air-gapped environments, data residency, and compliance requirements. Deployed on Kubernetes via Helm. You manage the infrastructure, updates, and scaling. Requires a license from CircleCI.
Speed Performance Features
Parallelism — run N copies of a job to split tests across containers. Docker layer caching — reuse previously built layers. Caching — persist dependencies between builds. Resource classes — right-size CPU/RAM per job.
Ecosystem Orbs & Integrations
Orbs are reusable, shareable packages of CircleCI configuration (commands, jobs, executors). The Orb Registry has thousands of orbs for AWS, Docker, Slack, Kubernetes, Terraform, and more. Dramatically reduces config boilerplate.
Git Platform Agnostic
Works with GitHub (OAuth app and GitHub App), GitLab (SaaS and self-managed), and Bitbucket (Cloud and Data Center). Triggers pipelines on push, pull request, and tag events. Each platform has slightly different integration features.
Pricing Tiers & Credits
CircleCI uses a credit-based pricing model. Different resource classes consume credits at different rates. Free tier: 30,000 credits/month (credits do not roll over). Performance tier adds concurrency, DLC, and additional credits purchasable in 25,000-credit blocks. Scale tier adds self-hosted runners and audit logs.
Configuration
All CircleCI pipeline configuration lives in .circleci/config.yml at the root of your repository. The config file defines the version, optional orbs, jobs (units of work), and workflows (orchestration of jobs).
Config structure
The top-level keys in a CircleCI config are:
version— always2.1(current version, enables orbs, reusable config, pipelines)orbs— import reusable configuration packages from the Orb Registryjobs— define units of work (executor, steps)workflows— orchestrate jobs (ordering, parallelism, filters, approvals)commands— reusable step sequences (like functions)executors— reusable executor definitionsparameters— pipeline-level parameters for dynamic configuration
Job anatomy
A job defines the executor (runtime environment), working directory, environment variables, and a sequence of steps to execute.
# Key step types
steps:
- checkout # Clone the repo
- run: # Execute a shell command
name: Install deps
command: npm ci
- restore_cache: # Restore a previously saved cache
keys:
- v1-deps-{{ checksum "package-lock.json" }}
- v1-deps-
- save_cache: # Save files to cache
key: v1-deps-{{ checksum "package-lock.json" }}
paths:
- node_modules
- store_artifacts: # Upload build artifacts
path: dist
- store_test_results: # Upload JUnit XML test results
path: test-results
- persist_to_workspace: # Share files with downstream jobs
root: .
paths:
- dist
- attach_workspace: # Attach files from upstream jobs
at: .
Environment variables in config
Environment variables can be set at the job level, step level, or inherited from project/context settings.
jobs:
build:
docker:
- image: cimg/node:20.11
environment:
NODE_ENV: production # Job-level env var
steps:
- checkout
- run:
name: Build
environment:
CI: "true" # Step-level env var
command: npm run build
Complete sample config.yml
version: 2.1
orbs:
node: circleci/node@5.2
docker: circleci/docker@2.6
executors:
node-executor:
docker:
- image: cimg/node:20.11
working_directory: ~/project
resource_class: medium
jobs:
build:
executor: node-executor
steps:
- checkout
- node/install-packages:
pkg-manager: npm
- run:
name: Build application
command: npm run build
- persist_to_workspace:
root: .
paths:
- dist
- node_modules
test:
executor: node-executor
parallelism: 4
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Run tests
command: |
TESTFILES=$(circleci tests glob "src/**/*.test.ts" | circleci tests split --split-by=timings)
npm test -- $TESTFILES
- store_test_results:
path: test-results
- store_artifacts:
path: coverage
deploy:
docker:
- image: cimg/base:current
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Deploy to production
command: |
echo "Deploying version ${CIRCLE_SHA1:0:7}..."
./scripts/deploy.sh
workflows:
build-test-deploy:
jobs:
- build
- test:
requires:
- build
- hold-for-approval:
type: approval
requires:
- test
filters:
branches:
only: main
- deploy:
requires:
- hold-for-approval
context: production-secrets
filters:
branches:
only: main
Dynamic configuration
Dynamic configuration uses setup workflows to generate or modify the pipeline config at runtime. This is essential for monorepos where you only want to build changed services.
# Enable dynamic config in .circleci/config.yml
setup: true
orbs:
continuation: circleci/continuation@1.0
jobs:
generate-config:
docker:
- image: cimg/base:current
steps:
- checkout
- run:
name: Generate pipeline config
command: ./scripts/generate-config.sh > /tmp/generated-config.yml
- continuation/continue:
configuration_path: /tmp/generated-config.yml
Config validation
# Validate config locally using the CircleCI CLI
circleci config validate
# Process and expand the config (resolve orbs, anchors)
circleci config process .circleci/config.yml
# Validate a specific config file
circleci config validate path/to/config.yml
Always run circleci config validate locally before pushing. Install the CircleCI CLI with curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/main/install.sh | bash. Add it to your pre-commit hooks to catch config errors early.
Executors
Executors define the runtime environment for jobs. CircleCI supports multiple executor types, each suited for different workloads. The executor determines the OS, available tools, isolation level, and resource class options.
Docker executor
The most common executor. Runs jobs inside Docker containers. You can specify multiple images — the first is the primary container, additional images run as service containers (databases, caches) accessible via localhost.
jobs:
test:
docker:
- image: cimg/node:20.11 # Primary container
environment:
DATABASE_URL: postgres://postgres:password@localhost:5432/testdb
- image: cimg/postgres:16.2 # Service container
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: testdb
- image: cimg/redis:7.2 # Another service container
resource_class: medium
steps:
- checkout
- run: npm ci
- run: npm test
CircleCI provides convenience images (cimg/*) that are optimized for CI:
cimg/base— minimal Ubuntu image with common CI toolscimg/node— Node.js with npm/yarncimg/python— Python with pipcimg/go— Go with standard toolchaincimg/rust— Rust with cargocimg/openjdk— Java with OpenJDK
Machine executor
Runs jobs in a full Linux VM. Required when you need Docker-in-Docker, privileged operations, or full kernel access.
jobs:
integration:
machine:
image: ubuntu-2404:current
resource_class: medium
steps:
- checkout
- run:
name: Build and test with Docker Compose
command: |
docker compose up -d
docker compose run tests
docker compose down
macOS executor
jobs:
ios-build:
macos:
xcode: "16.2.0"
resource_class: macos.m4pro.medium
steps:
- checkout
- run: xcodebuild -scheme MyApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 16' test
Windows executor
jobs:
windows-build:
machine:
image: windows-server-2022-gui:current
resource_class: windows.medium
steps:
- checkout
- run:
name: Build with MSBuild
command: MSBuild.exe MyProject.sln /p:Configuration=Release
shell: powershell.exe
Self-hosted runner
Run jobs on your own infrastructure. Install the CircleCI runner agent on any machine. Route jobs to runners using custom resource classes.
jobs:
deploy:
machine: true
resource_class: myorg/my-private-runner
steps:
- checkout
- run: ./deploy.sh
Executor comparison
| Executor | Isolation | Docker support | Best for | Startup |
|---|---|---|---|---|
| Docker | Container | No nested Docker | Most CI jobs, testing, building | ~5s |
| Machine | Full VM | Full Docker/Compose | Docker-in-Docker, privileged ops | ~30-60s |
| macOS | Full VM (M4 Pro) | No | iOS/macOS builds, Xcode | ~30-120s |
| Windows | Full VM | Limited | .NET, Windows-specific builds | ~30-60s |
| ARM | Container/VM | Depends on type | ARM-native builds, multi-arch | ~5-30s |
| Self-hosted | Your infra | Your choice | Air-gapped, GPU, special hardware | ~0s (always on) |
Use the Docker executor by default — it starts fastest and uses fewer credits. Switch to machine only when you need Docker-in-Docker or privileged operations. Use self-hosted runners when code cannot leave your network or you need specialized hardware (GPUs, FPGA).
Workflows
Workflows orchestrate the execution of jobs. They define job ordering, parallelism, dependencies, filters, scheduled triggers, and manual approval gates. A single pipeline can contain multiple workflows.
Sequential and parallel execution
workflows:
build-and-test:
jobs:
- build # Runs first
- test-unit: # Runs after build
requires:
- build
- test-integration: # Runs in parallel with test-unit
requires:
- build
- deploy: # Runs after BOTH tests pass
requires:
- test-unit
- test-integration
Workflow topology
Fan-in / fan-out
workflows:
fan-out-fan-in:
jobs:
- checkout-code
- lint:
requires: [checkout-code]
- test-api:
requires: [checkout-code]
- test-web:
requires: [checkout-code]
- test-worker:
requires: [checkout-code]
- build-image:
requires: [lint, test-api, test-web, test-worker]
Workflow filters
Filters control which branches and tags trigger specific jobs.
workflows:
deploy-pipeline:
jobs:
- build:
filters:
branches:
only:
- main
- develop
- deploy-staging:
requires: [build]
filters:
branches:
only: develop
- deploy-production:
requires: [build]
filters:
branches:
only: main
- release:
filters:
tags:
only: /^v\d+\.\d+\.\d+$/
branches:
ignore: /.*/
Scheduled workflows
The legacy triggers syntax below still works but is deprecated. The recommended approach is scheduled pipelines, configured via the CircleCI UI or API under Project Settings → Triggers. Scheduled pipelines offer better actor control, dynamic config support, and single-schedule-to-multiple-workflows mapping.
# Legacy triggers syntax (still functional, but prefer scheduled pipelines)
workflows:
nightly-security-scan:
triggers:
- schedule:
cron: "0 2 * * *" # Every night at 2 AM UTC
filters:
branches:
only: main
jobs:
- security-scan
- dependency-audit
Manual approval jobs
workflows:
deploy-with-approval:
jobs:
- build
- test:
requires: [build]
- hold:
type: approval # Pauses workflow until approved in UI
requires: [test]
- deploy-production:
requires: [hold]
context: production-secrets
Workspaces: sharing data between jobs
Workspaces allow jobs within the same workflow to share files. Use persist_to_workspace in an upstream job and attach_workspace in a downstream job.
jobs:
build:
docker:
- image: cimg/node:20.11
steps:
- checkout
- run: npm ci && npm run build
- persist_to_workspace:
root: .
paths:
- dist
- node_modules
deploy:
docker:
- image: cimg/base:current
steps:
- attach_workspace:
at: ~/project
- run: ls ~/project/dist # Files from build job are here
Workspaces persist only within a single workflow run. They are not shared across workflows or pipeline runs. For data that persists across builds, use caches. For build outputs you want to download later, use artifacts.
Orbs
Orbs are reusable, shareable packages of CircleCI configuration. They encapsulate commands, jobs, and executors into a single importable unit. Orbs dramatically reduce config boilerplate and promote best practices across projects.
What orbs contain
Commands Reusable steps
Named sequences of steps that can be invoked within any job. Like functions for your CI config. Example: aws-cli/setup installs and configures the AWS CLI in a single step.
Jobs Complete job definitions
Pre-built jobs with executor, steps, and parameters. Example: docker/publish builds and pushes a Docker image in one job declaration.
Executors Runtime environments
Pre-configured executors with the right tools installed. Example: node/default provides a Node.js environment with the specified version.
Parameters Customization
Orbs accept parameters to customize behavior. Example: specify the Node.js version, Docker image tag, or deployment target without modifying the orb itself.
Using orbs
version: 2.1
orbs:
node: circleci/node@5.2 # Import the Node.js orb
aws-cli: circleci/aws-cli@4.1 # Import the AWS CLI orb
docker: circleci/docker@2.6 # Import the Docker orb
slack: circleci/slack@4.13 # Import the Slack orb
jobs:
build:
executor: node/default # Use orb's executor
steps:
- checkout
- node/install-packages # Use orb's command
- run: npm run build
workflows:
main:
jobs:
- build
- docker/publish: # Use orb's job directly
image: myorg/myapp
tag: ${CIRCLE_SHA1:0:7}
requires: [build]
Popular orbs
| Orb | Purpose | Key commands/jobs |
|---|---|---|
circleci/node | Node.js CI | install-packages, test |
circleci/docker | Docker build/push | build, publish, hadolint |
circleci/aws-cli | AWS CLI setup | setup (supports role_arn param for OIDC) |
circleci/kubernetes | K8s deployments | install-kubectl, create-or-update-resource |
circleci/terraform | Terraform CI/CD | init, plan, apply |
circleci/slack | Slack notifications | notify, on-hold |
circleci/codecov | Code coverage | upload |
Creating custom orbs
# Initialize a new orb project
circleci orb init my-orb
# Validate the orb source
circleci orb validate src/@orb.yml
# Pack the orb from source directory
circleci orb pack src/ > orb.yml
# Publish a development version
circleci orb publish orb.yml myorg/my-orb@dev:alpha
# Promote to a semantic version
circleci orb publish promote myorg/my-orb@dev:alpha patch
Orb versioning
- Semantic versioning —
myorg/my-orb@1.2.3. Pin to major (@1), minor (@1.2), or exact (@1.2.3). - Volatile (dev) —
myorg/my-orb@dev:alpha. Mutable, used during development. Expires after 90 days. - Private orbs — organization-scoped orbs not visible in the public registry. Available on paid plans.
Pin orbs to a major version (circleci/node@5) for stability with automatic minor/patch updates. For critical production pipelines, pin to the exact version (circleci/node@5.2.0). Always review orb changelogs before major version bumps.
Caching & Artifacts
CircleCI provides three mechanisms for persisting data: caches (across builds), workspaces (within a workflow), and artifacts (build outputs). Understanding when to use each is key to fast, efficient pipelines.
Caching dependencies
Caches persist between pipeline runs. Use them for dependencies that rarely change (node_modules, pip packages, Go modules). Cache keys support template variables for intelligent invalidation.
steps:
- restore_cache:
keys:
# Exact match first
- v1-deps-{{ checksum "package-lock.json" }}
# Fallback to most recent cache with this prefix
- v1-deps-
- run: npm ci
- save_cache:
key: v1-deps-{{ checksum "package-lock.json" }}
paths:
- node_modules
- ~/.npm
Common cache key templates:
{{ checksum "file" }}— SHA256 of a file (lockfile changes invalidate cache){{ .Branch }}— current branch name{{ .Revision }}— current git SHA{{ epoch }}— Unix timestamp (always unique, use for forced invalidation){{ .Environment.variableName }}— environment variable value
Docker layer caching (DLC)
Docker layer caching is a premium feature that caches Docker image layers between builds. When building images, unchanged layers are reused instead of rebuilt, saving significant time.
jobs:
build-image:
machine:
image: ubuntu-2404:current
docker_layer_caching: true # Enable DLC
steps:
- checkout
- run: docker build -t myapp:latest .
Artifacts
Artifacts are files produced by a job that you want to persist and access after the build. They are browsable in the CircleCI UI and downloadable via the API.
steps:
- run: npm run build
- run: npm test -- --coverage
- store_artifacts:
path: dist
destination: build-output
- store_artifacts:
path: coverage
destination: coverage-report
Test results
Use store_test_results to upload JUnit XML test results. CircleCI parses these for test insights, flaky test detection, and test splitting by timing data.
steps:
- run:
name: Run tests with JUnit reporter
command: |
JEST_JUNIT_OUTPUT_DIR=test-results \
npm test -- --ci --reporters=jest-junit
- store_test_results:
path: test-results
Comparison: cache vs workspace vs artifact
| Feature | Persists across | Use case | Expiry |
|---|---|---|---|
| Cache | Pipeline runs | Dependencies (node_modules, pip) | 15 days (unused) |
| Workspace | Jobs in a workflow | Build outputs for downstream jobs | Workflow lifetime |
| Artifact | Accessible after build | Binaries, reports, screenshots | 30 days |
| Test results | Accessible after build | JUnit XML for insights/splitting | 30 days |
Caches are best-effort — they may not exist (first run, expired, different branch). Always write your config to work without a cache hit. The restore_cache fallback key pattern (prefix match) ensures graceful degradation to the nearest available cache.
Secrets & Contexts
CircleCI provides several mechanisms for managing secrets: project-level environment variables, organization-level contexts, OIDC tokens for cloud authentication, and integrations with external secret managers.
Project environment variables
Set in the CircleCI UI under Project Settings → Environment Variables. Available to all jobs in the project. Values are masked in job output logs.
- Set via UI or API (e.g.,
POST /api/v2/project/{project-slug}/envvar) - Cannot be read back once set (write-only in UI)
- Available as standard environment variables in jobs
- Forked PRs do not receive project secrets (security measure)
Contexts
Contexts are organization-level groups of environment variables. They are shared across projects and assigned to jobs in workflows.
workflows:
deploy:
jobs:
- deploy-staging:
context: staging-secrets
- deploy-production:
context:
- production-secrets
- shared-aws-credentials
Context features:
- Security groups — restrict which teams/users can trigger jobs using a context
- Context expressions — conditional access based on branch, tag, or other attributes
- Audit trail — track which pipelines used which contexts
- Multiple contexts per job — compose secrets from multiple context groups
OIDC tokens
CircleCI OIDC provides short-lived tokens for authenticating with cloud providers (AWS, GCP, Azure) without storing long-lived credentials. The token contains claims about the pipeline (org_id, project_id, branch, etc.).
jobs:
deploy-to-aws:
docker:
- image: cimg/aws:2025.01
environment:
AWS_ROLE_ARN: arn:aws:iam::123456789012:role/circleci-deploy
steps:
- checkout
- run:
name: Authenticate with AWS via OIDC
command: |
# CircleCI provides $CIRCLE_OIDC_TOKEN automatically
aws sts assume-role-with-web-identity \
--role-arn $AWS_ROLE_ARN \
--role-session-name circleci-${CIRCLE_BUILD_NUM} \
--web-identity-token $CIRCLE_OIDC_TOKEN \
--duration-seconds 3600 > /tmp/creds.json
export AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' /tmp/creds.json)
export AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' /tmp/creds.json)
export AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' /tmp/creds.json)
aws s3 cp dist/ s3://my-bucket/ --recursive
HashiCorp Vault integration
jobs:
deploy:
docker:
- image: cimg/base:current
steps:
- checkout
- run:
name: Fetch secrets from Vault
command: |
# Authenticate to Vault using AppRole
VAULT_TOKEN=$(vault write -field=token auth/approle/login \
role_id=$VAULT_ROLE_ID \
secret_id=$VAULT_SECRET_ID)
export VAULT_TOKEN
# Read secrets
DB_PASSWORD=$(vault kv get -field=password secret/myapp/db)
API_KEY=$(vault kv get -field=key secret/myapp/api)
# Use secrets (never echo them)
./deploy.sh
Never echo or printenv secrets in CI jobs. CircleCI masks known environment variable values, but derived values (e.g., base64-encoded, concatenated) are not masked. Use contexts over project variables for shared secrets, and prefer OIDC tokens over stored credentials for cloud access. Rotate credentials regularly.
Parallelism & Performance
CircleCI provides several features to dramatically speed up your pipelines: test splitting with parallelism, resource classes, Docker layer caching, and pipeline optimization techniques.
Test splitting with parallelism
Set parallelism: N on a job to run N copies simultaneously. Use circleci tests split to distribute test files across containers.
jobs:
test:
docker:
- image: cimg/node:20.11
parallelism: 4 # Run 4 copies of this job
steps:
- checkout
- run: npm ci
- run:
name: Run tests (split by timing)
command: |
# Glob test files, split by historical timing data
TESTFILES=$(circleci tests glob "src/**/*.test.ts" \
| circleci tests split --split-by=timings)
echo "Running tests: $TESTFILES"
npx jest $TESTFILES --ci --reporters=jest-junit
- store_test_results:
path: test-results
Before and after: parallelism speedup
Before Serial execution
400 test files running sequentially in a single container.
Total test time: 24 minutes
Container 1: 400 tests (24 min)
After parallelism: 4
400 test files split across 4 containers by timing data.
Total test time: ~6 minutes
Container 1: 100 tests (6 min)
Container 2: 100 tests (6 min)
Container 3: 100 tests (5.8 min)
Container 4: 100 tests (5.9 min)
Resource classes
Resource classes control the CPU and RAM allocated to a job. Larger resource classes run faster but consume more credits. The table below shows Docker executor classes; Linux VM (machine) and macOS classes have different specs and credit rates.
| Resource class (Docker) | vCPUs | RAM | Credits/min |
|---|---|---|---|
small | 1 | 2 GB | 5 |
medium | 2 | 4 GB | 10 |
medium+ | 3 | 6 GB | 15 |
large | 4 | 8 GB | 20 |
xlarge | 8 | 16 GB | 40 |
2xlarge | 16 | 32 GB | 80 |
Docker layer caching
# Machine executor with DLC
jobs:
build-image:
machine:
image: ubuntu-2404:current
docker_layer_caching: true
steps:
- checkout
- run: |
docker build -t myapp:$CIRCLE_SHA1 .
# Second build reuses cached layers
# Typical savings: 2-10 minutes per build
Pipeline optimization
- Path filtering — use dynamic configuration to only run jobs for changed services in a monorepo
- Conditional steps — use
when/unlessconditions to skip unnecessary steps - Skip CI — add
[ci skip]or[skip ci]to commit messages to skip the pipeline entirely - Cache aggressively — cache dependencies, build tools, and intermediate build artifacts
- Right-size resources — use
smallfor linting,mediumfor builds,largefor compilation-heavy jobs
# Conditional steps example
steps:
- run:
name: Deploy (only on main)
command: ./deploy.sh
when: on_success
- when:
condition:
equal: [main, << pipeline.git.branch >>]
steps:
- run: echo "This only runs on main"
Start with parallelism: 4 and --split-by=timings. After a few runs, CircleCI collects timing data and splits become near-optimal. If your test suite still takes too long, increase parallelism. The sweet spot is when each container runs for roughly the same duration (check the Test Insights tab).
Integrations
CircleCI integrates with a wide range of tools and platforms across the software delivery lifecycle. Most integrations are available as orbs, making setup straightforward.
Git platforms
GitHub GitHub Integration
Two integration modes: OAuth App (legacy) and GitHub App (recommended). GitHub App provides fine-grained permissions, check run status, and better organization controls. Supports GitHub.com and GitHub Enterprise Server.
GitLab GitLab Integration
Supports GitLab SaaS and self-managed instances. Uses a GitLab webhook for triggering pipelines. Project setup connects a GitLab repo to a CircleCI project with a personal or project access token.
Bitbucket Bitbucket Integration
Supports Bitbucket Cloud and Bitbucket Data Center. Connects via OAuth (Cloud) or access token (Data Center). Triggers pipelines on push and pull request events. Build statuses reported back as commit statuses.
Cloud providers
| Provider | Auth method | Orb | Key features |
|---|---|---|---|
| AWS | OIDC, access keys | circleci/aws-cli | S3, ECR, ECS, Lambda, CloudFormation deploys |
| GCP | OIDC, service account key | circleci/gcp-cli | GCR, GKE, Cloud Run, Cloud Functions |
| Azure | Service principal | circleci/azure-cli | ACR, AKS, App Service, Azure Functions |
Container registries
# Build and push to multiple registries using the Docker orb
orbs:
docker: circleci/docker@2.6
workflows:
build-and-push:
jobs:
- docker/publish:
image: myorg/myapp
tag: ${CIRCLE_SHA1:0:7},latest
registry: docker.io # Docker Hub
- docker/publish:
image: myapp
tag: ${CIRCLE_SHA1:0:7}
registry: 123456789012.dkr.ecr.us-east-1.amazonaws.com # ECR
Notifications
# Slack notifications using the Slack orb
orbs:
slack: circleci/slack@4.13
jobs:
deploy:
docker:
- image: cimg/base:current
steps:
- run: ./deploy.sh
- slack/notify:
event: pass
template: success_tagged_deploy_1
- slack/notify:
event: fail
mentions: "@oncall-team"
template: basic_fail_1
Deployment targets
K8s Kubernetes
circleci/kubernetes orb for kubectl and Helm. Deploy manifests, Helm charts, and Kustomize overlays. Combine with OIDC for cluster auth.
ECS AWS ECS
circleci/aws-ecs orb for ECS service updates. Build image, push to ECR, update task definition, and roll out new service version.
PaaS Heroku / Vercel / Netlify
Dedicated orbs for each platform. One-step deployments: build and deploy to Heroku, Vercel preview/production, or Netlify sites.
Security Scanning
Snyk, SonarQube, and Trivy orbs for vulnerability scanning, code quality analysis, and container image scanning integrated directly into your pipeline.
CircleCI Server
CircleCI Server is the self-hosted version of the CircleCI platform. It runs on Kubernetes and provides the same features as CircleCI Cloud, but within your own infrastructure. Use it when you need air-gapped environments, data residency, or strict compliance controls.
When to use CircleCI Server
- Air-gapped environments — code and build artifacts never leave your network
- Data residency — ensure all CI/CD data stays in a specific geographic region
- Compliance — FedRAMP, ITAR, HIPAA, or other regulations requiring self-hosted infrastructure
- Network restrictions — builds need access to internal services not exposed to the internet
Architecture
CircleCI Server is deployed as a Kubernetes application via Helm. The major components are:
Frontend Frontend services
Web UI, API server, webhook handlers. Handles user authentication, project configuration, and pipeline triggering.
Execution Execution layer
Manages job execution on Kubernetes pods, machine VMs, or self-hosted runners. Schedules and monitors job containers.
Data Data services
PostgreSQL (metadata), MongoDB (legacy), Redis (queues), S3-compatible storage (artifacts, caches, workspaces), Vault (encryption).
Output Output processor
Handles build logs, test results, and artifact storage. Streams real-time output to the UI.
Installation
# Add the CircleCI Helm repository
helm repo add circleci https://circleci-public.github.io/server-helm
helm repo update
# Create a values file with your configuration
# (license, GitHub/GitLab connection, storage, TLS, etc.)
# Install CircleCI Server
helm install circleci-server circleci/circleci-server \
--namespace circleci-server \
--create-namespace \
--values values.yaml
# Check installation status
kubectl get pods -n circleci-server
Supported Kubernetes platforms
| Platform | Support level | Notes |
|---|---|---|
| Amazon EKS | Fully supported | Most common deployment target |
| Google GKE | Fully supported | Works with standard and Autopilot clusters |
| Azure AKS | Fully supported | Requires Azure Files or Azure Disks for storage |
| OpenShift | Supported | Requires SCC configuration for pods |
Differences from CircleCI Cloud
- You manage infrastructure — Kubernetes cluster, databases, object storage, TLS certificates
- You manage updates — Helm chart upgrades on your schedule (no automatic updates)
- License required — contact CircleCI sales for server licensing
- Feature parity gap — some cloud features may arrive on server with a delay
- Self-hosted runners — same runner agent works with both cloud and server
CircleCI Server requires significant operational investment. You need a dedicated Kubernetes cluster (recommended 8+ nodes), external PostgreSQL, S3-compatible storage, and a team familiar with Helm chart management. Evaluate whether CircleCI Cloud with self-hosted runners meets your compliance needs before committing to a full server deployment.
Security & Compliance
Securing your CI/CD pipeline is critical — it has access to source code, secrets, and production infrastructure. CircleCI provides multiple layers of security controls for pipelines, secrets, and organizational governance.
Pipeline security
Contexts Restricted contexts
Restrict sensitive contexts (production credentials) to specific security groups. Only authorized team members can trigger jobs that use restricted contexts. Prevents unauthorized deployments.
Approval Approval gates
Use type: approval jobs to require manual approval before production deployments. Combined with restricted contexts, this ensures human review before sensitive operations.
Branch Branch protection
Use workflow filters to restrict production deployments to specific branches (e.g., main). Combined with Git branch protection rules, this prevents unauthorized code from reaching production.
Forks Fork protection
CircleCI does not pass project secrets to jobs triggered by pull requests from forked repositories. This prevents malicious forks from exfiltrating credentials.
Runner security
Self-hosted runners keep sensitive code on your infrastructure. Code is checked out, built, and tested on machines you control. Build artifacts never leave your network. Ideal for regulated industries.
Audit logs
CircleCI provides organization-level audit logs (Scale plan and above) that track:
- Context creation, deletion, and variable changes
- Project settings modifications
- User additions and removals
- Pipeline triggers and approval actions
- SSH access to build containers
# Download audit logs via API
curl -H "Circle-Token: $CIRCLECI_TOKEN" \
"https://circleci.com/api/v2/organization/${ORG_ID}/audit-log?start-date=2026-03-01" \
| jq '.items[]'
Compliance certifications
| Certification | Platform | Details |
|---|---|---|
| SOC 2 Type II | Cloud | Annual audit covering security, availability, and confidentiality |
| FedRAMP | Cloud & Server | CircleCI Cloud is FedRAMP authorized (LI-SaaS); Server deployments inherit your infrastructure's compliance posture |
| Data retention | Cloud | Configurable artifact/log retention. Build data deleted after retention period |
Supply chain security
# Sign container images with Cosign in your pipeline
jobs:
sign-image:
docker:
- image: cimg/base:current
steps:
- run:
name: Sign image with Cosign
command: |
cosign sign --key env://COSIGN_PRIVATE_KEY \
myregistry.com/myapp:${CIRCLE_SHA1:0:7}
- run:
name: Generate SBOM
command: |
syft packages myregistry.com/myapp:${CIRCLE_SHA1:0:7} \
-o spdx-json > sbom.json
- store_artifacts:
path: sbom.json
Config policies
Organization-level config policies allow administrators to enforce standards across all projects. Policies are written in OPA (Open Policy Agent) Rego language.
# Example policy: require approval for production deploys
package org
import future.keywords
deny[msg] {
some job in input.workflows[_].jobs[_]
job[_].context[_] == "production-secrets"
not has_approval_before(input.workflows, job)
msg := "Production context requires an approval job"
}
Treat your CI/CD pipeline as a production system. An attacker who compromises your pipeline has access to your source code, secrets, and deployment credentials. Enable restricted contexts, use OIDC over stored credentials, require approval gates for production, and audit all changes to pipeline configuration.
Production Checklist
- Use config version 2.1 — enables orbs, reusable config, pipeline parameters, and all modern features. There is no reason to use older versions.
- Validate config before pushing — run
circleci config validatelocally. Add it to pre-commit hooks to catch YAML errors before they waste pipeline credits. - Use orbs for common tasks — don't reinvent AWS CLI setup, Docker build/push, or Slack notifications. Use official orbs and pin them to a major version.
- Use contexts for shared secrets — prefer organization-level contexts over project environment variables. Restrict sensitive contexts to security groups.
- Enable OIDC for cloud access — use CircleCI OIDC tokens instead of stored AWS/GCP/Azure credentials. Eliminates credential rotation burden.
- Enable test splitting with parallelism — for test suites over 5 minutes, enable
parallelismandcircleci tests split --split-by=timings. Upload JUnit XML viastore_test_resultsto feed timing data. - Cache dependencies aggressively — use
save_cache/restore_cachewith checksum-based keys for all dependency directories. Always include a fallback key prefix. - Right-size resource classes — use
smallfor linting,mediumfor standard builds,largeorxlargefor compilation-heavy jobs. Monitor credit usage and adjust. - Use approval gates for production — add
type: approvaljobs before production deployments. Combine with restricted contexts for defense in depth. - Use workflow filters — restrict production deploys to
mainbranch. Use tag filters for release workflows. Never deploy from feature branches. - Enable Docker layer caching — if you build Docker images, enable DLC to save 2-10 minutes per build. Worth the premium cost for frequent builders.
- Store test results — always upload JUnit XML with
store_test_results. Enables test insights, flaky test detection, and timing-based test splitting. - Use dynamic config for monorepos — set up dynamic configuration with path filtering to only build changed services. Saves significant credits and time.
- Set up notifications — use the Slack orb to notify on failures and deployment events. Ensure the team knows when builds break or deploys complete.
- Enable config policies — for organizations with multiple teams, use config policies to enforce standards (approval gates, context restrictions, resource class limits).
- Audit and rotate secrets — review context and project environment variables quarterly. Remove unused secrets. Rotate credentials on a regular schedule.