# ansible-role-jenkins: a packaged Jenkins install for RHEL and Debian servers

> The geerlingguy Ansible role for Jenkins installs the CI server from the official package repositories on RHEL, CentOS, Debian and Ubuntu, and wires plugins, ports, proxy settings and systemd options through a documented set of variables. It suits teams standardising on Ansible who want a repeatable Jenkins box, and it is a poor fit if you need a containerised or configuration as code Jenkins.

**geerlingguy/ansible-role-jenkins** — Ansible Role - Jenkins CI

- Repository: https://github.com/geerlingguy/ansible-role-jenkins
- Website: https://galaxy.ansible.com/geerlingguy/jenkins/
- Stars: 850 · Forks: 756
- Language: Groovy
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/geerlingguy-ansible-role-jenkins

## One role, two package ecosystems, no configuration management of its own

The role is described in a single line: it installs Jenkins CI on RHEL and CentOS and on Debian and Ubuntu servers.

That is the whole contract, and it is a deliberately narrow one. What you get is a server with Jenkins installed from the official package repositories, configured, running and reachable, with a set of plugins installed and a few operational knobs set. What you do not get is a way to describe your pipelines, folders or credentials as code.

The audience is a platform or infrastructure team that already lives in Ansible and wants the CI server to be a provisioned artifact rather than a machine somebody set up by hand. The homepage points at the Ansible Galaxy listing, so the role is distributed the way Ansible roles are normally distributed.

The repository layout is the standard Ansible role skeleton, with tasks, defaults, handlers, meta, vars and templates directories, plus a molecule directory for testing. The test playbooks inside molecule/default are worth knowing about even if you never run them, because the README points there as the place to see how to use a newer version of Java for your operating system, which is the requirement most likely to bite you on a distribution that ships an old JRE.

The project is MIT licensed, carries an ansible-lint configuration and a yamllint configuration, and has a CI badge, so the role is linted and tested in its own pipeline rather than maintained by hand.

## present by default, and latest only if you ask for it

The first variable decides whether the server stays put or moves forward.

```yaml
jenkins_package_state: present
jenkins_hostname: localhost
jenkins_home: /var/lib/jenkins
jenkins_http_port: 8080
```

By default the role installs Jenkins but will not upgrade Jenkins when using package based installs. If you want to always update to the latest version, the documentation says to change the state to latest.

That default is a deliberate choice and it is the right one for a CI server. A Jenkins upgrade can change behaviour, plugin compatibility and the initial setup wizard, and having those changes arrive as a side effect of an unrelated Ansible run is how CI outages happen. Pinning to present and upgrading deliberately is the behaviour most teams want.

The same reasoning runs through the plugin variables. jenkins_plugins_state defaults to present, and the documentation notes that for any plugin which has a specific version set in the jenkins_plugins list, the state present is used instead of the jenkins_plugins_state value. So you can set the global state to latest for unpinned plugins while keeping a specific version for the one plugin where the version matters.

That is a small but useful detail. It means a single variable can express a policy of tracking latest for most plugins while pinning the one that breaks, without needing per plugin conditionals in your own playbook.

## The admin account is created with a password you must remember to change

The role creates the initial administrator account itself, and the defaults are visible in the variables list.

```yaml
jenkins_admin_username: admin
jenkins_admin_password: admin
```

These are described as the default admin account credentials which will be created the first time Jenkins is installed. There is also a jenkins_admin_password_file variable, defaulting to an empty string, which names a password file created at /var/lib/jenkins/secrets/initialAdminPassword.

The mechanism is worth understanding. The role disables the Jenkins 2.0 setup wizard by default through the Java option -Djenkins.install.runSetupWizard=false, which is what allows it to create the account unattended. That is the whole reason the credential variables exist, and it is also the reason they are dangerous if left alone.

A CI server reachable on a network port with a known default administrator password is a serious exposure, and this role will install exactly that if you do not override the defaults. Setting jenkins_admin_password, or using the password file variant, is not an optional hardening step, it is part of using the role correctly.

