Chapter 26Lesson 01~150 minutes

Jenkins Configuration as Code, YAML Bundles, Secrets, Reloading, Validation, and Git-Managed Controller State: Concepts, Architecture, and Mental Model

Jenkins Configuration as Code (JCasC) turns controller settings into reviewable YAML, but reproducibility only exists when plugin prerequisites, secret sources, reload behavior, Git identity, live state and recovery artifacts remain separate and observable. Build that mental model before changing the controller.

JCasCYAMLController stateSecretsValidationDrift

Learning objectives

  • Explain what JCasC owns and what remains outside it.
  • Trace versioned YAML and secret references through configurator validation into live controller state.
  • Separate plugin binaries, JENKINS_HOME, Git source, secrets and exported evidence.
  • Use read-only inspection before a reload or restart.
  • Define a drift-and-recovery model that makes controller configuration reproducible.

1. The practical problem: UI configuration is easy to change and hard to reproduce

A Jenkins controller accumulates global settings: security realm, authorization, node defaults, clouds, tool configuration, credentials providers, system messages and plugin-specific settings. If those settings exist only as clicks in the UI, a second controller or disaster-recovery rebuild depends on memory, screenshots and undocumented ordering.

JCasC moves supported controller configuration into human-readable YAML that can be code-reviewed. That does not make all Jenkins state declarative. Plugins still have to be installed separately; jobs/build records remain separate; secrets require a protected source; some plugin data is not portable; and a running controller can drift after manual UI edits until configuration is reapplied.

2. Mental model: source → schema → apply → evidence → recovery

The causal chain is: versioned JCasC YAML plus secret references → installed plugin/configurator schema → validation → controller startup/reload → live runtime settings → export/drift evidence → Git rollback and, when needed, a JENKINS_HOME snapshot.

Mental model: source → schema → apply → evidence → recovery
flowchart TD
A[Git commit: JCasC YAML] --> B[Secret references]
B --> C[Installed plugins + configurator schema]
C --> D[Parse / resolve / validate]
D --> E[Startup or administrative reload]
E --> F[Live controller configuration]
F --> G[Export + read-only inspection]
G --> H[Drift comparison]
H --> I[Revert commit / restore snapshot]
I --> D

YAML → schema: a key is meaningful only if Jenkins core or an installed plugin contributes the matching configurator. Secret reference → resolution: the placeholder is committed, but the value comes from a protected source at apply time. Validation → apply: YAML syntax success is not enough; JCasC must resolve configurators and types. Apply → live state: reload changes controller-global state without recreating builds/workspaces. Live state → evidence: export, logs and UI inspection are observations, not automatically the canonical source. Recovery: Git handles desired configuration; snapshots still protect controller data that JCasC does not own.

3. State that must remain distinct

Layer Examples Evidence
Controller/runtime Jenkins 2.568.3, Java 21, JENKINS_HOME startup log, About/System Information, image digest
Plugin/configurator JCasC 2121…, Credentials 1511…, plugin-specific schemas Installed plugins + JCasC reference
Desired configuration YAML files and CASC_JENKINS_CONFIG Git commit, file SHA-256, source path
Secret source file/Docker/Kubernetes/Vault/env resolver source type/path/owner; never the secret value
Live configuration system message, security realm, global settings UI/API/export after apply
Job/build item XML, build number, Pipeline CPS state job/build URL, source SHA, run logs
Agent/workspace node process and workspace files node/label/path/tool evidence
Recovery accepted Git commit plus controller snapshot restore drill and verification record

Changing a JCasC system message does not alter a running agent workspace. Installing a new plugin is not a JCasC reload. Restoring YAML cannot recreate lost build history. Keep those boundaries explicit.

4. How JCasC finds configuration

The plugin reads CASC_JENKINS_CONFIG or the equivalent Java system property. A source may be a local file, directory, file URI, HTTP/HTTPS URL, or comma-separated set. If the source is a directory, JCasC recursively discovers YAML files.

No implicit precedence. Discovered files must be supplementary. If two files attempt to define the same configuration value, JCasC can reject the set with a ConfiguratorException. Do not design “base.yaml + override.yaml” around traversal order.

5. Plugin installation is a prerequisite, not JCasC content

JCasC configures objects exposed by Jenkins core and installed plugins. It does not install those plugins. A reproducible controller therefore needs two versioned inputs: a plugin manifest/controller image and a JCasC repository. Upgrade the plugin set in a tested candidate first, validate the candidate schema against the YAML, then promote the pair.

