Skip to main contentSkip to navigation
[email protected]
Client AreaSupport
Hosting Mammoth
HostingMammothYour Data, Our Responsibility
Home
Solutions
Hosting Services
Store
Pricing
About
Blog
API
Contact

Stay Ahead of the Curve

Get the latest insights on cybersecurity, AI innovations, and enterprise data solutions delivered to your inbox.

Hosting Mammoth
HostingMammothEnterprise Solutions

Enterprise-grade data solutions. Hosting, recovery, cybersecurity, and AI-powered services for businesses worldwide.

[email protected]
Sun - Fri, 9:00am - 5:00pm

Services

  • Cloud Hosting
  • Data Recovery
  • Cybersecurity
  • Legal Support
  • MSP Services
  • Web Development
  • AI Services
  • Free Server Migration

Hosting

  • VPS Hosting (NVMe SSD)
  • VDS Hosting (NVMe)
  • Storage VPS (High SSD)
  • GPU Servers
  • Managed Services
  • Cloud Firewall
  • Load Balancer
  • One-Click Apps
  • n8n Hosting
  • Object Storage
  • FAQ

Company

  • Store
  • Pricing
  • About Us
  • Locations
  • Blog
  • Testimonials
  • Contact
  • Affiliate Program
  • White-Label
  • Terms of Service
  • Privacy Policy
  • Browser Cookies
  • SLA

Support

  • Client Area
  • Submit Ticket
  • Knowledge Base
  • Server Status
  • API Documentation

© 2026 Hosting Mammoth. All rights reserved.

Knowledge Base
Getting StartedAccount ManagementVPS HostingGPU ServersStorage VPSCloud FirewallLoad BalancerServer ManagementBilling & PaymentsSupport & TicketsAffiliate ProgramReseller ProgramMarketplace & Appsn8n HostingManaged ServicesServer MigrationAPI & DevelopersSecurityTroubleshootingGlossaryInstall Guides
  1. Home
  2. /
  3. Support
  4. /
  5. Install Guides
  6. /
  7. How To Install Jenkins Ubuntu
GUIDEInstall Guides

How to Install Jenkins on Ubuntu 24.04 — Self-Hosted CI/CD Server

27 min read

How to Install Jenkins on Ubuntu 24.04 — Self-Hosted CI/CD Server

Jenkins is the most widely deployed automation server on the planet, powering continuous integration and delivery pipelines at companies ranging from two-person startups to Fortune 50 enterprises. This guide walks through a production-ready Jenkins installation on Ubuntu 24.04, from the first apt update to a fully configured controller-agent architecture sitting behind an Nginx TLS reverse proxy, building your code on every push to GitHub.

Need a VPS first? The CloudCore Professional plan (EUR 19.99/month) provides the 4 GB of RAM and multi-core CPU that a Jenkins controller plus one or two inline agents will use comfortably.

