# Jenkins Configuration as Code Plugin (JCasC): declarative Jenkins config from a YAML file

> JCasC replaces clicking through the Jenkins manage UI with a YAML file that the plugin reads at startup. It suits teams that already treat Jenkins as an artifact to rebuild, and it fails loudly when two config files disagree.

**jenkinsci/configuration-as-code-plugin** — Jenkins Configuration as Code Plugin

- Repository: https://github.com/jenkinsci/configuration-as-code-plugin
- Website: https://plugins.jenkins.io/configuration-as-code
- Stars: 2,791 · Forks: 757
- Language: Java
- License: MIT
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/jenkinsci-configuration-as-code-plugin

## What JCasC replaces, and who feels the pain

Jenkins configuration lives in the web UI under Manage, spread across dozens of screens, and it is stored in XML files under the Jenkins home directory. The README describes the situation plainly: setting up Jenkins is complex because both the core and its plugins require tuning, with dozens of parameters to set inside the manage section. Two workarounds existed before this plugin. One is clicking through the UI on every rebuild. The other is Groovy init scripts, which the README notes can do everything at your own risk, but require knowing Jenkins internals and being confident writing Groovy against the Jenkins API.

JCasC takes a third position. It calls itself an opinionated way to configure Jenkins from human-readable declarative configuration files, and the stated goal is that writing such a file should be feasible without being a Jenkins expert, because you are translating a configuration process you already perform in the UI into code. That framing matters for who this is for. It is not aimed at people who have never run Jenkins. It is aimed at people who know what they want Jenkins to look like and are tired of producing that state by hand. If your Jenkins is a long-lived pet server that one person tuned over five years, JCasC does not retroactively describe it. You have to write the file yourself, or export one first.

## How the plugin maps YAML onto Jenkins objects

The configuration file is organized by root element, and each root maps to a part of the Jenkins model. The README's example shows a jenkins root for the Jenkins object itself, plus separate roots for tool, credentials and other global configuration elements. Inside jenkins you can set systemMessage, globalNodeProperties, securityRealm, nodes and slaveAgentPort. The tool root holds installations such as git with a name and a home path. The credentials root holds a system block with domainCredentials, and inside that a list of credential entries such as basicSSHUserPrivateKey with scope, id, username, passphrase, description and a privateKeySource.

The plugin reads these files and binds the values onto the corresponding Jenkins objects. The README points to a JSON schema for validating configurations and a merge strategy document, which tells you the binding is not a blind overwrite of everything: there is a defined merge behaviour, documented separately. Variable interpolation runs across all configuration blocks. JCasC treats ${VAR} as an interpolation expression everywhere, and if you need a literal ${...} string you must escape it as ^${VAR}. That escaping rule is easy to forget and it applies to any value, not just secrets, which is a real source of surprise when a job name or a message happens to contain that pattern.

## Installing the plugin and running your first config file

There is no separate binary. JCasC is a Jenkins plugin, so the install path is the plugin manager or an image that already contains it. The README's Getting Started section says to start a Jenkins instance with the Configuration as Code plugin installed, and notes that those running Jenkins as a Docker container should include the plugin, possibly through the pre-installing plugins mechanism described in the jenkinsci/docker repository.

Once the plugin is present, it looks for the CASC_JENKINS_CONFIG environment variable. That variable is a comma-separated list, and each element can be a folder, a local file path or URI, or an HTTP or HTTPS URL.

```yaml
jenkins:
  systemMessage: "Jenkins configured automatically by Jenkins Configuration as Code plugin\n\n"
```

If an element points to a folder, the plugin traverses it recursively and picks up files ending in .yml, .yaml, .YAML or .YML. After Jenkins restarts with a file like the one above in place, the system message on the dashboard should read as configured. If you cannot set an environment variable because a package manager owns the startup file, the README offers the casc.jenkins.config Java property instead, and gives the RHEL/CentOS example of appending the following to the JENKINS_JAVA_OPTIONS entry in /etc/sysconfig/jenkins:

```bash
-Dcasc.jenkins.config=/jenkins/casc_configs
```

The README also notes a default location when neither is set, so the plugin does have a fallback path if you configure nothing.

## The supplementary-files rule is the sharpest edge

The README is explicit that all discovered configuration files must be supplementary and cannot overwrite each other's configuration values. A conflict raises a ConfiguratorException. Because of that rule, the order in which the folder is traversed does not affect the outcome, which is a deliberate design choice: the plugin refuses to guess a winner rather than applying files in some order and hoping you remember it.

