Jenkins Configuration as Code: Reproducible Controller Setup in YAML
Learn how to declare a Jenkins controller’s system settings, plugins, security, and seed jobs in a single YAML file, reduce drift, and recover quickly.
17 May 2026, 00:13 UTC

When you spin up a new Jenkins controller, the usual approach is to click through the web UI, install plugins, create an admin account, and seed jobs. That manual process introduces drift between dev, test, and production, and makes disaster recovery a guessing game.
Jenkins Configuration as Code (JCasC) – A Quick Overview
JCasC is a plugin that loads a declarative YAML file at startup and applies system‑wide settings. It covers controller‑level concerns: global properties, installed plugins, security realms, authorization strategies, credentials providers, and seed jobs. It does not replace job authoring; for that you still need Job DSL or Pipeline shared libraries.
Building a Minimal jenkins.yaml
Place the file at $JENKINS_HOME/jenkins.yaml. The Jenkins process must have write permission to that directory, and an administrator must be able to restart the service. A syntax error will prevent the controller from starting, so validate the YAML before deploying.
# $JENKINS_HOME/jenkins.yaml
jenkins:
systemMessage: 'Managed by JCasC'
numExecutors: 2
scmCheckoutRetryCount: 2
unclassified:
location:
url: 'https://jenkins.example.com/'
securityRealm:
local:
allowsSignup: false
users:
- id: 'admin-user'
password: '$2y$10$...' # placeholder for a hashed password
authorizationStrategy:
loggedInUsersCanDoAnything:
allowAnonymousRead: false
credentials:
system:
domainCredentials:
- credentials:
- usernamePassword:
id: 'github-app'
username: 'app-user'
password: '<GITHUB_APP_TOKEN>'
plugins:
installed:
- artifactId: 'configuration-as-code'
version: '1.47'
- artifactId: 'github-branch-source'
version: '1720.v115_a_8553336'
jobs:
- script: |
pipelineJob('example-pipeline') {
definition {
cpsScm {
scm {
git {
remote { url('https://github.com/org/repo.git') }
}
}
scriptPath('Jenkinsfile')
}
}
}
In the example above, the jobs section creates a seed job that pulls a Pipeline from a Git repository. The job definition is written in Groovy DSL and stored in the YAML, making it version‑controlled alongside the controller settings.
Operational Verification After Restart
Restart Jenkins (e.g.,
systemctl restart jenkinson Linux). The Configuration as Code plugin will read the YAML on startup.Navigate to Manage Jenkins > System Configuration and confirm that the system message, executor count, and location URL match the YAML.
Open Manage Jenkins > Plugin Manager and verify that the plugin list matches the
plugins.installedsection. The logs in Manage Jenkins > System Log > Configuration as Code will show any missing or mismatched plugin versions.Use the REST API to list jobs:
curl -s https://jenkins.example.com/api/json?tree=jobs[name,type]and compare the output with the expected job names defined in the YAML.
Trade‑offs and Caveats
JCasC does not automatically rotate credentials. Store secrets in an external vault and reference them via the credentials provider.
Plugin version mismatches between the YAML and the runtime can cause startup failures. Pin exact versions and test upgrades on a non‑production controller first.
Changing the security realm can lock administrators out. Keep a local admin fallback account and validate the YAML before restarting.
Legacy plugins with complex configuration may not be fully supported by JCasC. In such cases, combine JCasC with Job DSL or shared libraries for full job definitions.
Actionable Takeaway
Treat the Jenkins controller as infrastructure. Store a single jenkins.yaml in source control, run jenkins-cli.jar or a Docker image that starts Jenkins with that file, and rely on the Configuration as Code plugin to bootstrap every environment. This approach eliminates manual drift, speeds disaster recovery, and makes the controller itself a first‑class citizen in your CI/CD pipeline.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.