If YAML refers to a plugin setting that is missing or renamed, the failure belongs to the controller/plugin/configurator layer—not the queue or agent layer.

6. Secret placeholders and strict resolution

JCasC supports SecretSource resolution. The source code should contain a placeholder such as ${lab_admin_password}, while the value is injected from a file-backed secret, external provider or other protected resolver. Environment variables can also resolve values, but they are broadly observable in many runtimes and are not the preferred home for long-lived secrets.

Enable CASC_STRICT_SECRET_RESOLUTION=true for governed environments. Without strict resolution, an unresolved variable can become an empty string with a warning; strict mode aborts the reload when a required secret is missing, leaving the prior working configuration in place.

7. Read-only inspection before mutation

Before any reload, record the controller and the exact source identity. Do not dump the whole container environment after secrets are injected.

# Safe host-side inspection of non-secret identities only
sha256sum jcasc/*.yaml
git rev-parse HEAD
docker image inspect jenkins/jenkins:2.568.3-lts-jdk21 \
  --format '{{json .RepoDigests}}'

# On the controller UI:
# Manage Jenkins → Plugins → Installed
# Manage Jenkins → Configuration as Code
# Record JCasC plugin version, configured source, and last-load evidence.

Also inspect the instance-specific JCasC reference/documentation. That reference is generated from the installed controller/plugin set, which is exactly why a YAML file must be tested against the target baseline rather than an abstract example.

8. Validation has layers

Gate What it catches What it cannot prove
YAML parser/linter indentation and syntax Jenkins configurator names/types
Instance reference/schema available configurators and many types all runtime side effects; JSON schema is still beta
JCasC check/apply on clone source conflicts, secret resolution, plugin model every downstream job/external integration
Clean restart test startup initialization and plugin/config coherence production traffic behavior
Representative smoke tests critical Jenkins paths after change unknown/unexercised workflows

9. Reload is an administrative state change; restart is a runtime boundary

Current JCasC supports controlled reload from the UI, authenticated endpoint and Jenkins CLI. The reload action is privileged because it can change global security and controller behavior. Do not expose a reload token casually or call reload from a normal Pipeline; upstream documentation specifically discourages the Groovy/Pipeline shortcut.

Reload is appropriate when the installed configurators support the desired change and no plugin/core/Java lifecycle change is involved. Restart is the stronger boundary when plugins or runtime changed, when startup itself must be tested, or when the rollback plan depends on a clean initialization.

10. Export, drift and Git identity

The export feature is valuable evidence: it shows what the current controller can serialize. It is not automatically a clean replacement for the authored repository. Exports may include defaults, plugin-version-specific structure and encrypted values bound to the current controller secret key. Review and normalize rather than committing exports blindly.

Drift is the difference between approved source and live controller state. A manual UI edit to a JCasC-owned field can create temporary drift; a controlled reload/startup should reconcile it. Record both the drift observation and the Git commit that reasserted state.

11. Common wrong approaches

  • Commit literal passwords/tokens into YAML because “the repository is private.”
  • Use a mutable remote YAML URL with no commit/digest evidence.
  • Assume JCasC installs missing plugins.
  • Split the same attribute across files and expect last-file-wins.
  • Treat “reload returned 200” as proof every job and external integration still works.
  • Delete JENKINS_HOME when a YAML key fails instead of preserving the first error.
  • Allow application developers to edit admin-equivalent configuration without protected review.
Next lesson

Guided Hands-On Workflow and Core Operations

Create a disposable controller from a pinned plugin image, Git-managed YAML and file-backed fake secret, then prove reload, drift and reconciliation with observable evidence.

Knowledge check

Answer before revealing the explanation.

1. Why does JCasC not replace plugin management?

2. What does CASC_JENKINS_CONFIG identify?

3. Why must multiple JCasC files be supplementary?

4. Why is a JCasC export evidence rather than automatically the canonical source file?

5. What does strict secret resolution change?

Official references and version notes

Verified baseline — 17 September 2026. Labs use Jenkins 2.568.3 LTS with Java 21; Jenkins 2.568.3 is tested with Java 21 and 25. Configuration as Code is 2121.v86fe99d4b_b_a_b_, released 30 August 2026 and requiring Jenkins 2.541.1. Credentials is 1511.v2e3cb_0008ef0, also requiring Jenkins 2.541.1. The disposable image starts from jenkins/jenkins:2.568.3-lts-jdk21; record its platform-specific image digest before execution. Re-check versions, security advisories and configurator reference output before reusing the lab because plugin schemas can change independently of Jenkins core.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.