This commit is contained in:
Arvydas Silanskas 2024-09-28 11:03:12 +03:00
commit fb0137cd2c
7 changed files with 159 additions and 0 deletions

26
README.adoc Normal file
View File

@ -0,0 +1,26 @@
= Docker based Jenkins setup through Configuration-as-Code
== Running
. Run `create-keys.sh` to generate SSH keys used for Jenkins controller to talk to Jenkins agent;
. Run `echo -n 'password' > adminpassword` to setup password for admin user (watchout to not add newlines);
. Run `docker compose up -d`;
. (Optionally) Add `update.sh` script to be run by cron periodically.
If all went well jenkins should be reachable on `localhost:8080`, login with user `admin` and password from step 2.
== Workflow for setting up jobs
. A pull request is initiated on a git platform where this configuration is hosted, with necessary changes in `jenkins.yml` jobs section;
. Maintainer(s) review the change, merge if appropriate;
. Either periodically, manually, or on some way set up trigger, machine hosting Jenkins controller does a `git pull` and `docker compose up -d --build`, after which the changes should appear on CI.
== User permissions and per-project secrets
Jobs often need secrets, however these secrets should be scoped per-user / project. A solution is therefore to use folders and matrix authentication plugin. For each user or project a top level folder should be created. In this folder administrator configures full permissions to necessary users (folder view -> Configure -> General -> Enable project-based-security). Users are then able to and edit secrets, but only for their jobs.
== Points of Improvement
. Externalize user management (eg LDAP);
. Use vaults for secret storage;
. Change agent from persistent ssh to an adhoc provisioned instance.

5
create-keys.sh Normal file
View File

@ -0,0 +1,5 @@
rm -f id_rsa
rm -f id_rsa.pub
ssh-keygen -t rsa -b 4096 -f ./id_rsa
(echo -n 'JENKINS_AGENT_SSH_PUBKEY=' ; cat id_rsa.pub) > agent.env

24
docker-compose.yml Normal file
View File

@ -0,0 +1,24 @@
services:
jenkins-controller:
build:
context: .
dockerfile: jenkins.Dockerfile
environment:
- CASC_JENKINS_CONFIG=/jenkins.yml
volumes:
- ./jenkins.yml:/jenkins.yml
- ./id_rsa:/secrets/id_rsa
- ./adminpassword:/secrets/adminpassword
- jenkins-data:/var/jenkins_home
ports:
- 8080:8080
jenkins-agent:
env_file: ./agent.env
build:
context: .
dockerfile: jenkins-agent.Dockerfile
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
volumes:
jenkins-data:

4
jenkins-agent.Dockerfile Normal file
View File

@ -0,0 +1,4 @@
FROM jenkins/ssh-agent:latest
COPY --from=docker:dind /usr/local/bin/docker /usr/local/bin/
RUN groupadd docker -g 971
RUN usermod -aG docker jenkins

2
jenkins.Dockerfile Normal file
View File

@ -0,0 +1,2 @@
FROM jenkins/jenkins:jdk17
RUN jenkins-plugin-cli --plugins 'configuration-as-code:latest ssh-slaves:latest credentials-binding:latest subversion:latest job-dsl:latest pipeline-model-definition:latest pipeline-build-step:latest ansible:latest git:latest workflow-aggregator:latest docker-workflow:latest ws-cleanup:latest pipeline-graph-view:latest ssh-agent:latest matrix-auth:latest'

88
jenkins.yml Normal file
View File

@ -0,0 +1,88 @@
jenkins:
systemMessage: "Jenkins CASC"
numExecutors: 0
nodes:
- permanent:
mode: NORMAL
name: "agent1"
labelString: "docker"
numExecutors: 8
remoteFS: "/home/jenkins/agent"
launcher:
SSHLauncher:
host: "jenkins-agent"
port: 22
credentialsId: agent_ssh
launchTimeoutSeconds: 60
maxNumRetries: 3
retryWaitTime: 30
sshHostKeyVerificationStrategy:
manuallyTrustedKeyVerificationStrategy:
requireInitialManualTrust: false
authorizationStrategy:
projectMatrix:
entries:
- group:
name: "authenticated"
permissions:
- "Job/Read"
- "Overall/Read"
- user:
name: "admin"
permissions:
- "Overall/Administer"
- user:
name: "anonymous"
permissions:
- "Job/Read"
- "Overall/Read"
securityRealm:
local:
allowsSignup: false
users:
- id: admin
name: admin
password: "${readFile:/secrets/adminpassword}"
appearance:
pipelineGraphView:
showGraphOnBuildPage: true
showGraphOnJobPage: true
credentials:
system:
domainCredentials:
- credentials:
- basicSSHUserPrivateKey:
scope: GLOBAL
id: agent_ssh
username: "jenkins"
description: "SSH key for jenkins agent"
privateKeySource:
directEntry:
privateKey: "${readFile:/secrets/id_rsa}"
jobs:
- script: >
folder('index_scheme_org') {
displayName: 'index.scheme.org'
}
- script: >
folder('index_scheme_org2') {
displayName: 'index.scheme.org2'
}
- script: >
multibranchPipelineJob('index_scheme_org/build') {
displayName: 'Build and deploy'
branchSources {
git {
id('github')
remote('https://github.com/schemeorg-community/index.scheme.org')
}
}
orphanedItemStrategy {
discardOldItems {
numToKeep(10)
}
}
}

10
update.sh Normal file
View File

@ -0,0 +1,10 @@
#!/bin/bash
git fetch
if [[ $(git rev-parse HEAD) != $(git rev-parse @{u}) ]]
then
echo 'Behind remote config; updating'
git pull
docker compose up -d --build
fi