Install Ubuntu 20.04
I install a minimal desktop instance.
Install packages needed for later:
apt-get install -y vim git build-essential openssh-server curl wget
Update and upgrade:
sudo -i
apt-get update
apt-get upgrade
Open the firewall ports needed for later:
ufw allow 8080
ufw allow 22
ufw allow 3000
ufw allow 80
ufw allow 443
ufw allow 8443
ufw enable
ufw status
Install Gitea
First install MariaDB Server for use with Gitea:
apt-get install -y mariadb-server
mysql_secure_installation
Set a password
Select yes to the remaining questions.
Create a database to make sure everything is working correctly, change the password to your own:
mysql -u root -p
create database gitea;
grant all privileges on gitea.* to 'gitea'@localhost identified by 'password';
quit;
Add the Gitea repository, install Gitea and start it:
curl -sL -o /etc/apt/trusted.gpg.d/morph027-gitea.asc https://packaging.gitlab.io/gitea/gpg.key
echo "deb [arch=amd64] https://packaging.gitlab.io/gitea gitea main" | sudo tee /etc/apt/sources.list.d/morph027-gitea.list
apt-get update
apt-get install -y gitea
systemctl start gitea
systemctl enable gitea
Create the log directory:
mkdir -p /var/log/gitea
Go to the Gitea web page on your server:
http://ip.add.re.ss:3000
Also make sure you can get there by name:
http://gitea.home.local:3000
Create the Administrator Username and password. Make changes to the Gitea configuration as you feel appropriate, however, the log path should now be:
/var/log/gitea
Change the log directory ownership:
chown gitea:gitea /var/log/gitea
<p id="On Gitea create an organization:Dashboard -> Organization
Organization Name: Home
Add the jenkins user:
Site Administration -> User Accounts -> Create User Account
Do not require the user to change the password on next login.
People:
jenkins
jud

