HOWTO – Bootstrap Jenkins Controller on Control Node (ctrl-01)¶
Bring the control node (ctrl-01) up to a healthy Jenkins controller using Ansible roles,
a Docker Engine baseline, and JCasC. At the end of this HOWTO, ctrl-01 runs a controller
in Docker with a pinned plugin set and reproducible configuration, ready to orchestrate
platform pipelines with work executed on agents.
Difficulty: Intermediate
Prerequisites: SSH access to ctrl-01, Ansible control machine, and a secrets method
(Ansible Vault / AKV / CI variables) to provide the initial admin password.
Demo¶
No academy walkthrough recording is linked here yet.
- Source: View role on GitHub
Context¶
This HOWTO applies when:
ctrl-01already has a consistent OS baseline and network reachability.- You want Jenkins to be the governed CI control plane that triggers platform runs.
- You want the controller to remain lightweight (controller-only operation) and push workload to agents (Docker bootstrap now; RKE2 pod agents in steady state).
This HOWTO is aligned to:
Steps¶
1. Confirm baseline and connectivity¶
- Confirm Ansible connectivity:
ansible ctrl_nodes -m ping -i <inventory>
- Confirm OS facts (optional):
ansible ctrl_nodes -m setup -a 'filter=ansible_distribution*' -i <inventory>
Expected result:
- Ping succeeds.
- Target OS matches your platform baseline.
2. Apply Docker Engine baseline (ADR-0608)¶
Apply the Docker Engine baseline role to ensure Docker Engine and the Compose v2 plugin are present and healthy.
Example playbook:
- name: Bootstrap Docker Engine baseline on ctrl-01
hosts: ctrl_nodes
become: true
gather_facts: true
collections:
- hybridops.common
roles:
- role: hybridops.common.docker_engine
vars:
docker_engine_users:
- "{{ ansible_user | default('root') }}"
Run:
ansible-playbook -i <inventory> deployment/playbooks/bootstrap_docker_ctrl01.yml
Expected result on ctrl-01:
docker version
docker compose version
3. Deploy the Jenkins controller (ADR-0603)¶
Provide the admin password via your secret method (Vault/AKV/CI vars). Example vars:
jenkins_admin_username: "admin"
jenkins_admin_password: "{{ vault_jenkins_admin_password }}"
jenkins_enable_healthcheck: true
# Bootstrap/lab only: enable a single executor to run trivial jobs before agents exist.
jenkins_controller_num_executors: 1
Example playbook:
- name: Bootstrap Jenkins controller on ctrl-01
hosts: ctrl_nodes
become: true
gather_facts: true
collections:
- hybridops.app
roles:
- role: hybridops.app.jenkins_controller
Run:
ansible-playbook -i <inventory> deployment/playbooks/bootstrap_jenkins_ctrl01.yml
Expected result:
- Container
jenkins-controlleris running. - HTTP endpoint responds on the configured port.
- JCasC files are rendered under the controller home and loaded at startup.
4. Validate readiness¶
- Container status:
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" | rg 'jenkins-controller'
- HTTP endpoint:
curl -sS -o /dev/null -w "HTTP=%{http_code}\n" http://localhost:8080/login
- JCasC rendered files:
sudo ls -la /opt/jenkins/jenkins_home/casc_configs/
-
Controller executor policy:
-
Bootstrap:
jenkins_controller_num_executors: 1(temporary) - Standard: set back to
0once agents are configured
Validation¶
Consider this complete when:
- Docker baseline is installed and verified (
docker+docker compose). - Jenkins controller container is healthy and stable.
- JCasC is loading (no Configuration as Code boot failures in logs).
- You can authenticate to
/whoAmI/api/jsonusing admin credentials.
Suggested evidence capture:
docker psoutputdocker logs --tail 200 jenkins-controller- HTTP probe output (
curl -I/ status codes) - The rendered
casc_configs/directory listing
Troubleshooting¶
-
Controller restart loop / JCasC boot failure
Inspect logs and validate the rendered YAML:docker logs --tail 200 jenkins-controller sudo sed -n '1,200p' /opt/jenkins/jenkins_home/casc_configs/00-controller.yaml -
Permissions errors under JENKINS_HOME
Ensure ownership matches the container user:sudo chown -R 1000:1000 /opt/jenkins/jenkins_home -
Endpoint never becomes healthy
Increase memory (jenkins_memory) and re-check logs.
References¶
- ADRs:
- ADR-0608 – Docker Engine baseline
-
ADR-0603 – Run Jenkins controller on control node; agents on RKE2
-
Roles:
- GitHub –
hybridops.app.jenkins_controller -
Operations:
- Runbooks – Jenkins
Maintainer: HybridOps
License: MIT-0 for code, CC-BY-4.0 for documentation