The related network defaults are worth a look at the same time. The web interface listens on 8080, and the role can set a URL prefix so that Jenkins is served from a path such as /jenkins rather than the root, which is what you want when something else already owns the front of the domain.

## Plugin lists accept pinned versions, and the update centre is cached

Plugins are declared as a list, and the format accepts either a bare name or a dictionary.

```yaml
jenkins_plugins:
  - blueocean
  - name: influxdb
    version: "1.12.1"
```

Items can use name or a dictionary with name and version keys to pin a specific version of a plugin. A second variable, jenkins_plugins_install_dependencies, defaults to true and decides whether installing a plugin should also install its plugin dependencies.

The update centre itself is treated as a cache. jenkins_plugin_updates_expiration is the number of seconds after which a new copy of update-center.json is downloaded, with a default of 86400, one day, and setting it to 0 means no cache file is used. The URL it comes from is jenkins_updates_url, defaulting to https://updates.jenkins.io.

These two variables together are the interesting part. A cached update centre means faster, more repeatable plugin resolution, but it also means the metadata the role acts on can be a day old. In an air gapped or bandwidth constrained environment, caching the update centre is what makes plugin installation practical at all, because otherwise every run has to fetch it.

There is also jenkins_plugin_timeout, the server connection timeout in seconds when installing Jenkins plugins, defaulting to 30, which is the setting to raise if your installation sits behind a slow link and plugins time out mid-run.

## Version pinning works only if the repository carries that version

By default the role installs the latest version of Jenkins using the official repositories for the platform. Two variables control the source, and they are easy to misread.

```yaml
jenkins_version: "2.346"
jenkins_pkg_url: "http://www.example.com"
```

The documentation says the Jenkins version can be pinned to any version available on the Debian and Ubuntu package URL or on the RHEL and CentOS package URL, and that if the version you need is not available at the default package URLs you can override the URL with your own. There is a note that the role depends on the same naming convention that the package URLs use, which is the detail that bites people: the pinned version has to exist under the expected name in whichever repository you point at, so a custom internal mirror has to reproduce the upstream layout exactly.

There is a second switch worth understanding because its description reads oddly. jenkins_prefer_lts defaults to false, and the documentation says you can install the current LTS version instead by setting it to false. The variable name says prefer LTS while the text describes setting it to false to get the LTS, which is a contradiction in the documentation itself. The repository URLs are what settle it: each one appends a -stable suffix when the variable is true.

```yaml
jenkins_repo_url: https://pkg.jenkins.io/redhat{{ '-stable' if (jenkins_prefer_lts | bool) else '' }}/jenkins.repo
```

So the stable repository is selected when the flag is true, and you should verify which behaviour you get on the version of the role you pin before assuming you have the LTS line.

## systemd override.conf is the extension point for everything else

Anything that is not a package, a plugin or a repository is expressed as a change to the systemd override file, and the role exposes that as a structured list.

```yaml
jenkins_init_changes:
  - option: "JENKINS_OPTS"
    value: "{{ jenkins_options }}"
  - option: "JAVA_OPTS"
    value: "{{ jenkins_java_options }}"
  - option: "JENKINS_HOME"
    value: "{{ jenkins_home }}"
  - option: "JENKINS_PREFIX"
    value: "{{ jenkins_url_prefix }}"
  - option: "JENKINS_PORT"
    value: "{{ jenkins_http_port }}"
```

The default set of changes sets the configured URL prefix, the Jenkins home directory and the Jenkins port, and adds the configured Jenkins and Java options. You can add other option and value pairs if you need to set other options in the same file, so the mechanism is a generic list rather than a fixed set of switches.

Two of those feed variables you will actually use. jenkins_options passes extra options to Jenkins on startup through JENKINS_OPTS, and the documentation gives the HTTP keep alive timeout as an example. jenkins_java_options does the same for JENKINS_JAVA_OPTS, with the timezone example -Dorg.apache.commons.jelly.tags.fmt.timeZone=America/New_York, and by default carries the option that disables the setup wizard.

