Checkpoint Lab — JENKINS_HOME, Filesystem Layout, Controller Configuration, System Settings, Tools, and Global Properties
Checkpoint lab: map, modify, snapshot, restore, and verify a disposable Jenkins controller while proving which state is durable and which state is intentionally ephemeral.
Learning objectives
- Map the durable state of a disposable Jenkins controller without exposing secret contents.
- Make controlled system/global-property changes and predict which persisted files/state should change.
- Create separated ordinary-data and secret-key snapshots at a consistent stopped-controller point.
- Restore into a new named volume and new controller identity, then verify configuration, version, persistence, and absence of container-local temporary state.
- Produce an evidence packet that distinguishes successful restore of Jenkins from external-system or workspace recovery.
1. Scenario and success criteria
You are handed a disposable Jenkins controller and told, “We have a volume, so disaster recovery is covered.” Your task is to prove or disprove that claim. You will create synthetic configuration, inventory the home directory, create a stopped-controller snapshot, recreate the controller from separated backup volumes, and verify exactly what returns.
2. Preflight and disposable resource identity
docker --version
docker image inspect jenkins/jenkins:2.568.3-jdk21 --format '{{index .RepoDigests 0}}' || \
docker pull jenkins/jenkins:2.568.3-jdk21
# Required names for this checkpoint:
# source controller: jenkins-ch03-controller
# source home: jenkins-ch03-home
# config backup: jenkins-ch03-config-backup
# secret backup: jenkins-ch03-secret-backup
# restore home: jenkins-ch03-restored-home
# restored controller:jenkins-ch03-restored
If the Lesson 2 source controller still exists, reuse it. Otherwise
recreate it on 127.0.0.1:18083 using the official image
and named volume, complete local setup, set the System Message to
DevOps Academy — Chapter 03 disposable controller, and
add global environment variable ACADEMY_CHAPTER=03.
3. Predict the state changes before acting
Write these predictions into
jenkins-ch03-checkpoint/predictions.txt before taking
the snapshot:
-
The System Message and global property will be serialized under
JENKINS_HOMEand survive restart/restore. -
$JENKINS_HOME/ch03-durable-marker.txtwill return after restore because it is in the backed-up home. -
/tmp/jenkins-ch03-ephemeral.txtwill not return because it belonged to the old container layer. - The restored controller needs the matching protected secret-key material to interpret encrypted controller data correctly.
- External systems and agent workspaces are not recreated by this controller-home restore.
4. Capture source-controller evidence
mkdir -p jenkins-ch03-checkpoint
docker exec jenkins-ch03-controller sh -lc '
printf "home=%s\n" "$JENKINS_HOME"
id
java -version 2>&1 | head -4
stat -c "owner=%U:%G mode=%a path=%n" "$JENKINS_HOME"
stat -c "%y %s %n" "$JENKINS_HOME/config.xml"
grep -n -E "systemMessage|ACADEMY_CHAPTER" "$JENKINS_HOME/config.xml" || true
printf "top-level-size-map:\n"
du -sh "$JENKINS_HOME"/* 2>/dev/null | sort -h | tail -25
' | tee jenkins-ch03-checkpoint/source-state.txt
docker inspect --format='image={{.Config.Image}} mounts={{json .Mounts}}' \
jenkins-ch03-controller > jenkins-ch03-checkpoint/source-container.txt
In the UI, record Jenkins core version and installed plugin names/versions. Do not copy plugin configuration or secret values into the evidence packet.
5. Create one durable and one ephemeral marker
docker exec jenkins-ch03-controller sh -lc '
printf "durable-marker chapter03\n" > "$JENKINS_HOME/ch03-durable-marker.txt"
printf "ephemeral-marker chapter03\n" > /tmp/jenkins-ch03-ephemeral.txt
ls -l "$JENKINS_HOME/ch03-durable-marker.txt" /tmp/jenkins-ch03-ephemeral.txt
'
These synthetic markers make the recovery boundary visible. They are not substitutes for normal Jenkins configuration or artifact publication.
6. Create a consistent snapshot with separated key material
docker stop jenkins-ch03-controller
docker volume create jenkins-ch03-config-backup
docker volume create jenkins-ch03-secret-backup
# Replace any previous checkpoint archives inside the disposable backup volumes.
docker run --rm --entrypoint /bin/sh \
-v jenkins-ch03-home:/source:ro \
-v jenkins-ch03-config-backup:/backup \
jenkins/jenkins:2.568.3-jdk21 -c '
rm -f /backup/jenkins-home-nonsecrets.tgz &&
cd /source &&
tar --exclude=./secrets -czf /backup/jenkins-home-nonsecrets.tgz . &&
sha256sum /backup/jenkins-home-nonsecrets.tgz
' | tee jenkins-ch03-checkpoint/config-backup-sha256.txt
docker run --rm --entrypoint /bin/sh \
-v jenkins-ch03-home:/source:ro \
-v jenkins-ch03-secret-backup:/backup \
jenkins/jenkins:2.568.3-jdk21 -c '
rm -f /backup/jenkins-secrets.tgz &&
cd /source &&
tar -czf /backup/jenkins-secrets.tgz secrets &&
chmod 600 /backup/jenkins-secrets.tgz &&
stat -c "%a %s %n" /backup/jenkins-secrets.tgz
' > jenkins-ch03-checkpoint/secret-backup-metadata.txt
7. Restore into a fresh volume
docker rm jenkins-ch03-controller
docker volume rm jenkins-ch03-restored-home 2>/dev/null || true
docker volume create jenkins-ch03-restored-home
# Restore ordinary controller data.
docker run --rm --user root --entrypoint /bin/sh \
-v jenkins-ch03-config-backup:/config-backup:ro \
-v jenkins-ch03-restored-home:/restore \
jenkins/jenkins:2.568.3-jdk21 -c '
cd /restore && tar -xzf /config-backup/jenkins-home-nonsecrets.tgz
'
# Restore the separately protected secrets directory.
docker run --rm --user root --entrypoint /bin/sh \
-v jenkins-ch03-secret-backup:/secret-backup:ro \
-v jenkins-ch03-restored-home:/restore \
jenkins/jenkins:2.568.3-jdk21 -c '
cd /restore && tar -xzf /secret-backup/jenkins-secrets.tgz
'
# Normalize ownership to the Jenkins user defined by the image.
JENKINS_UID=$(docker run --rm --entrypoint /bin/sh jenkins/jenkins:2.568.3-jdk21 -c 'id -u jenkins')
JENKINS_GID=$(docker run --rm --entrypoint /bin/sh jenkins/jenkins:2.568.3-jdk21 -c 'id -g jenkins')
docker run --rm --user root --entrypoint /bin/sh \
-e JUID="$JENKINS_UID" -e JGID="$JENKINS_GID" \
-v jenkins-ch03-restored-home:/restore \
jenkins/jenkins:2.568.3-jdk21 -c 'chown -R "$JUID:$JGID" /restore'
docker run -d \
--name jenkins-ch03-restored \
--restart=no \
-p 127.0.0.1:18084:8080 \
-v jenkins-ch03-restored-home:/var/jenkins_home \
jenkins/jenkins:2.568.3-jdk21
docker logs --tail 100 jenkins-ch03-restored
Use a different loopback port so a mistaken source controller cannot be confused with the restore. The original source volume still exists and is not mounted by the restored controller.
8. Verify each prediction independently
docker exec jenkins-ch03-restored sh -lc '
printf "home=%s\n" "$JENKINS_HOME"
id
java -version 2>&1 | head -4
grep -n -E "systemMessage|ACADEMY_CHAPTER" "$JENKINS_HOME/config.xml" || true
printf "durable marker: "; cat "$JENKINS_HOME/ch03-durable-marker.txt"
if [ -e /tmp/jenkins-ch03-ephemeral.txt ]; then
echo "UNEXPECTED: old ephemeral marker exists"
exit 2
else
echo "expected: old ephemeral marker absent"
fi
' | tee jenkins-ch03-checkpoint/restored-state.txt
docker inspect --format='image={{.Config.Image}} mount={{range .Mounts}}{{.Name}}:{{.Destination}}{{end}}' \
jenkins-ch03-restored > jenkins-ch03-checkpoint/restored-container.txt
Open http://127.0.0.1:18084, authenticate using the
restored local training account, and verify the System Message and
global property. Confirm the installed plugin baseline matches the
source evidence. A dashboard that loads but has missing
configuration is a partial restore, not success.
9. Required evidence packet
Jenkins core, Java, image tag/digest, service UID/GID, source volume.
Safe excerpts proving synthetic System Message/global property plus file metadata.
Ordinary archive SHA-256 and separate-secret-backup existence/permission metadata; never secret contents.
Fresh volume/controller identity, logs, restored settings, plugin baseline, durable marker.
Old /tmp marker absent; note that agent
workspaces/external systems were not restored.
This local Docker exercise simulates separated key storage and does not prove production RPO/RTO, remote backup durability, or external-system DR.
10. Deliberate failure branch
To test your diagnostic model without damaging the successful restore, create a throwaway second restore volume and omit the separate secrets archive. Start it on another loopback port, inspect startup/login/credential-related evidence, then delete it. Do not copy random keys from another controller as a shortcut.
This optional branch exists to teach causality. The required checkpoint is the successful matched restore above.
11. Cleanup / rollback
docker rm -f jenkins-ch03-restored 2>/dev/null || true
docker volume rm jenkins-ch03-restored-home 2>/dev/null || true
# Keep source/backup volumes only if you want to repeat the exercise.
# When finished intentionally:
# docker volume rm jenkins-ch03-home jenkins-ch03-config-backup jenkins-ch03-secret-backup
# Evidence packet contains no secret archive. Review before retaining or sharing.
find jenkins-ch03-checkpoint -maxdepth 1 -type f -print
12. What the checkpoint proves—and does not prove
| Observation | Proves | Does not prove |
|---|---|---|
| Restored controller starts | Core/Java/home can load sufficiently to run. | Every job/plugin/integration works. |
| System Message/global property returned | Selected controller configuration was restored. | All external services or credentials are healthy. |
| Durable marker returned | File under home was in the backup/restore path. | An agent workspace would be restored. |
Old /tmp marker absent |
Container-local state was not part of controller-home restore. | All ephemeral state is harmless to lose. |
| Matching secret material restored | Required cryptographic recovery state is available. | It was stored with production-grade separation/access controls. |
13. Summary
- A credible Jenkins backup is a tested recovery procedure, not just a mounted volume or tar file.
- Controller configuration, secret-key recovery material, container-local state, agent workspaces, and external systems have separate ownership.
- Consistent snapshots, exact core/Java/plugin baseline, filesystem ownership, and matched keys all affect restore success.
- Evidence should prove recovery without disclosing sensitive key material.
- This chapter establishes the durable-state foundation needed before Chapter 04 adds users, authentication, authorization, folders, and least privilege.
Knowledge check
The restored Jenkins dashboard loads, but the System Message is missing. Is the checkpoint successful?
No. Startup only proves a runnable controller. Missing expected configuration means the restore is incomplete or based on the wrong snapshot.
Why restore to a fresh named volume and a different loopback port?
It prevents accidental reuse of the source volume/controller and makes the restore identity independently observable.
Why is the old /tmp marker expected to
disappear?
It lived in the original container filesystem, not the mounted
JENKINS_HOME backup boundary.
What is wrong with storing the ordinary backup and secret-key archive in one public artifact?
It collapses the protection boundary; an attacker who obtains both encrypted controller data and its key material may recover protected information.
What should happen before upgrading core/plugins during disaster recovery?
First restore and validate the known-good core/Java/plugin baseline where practical. Treat upgrades as a separate controlled change rather than mixing recovery and migration.
Does this checkpoint prove a deleted external artifact repository package can be restored from Jenkins?
No. External repositories own their own durable state and recovery. Jenkins may restore metadata or references, not the external package bytes.
Official references and version notes
- Configuring the System — current Jenkins home-directory and global system-configuration guidance.
- Managing Jenkins — current administrative surfaces for System, Tools, Plugins, status, and troubleshooting.
- System Information — controller system properties, environment variables, plugins, memory information, and diagnostics.
- Managing Tools — built-in tool-provider concepts and global tool configuration.
- Backing-up/Restoring Jenkins — backup scope, controller-key separation, and restore validation.
- Credentials security — why Jenkins secret-key material needs protection and separation from ordinary backups.
-
Storing Secrets
— technical description of Jenkins encryption keys under
$JENKINS_HOME/secrets. - Controller Isolation — current guidance for keeping routine builds off the built-in controller node.
- Jenkins LTS changelog and Java Support Policy — version/runtime assumptions for this chapter.
Version-sensitive statements were rechecked on
2026-09-14. The disposable baseline continues
Chapter 02 with Jenkins 2.568.3 LTS on
Java 21 using the official
jenkins/jenkins:2.568.3-jdk21 image. Jenkins and
plugins evolve; regenerate the storage map from the actual
controller, keep plugin-specific files opaque unless the plugin
documents them, and re-check backup/security guidance before
applying the patterns to a production controller.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.