Software List Required for Jenkins Server#
Required to Run Jenkins#
- Jenkins
- Jdk 17+ (Required to run Jenkins)
- Nginx (Optional, can be accessed directly via IP + port)
Business Requirements#
- Maven
- Modify Maven source
- JDK 8 (Consistent with the Java version required by the business code)
- NVM (Manage NodeJS versions)
- NodeJS 10.24.1
- NodeJS 12.22.12
- NodeJS 14.21.3
- NodeJS 16.20.2
- NodeJS 18.20.5
- NodeJS 20.18.1
- Code credential configuration (Required to pull code)
- SSH-Keygen
- GitLab account password
- PHP (Consistent with the PHP version required by the business code)
- Compress
- Ansible
- Configure account password
- Configure passwordless execution of sudo commands
Plugin List Required for Jenkins#
- Localization Support
- Localization: Chinese (Simplified)
- Locale
- GitLab Related
- Blue Ocean
- Role-based Authorization Strategy
- Pipeline: Stage View
- Build Pipeline
- Version Number
Software List Required for Application Server#
- JDK 8 (Required for backend Java package operation)
- Nginx (Required for frontend package proxy)
- Supervisord (Backend Java process management)
- PHP
- compose
Jenkins Installation Configuration#
Jenkins Server#
Install a Packaging Environment Consistent with the Business#
Install JDK 8#
Due to Oracle's enforcement of login downloads for older versions of JDK to ensure updates, we need to manually download JDK 8 from the Oracle Java website and then upload it to the server. Here we will upload the JDK 8 compressed package to the /usr/local/src/
directory on the server.
cd /usr/local/src
Unzip the precompiled JDK 8 compressed package and move it to the outer directory:
tar -zxvf jdk-8u371-linux-x64.tar.gz
mv jdk1.8.0_371 /usr/local/jdk8
Write environment variables for subsequent packaging calls:
echo 'PATH=$PATH:/usr/local/jdk8/bin
export PATH' >> /etc/profile
echo 'JAVA_HOME=/usr/local/jdk8' >> /etc/profile
Refresh the environment variables to make them effective.
source /etc/profile
Install and Configure Maven#
Install Maven
The download address for Maven is as follows: https://archive.apache.org/dist/maven/maven-3/
Choose the latest version to download.
For the server, you can use the wget
command to download, and for domestic servers, use the Tsinghua source to download. Here we download it to the /usr/local/src
directory.
cd /usr/local/src
wget https://archive.apache.org/dist/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz
Unzip the precompiled Maven compressed package and move it to the outer directory:
tar -zxvf apache-maven-3.9.9-bin.tar.gz
cp -r /usr/local/src/apache-maven-3.9.9 /usr/local/maven3.9
Write environment variables for subsequent packaging calls:
echo '
PATH=$PATH:/usr/local/maven3.9/bin
export PATH' >> /etc/profile
Refresh the environment variables to make them effective.
source /etc/profile
Configure Maven
The content that needs to be configured includes the following two points:
- Change the mirror source address to a domestic source
- Configure the private mirror source address
Modify the Maven configuration file:
vim /usr/local/maven3.9/conf/settings.xml
Add the following content:
...
<servers>
+ <server>
+ <id>self-hosted-nexus</id>
+ <username>${username}</username>
+ <password>${password}</password>
+ </server>
</servers>
...
<mirrors>
+ <mirror>
+ <id>self-hosted-nexus</id>
+ <mirrorOf>*</mirrorOf>
+ <name>self-hosted-nexus</name>
+ <url>${url}</url>
+ </mirror>
+ <mirror>
+ <id>aliyun-maven</id>
+ <mirrorOf>*</mirrorOf>
+ <url>https://maven.aliyun.com/repository/public/</url>
+ </mirror>
</mirrors>
...
Replace ${username}
and ${password}
with the account password for the private repository, and replace ${url}
with an accessible address.
Install NodeJS#
Install NVM
The download address for NVM is as follows: https://github.com/nvm-sh/nvm
Choose the latest version to download.
For the server, you can use the wget
command to download, and for domestic servers, use the Tsinghua source to download. Here we download it to the /usr/local/src
directory.
cd /usr/local/src
wget https://github.com/nvm-sh/nvm/archive/refs/tags/v0.40.1.tar.gz -O nvm-0.40.1.tar.gz
Unzip the precompiled NVM compressed package and move it to the outer directory:
tar -zxvf nvm-0.40.1.tar.gz
mv nvm-0.40.1 /usr/local/nvm0.40
Add it to the Bash configuration file:
echo "source /usr/local/nvm0.40/nvm.sh" >> ~/.bashrc
Refresh the Bash configuration to make it effective:
source ~/.bashrc
Install Multiple Versions of NodeJS
When using NVM to install NodeJS, if you cannot query the NodeJS version and can only see the io.js version, it is because NVM cannot connect to the NodeJS version server. You can specify the server for version installation.
NVM_NODEJS_ORG_MIRROR=https://nodejs.org/dist nvm install <nodejs_version>
# or
NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node/ nvm install <nodejs_version>
Use NVM to install various stable versions of NodeJS:
nvm install v10.24.1
nvm install v12.22.12
nvm install v14.21.3
nvm install v16.20.2
nvm install v18.20.5
nvm install v20.18.1
Install and Configure PHP#
[!TODO]
Install and Configure Jenkins#
Install Required Runtime for Jenkins#
The new version of Jenkins requires JDK 17 and above. Here we manually download the latest JDK version from the Oracle Java website and then upload it to the server's /usr/local/src/
directory.
cd /usr/local/src
Unzip the precompiled JDK 21 compressed package and move it to the outer directory:
tar -zxvf jdk-21-linux-x64.tar.gz
mv jdk21 /usr/local/jdk21
Here we do not write JDK 21 into the environment variables to avoid using the wrong JDK environment during packaging. We will use the absolute path to use JDK 21 when starting Jenkins.
Install Jenkins#
Download the installation package for the RedHat version of Jenkins. Domestic servers use the Tsinghua source to download.
cd /usr/local/src
wget https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/jenkins-2.491-1.1.noarch.rpm --no-check-certificate
Install the binary installation package
rpm -ivh jenkins-2.491-1.1.noarch.rpm
Configure Jenkins#
Modify the Jenkins startup configuration file
vim /usr/lib/systemd/system/jenkins.service
Modify the following content:
#
# This file is managed by systemd(1). Do NOT edit this file manually!
# To override these settings, run:
#
# systemctl edit jenkins
#
# For more information about drop-in files, see:
#
# https://www.freedesktop.org/software/systemd/man/systemd.unit.html
#
[Unit]
Description=Jenkins Continuous Integration Server
Requires=network.target
After=network.target
StartLimitBurst=5
StartLimitIntervalSec=5m
[Service]
Type=notify
NotifyAccess=main
ExecStart=/usr/bin/jenkins
Restart=on-failure
SuccessExitStatus=143
# Configures the time to wait for start-up. If Jenkins does not signal start-up
# completion within the configured time, the service will be considered failed
# and will be shut down again. Takes a unit-less value in seconds, or a time span
# value such as "5min 20s". Pass "infinity" to disable the timeout logic.
#TimeoutStartSec=90
# Unix account that runs the Jenkins daemon
# Be careful when you change this, as you need to update the permissions of
# $JENKINS_HOME, $JENKINS_LOG, and (if you have already run Jenkins)
# $JENKINS_WEBROOT.
- User=jenkins
+ User=root
- Group=jenkins
+ Group=root
# Directory where Jenkins stores its configuration and workspaces
- Environment="JENKINS_HOME=/var/lib/jenkins"
+ Environment="JENKINS_HOME=/data/jenkins"
- WorkingDirectory=/var/lib/jenkins
+ WorkingDirectory=/data/jenkins
# Location of the Jenkins WAR
#Environment="JENKINS_WAR=/usr/share/java/jenkins.war"
# Location of the exploded WAR
Environment="JENKINS_WEBROOT=%C/jenkins/war"
# Location of the Jenkins log. By default, systemd-journald(8) is used.
#Environment="JENKINS_LOG=%L/jenkins/jenkins.log"
# The Java home directory. When left empty, JENKINS_JAVA_CMD and PATH are consulted.
#Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
+ Environment="JAVA_HOME=/usr/local/jdk21"
# The Java executable. When left empty, JAVA_HOME and PATH are consulted.
#Environment="JENKINS_JAVA_CMD=/etc/alternatives/java"
# Arguments for the Jenkins JVM
Environment="JAVA_OPTS=-Djava.awt.headless=true"
# Unix Domain Socket to listen on for local HTTP requests. Default is disabled.
#Environment="JENKINS_UNIX_DOMAIN_PATH=/run/jenkins/jenkins.socket"
# IP address to listen on for HTTP requests.
# The default is to listen on all interfaces (0.0.0.0).
#Environment="JENKINS_LISTEN_ADDRESS="
# Port to listen on for HTTP requests. Set to -1 to disable.
# To be able to listen on privileged ports (port numbers less than 1024),
# add the CAP_NET_BIND_SERVICE capability to the AmbientCapabilities
# directive below.
Environment="JENKINS_PORT=8080"
# IP address to listen on for HTTPS requests. Default is disabled.
#Environment="JENKINS_HTTPS_LISTEN_ADDRESS="
# Port to listen on for HTTPS requests. Default is disabled.
# To be able to listen on privileged ports (port numbers less than 1024),
# add the CAP_NET_BIND_SERVICE capability to the AmbientCapabilities
# directive below.
#Environment="JENKINS_HTTPS_PORT=443"
# Path to the keystore in JKS format (as created by the JDK's keytool).
# Default is disabled.
#Environment="JENKINS_HTTPS_KEYSTORE=/path/to/keystore.jks"
# Password to access the keystore defined in JENKINS_HTTPS_KEYSTORE.
# Default is disabled.
#Environment="JENKINS_HTTPS_KEYSTORE_PASSWORD=s3cR3tPa55w0rD"
# IP address to listen on for HTTP2 requests. Default is disabled.
#Environment="JENKINS_HTTP2_LISTEN_ADDRESS="
# HTTP2 port to listen on. Default is disabled.
# To be able to listen on privileged ports (port numbers less than 1024),
# add the CAP_NET_BIND_SERVICE capability to the AmbientCapabilities
# directive below.
#Environment="JENKINS_HTTP2_PORT="
# Controls which capabilities to include in the ambient capability set for the
# executed process. Takes a whitespace-separated list of capability names, e.g.
# CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, CAP_SYS_PTRACE. Ambient capability sets are
# useful if you want to execute a process as a non-privileged user but still
# want to give it some capabilities. For example, add the CAP_NET_BIND_SERVICE
# capability to be able to listen on privileged ports (port numbers less than
# 1024).
#AmbientCapabilities=CAP_NET_BIND_SERVICE
# Debug level for logs. The higher the value, the more verbose. 5 is INFO.
#Environment="JENKINS_DEBUG_LEVEL=5"
# Set to true to enable logging to /var/log/jenkins/access_log.
#Environment="JENKINS_ENABLE_ACCESS_LOG=false"
# Servlet context (important if you want to use reverse proxying)
#Environment="JENKINS_PREFIX=/jenkins"
# Arbitrary additional arguments to pass to Jenkins.
# Full option list: java -jar jenkins.war --help
#Environment="JENKINS_OPTS="
# Maximum core file size. If unset, the value from the OS is inherited.
#LimitCORE=infinity
# Maximum file size. If unset, the value from the OS is inherited.
#LimitFSIZE=infinity
# File descriptor limit. If unset, the value from the OS is inherited.
#LimitNOFILE=8192
# Maximum number of processes. If unset, the value from the OS is inherited.
#LimitNPROC=32768
# Set the umask to control the permission bits of files that Jenkins creates.
#
# 0027 makes files read-only for group and inaccessible for others, which some
# security sensitive users might consider beneficial, especially if Jenkins
# is running on a server that is used for multiple purposes. Beware that 0027
# permissions would interfere with sudo scripts that run on the controller
# (see JENKINS-25065).
#
# Note also that the particularly sensitive parts of $JENKINS_HOME (such as
# credentials) are always written without 'other' access. So the umask values
# only affect job configuration, build records, etc.
#
# If unset, the value from the OS is inherited, which is normally 0022.
# The default umask comes from pam_umask(8) and /etc/login.defs.
#UMask=0022
[Install]
WantedBy=multi-user.target
After modifying, reload the configuration file
systemctl daemon-reload
Here, the working directory of Jenkins is modified to be under the /data
path, and you need to manually create this directory:
mkdir -p /data/jenkins
After creation, run Jenkins
systemctl enable jenkins --now
Use the following command to check the running status:
systemctl status jenkins
If it runs successfully, you can access the Jenkins web interface through the Jenkins server IP address + port 8080 within the same local area network.
The default password can be viewed with the following command:
cat /data/jenkins/secrets/initialAdminPassword
The default download source for Jenkins is slow in China and needs to be changed to the Tsinghua source:
vim /data/jenkins/hudson.model.UpdateCenter.xml
Modify the following content:
<?xml version='1.1' encoding='UTF-8'?>
<sites>
<site>
<id>default</id>
- <url>https://updates.jenkins.io/update-center.json</url>
+ <url>https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json</url>
</site>
</sites>
After installing Jenkins, the directories required at startup have already been generated, and the update address is still update.jenkins.io
, which still needs to be changed to a domestic source:
cd /data/jenkins/updates
sed -i 's#updates.jenkins.io/download/plugins#mirrors.tuna.tsinghua.edu.cn/jenkins/plugins#g' default.json
sed -i 's#www.google.com#www.bilibili.com#g' default.json
Configure Code Pull Credentials#
Pull Using SSH Protocol#
If Jenkins can use the SSH protocol to pull code, you can configure the public key of the local SSH on the Git server.
First, generate SSH-Keygen. For security reasons, GitHub no longer allows the generation of keys based on the RSA2048 algorithm. Here we use the ed25519 algorithm. If the server cannot support this algorithm, you can use the RSA4096 algorithm.
ssh-keygen -t ed25519 -C "[email protected]"
# or
ssh-keygen -t rsa -b 4096 -C "[email protected]"
When the system prompts "Enter file in which to save the key," you can press Enter to end the default file location. If you have created it before, ssh-keygen may ask you to overwrite the key. In this case, you can customize the name of the newly created file. At this point, you can modify the .gitconfig
file to specify which key to use for code pulling. Here we assume the newly generated key is named id_rsa_gitlab
and id_rsa_gitlab.pub
.
Modify the SSH configuration file:
vim /root/.ssh/config
Write the following content:
Host self-hosted-gitlab
HostName gitlab.example.com
User git
IdentityFile /root/.ssh/id_rsa_gitlab
IdentitiesOnly yes
At the same time, you need to configure the content of the id_rsa_gitlab.pub
file on the GitLab server.
Pull Using HTTP Protocol#
When you cannot use the SSH protocol to pull code, you need to configure the login credentials for the Git repository.
In the Jenkins web interface, click in the following order:
[Manage Jenkins] -> [Credentials] -> Bottom [System] -> [Global credentials (unrestricted)] -> [+ Add Credentials]
Select the type of credentials: Username with password
, and fill in the Git server username and address according to the specific information.
Configure Ansible for Distribution#
Use Ansible software to distribute the completed compiled business code package. During the distribution process, the scp
command is used, so ensure that the Jenkins server and the business server can communicate via the SSH protocol.
Install Ansible on the Jenkins server
yum install -y ansible
Configure the Ansible software's hosts file:
vim /etc/ansible/hosts
Write the following content:
+ [web]
+ 192.168.50.101 ansible_ssh_port=22 ansible_ssh_user=nginx ansible_ssh_pass="your_password"
+ 192.168.50.102 ansible_ssh_port=22 ansible_ssh_user=nginx ansible_ssh_pass="your_password"
The two servers 192.168.50.101 and 192.168.50.102 are the servers where the business is located. Ensure that these two servers can be logged in using the nginx
user.
After completion, use the Ansible Ping module for testing:
ansible web -m ping
A return value of pong
indicates success.
Configure Nginx Reverse Proxy#
After the Jenkins service starts successfully, it can be accessed via IP:Port
using a jump server within the local area network. For external access, you need to configure Nginx reverse proxy with the following configuration:
This Nginx configuration file is configured on the outermost proxy server.
vim /usr/local/nginx1.27/conf/conf.d/jenkins.conf
Write the following content:
upstream jenkins {
keepalive 32; # keepalive connections
server 127.0.0.1:8080; # jenkins ip and port
}
# Required for Jenkins websocket agents
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80; # Listen on port 80 for IPv4 requests
server_name jenkins.example.com; # replace 'jenkins.example.com' with your server domain name
# this is the jenkins web root directory
# (mentioned in the output of "systemctl cat jenkins")
root /var/run/jenkins/war/;
access_log /var/log/nginx/jenkins.access.log;
error_log /var/log/nginx/jenkins.error.log;
# pass through headers from Jenkins that Nginx considers invalid
ignore_invalid_headers off;
location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
# rewrite all static files into requests to the root
# E.g /static/12345678/css/something.css will become /css/something.css
rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
}
location /userContent {
# have nginx handle all the static requests to userContent folder
# note : This is the $JENKINS_HOME dir
root /var/lib/jenkins/;
if (!-f $request_filename){
# this file does not exist, might be a directory or a /**view** url
rewrite (.*) /$1 last;
break;
}
sendfile on;
}
location / {
sendfile off;
proxy_pass http://jenkins;
proxy_redirect default;
proxy_http_version 1.1;
# Required for Jenkins websocket agents
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_max_temp_file_size 0;
#this is the maximum upload size
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_request_buffering off; # Required for HTTP CLI commands
}
}
If you encounter some path issues when using Blue Ocean, add the following code snippet to the configuration file:
if ($request_uri ~* "/blue(/.*)") {
proxy_pass http://YOUR_SERVER_IP:YOUR_JENKINS_PORT/blue$1;
break;
}
Web Application Server#
Configure Nginx User Permissions#
Since Jenkins needs to distribute the completed packaged code, the distribution process may involve operations that require root
permissions. When executing sudo
, a password needs to be entered, so the permissions of the nginx
user need to be modified to allow passwordless execution of sudo
commands.
Modify the following file content:
vim /etc/sudoers
Add the following content:
...
## Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: ALL
+ nginx ALL=(ALL) NOPASSWD: ALL
...
Ensure that the nginx
user exists on the business server and can execute login operations. If the nginx
user was created with the /sbin/nologin
parameter, you can perform the following operation to restore it:
vim /etc/passwd
Modify the following content:
- nginx:x:1000:1000::/home/nginx:/sbin/nologin
+ nginx:x:1000:1000::/home/nginx:/bin/bash
Install Software Environment Required by the Business#
Install JDK 8#
Due to Oracle's enforcement of login downloads for older versions of JDK to ensure updates, we need to manually download JDK 8 from the Oracle Java website and then upload it to the server. Here we will upload the JDK 8 compressed package to the /usr/local/src/
directory on the server.
cd /usr/local/src
Unzip the precompiled JDK 8 compressed package and move it to the outer directory:
tar -zxvf jdk-8u371-linux-x64.tar.gz
mv jdk1.8.0_371 /usr/local/jdk8
Write environment variables for subsequent packaging calls:
echo 'PATH=$PATH:/usr/local/jdk8/bin
export PATH' >> /etc/profile
echo 'JAVA_HOME=/usr/local/jdk8' >> /etc/profile
Refresh the environment variables to make them effective.
source /etc/profile
Install and Configure Supervisord#
Install Supervisord
For Java processes, using commands like nohup
to start them does not allow for complete control and monitoring of the processes. Here we choose to use Supervisord to manage and monitor Java processes.
Download the Supervisord source code to the /usr/local/src
directory:
cd /usr/local/src
wget https://files.pythonhosted.org/packages/ce/37/517989b05849dd6eaa76c148f24517544704895830a50289cbbf53c7efb9/supervisor-4.2.5.tar.gz
Unzip:
tar -zxvf supervisor-4.2.5.tar.gz
Since Supervisord is written in Python, it needs to be installed using Python:
cd /usr/local/src/supervisor-4.2.5
python3 setup.py install
After installation, write the supervisord
command into the global variables:
ln -sf /usr/local/bin/supervisor* /usr/bin/
ln -sf /usr/local/bin/echo_supervisord_conf /usr/bin/
Once written successfully, you can check the version with the following command:
supervisord --version
Configure Supervisord
Create the working directory required for Supervisord to run:
mkdir -p /etc/supervisord.d
mkdir -p /var/log/supervisor
mkdir -p /var/run/supervisor
Create the default configuration file:
echo 'D /var/run/supervisor 0775 root root -' > /etc/tmpfiles.d/supervisor.conf
echo_supervisord_conf > /etc/supervisord.conf
Modify the configuration file content:
...
[unix_http_server]
- file=/tmp/supervisor/supervisor.sock ; (the path to the socket file)
+ file=/var/run/supervisor/supervisor.sock ; (the path to the socket file)
[supervisorctl]
- serverurl=unix:///tmp/supervisor/supervisor.sock ; use a unix:// URL for a unix socket
+ serverurl=unix:///var/run/supervisor/supervisor.sock ; use a unix:// URL for a unix socket
[inet_http_server] ; inet (TCP) server disabled by default
- ;port=*:9001 ; ip_address:port specifier, *:port for all iface
+ port=*:9001 ; ip_address:port specifier, *:port for all iface
- ;username=admin ; default is no username (open server)
+ username=admin ; default is no username (open server)
- ;password=<password> ; default is no password (open server)
+ password=<password> ; default is no password (open server)
[supervisord]
- logfile=/tmp/supervisor/supervisord.log
+ logfile=/var/log/supervisor/supervisord.log
[include]
+ files = supervisord.d/*/*.ini supervisord.d/*.ini
Create the Systemd configuration file
vim /etc/systemd/system/supervisord.service
Write the following content:
# supervisord service for systemd (CentOS 7.0+)
# by ET-CS (https://github.com/ET-CS)
[Unit]
Description=Supervisor daemon
[Service]
Type=forking
ExecStart=/usr/bin/supervisord
ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown
ExecReload=/usr/bin/supervisorctl $OPTIONS reload
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
Start Supervisord and configure it to start on boot:
systemctl daemon-reload
systemctl enable supervisord --now
Based on different needs, use directory classification and write the following configuration according to specific business:
vim /etc/supervisord.d/${example-work}/${example-program}
Write the following content:
Warning
Replace the variables in the configuration file with specific values for the business as needed.
[program: ${example-program}]
command=/usr/local/jdk8/bin/java -jar -Xms1g -Xmx1g -Dspring.profiles.active=${env} -Dserver.port=${port} /data/contents/${example-work}/${example-program}.jar
directory=/data/contents/${example-work}/
startsecs=10
autorestart=true
startretries=3
user=root
priority=999
redirect_stderr=true
stdout_logfile_maxbytes=1GB
stdout_logfile_backups = 1
stopasgroup=false
killasgroup=false
stdout_logfile=/data/logs/${example-work}-${example-program}.log
Install Nginx#
The Nginx on the business server only provides the simplest reverse proxy service. SSL certificate parsing, access routing, and access frequency limits will be handled by the outermost proxy and WAF, so only the most basic functionality needs to be installed.
Install PHP#
[!TODO]