Automatically setup a JENKINS 2.32.1 server (with a script) - jenkins

I am recently trying to automatically setup a jenkins server with a script.
The aim is, that I simply run that one shell scirpt after a fresh server (aws instance) is started and then the whole server is ready to use.
What does this mean:
I don't wanna see that first question for the secret file (has to be done automatically or disabled)
I don't want to set a admin password, well not by using the UI but by setting it via terminal.
Add some users with permissions
Add SSH private keys for connections to github/bitbucket
Install pre-chosen plugins
Additionally paste some existing jobs into that jenkins
Is there a way to do that? Or (what I didn't try so far) is it possible to just copy a pre-configured jenkins and run that? Like a "jenkins"-image =)

The Jenkins home directory contains a init.groovy.d directory.
Any groovy script within this directory is executed at boot in lexicographical order. Currently I am running my Jenkins master inside a container, which is pre-provisioned, but you could also easily use configuration management tools to provision your Jenkins master instance with these groovy scripts.
Here is one example I use for integrating private keys from $JENKINS_HOME/.ssh into my Jenkins credential store:
import jenkins.model.*
import com.cloudbees.plugins.credentials.*
import com.cloudbees.plugins.credentials.common.*
import com.cloudbees.plugins.credentials.domains.*
import com.cloudbees.plugins.credentials.impl.*
import com.cloudbees.jenkins.plugins.sshcredentials.impl.*
domain = Domain.global()
store = Jenkins.instance.getExtensionList('com.cloudbees.plugins.credentials.SystemCredentialsProvider')[0].getStore()
// private git keys
privateRepoKeys = ["key1", "key2"]
privateRepoKeys.each {
privateKey = new BasicSSHUserPrivateKey(
CredentialsScope.GLOBAL,
"jenkins-${it}",
"jenkins",
new BasicSSHUserPrivateKey.FileOnMasterPrivateKeySource("/var/jenkins_home/.ssh/${it}"),
"",
"Jenkins ${it} Key"
)
store.addCredentials(domain, privateKey)
}
Here is another example that I use for adding a default admin:
import jenkins.model.*
import hudson.security.*
def instance = Jenkins.getInstance()
def hudsonRealm = new HudsonPrivateSecurityRealm(false)
hudsonRealm.createAccount("my_admin", "my_pw")
instance.setSecurityRealm(hudsonRealm)
def strategy = new GlobalMatrixAuthorizationStrategy()
strategy.add(Jenkins.ADMINISTER, "my_admin")
instance.setAuthorizationStrategy(strategy)
instance.save()
I use more scripts to completely bootstrap my Jenkins (hooking it up with the slave machines, configuring global tools, configuring global variables...). So far I didn't hit a limitation with this for my use cases.
Update:
I just created a gist with a collection of groovy scripts I gathered and that I use to bootstrap Jenkins. Will try to keep it up to date.

Yes, there are many ways and steps to do that. You can have a look at the Docker container, Chef cookbook or Puppet module. They do things like adding
-Djenkins.install.runSetupWizard=false
to Jenkins startup parameters.
They (at least Docker and Chef) also have their means to install plugins.
Answering this within a single question here is IMHO a bit too much, so I'm mainly pointing to off-site resources and ask you to post a new question, once your have a particular problem with one of the steps.

Related

Best way to store the deployment path in jenkins

I am creating jenkins pipeline for all our application where I wanted to build and deploy. I can able to achieve that but all the deployment paths are hard coded on the pipeline script.
We have around 8 application and 5 environments. it means I need to specify 40 different deployable path on the pipeline scripts.
I like to know, are they any best way to store the deployment path?. I thought about storing them in XML and reading that while doing the build, but not sure on implementation.
looking for some ideas.
script {
def msbuild tool name: 'Msbuila', type: 'msbuild'
def action "${msbuild}\\msbuild.exe"
def rootPath "${NORKSPACE}\\test\\test";
def sinPath "${rootPath}\\test.sin"
def binPath "${rootPath}\\test\\bin"
bat “nuget restore \"${sinPath}\""
bat "\"${action}\" \"${sinPath)\" "
robocopy("\"${binPath}\" \"\\\\t.test.com\\test\" /MIR /xF ")
}
What I would do is use a config repository, having it configured this way:
Each application is a different repository (example: app_config)
Each environment is a different file
The same enviroment file in each repository is called by the same name
Each enviroment file is a yaml (key:value)
Then on the jenkins pipeline I would get the repo, read the yaml using readYAML (check the command usage and name, theres is a while since I used it) and load it on a map.
Then you use the variables of the map and that should help you
The tricky part is how to match the code repositories and the config repositories. As I mentioned before, I would use the same name and append "_config"

How to use a GitLab link for applying jenkins.yml file for the concept of Jenkins Configuration as Code

I have a local instance of Jenkins. I have previously tried storing the jenkins.yml in my system and giving its path on http://localhost:8080/configuration-as-code. This worked but I want to use a Gitlab repository to store the jenkins.yml file.
I have already tried giving the gitlab link of my jenkins.yml in the path or URL textbox. Some weird things happened, like
1. jenkins broke or huge error console
2. It reapplies the previous configuration(from system path)
jenkins:
systemMessage: "Hello, world"
Your problem as described: you want the job configuration to be saved in GIT and, when a build is triggered, the job should get the current stand of its configuration from there and then, run the build.
Maybe there is a kind of plug-in that does it for you, but I am not aware of any. Maybe anyone?
My suggestion is to define a pipeline job and use a declarative pipeline. It is a file, normally named Jenkinsfile that can be stored in GIT. In the Job, you define the GIT address and when you trigger a build, the file is got from GIT and executed.
There are several flaws in this: pipelines learning curve is not small, you are confronted with groovy (not XML!) and your current XML file is barelly useful.
Maybe someone shows up and tells us about new (for me) plugin that solves your problem using the configuration XML file. In the other hand, pipelines are such a beautyful feature that I encourage you to give it a try

Configuring plugins with Jenkins Job Builder

I'm trying to use Jenkins Job Builder to install jenkins plugins, but I misunderstand what JJB can do or I'm doing something wrong. I used the get-plugins-info command to get a YAML description of my plugins. Later, when rebuilding the jenkins installation, I used jenkins-jobs -p plugins_info.yaml jobs in the hopes that JJB would install the plugins listed in the YAML file. But it didn't install the plugins.
So my first question is: should I even expect JJB to install these plugins? The documentation for what JJB is doing with the plugin information is limited, so I'm running on assumptions here.
Assuming JJB is supposed to be installing the plugins in the YAML file, how can I figure out why it's not? I've looked at jenkins' logs to no avail.
I'll start by mentioning that I use Jenkins Job Builder for creating and versioning my jobs. But if you want to install/configure plugins in Jenkins in an automated fashion you can use init.groovy.d scripts that will initialize your jenkins instance. In order to do so create the following directory ${JENKINS_HOME}/init.groovy.d/ then place your groovy scripts in that directory. This is a script that I use to install plugins when I start Jenkins.
import jenkins.model.*
import java.util.logging.Logger
def logger = Logger.getLogger("")
def installed = false
def initialized = false
def plugins = ["git", "cloudbees-folder", "build-timeout"]
logger.info("" + plugins)
def instance = Jenkins.getInstance()
def pm = instance.getPluginManager()
def uc = instance.getUpdateCenter()
plugins.each {
logger.info("Checking " + it)
if (!pm.getPlugin(it)) {
logger.info("Looking UpdateCenter for " + it)
if (!initialized) {
uc.updateAllSites()
initialized = true
}
def plugin = uc.getPlugin(it)
if (plugin) {
logger.info("Installing " + it)
def installFuture = plugin.deploy()
while(!installFuture.isDone()) {
logger.info("Waiting for plugin install: " + it)
sleep(3000)
}
installed = true
}
}
}
if (installed) {
logger.info("Plugins installed, initializing a restart!")
instance.save()
instance.restart()
}
Add as many plugin names to the array plugins. Hope this help you and others out.
JJB has no capability to manage Jenkins Plugins. You will need to look into other tools to handle that for you such as puppet, ansible, etc...
The usage for "get-plugins-info" and the "-p" parameter in the update command is to pass currently installed plugin info to JJB in cases where a system administrator does not want to all JJB "administrator" access permissions in Jenkins to "query" plugin info during the update run. The latest versions of Jenkins no longer allows anonymous querying of plugin info and unfortunately moved that permission to the administrator permission inside of Jenkins.
plugins-info is useful because JJB supports multiple versions of certain plugins and needs to know what the installed version is to appropriately create the XML depending on supported versions.

Update Jenkins Plugins via Artifactory

I want to update Jenkins plugin via Artifactory.
Create a remote repo named Jenkins-update
Create a local repo named jenkins-update-center
Get the update-center.json from repo Jenkins-update to local and modify the URL from 'http://updates.jenkins-ci.org/' to my own URL 'https://artifacts.xxx.com/artifactory/Jenkins-update/' in update-center.json, then put update-center.json into local repo.
#!/bin/sh
curl -L -o /tmp/update-center.json http://localhost:8081/artifactory/Jenkins-update-cache/update-center.json
sed -i 's#http://updates.jenkins-ci.org/#https://artifacts.xxx.com/artifactory/Jenkins-update/#g' /tmp/update-center.json
curl -L -uuser:pass -T /tmp/update-center.json "http://localhost:8081/artifactory/jenkins-update-center/update-center.json"
Change the default update site from 'http://updates.jenkins-ci.org/' to 'https://artifacts.xxx.com/artifactory/jenkins-update-center/update-center.json' in Jenkins
There is an error 'SHA-512 digest mismatch: expected=49a22dc23f739a76623d10128b6803f79e0489de3ded0f1d01f3dfba4557136c7f318baaf4749a7713ec4b3f56633f2ac3afc4703e87d423ede029d68f84c74d in 'update site 'default''' when I click 'check now' button.
What should I do to make Jenkins update plugins from Artifactory?
Tkx
As soon as the content of update-center.json changed you need to re-generate "signature" section of this file.
For that you need to generate your key pair (see more details in How to create a local mirror of public Jenkins update site?)
Also you may use the following proposed approach :
there is probably a better way, by having a sandbox Jenkins on a system that has access to the internet. You update the server using the UI and then you can test that updated Jenkins thoroughly. When done, you just need to copy the war and hpi files over to your 'production' Jenkins. now you have even a nice process and QA in place.
Another way is to setup a transparent https proxy between your Jenkins and Artifactory server - in that case update-center.json will not change and signature verification should work fine.
With best regards,
Dmytro Gorbunov
As of 2023-01-10 there is a problem with making a mirror of the jenkins plugins on artifactory.
Artifactory documentation decribes only how to create a mirror: https://jfrog.com/knowledge-base/how-to-configure-artifactory-as-a-mirror-for-jenkins-plugins/
But this is not a complete solution. Because this leads to the situation when every plugin shall be manually updated. Having plugins with bunch of dependencies it is huge effort.
There is a need to generate a file: update-center.json
There is an internal jenkins tool to do this: https://github.com/jenkins-infra/update-center2, but documentation is poor and contains vague statements like:
With a few modifications it could easily be used to generate your corporate update center as well.
Without clear description, what shall be done.
I tried to follow steps and completely failed. Tool require some special environment variables, which are also not documented and so on.
So as of my experience mirroring jenkins plugins on artifactory is practically not possible. And honestly spoken, I would like to be wrong here.

Remove Jenkins Plugins via Script

Does anyone know how I can remove jenkins plugins from a script? I know there is no CLI command that exists for it. But was wondering, maybe you can just delete the plugin folder, and attempt to delete all associated data.
Reason I want this, is I want to develop a script that will run nightly. It will scan each Jenkins server, remove plugins if not found in file stored in GIT, it will add plugins if new ones are added, and upgrade or downgrade other plugins if the version doesn't match. The goal is to keep all Jenkins servers in sync as far as plugins go.
Any thoughts on how I can achieve this goal?
groovy script for removing a plugin:
String pluginNameToRemove = "myPluginToRemove"
def jenkins = Jenkins.getInstance()
def pluginManager = jenkins.getPluginManager()
def pluginWrapperToUninstall = pluginManager.getPlugin(pluginNameToRemove)
pluginWrapperToUninstall.doDoUninstall()
You can also remove the content of the plugins folder, download all the plugins you want according to the file, copy them to the plugins folder and restart jenkins. (We have a very similar flow on our environment for deploying jenkins instances)

Resources