In practice this changes how you split configuration. Splitting by concern works: one file for the security realm, one for credentials, one for agent definitions. Splitting by environment does not, if both files set the same key. A base file plus an override file is a pattern people reach for, and it is exactly the pattern this rule rejects. The failure mode is also blunt: the load fails rather than silently applying a partial configuration, which is safer but means a single duplicated key can block startup until you find it. The README does not document rollback for a failed load, so plan for a way to get back to a working configuration before you push a change.

## Where JCasC is the wrong tool

JCasC configures the Jenkins controller and the global configuration of supported plugins. It is not a job definition format, and it is not a replacement for pipeline definitions or for a job DSL. If your problem is that job definitions are inconsistent, this plugin is not the answer.

A second boundary is plugin coverage. The README maintains a Supported Plugins list and a separate section on adding JCasC support to a plugin, which tells you support is per-plugin and has to be implemented. A plugin that has no data-bound configurator cannot be configured from YAML, and its settings will keep living in the UI. The README also carries a Security considerations section, which is worth reading before you put credentials in a file, since the whole point of JCasC is that the configuration, including secrets, becomes text that moves through your repository and CI system. The README's own example uses ${SSH_KEY_PASSWORD} and ${SSH_PRIVATE_KEY} rather than literal values, and the secrets document is where the handling rules live. Finally, if your Jenkins changes several times a day through the UI by many people, converting it to a file that is applied at startup is a workflow change, not just a plugin install, and it will not stick until the UI habit stops.

## JCasC versus Groovy init scripts and Ansible

The most direct alternative is the Groovy init script approach that JCasC was written to replace. A Groovy script calls the Jenkins API directly and can do anything, including things JCasC has no binding for. The trade-off is the one the README states: you need to know Jenkins internals and be confident writing Groovy on top of the API. JCasC trades that power for a declarative file that a Jenkins user can read without knowing the API. If you need to do something no configurator exposes, Groovy remains the escape hatch, and the two can coexist.

Ansible is a different kind of alternative, and it appears in the related searches as a comparison people make. Ansible configures the machine around Jenkins: packages, files, services, environment variables. It does not understand the Jenkins object model, so it cannot set a security realm or define a credential through the Jenkins API. The two compose naturally, since CASC_JENKINS_CONFIG is an environment variable that Ansible can set and the config files are just files Ansible can template. Choosing between them is a category error; the real question is whether you also need something to manage the host.

## Maintenance, releases and licence

The repository is not archived and the last push was on 2026-09-14, with releases on 2026-08-30, 2026-08-10 and 2026-08-07. That release cadence is a signal about upgrade cost: the version strings follow the Jenkins plugin convention with a long hash suffix, so each release is a plugin update through the normal Jenkins plugin manager rather than something you pin in a lockfile you control. The practical cost is that a Jenkins upgrade and a JCasC upgrade arrive together, and a plugin update can change which configurators exist.

The licence is MIT. That is permissive and places few obligations on how you redistribute or modify the plugin. It says nothing about the configuration files you write, which are yours, and it says nothing about the secrets you place in them. Nothing here is legal advice; if you are redistributing a Jenkins image with this plugin baked in, check the licence file in the repository rather than relying on this summary.

## Conclusion

Adopt JCasC if Jenkins is something you rebuild from a repository and you want security realms, credentials, agents and tool installations to live in reviewable YAML. Do not adopt it if your Jenkins has been hand-tuned for years and nobody can reconstruct what the UI currently holds: the plugin applies configuration, it does not discover and rewrite your existing state for you. Before rolling it out, verify three things on a throwaway instance: that every plugin you rely on has a data-bound configurator, that no two files under CASC_JENKINS_CONFIG set the same value, and that every ${VAR} in your YAML is actually present in the environment, because an unresolved one fails the load rather than passing through.

## FAQ

### How can I configure Jenkins as code with the Jenkins Configuration as Code plugin?

Install the plugin, then point the CASC_JENKINS_CONFIG environment variable at a folder, file or URL containing YAML. The plugin reads the files and binds the values onto the corresponding Jenkins objects.

### How do I add plugins to Jenkins when using JCasC?

JCasC configures plugins, it does not install them. The README's Getting Started section points Docker users at the pre-installing plugins mechanism in the jenkinsci/docker repository, and the plugin itself is installed through the normal Jenkins plugin manager.

### Does JCasC use port 8080?

Port 8080 is the Jenkins web UI port, not something JCasC configures. The port JCasC exposes in its own example is slaveAgentPort, set to 50000 for agent connections.

## Sources

- [jenkinsci/configuration-as-code-plugin on GitHub](https://github.com/jenkinsci/configuration-as-code-plugin)
- [License: MIT](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/LICENSE)
- [Project website](https://plugins.jenkins.io/configuration-as-code)
- [README](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/README.md)
- [Releases](https://github.com/jenkinsci/configuration-as-code-plugin/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jenkinsci-configuration-as-code-plugin