Table of Contents

  • What is Jenkins?
  • Why Self-Host Jenkins vs. GitHub Actions or CircleCI?
  • Prerequisites
  • Step 1: Update System Packages
  • Step 2: Install OpenJDK 17
  • Step 3: Add the Jenkins LTS apt Repository
  • Step 4: Install and Start Jenkins
  • Step 5: Unlock Jenkins and Run the Setup Wizard
  • Step 6: Install Recommended Plugins and Create an Admin User
  • Step 7: Configure Global Security
  • Step 8: Controller-Agent Architecture
  • Step 9: Write Your First Declarative Pipeline
  • Step 10: Multibranch Pipelines and GitHub Webhooks
  • Step 11: The Credentials Store
  • Step 12: Blue Ocean for a Modern UI
  • Step 13: Nginx Reverse Proxy with Let's Encrypt TLS
  • Step 14: Back Up Jenkins with ThinBackup
  • Troubleshooting
  • FAQ
  • Next Steps
  • What is Jenkins?

    Jenkins is an open-source automation server, originally released in 2011 as a fork of the Hudson project, and maintained today by the Continuous Delivery Foundation. It orchestrates the repetitive work that sits between a developer pressing git push and a production server receiving new code: compiling, testing, packaging, scanning, deploying, and notifying.

    Out of the box Jenkins is a single Java process that exposes a web UI, an HTTP API, and a remoting protocol for distributed builds. Its real power comes from the plugin ecosystem — over 1,800 community plugins cover everything from Git and GitHub integration to Docker, Kubernetes, Slack notifications, SonarQube analysis, Artifactory publishing, and dozens of cloud providers. Pipelines are defined as code via the Jenkinsfile, a Groovy-based DSL that lives alongside your application source.

    Jenkins shines when builds are heavy, parallelisable, and cost-sensitive. A single controller can dispatch work to dozens of ephemeral agents, run long integration suites against real databases, or compile cross-platform artifacts without burning through a per-minute billing meter. See the official documentation at jenkins.io/doc for the full reference.

    Why Self-Host Jenkins vs. GitHub Actions or CircleCI?

    Managed CI services are tempting for small projects — the free tiers are generous, setup is trivial, and there is no server to maintain. Once your team or your test suite grows, the economics flip.

    • Cost at scale. GitHub Actions bills USD 0.008 per minute on Linux once the 2,000–3,000 free minutes per month are exhausted. A single repo running a 15-minute pipeline on every push from a team of ten can burn through 30,000 minutes a month, which is roughly USD 240. CircleCI's performance plans start at USD 15 per user plus usage credits, and Buildkite charges per agent. A CloudCore Professional VPS at EUR 19.99/month gives you unlimited build minutes, as many parallel jobs as your CPU supports, and no surprise overage bills.
    • Hardware control. On managed runners you pick from a short menu of preset machines. On your own VPS you can pin builds to NVMe storage, mount local Docker layer caches, tune kernel parameters, or attach GPU accelerators for ML pipelines.
    • Private network access. Self-hosted Jenkins sits inside your own network perimeter, so it can reach internal databases, staging environments, and private package registries without firewall gymnastics or expensive "runner inside VPC" add-ons.
    • No vendor lock-in. A Jenkinsfile is portable. GitHub Actions workflows, CircleCI configs, and Buildkite pipelines all use proprietary YAML formats, so migrating later means rewriting every job.
    • Data residency and compliance. For EU teams handling regulated data, keeping CI artifacts on a known EU-hosted VPS simplifies GDPR and sector-specific audits.
    • Deep customization. Jenkins plugins can extend the UI, add new DSL steps, integrate with internal systems, and hook into every lifecycle event. Managed services expose a fraction of this surface.

    Rough Cost Comparison at 30,000 Build Minutes / Month

    PlatformMonthly CostParallelismCaveats
    GitHub Actions (hosted)~USD 216 (overage)20 concurrentLinux only at this price; macOS/Windows 10x cost
    CircleCI Performance~USD 150+30 concurrentCredit-based, easy to overrun
    Buildkite (hosted agents)~USD 200+Agent-basedPay per agent-minute
    Self-hosted Jenkins (CloudCore Professional)EUR 19.99Limited by CPU/RAMYou own uptime and patches
    Once your pipeline usage is predictable and non-trivial, a EUR 19.99 VPS pays for itself in the first day of the month.

    Prerequisites

    Before you begin, make sure you have:

    • A VPS running Ubuntu 24.04 LTS with root or sudo access
    • SSH access to your server
    • At least 4 GB of RAM for the controller (8 GB+ recommended if you intend to run inline builds)
    • At least 20 GB of free disk space (Jenkins data grows with build history and artifacts)
    • A domain name pointing to your server's public IP, for TLS later on
    Recommended Plan: CloudCore Professional
    >
    Our CloudCore Professional plan is the sweet spot for a Jenkins controller plus one or two inline build executors:
    >
    - 6 vCPU cores
    - 12 GB RAM
    - 100 GB NVMe SSD
    - Unmetered bandwidth
    - EUR 19.99/month
    >
    For teams running heavier test matrices, add a second VPS as a dedicated build agent — Jenkins handles distributed agents natively.

    Connect to the server to get started:

    bash
    ssh root@your-server-ip

    Step 1: Update System Packages

    Refresh the apt package index and apply any pending updates. This ensures the kernel, OpenSSL, and system libraries are current before Jenkins pulls in its Java runtime.

    bash
    sudo apt update && sudo apt upgrade -y

    If the kernel was upgraded, reboot:

    bash
    sudo reboot

    Reconnect after a minute and continue.

    Step 2: Install OpenJDK 17

    Jenkins 2.426 and later require Java 17 or Java 21. Ubuntu 24.04 ships OpenJDK 17 directly from the default repositories, so no third-party PPA is needed.

    Install the headless JRE (no GUI libraries, much smaller footprint):

    bash
    sudo apt install -y openjdk-17-jre-headless

    Verify the installation:

    bash
    java -version

    Expected output:

    text
    openjdk version "17.0.13" 2025-10-15
    OpenJDK Runtime Environment (build 17.0.13+11-Ubuntu-2ubuntu124.04)
    OpenJDK 64-Bit Server VM (build 17.0.13+11-Ubuntu-2ubuntu124.04, mixed mode, sharing)

    If you plan to build Java applications on this same server, install the full JDK instead:

    bash
    sudo apt install -y openjdk-17-jdk-headless

    Step 3: Add the Jenkins LTS apt Repository

    The LTS (Long Term Support) release line is the right choice for production — it receives security fixes for 12 weeks at a time and is the version the plugin ecosystem targets first.

    Import the Jenkins signing key:

    bash
    sudo wget -O /usr/share/keyrings/jenkins-keyring.asc \
      https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key

    Add the apt source:

    bash
    echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \
      https://pkg.jenkins.io/debian-stable binary/" | \
      sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null

    Refresh the package index so apt sees the new repo:

    bash
    sudo apt update

    Step 4: Install and Start Jenkins

    Install the jenkins package:

    bash
    sudo apt install -y jenkins

    The package creates a dedicated jenkins system user, installs the main WAR into /usr/share/java/jenkins.war, and drops a systemd unit at /lib/systemd/system/jenkins.service. The service starts automatically.

    Verify the service is running:

    bash
    sudo systemctl status jenkins

    Expected output:

    text
    ● jenkins.service - Jenkins Continuous Integration Server
         Loaded: loaded (/lib/systemd/system/jenkins.service; enabled; preset: enabled)
         Active: active (running) since Thu 2026-04-16 09:12:03 UTC; 10s ago
       Main PID: 4821 (java)
          Tasks: 41 (limit: 14236)
         Memory: 512.3M
            CPU: 18.412s

    Jenkins listens on TCP port 8080 by default. Open it in your firewall if UFW is enabled:

    bash
    sudo ufw allow 8080/tcp
    sudo ufw allow OpenSSH
    sudo ufw --force enable

    If you plan to attach inbound agents via JNLP, also open the agent port (by default random; you will fix it in Step 8):

    bash
    sudo ufw allow 50000/tcp

    Step 5: Unlock Jenkins and Run the Setup Wizard

    Browse to http://your-server-ip:8080. On first access Jenkins displays an Unlock Jenkins screen asking for the initial admin password.

    Read the password from disk:

    bash
    sudo cat /var/lib/jenkins/secrets/initialAdminPassword

    Expected output:

    text
    7f3d1a2b4c5e6f7a8b9c0d1e2f3a4b5c

    Paste this value into the web form and click Continue. The password is a one-time unlock token and can be discarded afterwards.

    Step 6: Install Recommended Plugins and Create an Admin User

    On the next screen Jenkins asks whether to install suggested plugins or pick plugins manually. Click Install suggested plugins. This batch installs roughly 20 plugins covering the common ground:

    • Git, GitHub Branch Source, Pipeline, Pipeline: Stage View
    • Credentials Binding, SSH Build Agents
    • Timestamper, Workspace Cleanup, Build Timeout
    • Email Extension, Mailer
    • Matrix Authorization Strategy, LDAP
    Installation takes 2–5 minutes depending on bandwidth. If a plugin fails, click Retry — transient timeouts to updates.jenkins.io are common.

    Once plugins finish, the Create First Admin User form appears. Fill in a real username (not admin), a strong password, your full name, and an email. Click Save and Continue.

    On the Instance Configuration page, set the Jenkins URL to the public address you will use, for example https://jenkins.example.com/. This URL is baked into webhook callbacks, email links, and agent JNLP files — changing it later requires updating each integration, so get it right now.

    Click Save and Finish, then Start using Jenkins.

    Step 7: Configure Global Security

    The defaults are sane, but a handful of tweaks harden a public-facing Jenkins significantly. Navigate to Manage Jenkins → Security.

  • Authorization: Matrix-based security. Switch from "Logged-in users can do anything" to Matrix-based security. Grant your admin user the Overall/Administer permission. For every other user, grant only Overall/Read plus the job-level permissions they need. Do not grant anonymous any permission.
  • Markup Formatter: Safe HTML. Prevents stored XSS via build descriptions.
  • CSRF Protection. Enabled by default in modern Jenkins — leave it on.
  • Agent → Controller Access Control. Enabled by default — leave it on. This prevents a compromised agent from reading controller filesystem paths.
  • CLI over Remoting. Scroll to Agents and ensure "Enable CLI over Remoting" is unchecked. The HTTP-based CLI is enough.
  • Fixed TCP port for inbound agents. Set TCP port for inbound agents to a fixed number like 50000 so firewall rules are stable.
  • Click Save. Then visit Manage Jenkins → System and confirm the Jenkins URL matches your public hostname.

    Step 8: Controller-Agent Architecture

    A single-node Jenkins (controller runs builds on itself) works for a hobby project, but for anything serious you want a controller-agent split: the controller schedules jobs and serves the UI, and agents run the actual builds. This isolates untrusted build code from the controller filesystem and lets you scale horizontally.

    SSH Build Agents

    The simplest agent type is an SSH agent — any Linux machine reachable via SSH can be pressed into service.

    On the agent machine:

    bash
    sudo adduser --disabled-password --gecos "" jenkins
    sudo mkdir -p /home/jenkins/.ssh
    sudo chown jenkins:jenkins /home/jenkins/.ssh
    sudo chmod 700 /home/jenkins/.ssh
    sudo apt install -y openjdk-17-jre-headless git

    On the controller, generate an SSH keypair for Jenkins:

    bash
    sudo -u jenkins ssh-keygen -t ed25519 -N "" -f /var/lib/jenkins/.ssh/id_ed25519
    sudo cat /var/lib/jenkins/.ssh/id_ed25519.pub

    Copy the public key into /home/jenkins/.ssh/authorized_keys on the agent. In the Jenkins UI, go to Manage Jenkins → Nodes → New Node, give it a name (e.g. agent-linux-01), choose Permanent Agent, and configure:

    • Remote root directory: /home/jenkins/agent
    • Labels: linux docker (used by pipelines to target this agent)
    • Launch method: Launch agents via SSH
    • Host: the agent's IP
    • Credentials: add a new "SSH Username with private key" credential using the private key from /var/lib/jenkins/.ssh/id_ed25519
    • Host Key Verification Strategy: Known hosts file
    Save. Within a few seconds the agent shows a green checkmark on the Nodes page.

    Docker Agents

    For disposable, clean-room builds, the Docker Pipeline and Docker plugins let Jenkins spin up a container per pipeline run. Install Docker on the agent (or on the controller if you accept the security trade-off):

    bash
    curl -fsSL https://get.docker.com | sudo sh
    sudo usermod -aG docker jenkins

    Configure a Docker cloud under Manage Jenkins → Clouds → New cloud → Docker, pointing at unix:///var/run/docker.sock (local) or a remote tcp:// endpoint. Define templates such as jenkins/inbound-agent:latest with labels docker linux, and Jenkins will start a container on demand when a pipeline requests that label.

    This pattern — ephemeral Docker agents on each build — is the gold standard for reproducibility and is covered in depth in our Docker install guide.

    Step 9: Write Your First Declarative Pipeline

    Jenkins pipelines come in two flavors: scripted (pure Groovy) and declarative (structured DSL). Declarative is strongly recommended — it is easier to read, validates at parse time, and plays well with Blue Ocean.

    Create a new item from the dashboard, select Pipeline, name it hello-pipeline, and paste the following into the Pipeline script field:

    groovy
    pipeline {
        agent { label 'linux' }

    options { timeout(time: 10, unit: 'MINUTES') buildDiscarder(logRotator(numToKeepStr: '20')) timestamps() }

    environment { APP_NAME = 'demo-service' }

    stages { stage('Checkout') { steps { git url: 'https://github.com/jenkinsci/pipeline-examples.git', branch: 'master' } }

    stage('Build') { steps { sh 'echo "Building ${APP_NAME} on $(hostname)"' sh 'uname -a' } }

    stage('Test') { parallel { stage('Unit') { steps { sh 'echo "running unit tests"' } } stage('Lint') { steps { sh 'echo "running lint"' } } } }

    stage('Deploy') { when { branch 'main' } steps { sh 'echo "deploying ${APP_NAME}"' } } }

    post { success { echo 'Build succeeded' } failure { echo 'Build failed — check the console log' } always { cleanWs() } } }

    Click Save, then Build Now. The Stage View shows each stage as a column, with green or red indicators per run. Declarative pipelines cover when conditions, parallel stages, matrix builds, shared libraries, and timeouts out of the box.

    The recommended workflow is to commit this pipeline as a Jenkinsfile at the root of the application repo — then Jenkins executes whatever pipeline is on the branch it is building, and pipeline changes go through code review just like application changes.

    Step 10: Multibranch Pipelines and GitHub Webhooks

    A Multibranch Pipeline scans a Git repository and automatically creates a Jenkins job for every branch and pull request that contains a Jenkinsfile. Combined with a GitHub webhook, this gives you on-push CI without any per-branch configuration.

    Create a new item, select Multibranch Pipeline, name it after your repo, and configure:

    • Branch Sources → GitHub
    • Credentials: a GitHub personal access token with repo scope (add it via the Credentials store — see Step 11)
    • Repository HTTPS URL: https://github.com/your-org/your-repo
    • Behaviours: Discover branches, Discover pull requests from origin, Discover pull requests from forks
    • Build Configuration → Mode: by Jenkinsfile (default path)
    Save. Jenkins performs an initial scan and creates a job for each branch.

    Configuring the GitHub Webhook

    Jenkins polls GitHub every few minutes by default, but webhooks are much faster. On the GitHub repo, go to Settings → Webhooks → Add webhook:

    • Payload URL: https://jenkins.example.com/github-webhook/
    • Content type: application/json
    • Events: Let me select — pick Pushes, Pull requests, and Branch or tag creation
    GitHub immediately sends a ping. Back in Jenkins, the multibranch scan is triggered within a second or two of every subsequent push.

    If you prefer self-hosted Git forges, the same flow works with our Gitea install guide — the Git plugin treats any Git remote identically.

    Step 11: The Credentials Store

    Hard-coding passwords in Jenkinsfiles is a cardinal sin. Jenkins ships with an encrypted Credentials store that plugins can pull from at build time.

    Navigate to Manage Jenkins → Credentials → System → Global credentials (unrestricted) → Add Credentials. Common kinds:

    • Username with password — for basic-auth APIs and Docker registries
    • SSH Username with private key — for deploying to remote hosts
    • Secret text — for API tokens (GitHub, Slack, AWS session tokens)
    • Secret file — for service-account JSONs and kubeconfig files
    • Certificate — for TLS client auth
    Give each credential an ID (e.g. github-pat, aws-prod-deploy). Consume them in pipelines with the credentials() helper or the withCredentials block:

    groovy
    pipeline {
        agent { label 'linux' }
        environment {
            GITHUB_TOKEN = credentials('github-pat')
        }
        stages {
            stage('Push tag') {
                steps {
                    withCredentials([sshUserPrivateKey(
                        credentialsId: 'deploy-key',
                        keyFileVariable: 'DEPLOY_KEY')]) {
                        sh 'ssh -i $DEPLOY_KEY deploy@prod "touch /tmp/deployed"'
                    }
                }
            }
        }
    }

    Secrets are masked in build console logs automatically — never echo them to stdout anyway.

    For even stronger hygiene, integrate HashiCorp Vault via the HashiCorp Vault Plugin and let Jenkins fetch short-lived dynamic secrets per build.

    Step 12: Blue Ocean for a Modern UI

    The classic Jenkins UI is functional but dated. Blue Ocean is an alternative frontend with a cleaner pipeline visualization, better PR-centric views, and a pipeline editor.

    Install via Manage Jenkins → Plugins → Available plugins, search Blue Ocean, select it, and install without restart. A new Open Blue Ocean link appears in the left sidebar.

    Blue Ocean shines on multibranch pipelines — each branch gets a dedicated card, each run shows a timeline with per-stage logs, and PRs have a comment-style build status. It is a nice productivity boost for developers who live in the Jenkins UI day to day, though the classic UI remains the source of truth for administration.

    Step 13: Nginx Reverse Proxy with Let's Encrypt TLS

    Never expose port 8080 directly on the public internet. Terminate TLS on Nginx in front of Jenkins, and keep port 8080 bound to localhost.

    First, tell Jenkins to listen only on localhost. On systemd-based installs, create an override:

    bash
    sudo systemctl edit jenkins

    Add:

    text
    [Service]
    Environment="JENKINS_LISTEN_ADDRESS=127.0.0.1"

    Reload and restart:

    bash
    sudo systemctl daemon-reload
    sudo systemctl restart jenkins

    Install Nginx and Certbot:

    bash
    sudo apt install -y nginx certbot python3-certbot-nginx

    Create the site config:

    bash
    sudo tee /etc/nginx/sites-available/jenkins > /dev/null <<'EOF'
    upstream jenkins {
        server 127.0.0.1:8080 fail_timeout=0;
        keepalive 32;
    }

    server { listen 80; server_name jenkins.example.com; return 301 https://$host$request_uri; }

    server { listen 443 ssl http2; server_name jenkins.example.com;

    ssl_certificate /etc/letsencrypt/live/jenkins.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/jenkins.example.com/privkey.pem;

    # Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN;

    # Jenkins needs a generous body size for plugin uploads and artifacts client_max_body_size 100m; client_body_buffer_size 128k;

    location / { proxy_pass http://jenkins; 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 Connection "";

    proxy_redirect http://jenkins/ https://$host/;

    # Required for long-running builds and SSE in Blue Ocean proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 900s; proxy_send_timeout 900s; } } EOF

    Replace jenkins.example.com with your domain. Enable the site and obtain a certificate:

    bash
    sudo ln -s /etc/nginx/sites-available/jenkins /etc/nginx/sites-enabled/
    sudo rm -f /etc/nginx/sites-enabled/default
    sudo nginx -t
    sudo systemctl reload nginx
    sudo certbot --nginx -d jenkins.example.com

    Certbot edits the config to point at the new certificate and installs a renewal timer. Reload Nginx:

    bash
    sudo systemctl reload nginx

    Close port 8080 on the firewall now that Jenkins is only reachable via Nginx:

    bash
    sudo ufw delete allow 8080/tcp
    sudo ufw allow 'Nginx Full'

    Finally, update the Jenkins URL under Manage Jenkins → System to https://jenkins.example.com/ so webhooks and email links use the TLS endpoint.

    Step 14: Back Up Jenkins with ThinBackup

    Jenkins state lives in /var/lib/jenkins (a.k.a. JENKINS_HOME) — configuration, job definitions, plugins, build history, and credentials. Without a backup strategy one bad plugin upgrade can ruin your day.

    Install the ThinBackup plugin via Manage Jenkins → Plugins → Available plugins. After restart, a new ThinBackup entry appears under Manage Jenkins.

    Configure it with:

    • Backup directory: /var/lib/jenkins-backups (create this directory owned by jenkins:jenkins)
    • Full backup schedule: H 2 0 (Sunday at ~2 am)
    • Differential backup schedule: H 2 1-6 (every other night)
    • Max number of backup sets: 10
    • Files excluded from backup: .*\.log (skip verbose logs)
    • Check: Backup build results, Backup configuration history, Clean up differential backups
    Create the destination:

    bash
    sudo mkdir -p /var/lib/jenkins-backups
    sudo chown jenkins:jenkins /var/lib/jenkins-backups

    Trigger a backup immediately to verify everything works — click Backup Now on the ThinBackup page.

    Offsite Copies with restic

    ThinBackup keeps you safe from configuration mistakes but not from disk loss. Layer an offsite copy on top:

    bash
    sudo apt install -y restic
    sudo restic -r s3:s3.amazonaws.com/your-bucket/jenkins init
    sudo restic -r s3:s3.amazonaws.com/your-bucket/jenkins backup /var/lib/jenkins-backups

    Schedule it via cron:

    bash
    sudo crontab -e

    Append:

    text
    30 3   * restic -r s3:s3.amazonaws.com/your-bucket/jenkins backup /var/lib/jenkins-backups --password-file /root/.restic-password

    Now your Jenkins survives both human error and hardware failure.

    Troubleshooting

    ProblemCauseSolution
    jenkins.service: Failed with result 'exit-code' on startupWrong Java versionConfirm java -version shows 17 or 21. Reinstall with sudo apt install --reinstall openjdk-17-jre-headless
    Setup wizard hangs on "Getting started"Plugins failing to downloadRetry, or visit Manage Jenkins → Update Sites and confirm the URL is reachable. Check DNS and outbound HTTPS.
    Nginx 502 Bad Gateway after moving behind proxyJenkins not listening on 127.0.0.1Check ss -tlnp — Jenkins should be on 127.0.0.1:8080. Verify systemd override and restart Jenkins.
    Builds queue forever, never runNo executor availableCheck Manage Jenkins → Nodes. Controller may have 0 executors set (correct for controller-agent). Connect an agent or raise controller executors.
    GitHub webhook returns 403CSRF crumb requiredUpgrade GitHub plugin to latest — old versions did not send the crumb. Or switch to HMAC secret validation.
    No space left on device after a few weeksBuild history + artifactsAdd a buildDiscarder to every pipeline (numToKeepStr: '20'), or use the Discard Old Builds job option.
    Agent disconnects intermittentlyFirewall closing idle connectionsOn the agent, add -keepAlive to the JNLP launch command, or switch the agent to SSH launcher which tunnels over a persistent TCP session.
    javax.net.ssl.SSLHandshakeException on outbound callsCorporate proxy with custom CAImport the CA into $JAVA_HOME/lib/security/cacerts with keytool -importcert, then restart Jenkins.

    Useful Log Locations

    bash
    # Main Jenkins log
    sudo journalctl -u jenkins -f

    Older package layout

    sudo tail -f /var/log/jenkins/jenkins.log

    Per-job workspace and build logs

    ls /var/lib/jenkins/jobs/<job-name>/builds/

    FAQ

    Which Java version does Jenkins require on Ubuntu 24.04?

    Jenkins 2.426 and later require Java 17 or Java 21. Ubuntu 24.04 ships OpenJDK 17 directly, which is the cleanest option — no PPA, no third-party repository, and fully supported by the Jenkins LTS line. Do not attempt to run Jenkins on Java 11 anymore; newer plugins use Java 17 bytecode and will throw UnsupportedClassVersionError.

    Should I self-host Jenkins or use GitHub Actions?

    Self-hosted Jenkins wins on cost once your monthly CI minutes exceed roughly 2,000–3,000 (the GitHub free tier). A EUR 19.99 VPS gives you unlimited build minutes versus USD 0.008 per minute overage on GitHub Actions. Jenkins also wins on hardware control, private network access, and deep customization. GitHub Actions wins on zero-maintenance simplicity. A common hybrid is to run lightweight PR checks on GitHub Actions and heavy nightly suites, integration tests, and release pipelines on self-hosted Jenkins.

    How do I scale Jenkins beyond a single VPS?

    Add build agents. The Jenkins controller stays lightweight — it schedules jobs and stores artifacts — while agents run on separate machines. Agent types include SSH (any Linux host), JNLP/inbound (firewall-friendly), Docker (ephemeral containers per build), and Kubernetes (pods per build). Start with one SSH agent on a second VPS, then add Docker templates as your test matrix grows. The Jenkins Kubernetes plugin is the endgame for elastic, autoscaling CI.

    Is Jenkins secure to expose on the public internet?

    Yes, with standard hardening: front with Nginx + TLS (Step 13), bind Jenkins to localhost, enable matrix-based authorization with no anonymous permissions, disable CLI-over-remoting, use the Credentials store for secrets, keep the controller Java process away from builds (use agents), and patch the LTS release promptly when CVEs are announced. Jenkins publishes a security advisory mailing list — subscribe at jenkins.io/security.

    How do I back up Jenkins configuration and jobs?

    Install the ThinBackup plugin for scheduled full and differential backups of JENKINS_HOME, then layer an offsite copy with restic, borg, or rsync. Exclude the workspace/ directories (re-creatable from source) and large build artifacts (store in a dedicated artifact server like Nexus or Artifactory). Test the restore procedure quarterly — an untested backup is not a backup.

    What is a Jenkinsfile and why should I use one?

    A Jenkinsfile is a text file at the root of your repository that defines the entire pipeline using the declarative (or scripted) DSL. Storing it in Git means pipeline changes go through the same code review, testing, and rollback workflow as application code. Different branches can have different pipelines (a hotfix branch might skip integration tests), and bisecting a pipeline bug is as easy as git log. Inline pipelines configured through the UI lose all of this.

    Can I run Jenkins builds inside Docker containers?

    Yes, and you should whenever practical. The Docker Pipeline plugin lets any stage declare agent { docker { image 'node:20' } }, and Jenkins runs the stage inside a fresh container. This gives each build a clean, reproducible environment without polluting the host with toolchains. Pair with Docker Cloud configuration to spin up throwaway inbound agents on demand. Teams running many parallel builds often move to our Drone CI guide or Woodpecker CI guide for container-first workflows, while keeping Jenkins for legacy and Java-heavy pipelines.

    Next Steps

    • Explore alternative CI systems. Every self-hosted CI has trade-offs. Our guides on Drone CI, Woodpecker CI, and Concourse compare alternatives that are container-first and YAML-native.
    • Pair Jenkins with self-hosted Git. Installing Gitea gives you a GitHub-style frontend on your own VPS; Jenkins multibranch scans it exactly like GitHub.
    • Standardize build environments with Docker. Follow the Docker install guide on your Jenkins agents so pipelines can use agent { docker { image '...' } } freely.
    • Wire up notifications. Install the Slack, Microsoft Teams, or Discord plugin and post { failure { slackSend ... } } in your pipelines so failures surface where your team already lives.
    • Add static analysis and security scanning. SonarQube, Trivy (container CVEs), and OWASP Dependency-Check plugins integrate as pipeline stages and fail builds on new vulnerabilities.
    • Migrate to configuration-as-code. The JCasC (Configuration as Code) plugin encodes your entire Jenkins configuration into a YAML file, so a fresh install is a helm install or docker run away. Combined with a restored JENKINS_HOME, it makes disaster recovery nearly automatic.
    Full reference documentation lives at jenkins.io/doc — bookmark the Pipeline syntax reference and the Plugin index as you grow your setup.

    Running Jenkins on a VPS that can handle it
    >
    Jenkins controllers are memory-hungry, and build executors compound that. The CloudCore Professional plan gives you 6 vCPU, 12 GB RAM, and 100 GB NVMe for EUR 19.99/month — enough for a controller, two inline executors, and headroom for a dozen concurrent pipeline branches.
    >
    - Ubuntu 24.04 LTS image with SSH key pre-installed
    - 1 Gbps unmetered bandwidth for pulling container images
    - NVMe storage for fast workspace checkouts
    - Snapshot-based backups for easy rollback
    >
    Deploy a Jenkins-ready VPS and be building code in under 40 minutes.

    Was this article helpful?

    ← Back to Install GuidesBrowse all categories →

    Still have questions?

    Contact Support →Submit a Ticket