Install Jenkins
First install the Jenkins prerequisites:
apt-get install openjdk-11-jdk
java -version
openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing)
Add the Jenkins repository and install Jenkins:
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
apt-get update
apt-get install -y jenkins
Unlock Jenkins by go to the URL:
http://192.168.128.65:8080
cat /var/lib/jenkins/secrets/initialAdminPassword
9c48273795be49b39aa2ba4a99ce5f93
Paste the code into the Administrator password field.
Install the suggested plugins.
Create the first Admin User.
Create the Self-signed Certificate
Back up the SSL configuration file and create a Jenkins configuration file.
cp /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.0
cp /etc/ssl/openssl.cnf /etc/ssl/jenkins.cnf
Edit the jenkins file and add the subject_alt_name stanza below in the [ v3_va ] section:
vim /etc/ssl/jenkins.cnf
[ v3_ca ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = gitea
DNS.2 = gitea.home.local
DNS.3 = jenkins
DNS.4 = jenkins.home.local
DNS.5 = localhost
IP.1 = 127.0.0.1
IP.2 = 192.168.128.65
This is the jenkins.cnf file I used. Copy this file into the /etc/ssl directory.
cat /etc/ssl/jenkins.cnf | egrep -v ^#
HOME = .
oid_section = new_oids
[ new_oids ]
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
x509_extensions = usr_cert # The extensions to add to the cert
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
default_days = 365 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = default # use public key default MD
preserve = no # keep passed DN ordering
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
x509_extensions = v3_ca # The extensions to add to the self signed cert
string_mask = utf8only
req_extensions = v3_req # The extensions to add to a certificate request
[ req_ext ]
subjectKeyIdentifier = hash
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
nsComment = "OpenSSL Generated Certificate"
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = US
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Georgia
localityName = Locality Name (eg, city)
localityName_default = Evans
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Home
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Office
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
[ v3_req ]
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
subjectAltName = @alt_names
[ crl_ext ]
authorityKeyIdentifier=keyid:always
[ proxy_cert_ext ]
basicConstraints=CA:FALSE
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
[ tsa ]
default_tsa = tsa_config1 # the default TSA section
[ tsa_config1 ]
dir = ./demoCA # TSA root directory
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
signer_digest = sha256 # Signing digest to use. (Optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
other_policies = tsa_policy2, tsa_policy3 # acceptable policies (optional)
digests = sha1, sha256, sha384, sha512 # Acceptable message digests (mandatory)
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
clock_precision_digits = 0 # number of digits after dot. (optional)
ordering = yes # Is ordering defined for timestamps?
# (optional, default: no)
tsa_name = yes # Must the TSA name be included in the reply?
# (optional, default: no)
ess_cert_id_chain = no # Must the ESS cert id chain be included?
# (optional, default: no)
ess_cert_id_alg = sha1 # algorithm to compute certificate
# identifier (optional, default: sha1)
[ alt_names ]
DNS.1 = gitea
DNS.2 = gitea.home.local
DNS.3 = jenkins
DNS.4 = jenkins.home.local
DNS.5 = localhost
IP.1 = 127.0.0.1
IP.2 = 192.168.128.65
# End /etc/ssl/jenkins.conf
The self-signed certificate will be used for Nginx later. Create a self-signed certificate:
openssl req -x509 -nodes -days 3650 -config /etc/ssl/jenkins.cnf -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt -sha256 -reqexts v3_req
Country Name (2 letter code) [US]:
State or Province Name (full name) [Georgia]:
Locality Name (eg, city) [Evans]:
Organization Name (eg, company) [Home]:
Organizational Unit Name (eg, section) [Office]:
Common Name (e.g. server FQDN or YOUR name) []:gitea.home.local
Email Address []:
Check the certificate you just created:
openssl x509 -in /etc/ssl/certs/nginx-selfsigned.crt -text -noout
openssl x509 -in /etc/ssl/certs/nginx-selfsigned.crt -noout -ext subjectAltName
Create a pkcs12 file, do not leave the password blank:
openssl pkcs12 -export -out jenkins-selfsigned.p12 -inkey /etc/ssl/private/nginx-selfsigned.key -in /etc/ssl/certs/nginx-selfsigned.crt
Enter Export Password:
Verifying - Enter Export Password:
Use keytool for Java and Jenkins to convert from .p12 to .jks. Just FYI new password will be added to the Jenkins configuration file:
keytool -importkeystore -destkeystore jenkins.jks -deststoretype PKCS12 -srcstoretype PKCS12 -srckeystore jenkins-selfsigned.p12
Create a directory for the jenkins keystore, and place our keystore in it:
mkdir -p /etc/jenkins
mv /etc/ssl/jenkins.jks /etc/jenkins/
chown -R jenkins: /etc/jenkins
chmod 700 /etc/jenkins
chmod 600 /etc/jenkins/jenkins.jks
Verify the .jks file:
keytool -list -v -keystore /etc/jenkins/jenkins.jks
Backup the Jenkins Configuration file:
cp /etc/default/jenkins /etc/default/jenkins.0
Edit the Jenkins configuration file to add SSL by add the following configuration stanza below:
vim /etc/default/jenkins
HTTP_PORT="-1"
HTTPS_PORT="8443"
HTTPS_KEYSTORE="/etc/jenkins/jenkins.jks"
HTTPS_KEYSTORE_PASSWORD="<your-password>"
JENKINS_ARGS="--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT --httpsPort=$HTTPS_PORT --httpsKeyStore=$HTTPS_KEYSTORE --httpsKeyStorePassword=$HTTPS_KEYSTORE_PASSWORD"
Restart Jenkins:
systemctl restart jenkins
Navigate to Jenkins on your browser:
https://192.168.128.65:8443
Configure Nginx as an SSL Termination Proxy
Install Nginx and allow it through the firewall.
apt-get install -y nginx
systemctl status nginx
ufw allow 'Nginx Full'
ufw status
Go to web page and make sure it works:
http://192.168.128.65
http://gitea.home.local

Back up the default sites file:
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.0
First we will set up Nginx to proxy for Gitea and Gitea will be the default redirect if you just go to the website:
cat /etc/nginx/sites-available/default | egrep -v ^#
server {
# gitea.home.local is the default
listen 80;
server_name gitea.home.local;
return 301 https://$server_name$request_uri;
}
server {
server_name gitea.home.local;
listen 443 ssl http2;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
# Log files
access_log /var/log/nginx/gitea.access.log;
error_log /var/log/nginx/gitea.error.log;
# Handle / requests
location / {
proxy_pass http://192.168.128.65:3000;
}
}
Set up Nginx for SSL:
cat /etc/nginx/snippets/self-signed.conf
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
cat /etc/nginx/snippets/ssl-params.conf
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
Check and make sure the firewall is open:
ufw app list
Available applications:
CUPS
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
Test the Nginx configuration:
nginx -t
nginx: [warn] "ssl_stapling" ignored, issuer certificate not found for certificate "/etc/ssl/certs/nginx-selfsigned.crt"
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Make sure you can login to Gitea:
https://192.168.128.65
https://gitea.home.local
Set up Nginx to proxy for Jenkins:
Backup the Nginx configuration for Gitea:
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.gitea.works
Change the file /etc/nginx/sites-available/default to work for Jenkins:
server {
server_name jenkins.home.local;
listen 443 ssl http2;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
location / {
proxy_set_header Host $host:$server_port;
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_pass http://192.168.128.65:8080;
proxy_read_timeout 90;
proxy_redirect http://192.168.128.65:8080 https://jenkins.home.local;
proxy_http_version 1.1;
proxy_request_buffering off;
add_header 'X-SSH-Endpoint' 'jenkins.home.local:50022' always;
}
}
Check the Nginx configuration and restart:
nginx -t
systemctl restart nginx
Test that you can login to the Jenkins server.
https://192.168.128.65
https://jenkins.home.local

Backup the Nginx configuration for Jenkins:
cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.jenkins.works
Now combine the two configuration files:
cat /etc/nginx/sites-available/default | egrep -v ^#
server {
server_name jenkins.home.local;
listen 443 ssl http2;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
location / {
proxy_set_header Host $host:$server_port;
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_pass http://192.168.128.65:8080;
proxy_read_timeout 90;
proxy_redirect http://192.168.128.65:8080 https://jenkins.home.local;
proxy_http_version 1.1;
proxy_request_buffering off;
add_header 'X-SSH-Endpoint' 'jenkins.home.local:50022' always;
}
}
server {
# gitea.home.local is the default
listen 80;
server_name gitea.home.local;
return 301 https://$server_name$request_uri;
}
server {
server_name gitea.home.local;
listen 443 ssl http2;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
# log files
access_log /var/log/nginx/gitea.access.log;
error_log /var/log/nginx/gitea.error.log;
# Handle / requests
location / {
proxy_pass http://192.168.128.65:3000;
}
}
Check the Nginx configuration and restart:
nginx -t
systemctl restart nginx
Now change Jenkins to listen on 127.0.0.1 and Nginx to redirect to 127.0.0.1.
Edit the file /etc/default/jenkins:
HTTP_PORT=8080
HTTP_HOST=127.0.0.1
JENKINS_ARGS="--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT --httpListenAddress=$HTTP_HOST"
Then restart Jenkins:
systemctl restart jenkins
Change the IP address from 192.168.128.65 to 127.0.0.1 in the file /etc/nginx/sites-available/default.
server {
server_name jenkins.home.local;
listen 443 ssl http2;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
location / {
proxy_set_header Host $host:$server_port;
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_pass http://127.0.0.1:8080;
proxy_read_timeout 90;
proxy_redirect http://127.0.0.1:8080 https://jenkins.home.local;
proxy_http_version 1.1;
proxy_request_buffering off;
add_header 'X-SSH-Endpoint' 'jenkins.home.local:50022' always;
}
}
Check the Nginx configuration and restart:
nginx -t
systemctl restart nginx
Make sure both Gitea and Jenkins still work.
Integrate Jenkins with Gitea:
Login to Gitea as the administrator user and create an Organization.

Create a team in Gitea and add yourself and jenkins to the team.

Now create a repository under the Home organization:

Navigate in the Jenkins Dashboard as the Admin user:
Manage Jenkins -> Manage Plugins -> Available -> Search -> gitea
Gitea plugin
Install without restart

Navigate in the Jenkins Dashboard as the Admin user:
Manage Jenkins -> Configure System -> Gitea Servers -> Add
Server URL:
http://192.168.128.65:3000
Click Save
On the Jenkins server create a Jenkins Project:
New Item
Enter an item name
Gitea Organization Folder
Choose:
Organization Folder
OK

Gitea Organization Folder
Display Name: Gitea Integration
Projects -> Repository Sources -> Add ->Gitea Organization
Server will fill in automatically
Credentials
Add
jenkins


Create the repository on your development box and initialize git:
mkdir Test
cd Test
touch README.md
vim Jenkinsfile
pipeline {
agent any
stages {
stage('Do nothing') {
steps {
sh '/bin/true'
}
}
}
}
git config --global http.sslverify false
git init
git add .
git commit -m “Added README.md and Jenkinsfile”
git remote add origin https://gitea.home.local/jud/Test.git
git push -u origin master
Check the Jenkins Log:

Make the change in the Gitea configuration file so that the URL shows correctly for a repository:
vim /etc/gitea/app.ini
ROOT_URL = https://gitea.home.local/
systemctl restart gitea