Behind a reverse proxy, jenkins_proxy_host, jenkins_proxy_port and jenkins_proxy_noproxy configure the proxy settings, with 127.0.0.1 and localhost in the no-proxy list by default. The documentation is clear that without these Jenkins is configured for a direct internet connection, which is the failure mode you get when a proxied Jenkins cannot reach the update centre.

## The role waits for Jenkins to answer before it declares success

Ansible tasks that start a service and immediately assert it works tend to be flaky, and this role handles that with two variables.

```yaml
jenkins_connection_delay: 5
jenkins_connection_retries: 60
```

The amount of time and number of times to wait when connecting to Jenkins after initial startup, to verify that Jenkins is running. The total time to wait is delay times retries, so the default is 300 seconds before timing out.

Five minutes of patience is not excessive for a first start, because a cold Jenkins has to start the JVM, load the plugin set, initialise the home directory and then open its HTTP port, and a role with a large plugin list can take a while to reach a state where it answers requests.

The other side of the same behaviour is the restart method. jenkins_restart_method defaults to service, and the documentation says you can change it to safe-restart if you want. The distinction matters when the role has to restart Jenkins after a configuration change: a service restart is fast and blunt, while a safe restart drains running builds first, which is what you want if the role is applied to a controller that is in the middle of a build.

Taken together with the handlers directory in the repository, the restart handling is the part of the role that decides whether an Ansible run can interrupt a running pipeline, and it is worth setting deliberately rather than inheriting the default.

## Conclusion

This role suits a platform team that provisions Jenkins servers with Ansible and wants one reviewed set of variables for the package source, the plugin list, the admin credentials and the systemd overrides, since the role does exactly that and nothing more. It does not suit a team that wants Jenkins in a container, or one that expects the role to manage the configuration of running jobs, because it provisions the service and its plugins and stops there. Before you use it in production, change jenkins_admin_password from its default of admin, decide explicitly whether jenkins_package_state should be present or latest, and check the Jenkins version you are pinning against the repository URLs, since the role installs the latest version by default and the last push to the repository was on 2026-09-08.

## FAQ

### What platforms does the geerlingguy Jenkins Ansible role support?

The role installs Jenkins CI on RHEL and CentOS and on Debian and Ubuntu servers, using the official package repositories for each platform family. The repository URLs can be overridden if you run an internal mirror.

### What are the requirements for installing Jenkins with this role?

The README states that curl must be installed on the server, and that newer versions of Jenkins require Java 8 or later. It points at the test playbooks in the molecule/default directory as an example of using a newer Java version for your operating system.

### How do I stop the role from upgrading Jenkins on every run?

The default jenkins_package_state of present installs Jenkins without upgrading it when using package based installs. Setting it to latest makes the role always update to the latest version.

### Can I pin a specific Jenkins plugin version?

Yes. The jenkins_plugins list accepts either a bare plugin name or a dictionary with name and version keys, and a plugin with an explicit version keeps the present state even if jenkins_plugins_state is set to latest.

### How do I configure Jenkins to run behind a proxy?

Set jenkins_proxy_host, jenkins_proxy_port and jenkins_proxy_noproxy. The documentation notes that without those settings Jenkins is configured with a direct internet connection, and 127.0.0.1 and localhost are in the default no-proxy list.

## Sources

- [geerlingguy/ansible-role-jenkins on GitHub](https://github.com/geerlingguy/ansible-role-jenkins)
- [Issues](https://github.com/geerlingguy/ansible-role-jenkins/issues)
- [License: MIT](https://github.com/geerlingguy/ansible-role-jenkins/blob/master/LICENSE)
- [Project website](https://galaxy.ansible.com/geerlingguy/jenkins/)
- [README](https://github.com/geerlingguy/ansible-role-jenkins/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/geerlingguy-ansible-role-jenkins
