Jenkins is an open-source automation server used to build, test and deploy software through pipelines defined as code. In this tutorial you will install the Jenkins LTS release on Ubuntu 24.04 from the official Jenkins repository, run it behind Nginx with a free Let's Encrypt certificate, complete the setup wizard and run a first pipeline. At the end you will also schedule a simple backup of the Jenkins home directory.
Prerequisites
To follow this guide you need:
- A server running Ubuntu 24.04 LTS, for example a CubePath VPS, with at least 2 GB of RAM and 20 GB of free disk space. Jenkins starts with less, but builds quickly use memory and disk.
- A non-root user with
sudoprivileges. - A domain name with a DNS A record pointing to the server's public IP. This guide uses
jenkins.your_domain. - Ports 22, 80 and 443 reachable from the Internet.
Step 1 - Installing Java
Jenkins runs on the Java Virtual Machine and current LTS releases support Java 21. Install the headless OpenJDK 21 runtime from the Ubuntu repositories:
sudo apt update
sudo apt install -y fontconfig openjdk-21-jre-headless
Check the installed version:
java -version
openjdk version "21.0.8" 2025-07-15
OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1)
OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing)
The exact patch version may differ. You do not need to set JAVA_HOME: the Jenkins package finds java on the PATH.
Step 2 - Adding the Jenkins repository
The Ubuntu archive does not ship Jenkins, so add the official LTS (debian-stable) repository. First download its signing key into /etc/apt/keyrings:
sudo install -m 0755 -d /etc/apt/keyrings
sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
Then add the repository, restricted to that key:
echo "deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/" | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null
Update the package index. The Jenkins repository should appear without errors:
sudo apt update
...
Get:5 https://pkg.jenkins.io/debian-stable binary/ Release [2,044 B]
Get:6 https://pkg.jenkins.io/debian-stable binary/ Release.gpg [833 B]
...
NoteThe Jenkins project rotates its repository key from time to time. If
apt updatereportsNO_PUBKEYor an expired signature, download the current key file listed on pkg.jenkins.io/debian-stable and repeat thewgetcommand with it.
Step 3 - Installing Jenkins
Install the package:
sudo apt install -y jenkins
The package creates a jenkins system user, stores all data in /var/lib/jenkins and starts the jenkins service. Confirm that it is running:
sudo systemctl status jenkins
● jenkins.service - Jenkins Continuous Integration Server
Loaded: loaded (/usr/lib/systemd/system/jenkins.service; enabled; preset: enabled)
Active: active (running) since Thu 2026-09-24 10:12:03 UTC; 20s ago
...
By default Jenkins listens on port 8080 on every interface. Since Nginx will be the only public entry point, bind Jenkins to localhost with a systemd override:
sudo systemctl edit jenkins
Add these lines in the editable area between the comments, then save and close the file:
[Service]
Environment="JENKINS_LISTEN_ADDRESS=127.0.0.1"
Restart Jenkins and check which address it listens on:
sudo systemctl restart jenkins
sudo ss -tlnp | grep 8080
LISTEN 0 50 [::ffff:127.0.0.1]:8080 *:* users:(("java",pid=4211,fd=8))
Jenkins can take up to a minute to start. If the command returns nothing, wait and run it again, or follow the log with sudo journalctl -u jenkins -f.
Step 4 - Configuring Nginx as a reverse proxy
Install Nginx:
sudo apt install -y nginx
Create a server block for Jenkins:
sudo nano /etc/nginx/sites-available/jenkins
Add the following configuration, replacing jenkins.your_domain with your domain. The map block and the Upgrade headers let the Jenkins web interface use WebSockets, and proxy_request_buffering off avoids buffering large uploads such as plugin files:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name jenkins.your_domain;
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $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_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 90s;
proxy_request_buffering off;
}
}
Enable the site, test the syntax and reload Nginx:
sudo ln -s /etc/nginx/sites-available/jenkins /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
If UFW is active, allow SSH and web traffic. Port 8080 does not need a rule because Jenkins only listens on localhost:
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw status
Step 5 - Enabling HTTPS with Let's Encrypt
Install Certbot and its Nginx plugin:
sudo apt install -y certbot python3-certbot-nginx
Request a certificate. Certbot validates the domain, edits the Jenkins server block to use the certificate and adds a redirect from HTTP to HTTPS:
sudo certbot --nginx -d jenkins.your_domain
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/jenkins.your_domain/fullchain.pem
...
Successfully deployed certificate for jenkins.your_domain to /etc/nginx/sites-enabled/jenkins
Congratulations! You have successfully enabled HTTPS on https://jenkins.your_domain
The Ubuntu package installs a systemd timer that renews certificates automatically. Test the renewal process:
sudo certbot renew --dry-run
Step 6 - Completing the setup wizard
Open https://jenkins.your_domain in your browser. Jenkins asks for the initial administrator password, which it wrote to a file during the first start:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
3f1e9c2b7a8d4e5f9a0b1c2d3e4f5a6b
Paste it into the Unlock Jenkins page and continue:
- Customize Jenkins: choose Install suggested plugins. This installs Git, Pipeline, Credentials and the other plugins most setups need.
- Create First Admin User: create your own administrator account with a strong password. After this step the initial password stops working.
- Instance Configuration: confirm that the Jenkins URL is
https://jenkins.your_domain/. Jenkins uses it in links, emails and webhooks.
After Start using Jenkins you land on the dashboard. Go to Manage Jenkins: if the reverse proxy is misconfigured, Jenkins shows a warning saying "It appears that your reverse proxy set up is broken". No warning means the proxy headers are correct.
Step 7 - Running your first pipeline
A pipeline describes the build as code in the Groovy-based Jenkinsfile syntax. Create a test job to confirm that Jenkins can run steps on this server:
- On the dashboard, click New Item.
- Enter
hello-pipelineas the name, select Pipeline and click OK. - Scroll to the Pipeline section, keep Pipeline script as the definition and paste this script:
pipeline {
agent any
stages {
stage('Info') {
steps {
sh 'uname -a'
sh 'java -version'
}
}
stage('Build') {
steps {
sh 'echo "Building on $NODE_NAME, build #$BUILD_NUMBER"'
}
}
}
post {
success {
echo 'Pipeline finished successfully'
}
}
}
- Click Save, then Build Now.
Open the build from the Builds list and click Console Output. The last lines should look like this:
Building on built-in, build #1
...
Pipeline finished successfully
[Pipeline] End of Pipeline
Finished: SUCCESS
For real projects, commit the pipeline to your repository as a file named Jenkinsfile and, in the job, set Definition to Pipeline script from SCM with your repository URL. Store Git tokens and SSH keys under Manage Jenkins > Credentials and reference them by ID, never inline in the Jenkinsfile.
TipRunning builds on the built-in node is fine for testing, but in production add at least one agent and set the number of executors on the built-in node to 0 under Manage Jenkins > Nodes. Builds then cannot read files in the Jenkins home directory.
Step 8 - Backing up the Jenkins home directory
All jobs, credentials, plugins and settings live in /var/lib/jenkins. Workspaces and caches can be rebuilt, so the backup below excludes them. Create the script:
sudo nano /usr/local/sbin/jenkins-backup
#!/usr/bin/env bash
set -euo pipefail
backup_dir="/var/backups/jenkins"
jenkins_home="/var/lib/jenkins"
keep_days=14
stamp="$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
chmod 700 "$backup_dir"
tar -czf "$backup_dir/jenkins-$stamp.tar.gz" \
--exclude="./workspace" \
--exclude="./caches" \
--exclude="./.cache" \
-C "$jenkins_home" .
find "$backup_dir" -name 'jenkins-*.tar.gz' -mtime +"$keep_days" -delete
Make it executable and run it once to test it:
sudo chmod 750 /usr/local/sbin/jenkins-backup
sudo /usr/local/sbin/jenkins-backup
sudo ls -lh /var/backups/jenkins
total 92M
-rw-r--r-- 1 root root 92M Sep 24 10:48 jenkins-20260924-104812.tar.gz
Schedule it every night at 02:30 with a cron file:
echo '30 2 * * * root /usr/local/sbin/jenkins-backup' | sudo tee /etc/cron.d/jenkins-backup > /dev/null
The archive contains encrypted credentials together with the keys that decrypt them (secrets/ and secret.key), so treat it as sensitive and copy it to off-server storage. To restore, stop Jenkins, extract the archive into /var/lib/jenkins, run sudo chown -R jenkins:jenkins /var/lib/jenkins and start the service again.
Troubleshooting
502 Bad Gatewayin the browser: Jenkins is still starting or has stopped. Checksudo systemctl status jenkinsandsudo journalctl -u jenkins -n 50.- Jenkins fails to start after an upgrade with a Java version error: the new release requires a newer Java. Install the version named in the log (for example
openjdk-21-jre-headless) and restart the service. - "It appears that your reverse proxy set up is broken": the
HostorX-Forwarded-Protoheader is missing in the Nginx block, or the Jenkins URL in Manage Jenkins > System does not match the address you use in the browser. apt updatefails on the Jenkins repository: the signing key changed. Download the current key as explained in Step 2.- Builds fail with "No space left on device": old builds and workspaces fill the disk. Set Discard old builds in each job and check usage with
sudo du -sh /var/lib/jenkins/*.
Conclusion
Jenkins now runs on Ubuntu 24.04, reachable only through Nginx over HTTPS, with a working pipeline and nightly backups of its configuration. From here, connect a Git repository with a Jenkinsfile and a webhook so each push triggers a build, add a dedicated build agent so jobs do not run on the controller, and review Manage Jenkins > Security to decide who can create and run jobs. Keep Jenkins and its plugins updated from Manage Jenkins > Plugins, since most Jenkins security advisories affect plugins.