├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── Dockerfile ├── Dockerfile.debug ├── LICENSE ├── MAINTAINERS ├── README.md ├── SUPPORT.md ├── examples ├── Dockerfile ├── README.md └── files │ ├── base-plugins.txt │ ├── jenkins_wrapper.sh │ ├── setup_reporting.groovy │ └── setup_security.groovy ├── files ├── base-plugins.txt ├── debug_logging.properties ├── debug_logs.groovy ├── jenkins.yaml └── jenkins_wrapper.sh └── update.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | script: 7 | - docker build -t jenkins-docker-master . 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # changelog 2 | 3 | ## 2.176.1-1 4 | * Bump LTS 5 | 6 | ## 2.164.1-1 7 | * Bump LTS 8 | 9 | ## 2.121.2-1 10 | * Bump LTS 11 | 12 | ## 2.121.1-1 13 | * Bump LTS 14 | 15 | ## 2.107.3-1 16 | 17 | * Bump LTS 18 | 19 | ## 2.107.2-1 20 | 21 | * Bump LTS 22 | 23 | ## 2.107.1-1 24 | 25 | * Bump LTS 26 | 27 | ## 2.89.4-1 28 | 29 | * Bump LTS 30 | 31 | ## 2.89.3-1 32 | 33 | * Bump LTS 34 | * Fix Dockerfile to use correct path for [tini](https://github.com/krallin/tini) 35 | 36 | ## 2.89.2-2 37 | 38 | * Enabling CSRF Protection in the setup_security.groovy script. 39 | * Limiting the agent protocols to JNLP4 and CLI2 in the setup_security.groovy script per security and deprecation warnings. 40 | 41 | ## 2.89.2-1 42 | 43 | * Bump LTS for security fixes 44 | * Fix typos 45 | 46 | ## 2.89.1-1 47 | 48 | * Bump LTS 49 | 50 | ## 2.73.3-2 51 | 52 | * Order `MAINTAINERS` alphabetically 53 | * Use environment variables in `jenkins_wrapper.sh` instead of having to sed in Dockerfile 54 | * Format `README.md` to more clearly have Jenkins versions displayed 55 | * Update formatting on `examples/files/README.md` 56 | * Format `Dockerfile` to get rid `Empty continuation line found` errors 57 | * Remove `chmod` from `Dockerfile` in favor of committing files to Github with correct permissions 58 | 59 | ## 2.73.3-1 60 | 61 | * Bump LTS 62 | 63 | ## 2.73.2-2 64 | 65 | * Fix Dockerfile argument scoping issues for `jenkins.install.UpgradeWizard.state` and `jenkins.install.InstallUtil.lastExecVersion` 66 | 67 | ## 2.73.2-1 68 | 69 | * Bump Jenkins LTS to 2.73.2 70 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo. 2 | * @target/jays-admins 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to reuse 2 | 3 | ## Issues 4 | 5 | Feel free to submit bugs or feature requests as issues. 6 | 7 | ## Pull Requests 8 | 9 | These rules must be followed for any contributions to be merged into master. 10 | 11 | 1. Fork this repo 12 | 1. Make any desired changes 13 | 1. Validate you changes meet your desired use case 14 | 1. Ensure the `JENKINS_VER` and `RELEASE` in `update.sh` are modified accordingly 15 | 1. Ensure documentation has been updated 16 | 1. Open a pull-request 17 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG JENKINS_VER=2.277.1 2 | 3 | FROM jenkins/jenkins:${JENKINS_VER} 4 | 5 | ARG JENKINS_VER 6 | ARG RELEASE=1 7 | 8 | USER root 9 | 10 | COPY files/jenkins_wrapper.sh /usr/local/bin/jenkins_wrapper.sh 11 | COPY files/jenkins.yaml /usr/local/bin/jenkins.yaml 12 | 13 | ENV CASC_JENKINS_CONFIG=/usr/local/bin/jenkins.yaml 14 | 15 | # create version files to ensure Jenkins does not prompt for setup 16 | # allow slave to master control - https://wiki.jenkins.io/display/JENKINS/Slave+To+Master+Access+Control 17 | # create file for plugin versioning 18 | RUN echo -n ${JENKINS_VER} > /usr/share/jenkins/ref/jenkins.install.UpgradeWizard.state && \ 19 | echo -n ${JENKINS_VER} > /usr/share/jenkins/ref/jenkins.install.InstallUtil.lastExecVersion && \ 20 | mkdir -p /usr/share/jenkins/ref/secrets/ && echo false > /usr/share/jenkins/ref/secrets/slave-to-master-security-kill-switch && \ 21 | echo ${JENKINS_VER}-${RELEASE} > /usr/share/jenkins/ref/jenkins.docker.image.version 22 | 23 | ENTRYPOINT ["/sbin/tini", "--", "/usr/local/bin/jenkins_wrapper.sh"] 24 | 25 | USER jenkins 26 | 27 | # Install plugins that are predefined in the base-plugins.txt file 28 | COPY files/base-plugins.txt /usr/share/jenkins/base-plugins.txt 29 | RUN cat /usr/share/jenkins/base-plugins.txt | xargs /usr/local/bin/install-plugins.sh 30 | -------------------------------------------------------------------------------- /Dockerfile.debug: -------------------------------------------------------------------------------- 1 | ARG JENKINS_VER=2.277.1 2 | ARG RELEASE=1 3 | 4 | FROM target/jenkins-docker-master:${JENKINS_VER}-${RELEASE} 5 | COPY files/debug_logs.groovy /usr/share/jenkins/ref/init.groovy.d/debug_logs.groovy 6 | COPY files/debug_logging.properties /usr/share/jenkins/debug_logging.properties 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2018 Target Brands, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /MAINTAINERS: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "file_format": "This MAINTAINERS file format is described at http://pup.pt/maintainers", 4 | "issues": "https://github.com/target/jenkins-docker-master/issues", 5 | "people": [ 6 | { 7 | "github": "delta592", 8 | "email": "Dax.Johnson@target.com", 9 | "name": "Dax Johnson" 10 | }, 11 | { 12 | "github": "slushpupie", 13 | "email": "Jay.Kline@target.com", 14 | "name": "Jay Kline" 15 | }, 16 | { 17 | "github": "sjqnn", 18 | "email": "Sean.J.Quinn@target.com", 19 | "name": "Sean Quinn" 20 | }, 21 | { 22 | "github": "JordanSussman", 23 | "email": "jordan.sussman@target.com", 24 | "name": "Jordan Sussman" 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecation Warning 2 | 3 | As of May 2021, this project has been deprecated and is now archived in favor of using [vela](https://github.com/go-vela) 4 | 5 | 6 | # jenkins-docker-master 7 | 8 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) 9 | [![release](https://img.shields.io/github/release/target/jenkins-docker-master.svg)](https://github.com/target/jenkins-docker-master/releases/latest) 10 | [![docker](https://img.shields.io/docker/automated/target/jenkins-docker-master.svg)](https://hub.docker.com/r/target/jenkins-docker-master) 11 | 12 | ## How to use this image 13 | 14 | ### Modify the image to company specific settings 15 | 16 | ```dockerfile 17 | FROM target/jenkins-docker-master:2.176.1 18 | COPY scripts-directory /usr/share/jenkins/ref/init.groovy.d/script.groovy 19 | ``` 20 | 21 | ### Create the Docker Swarm service 22 | 23 | Example docker service command: 24 | 25 | ```bash 26 | docker service create --name --mount type=bind,src=/path/to/source,dst=/var/jenkins_home 27 | -e JENKINS_URL=https:// -e JENKINS_SLAVE_AGENT_PORT= 28 | --network --publish --restart-condition on-failure 29 | target/jenkins-docker-master:2.176.1 30 | ``` 31 | 32 | Example [gelvedere](https://github.com/target/gelvedere) command: 33 | 34 | ```bash 35 | gelvedere --user-config /jenkins/user-configs/test.json --admin-config /jenkins/admin-configs/test.json --domain acme.com 36 | ``` 37 | 38 | ### Configuration 39 | 40 | The majority of base configuration should be done with groovy scripts when the image is created or started for the first time and as such, we have provided example groovy scripts [here](https://github.com/target/jenkins-docker-master/blob/master/examples). 41 | 42 | #### Authentication and Authorization 43 | 44 | The images take advantage of a few plugins to handle auth: 45 | 46 | - [github-oauth](https://plugins.jenkins.io/github-oauth) 47 | - [matrix-auth](https://plugins.jenkins.io/matrix-auth) 48 | - [role-strategy](https://plugins.jenkins.io/role-strategy) 49 | 50 | An example setup script can be found [here](https://github.com/target/jenkins-docker-master/blob/master/examples/files/setup_security.groovy) 51 | 52 | #### Reporting 53 | 54 | Various ways exist to report metrics from Jenkins, so we won't go into deep details of available options. However, we have had good luck with using the [jmx2graphite jar](https://github.com/logzio/jmx2graphite) in conjunction with [metrics](https://plugins.jenkins.io/metrics) and [metrics-graphite](https://plugins.jenkins.io/metrics-graphite) plugins. 55 | 56 | An example reporting script can be found [here](https://github.com/target/jenkins-docker-master/blob/master/examples/files/setup_reporting.groovy) 57 | 58 | #### Environment variables 59 | 60 | The following environment variables can be used to set up Jenkins: 61 | 62 | | Variable | Description | Example | 63 | | ------------------------ | ----------- | ------- | 64 | | JENKINS_SLAVE_AGENT_PORT | The TCP port for the slave agent to use. Must be unique to the cluster. | `5001` | 65 | | JAVA_OPTS | Additional java options for running. | `--server -XX:+UseG1GC` | 66 | 67 | ## Image Variants 68 | 69 | The `jenkins-docker-master` images come in a couple of flavors, each designed for a specific use case. All of the images extend the official [Jenkins LTS images](https://hub.docker.com/r/jenkins/jenkins) 70 | and as such, many of the options prescribed there apply to this image as well. 71 | 72 | ### `jenkins-docker-master:2.277.1-1` 73 | 74 | This is the de facto image. It is based off of `jenkins/jenkins:2.277.1` and includes a few modifications. It was created with the intention to be extended by using groovy scripts to setup ACLs using various plugins and as such, we have provided example groovy scripts [here](https://github.com/target/jenkins-docker-master/blob/master/examples). 75 | 76 | ### `jenkins-docker-master:debug-2.277.1-1` 77 | 78 | This image is based off of the `jenkins-docker-master:2.277.1-1` image. The noticeable difference is in relation to increasing log verbosity for troubleshooting. 79 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | * [The Jenkins users google group](https://groups.google.com/forum/?nomobile=true#!forum/jenkinsci-users) 2 | * [Stack Overflow](https://stackoverflow.com/search?tab=newest&q=jenkins) 3 | -------------------------------------------------------------------------------- /examples/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG JENKINS_VER=2.277.1 2 | ARG RELEASE=1 3 | 4 | FROM target/jenkins-docker-master:${JENKINS_VER}-${RELEASE} 5 | USER root 6 | 7 | RUN curl -sL https://github.com/logzio/jmx2graphite/releases/download/v1.1.0/jmx2graphite-1.1.0-javaagent.jar > /usr/share/jenkins/jmx2graphite.jar && \ 8 | curl -sL https://raw.githubusercontent.com/target/jenkins-docker-master/master/examples/files/base-plugins.txt > /usr/share/jenkins/base-plugins.txt && \ 9 | curl -sL https://raw.githubusercontent.com/target/jenkins-docker-master/master/examples/files/setup_security.groovy > /usr/share/jenkins/ref/init.groovy.d/setup.groovy.override && \ 10 | curl -sL https://raw.githubusercontent.com/target/jenkins-docker-master/master/examples/files/setup_reporting.groovy > /usr/share/jenkins/ref/init.groovy.d/setup_reporting.groovy.override 11 | 12 | USER jenkins 13 | 14 | RUN cat /usr/share/jenkins/base-plugins.txt | xargs /usr/local/bin/install-plugins.sh 15 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # jenkins-docker-master examples 2 | 3 | ## setup_security 4 | 5 | The `setup_security.groovy` script does the following: 6 | 7 | * Set master [executors](https://support.cloudbees.com/hc/en-us/articles/216456477-What-is-a-Jenkins-Executor-and-how-can-I-best-utilize-my-executors) to 0 8 | * Set [quiet period](https://jenkins.io/blog/2010/08/11/quiet-period-feature/) to 5 9 | * Set [slave agent port](http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html#setSlaveAgentPort-int-) to a user provided environment variable 10 | * Set [jenkins url](http://javadoc.jenkins-ci.org/jenkins/model/JenkinsLocationConfiguration.html#setUrl-java.lang.String-) to a user provided environment variable 11 | * Create a admin user 12 | * Sets email address to user provided environment variable 13 | * Sets ssh keypair to user provided environment variable 14 | * Setup new GithubSecurityRealm for [github-oauth](https://plugins.jenkins.io/github-oauth) 15 | * Setup new RoleBasedAuthorizationStrategy for [role-strategy](https://plugins.jenkins.io/role-strategy) 16 | * Define admin, developer, authenticated, and anonymous user roles and permissions 17 | 18 | The following is a example of using the security script: 19 | 20 | 1. Extend the base image and include the script 21 | 22 | ```dockerfile 23 | FROM target/jenkins-docker-master:latest 24 | 25 | COPY setup_security.groovy /usr/share/jenkins/ref/init.groovy.d/setup_security.groovy.override 26 | ``` 27 | 28 | **Note**: The security script requires that the [git](https://plugins.jenkins.io/git), [github](https://plugins.jenkins.io/github), [github-oauth](https://plugins.jenkins.io/github-oauth), [matrix-auth](https://plugins.jenkins.io/matrix-auth), and [role-strategy](https://plugins.jenkins.io/role-strategy) plugins are installed 29 | 30 | 1. Create a GitHub OAuth App by following the instructions on [GitHub](https://developer.github.com/enterprise/2.10/v3/oauth/) 31 | * Example homepage url - `https://accounting.jenkins.company.com` 32 | * Example Authorization callback URL - `https://accounting.jenkins.company.com/securityRealm/finishLogin` 33 | * Take note of the Client ID and Client secret as they will be used later 34 | 35 | 1. Define company specific environment variables 36 | 37 | | Variable | Description | Example | 38 | | --------------------------------- | ----------- | ------- | 39 | | GHE_KEY | TheGitHub OAuth Key | `abcdef0123456789abcd` | 40 | | GHE_SECRET | TheGitHub OAuth Secret | `h5qosu6bmrgrl8dgwynfps4e1z2jnio4hid2u3gp` | 41 | | JENKINS_ACL_MEMBERS_admin | A GitHub Org*Team to be admins of this instance | `target*Admins` | 42 | | JENKINS_ACL_MEMBERS_developer | A GitHub Org*Team to be developers on this instance (optional) | `jenkins*Contributors` | 43 | | ADMIN_SSH_PUBKEY | An ssh public key for the admin team to manage this instance | `ssh-rsa AAAAB3N....9CUz` | 44 | | JENKINS_URL | Specify the public URL used to access this instance | `https://accounting.jenkins.company.com/` | 45 | | JENKINS_ADMIN_EMAIL | Specify the email address associated with the owners of this instance | `owners@company.com` | 46 | | GHE_ADMIN | The default GitHub Org*Team to be admins of this instance | `Jenkins*Admins` 47 | 48 | ## setup_reporting 49 | 50 | The `setup_reporting.groovy` script sets up graphite metrics reporting. The following is a example of using the reporting script: 51 | 52 | 1. Extend the base image by including the reporting script and installing the [jmx2graphite jar](https://github.com/logzio/jmx2graphite) 53 | 54 | ```dockerfile 55 | FROM target/jenkins-docker-master:latest 56 | 57 | COPY setup_reporting.groovy /usr/share/jenkins/ref/init.groovy.d/setup_reporting.groovy.override 58 | RUN curl -sL https://github.com/logzio/jmx2graphite/releases/download/v1.1.0/jmx2graphite-1.1.0-javaagent.jar > /usr/share/jenkins/jmx2graphite.jar 59 | ``` 60 | 61 | **Note**: The reporting script requires that the [metrics](https://plugins.jenkins.io/metrics) and [metrics-graphite](https://plugins.jenkins.io/metrics-graphite) plugins are installed 62 | 63 | 1. Define company specific environment variables 64 | 65 | | Variable | Description | Example | 66 | | --------------------------------- | ----------- | ------- | 67 | | GRAPHITE_HOST | Specify the URL or IP address where to send graphite metrics | `graphite.acme.com` | 68 | | NAME | Name of the Jenkins master | `accounting` | 69 | | TEAM | Team using the Jenkins master | `stores` | 70 | 71 | ## Installing plugins 72 | 73 | Installing additional plugins is as simple as creating a text file with the list of plugins and extending the base image to include it. 74 | 75 | The examples/base-plugins.txt file is a list of our favorite plugins to install. The following is a example of installing plugins: 76 | 77 | ```dockerfile 78 | FROM target/jenkins-docker-master:latest 79 | 80 | COPY base-plugins.txt /usr/share/jenkins/base-plugins.txt 81 | RUN cat /usr/share/jenkins/base-plugins.txt | xargs /usr/local/bin/install-plugins.sh 82 | ``` 83 | -------------------------------------------------------------------------------- /examples/files/base-plugins.txt: -------------------------------------------------------------------------------- 1 | artifactory 2 | authorize-project 3 | build-token-root 4 | cloudbees-folder 5 | copyartifact 6 | credentials 7 | credentials-binding 8 | envinject 9 | git 10 | github 11 | github-oauth 12 | ghprb 13 | greenballs 14 | groovy 15 | job-dsl 16 | kubernetes 17 | mailer 18 | matrix-auth 19 | metrics 20 | metrics-graphite 21 | parameterized-trigger 22 | plain-credentials 23 | pipeline-model-definition 24 | pipeline-stage-view 25 | role-strategy 26 | script-security 27 | ssh-credentials 28 | ssh-slaves 29 | subversion 30 | urltrigger 31 | workflow-api 32 | workflow-aggregator 33 | workflow-cps 34 | workflow-multibranch 35 | workflow-job 36 | workflow-scm-step 37 | workflow-step-api 38 | workflow-support 39 | github-branch-source 40 | ws-cleanup 41 | -------------------------------------------------------------------------------- /examples/files/jenkins_wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | JENKINS_VER=2.277.1 4 | RELEASE=1 5 | 6 | # This enables you to directly tie versions of plugins to a specific version of Jenkins 7 | # The base dockerfile installs plugins, but it won't override plugins that are pinned, 8 | # so we will copy the plugin directory on each new version of Jenkins 9 | # More information - https://wiki.jenkins.io/display/JENKINS/Pinned+Plugins 10 | if [ "$(cat /var/jenkins_home/jenkins.docker.image.version)" != "${JENKINS_VER}-${RELEASE}" ] ; then 11 | echo "Updating plugins..." 12 | cp -var /usr/share/jenkins/ref/plugins/* /var/jenkins_home/plugins 13 | echo "${JENKINS_VER}-${RELEASE}" > /var/jenkins_home/jenkins.docker.image.version 14 | fi 15 | 16 | # setup java options 17 | JAVA_OPTS="${JAVA_OPTS} -server -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:+ParallelRefProcEnabled -XX:+UseStringDeduplication -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:G1HeapRegionSize=8m -XX:MetaspaceSize=500M -Djava.awt.headless=true -Djenkins.model.Jenkins.logStartupPerformance=true -Dhudson.InitReactorRunner.concurrency=64 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85" 18 | export JAVA_OPTS 19 | 20 | # https://github.com/jenkinsci/docker/blob/master/jenkins.sh 21 | exec /usr/local/bin/jenkins.sh "$@" 22 | -------------------------------------------------------------------------------- /examples/files/setup_reporting.groovy: -------------------------------------------------------------------------------- 1 | import jenkins.model.* 2 | 3 | import java.util.* 4 | import java.lang.reflect.* 5 | import net.sf.json.* 6 | import net.sf.json.groovy.* 7 | import java.util.logging.ConsoleHandler 8 | import java.util.logging.LogManager 9 | 10 | import jenkins.metrics.api.MetricsAccessKey 11 | import jenkins.metrics.impl.graphite.GraphiteServer 12 | 13 | def env = System.getenv() 14 | def logger = LogManager.getLogManager().getLogger("hudson.WebAppMain") 15 | 16 | def instance = Jenkins.get() 17 | 18 | logger.info("Setting up Graphite Metrics Reporting") 19 | 20 | graphite = new jenkins.metrics.impl.graphite.GraphiteServer(env['GRAPHITE_HOST'],2003,env['TEAM']+"."+env['NAME']) 21 | List graphiteServers = new ArrayList() 22 | graphiteServers.add(graphite) 23 | GraphiteServer.DescriptorImpl graphiteImpl = new GraphiteServer.DescriptorImpl() 24 | graphiteImpl.setServers(graphiteServers) 25 | instance.save() 26 | -------------------------------------------------------------------------------- /examples/files/setup_security.groovy: -------------------------------------------------------------------------------- 1 | import jenkins.model.* 2 | import hudson.security.* 3 | import org.jenkinsci.plugins.* 4 | import org.jenkinsci.plugins.GithubSecurityRealm 5 | 6 | import java.util.* 7 | import com.michelin.cio.hudson.plugins.rolestrategy.* 8 | import java.lang.reflect.* 9 | import net.sf.json.* 10 | import net.sf.json.groovy.* 11 | import java.util.logging.ConsoleHandler 12 | import java.util.logging.LogManager 13 | 14 | import hudson.model.Hudson.CloudList; 15 | import hudson.security.csrf.DefaultCrumbIssuer; 16 | import hudson.slaves.Cloud; 17 | 18 | import com.cloudbees.plugins.credentials.CredentialsScope 19 | import com.cloudbees.plugins.credentials.Credentials 20 | import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl 21 | import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey 22 | import com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey.FileOnMasterPrivateKeySource 23 | import com.cloudbees.plugins.credentials.SystemCredentialsProvider 24 | import com.cloudbees.plugins.credentials.domains.Domain 25 | 26 | def env = System.getenv() 27 | def logger = LogManager.getLogManager().getLogger("hudson.WebAppMain") 28 | 29 | def instance = Jenkins.get() 30 | 31 | // Set executors to 0 32 | instance.setNumExecutors(0) 33 | 34 | // Set quiet period - https://jenkins.io/blog/2010/08/11/quiet-period-feature/ 35 | instance.setQuietPeriod(5) 36 | 37 | // Set slave agent port - http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html#setSlaveAgentPort-int- 38 | int port = env['JENKINS_SLAVE_AGENT_PORT'].toInteger() 39 | instance.setSlaveAgentPort(port) 40 | 41 | // Set agent protocol list to JNLP4 and CLI2 by default - http://javadoc.jenkins.io/jenkins/model/Jenkins.html#getAgentProtocols-- 42 | Set agentProtocolsList = ['JNLP4-connect', 'Ping', 'CLI2-connect'] 43 | if(!instance.getAgentProtocols().equals(agentProtocolsList)) { 44 | instance.setAgentProtocols(agentProtocolsList) 45 | logger.info("Agent Protocols have changed. Setting: ${agentProtocolsList}") 46 | instance.save() 47 | } else { 48 | logger.info("Nothing changed. Agent Protocols already configured: ${instance.getAgentProtocols()}") 49 | } 50 | 51 | // Disable UI Warnings about Deprecated Agent Protocols/ CLI configurations set above. 52 | logger.info("Disabling UI warnings about deprecated agent protocols.") 53 | def agentprotocol = instance.getAdministrativeMonitor("jenkins.slaves.DeprecatedAgentProtocolMonitor") 54 | agentprotocol.disable(true) 55 | 56 | logger.info("Disabling UI warnings about CLI remoting being enabled.") 57 | def cliwarn = instance.getAdministrativeMonitor("jenkins.CLI") 58 | cliwarn.disable(true) 59 | 60 | // Enable CSRF Protection by default - http://javadoc.jenkins-ci.org/hudson/security/csrf/DefaultCrumbIssuer.html 61 | instance.setCrumbIssuer(new DefaultCrumbIssuer(true)) 62 | instance.save() 63 | 64 | // Set URL location - http://javadoc.jenkins-ci.org/jenkins/model/JenkinsLocationConfiguration.html#setUrl-java.lang.String- 65 | loc = JenkinsLocationConfiguration.get() 66 | loc.setUrl(env['JENKINS_URL']) 67 | 68 | // Create admin user - http://javadoc.jenkins-ci.org/hudson/model/User.html 69 | jknadm = hudson.model.User.get('jenkins-admin') 70 | jknadm.setFullName('Jenkins Admin User') 71 | jknadm.setDescription('This account is used by the Jenkins management team to administer this instance. Please do not delete it.') 72 | 73 | String emailAddress = env['JENKINS_ADMIN_EMAIL'] 74 | 75 | email = jknadm.getProperty(hudson.tasks.Mailer.UserProperty) 76 | if (email == null) { 77 | logger.info("Adding email to admin user") 78 | email = new hudson.tasks.Mailer.UserProperty(emailAddress) 79 | jknadm.addProperty(email) 80 | } else { 81 | if (!email. getAddress().equals(emailAddress)) { 82 | logger.warning("Resetting email to admin user") 83 | email = new hudson.tasks.Mailer.UserProperty(emailAddress) 84 | jknadm.addProperty(email) 85 | } 86 | } 87 | 88 | // https://github.com/jenkinsci/ssh-cli-auth-module/blob/master/src/main/java/org/jenkinsci/main/modules/cli/auth/ssh/UserPropertyImpl.java 89 | keys = jknadm.getProperty(org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl) 90 | if (keys == null) { 91 | logger.info("Adding new admin ssh key") 92 | keys = new org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl(env['ADMIN_SSH_PUBKEY']) 93 | jknadm.addProperty(keys) 94 | } 95 | 96 | jknadm.save() 97 | 98 | logger.info("Setting up GHE Auth") 99 | 100 | String gheKey = env['GHE_KEY'] 101 | String gheSecret = env['GHE_SECRET'] 102 | String gheUrl = env['GHE_URL'] 103 | String gheApiUrl = env['GHE_API_URL'] 104 | 105 | def githubRealm = new GithubSecurityRealm( 106 | gheUrl, 107 | gheApiUrl, 108 | gheKey, 109 | gheSecret, 110 | "read:org,user:email" 111 | ) 112 | instance.setSecurityRealm(githubRealm) 113 | instance.save() 114 | 115 | def authz 116 | def authStrategy = instance.getAuthorizationStrategy() 117 | 118 | if(authStrategy instanceof RoleBasedAuthorizationStrategy){ 119 | logger.info("Reusing Role Based Authorization Strategy") 120 | authz = (RoleBasedAuthorizationStrategy) authStrategy 121 | 122 | } else { 123 | logger.info("Setting Role Based Authorization Strategy") 124 | authz = new RoleBasedAuthorizationStrategy() 125 | instance.setAuthorizationStrategy(authz) 126 | instance.save() 127 | } 128 | 129 | // Define base roles 130 | logger.info("Defining base roles") 131 | 132 | // Make constructors available 133 | Constructor[] constrs = Role.class.getConstructors(); 134 | for (Constructor c : constrs) { 135 | c.setAccessible(true); 136 | } 137 | 138 | // Make the method assignRole accessible 139 | Method assignRoleMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("assignRole", String.class, Role.class, String.class); 140 | assignRoleMethod.setAccessible(true); 141 | 142 | Method getRoleMapMethod = RoleBasedAuthorizationStrategy.class.getDeclaredMethod("getRoleMap", String.class); 143 | getRoleMapMethod.setAccessible(true); 144 | 145 | roleMap = authz.getRoleMap(RoleBasedAuthorizationStrategy.GLOBAL) 146 | 147 | String gheAdmin = env['GHE_ADMIN'] 148 | 149 | // First: Define a datastructure that represents the roles+permissions we want to have at *install* time 150 | // Members defined in this list here will *always* get added back during a restart/upgrade 151 | permissionMap = [ 152 | admin:[ 153 | members: ["jenkins-admin",gheAdmin], 154 | permissions: ["hudson.model.Hudson.Administer"] 155 | ], 156 | developer:[ 157 | members: [], 158 | permissions: ["hudson.model.View.Delete", 159 | "hudson.model.Item.Workspace", 160 | "hudson.model.Item.Configure", 161 | "hudson.model.View.Create", 162 | "hudson.model.View.Read", 163 | "hudson.model.Run.Delete", 164 | "hudson.model.Item.Discover", 165 | "hudson.model.Hudson.Read", 166 | "hudson.model.Item.Delete", 167 | "hudson.model.View.Configure", 168 | "hudson.model.Item.ViewStatus", 169 | "hudson.model.Item.Move", 170 | "hudson.model.Item.Read", 171 | "hudson.model.Item.Build", 172 | "hudson.model.Item.Create", 173 | "hudson.model.Item.Cancel", 174 | "hudson.model.Run.Update"] 175 | ], 176 | authenticated: [ 177 | members: ["authenticated"], 178 | permissions: ["hudson.model.Item.Workspace", 179 | "hudson.model.View.Read", 180 | "hudson.model.Item.Discover", 181 | "hudson.model.Hudson.Read", 182 | "hudson.model.Item.ViewStatus", 183 | "hudson.model.Item.Read"] 184 | ], 185 | anonymous: [ 186 | members: ["anonymous"], 187 | permissions: ["hudson.model.Item.Discover"] 188 | ] 189 | ] 190 | 191 | logger.info("Assigning default permissions") 192 | 193 | // Loop through the permisisons we just defined 194 | permissionMap.each { roleName,rset -> 195 | Set permissions = new HashSet() 196 | rset.permissions.each { p -> 197 | permission = Permission.fromId(p) 198 | // If the permission we defined as a string does not exist (ie- its from 199 | // a plugin we didnt install) then just skip it 200 | if (permission != null) { 201 | permissions.add(permission) 202 | } 203 | } 204 | // Create a *new* Role object with the desired name and permissions 205 | Role role = new Role(roleName,permissions) 206 | // This will only add the role if the role is not already added. So local modifications will trump 207 | // this line. See https://github.com/jenkinsci/role-strategy-plugin/blob/master/src/main/java/com/michelin/cio/hudson/plugins/rolestrategy/RoleMap.java#L155-L159 208 | authz.addRole(RoleBasedAuthorizationStrategy.GLOBAL,role) 209 | // Loop through the members, adding them to the role. This will happen every time, so you cannot remove the 210 | // members defined here 211 | rset.members.each { member -> 212 | authz.assignRole(RoleBasedAuthorizationStrategy.GLOBAL,role,member) 213 | } 214 | 215 | // Inject additonal members based on environment variables. This happens every time, but the env's might change 216 | // from run to run 217 | if (env['JENKINS_ACL_MEMBERS_'+roleName] != null) { 218 | env['JENKINS_ACL_MEMBERS_'+roleName].tokenize(',').each { member -> 219 | authz.assignRole(RoleBasedAuthorizationStrategy.GLOBAL,role,member) 220 | } 221 | } 222 | } 223 | 224 | instance.save() 225 | -------------------------------------------------------------------------------- /files/base-plugins.txt: -------------------------------------------------------------------------------- 1 | git 2 | github 3 | github-oauth 4 | matrix-auth 5 | role-strategy 6 | configuration-as-code -------------------------------------------------------------------------------- /files/debug_logging.properties: -------------------------------------------------------------------------------- 1 | handlers=java.util.logging.ConsoleHandler 2 | jenkins.level=FINEST 3 | java.util.logging.ConsoleHandler.level=FINEST 4 | -------------------------------------------------------------------------------- /files/debug_logs.groovy: -------------------------------------------------------------------------------- 1 | import java.util.logging.ConsoleHandler 2 | import java.util.logging.FileHandler 3 | import java.util.logging.SimpleFormatter 4 | import java.util.logging.LogManager 5 | import jenkins.model.Jenkins 6 | 7 | // Log into the console 8 | def WebAppMainLogger = LogManager.getLogManager().getLogger("hudson.WebAppMain") 9 | WebAppMainLogger.addHandler (new ConsoleHandler()) 10 | 11 | // Log into a file 12 | def RunLogger = LogManager.getLogManager().getLogger("hudson.model.Run") 13 | def logsDir = new File(Jenkins.instance.rootDir, "logs") 14 | if(!logsDir.exists()){logsDir.mkdirs()} 15 | FileHandler handler = new FileHandler(logsDir.absolutePath+"/hudson.model.Run-%g.log", 1024 * 1024, 10, true); 16 | handler.setFormatter(new SimpleFormatter()); 17 | RunLogger.addHandler(handler) 18 | -------------------------------------------------------------------------------- /files/jenkins.yaml: -------------------------------------------------------------------------------- 1 | jenkins: 2 | agentProtocols: 3 | - "JNLP4-connect" 4 | - "Ping" 5 | authorizationStrategy: 6 | roleBased: 7 | roles: 8 | global: 9 | - assignments: 10 | - "Jenkins*Admins" 11 | - ${GHE_ADMIN} 12 | - ${JENKINS_ACL_MEMBERS_admin} 13 | name: "admin" 14 | pattern: ".*" 15 | permissions: 16 | - "Overall/Administer" 17 | - assignments: 18 | - "anonymous" 19 | name: "anonymous" 20 | pattern: ".*" 21 | permissions: 22 | - "Job/Discover" 23 | - assignments: 24 | - "authenticated" 25 | name: "authenticated" 26 | pattern: ".*" 27 | permissions: 28 | - "Overall/Read" 29 | - "Job/Discover" 30 | - "Job/Read" 31 | - "Job/Workspace" 32 | - "View/Read" 33 | - assignments: 34 | - ${JENKINS_ACL_MEMBERS_developer} 35 | name: "developer" 36 | pattern: ".*" 37 | permissions: 38 | - "Job/Move" 39 | - "Job/Build" 40 | - "Job/Create" 41 | - "View/Create" 42 | - "Job/Discover" 43 | - "Job/Read" 44 | - "Run/Delete" 45 | - "Job/Cancel" 46 | - "Overall/Read" 47 | - "Run/Update" 48 | - "Job/Delete" 49 | - "View/Delete" 50 | - "Job/Configure" 51 | - "Job/Workspace" 52 | - "View/Read" 53 | - "View/Configure" 54 | crumbIssuer: 55 | standard: 56 | excludeClientIPFromCrumb: true 57 | disableRememberMe: false 58 | disabledAdministrativeMonitors: 59 | - "jenkins.slaves.DeprecatedAgentProtocolMonitor" 60 | - "jenkins.CLI" 61 | labelAtoms: 62 | - name: "chef" 63 | - name: "linux" 64 | - name: "master" 65 | markupFormatter: "plainText" 66 | mode: NORMAL 67 | myViewsTabBar: "standard" 68 | numExecutors: 0 69 | primaryView: 70 | all: 71 | name: "all" 72 | projectNamingStrategy: "standard" 73 | quietPeriod: 5 74 | remotingSecurity: 75 | enabled: true 76 | scmCheckoutRetryCount: 0 77 | securityRealm: 78 | github: 79 | clientID: ${GHE_KEY} 80 | clientSecret: ${GHE_SECRET} 81 | githubApiUri: ${GHE_API_URL} 82 | githubWebUri: ${GHE_WEB_URL} 83 | oauthScopes: "read:org,user:email" 84 | updateCenter: 85 | sites: 86 | - id: "default" 87 | url: "https://updates.jenkins.io/update-center.json" 88 | views: 89 | - all: 90 | name: "all" 91 | viewsTabBar: "standard" -------------------------------------------------------------------------------- /files/jenkins_wrapper.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | JENKINS_VER=2.277.1 4 | RELEASE=1 5 | 6 | # This enables you to directly tie versions of plugins to a specific version of Jenkins 7 | # The base dockerfile installs plugins, but it won't override plugins that are pinned, 8 | # so we will copy the plugin directory on each new version of Jenkins 9 | # More information - https://wiki.jenkins.io/display/JENKINS/Pinned+Plugins 10 | if [ "$(cat /var/jenkins_home/jenkins.docker.image.version)" != "${JENKINS_VER}-${RELEASE}" ] ; then 11 | echo "Updating plugins..." 12 | cp -var /usr/share/jenkins/ref/plugins/* /var/jenkins_home/plugins 13 | echo "${JENKINS_VER}-${RELEASE}" > /var/jenkins_home/jenkins.docker.image.version 14 | fi 15 | 16 | # https://github.com/jenkinsci/docker/blob/master/jenkins.sh 17 | exec /usr/local/bin/jenkins.sh "$@" 18 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This is a simple script to update the version of jenkins being used 3 | 4 | JENKINS_VER=2.277.1 5 | RELEASE=1 6 | 7 | ### DO NOT MODIFY ANY LINES BELOW ### 8 | 9 | for fname in Dockerfile Dockerfile.debug files/jenkins_wrapper.sh examples/Dockerfile examples/files/jenkins_wrapper.sh 10 | do 11 | sed -i '' -E "s/JENKINS_VER=(.*)/JENKINS_VER=${JENKINS_VER}/g; s/RELEASE=(.*)/RELEASE=${RELEASE}/g" $fname 12 | done 13 | 14 | sed -i '' -E "s/(jenkins-docker-master:)[0-9]{1,2}\.[0-9]{1,3}\.[0-9]{1,2}-[0-9]{1,2}/jenkins-docker-master:${JENKINS_VER}-${RELEASE}/g" README.md 15 | sed -i '' -E "s/debug-[0-9]{1,2}\.[0-9]{1,3}\.[0-9]{1,2}-[0-9]{1,2}/debug-${JENKINS_VER}-${RELEASE}/g" README.md 16 | sed -i '' -E "s/jenkins\/jenkins:[0-9]{1,2}\.[0-9]{1,3}\.[0-9]{1,2}/jenkins\/jenkins:${JENKINS_VER}/g" README.md 17 | --------------------------------------------------------------------------------