Every long-lived Jenkins has the same disease: a plugin list nobody understands, an LTS version several years behind, and a shared fear that any update will break the release pipeline. The cure is not courage; it is a place to try the update where failure costs nothing. This post follows an engineer moving such a Jenkins to MassiveGRID PaaS, which is built on Virtuozzo Application Platform, formerly Jelastic, and using cloned environments to upgrade it safely.

The Jenkins belongs to a payments-software company we will call Corbel Systems: seven years old, 90 plugins, about 200 jobs, running on a VM whose operating system is out of support. The Jenkins DevOps Pack is the destination, with its controller on persistent storage and a scalable worker layer.

Step one: move, do not upgrade

The engineer's first rule is to change one thing at a time. The migration moves the existing Jenkins, at its existing version with its existing plugins, onto the platform. Upgrades come after, on clones. To do that she installs the pack, then replaces the fresh controller's home directory with Corbel's.

  1. On the old VM, stop Jenkins and archive JENKINS_HOME: jobs, plugins, users, credentials, the secrets directory and the master key, excluding build workspaces and most build history to keep the archive small.
  2. On the platform, install the Jenkins DevOps Pack and note its Jenkins version. If the old Jenkins is older, install the pack, then temporarily redeploy the controller container to the matching older image tag so the home directory is loaded by the version that wrote it.
  3. Upload the archive through the dashboard's file manager or SFTP, stop Jenkins on the controller, replace its home directory, fix ownership, start Jenkins.
  4. Log in with the old credentials. Jobs, plugins and credentials appear exactly as before, because Jenkins' encrypted credentials travel with the secrets directory and master key.
  5. Re-attach agents: the pack's worker layer registers itself, so the old static agent definitions are deleted and jobs are repointed to the workers' label.

The move took an evening. Nothing was upgraded, and the next morning's builds ran on the new controller.

Step two: the plugin audit, on a clone

Now the fun part. The engineer clones the Jenkins environment from the dashboard: a full copy of the controller with its home directory and the worker layer, in a few minutes, with its own URL. On the clone she does what nobody dared do on production: open Manage Plugins and look. Twenty-two of the 90 plugins are installed but used by no job; she uninstalls them on the clone and runs every job once with a dry-run parameter the team's pipelines already support. Nothing breaks. Eleven plugins are dependencies of others, kept. The remaining 57 are the real list, written down for the first time.

Step three: upgrade the plugins, then Jenkins, then plugins again

Jenkins upgrades are order-sensitive: plugins must be compatible with the target core, and some plugin versions require a newer core than you run. The safe sequence, executed entirely on the clone, is: update all plugins to the newest versions compatible with the current core; redeploy the controller container to the target LTS version (a platform container redeploy keeps the home directory); update plugins again to the versions that the new core unlocks; restart; run the job suite. On the clone this exposes two problems the team would have hit on production: a deprecated pipeline step in four Jenkinsfiles, and a credentials plugin that changed its storage format and required a one-time migration. Both are fixed on the clone and the fixes noted.

RoundWhereChangeResult
1Clone AUninstall 22 unused pluginsAll jobs pass
2Clone APlugins to latest for current coreAll jobs pass
3Clone AController redeployed to target LTS4 Jenkinsfiles need a step renamed
4Clone APlugins to latest for new coreCredentials plugin migration prompt; fixed
5Clone B (fresh clone of production)Rounds 1 to 4 replayed as a scriptAll jobs pass, 40 minutes
6ProductionSame script, Saturday morningAll jobs pass, 35 minutes

Round five is the important one. Clone B is a fresh copy of production taken after the fixes to the Jenkinsfiles were merged, and the whole upgrade is replayed from a script rather than by hand. If the script works on a fresh clone, it will work on production, which is the same thing one more time.

Step four: production, with rollback already made

On Saturday the engineer takes an on-demand clone of production as the rollback, runs the script, and watches the job suite pass. Had it failed, the platform's swap domains function would have pointed the Jenkins URL at the rollback clone in seconds. The rollback clone is deleted a week later, having cost a few dollars for its week of existence at a small cloudlet limit.

Keeping it from decaying again

The team adopts a cadence: monthly, clone production, apply the plugin updates, run the job suite, apply to production on Saturday, delete the clone. It takes about an hour and the clone costs cents. The controller's persistent home directory is archived nightly to a backup storage node, and a disk load alert warns before build history fills it. Seven years of accumulated fear became a recurring calendar entry.

Frequently Asked Questions

Can I use Jenkins' Configuration as Code instead of copying JENKINS_HOME?

Yes, and for a well-maintained Jenkins it is cleaner: export the configuration with the JCasC plugin, install the pack, apply the YAML. For a seven-year-old instance with hand-configured jobs, copying the home directory preserves everything exactly, and you can adopt JCasC afterwards on a clone.

Will the worker layer's agents work with my old jobs?

Jobs that target a label rather than a specific node work unchanged once the label matches the workers'. Jobs pinned to a named agent must be repointed. Tools the old agents had installed need to be provided on the workers, typically by using Docker-based build steps, which the pack's workers support.

How long does a clone of a large Jenkins take?

A few minutes for the containers, plus copying the home directory's disk; a controller with tens of gigabytes of build history takes longer. Pruning history before cloning speeds it up and is good hygiene anyway.

Upgrade the copy, then the real one

Move your Jenkins to the Jenkins DevOps Pack on MassiveGRID PaaS and clone it before every plugin or LTS upgrade. The clone costs cents an hour and doubles as your rollback. Free 14-day trial, no credit card.

Jenkins DevOps Pack on MassiveGRID PaaS

Further Reading