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 sudo privileges.
  • 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]
...

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:

  1. Customize Jenkins: choose Install suggested plugins. This installs Git, Pipeline, Credentials and the other plugins most setups need.
  2. Create First Admin User: create your own administrator account with a strong password. After this step the initial password stops working.
  3. 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:

  1. On the dashboard, click New Item.
  2. Enter hello-pipeline as the name, select Pipeline and click OK.
  3. 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'
        }
    }
}
  1. 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.

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 Gateway in the browser: Jenkins is still starting or has stopped. Check sudo systemctl status jenkins and sudo 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 Host or X-Forwarded-Proto header 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 update fails 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.