Skip to content

Quick Deploy

Deploy Jenkins from scratch in under 30 minutes.

Prerequisites

  • Docker Desktop installed and running
  • Git and GitHub CLI (gh) installed
  • A GitHub account (<your-github-username>)
  • A domain managed by Cloudflare (or use a temporary tunnel for testing)

Step 1 — Clone this repo

# Clone the repository and move into the project directory
git clone https://github.com/<your-github-username>/jenkins-config.git
cd jenkins-config

Step 2 — Set up Cloudflare Tunnel

Jenkins needs a public URL for GitHub webhooks and OAuth callbacks. Do this before creating the Jenkins CI Apps so you have the URL ready.

Full instructions: docs/cloudflare.md

Output: a stable public URL (e.g. https://jenkins.yourdomain.com) and a tunnel token to paste into .env.


Step 3 — Create Jenkins CI Apps

You need two separate GitHub Apps:

App Purpose What you get
Jenkins CI App Jenkins reads repos, posts build status, manages webhooks App ID + private key .pem + webhook secret
Jenkins Login App Jenkins user login via GitHub account Client ID + Client Secret

Full instructions: docs/github-apps.md


Step 4 — Configure .env

# Copy the example file — never commit the resulting .env
cp .env.example .env

Open .env and fill in the required values. Every variable is documented with a comment explaining its purpose, valid values, and when to change it. The minimum required set to start the platform:

# Core Jenkins credentials and public URL
JENKINS_ADMIN_PASSWORD=<strong-random-password>
JENKINS_URL=https://jenkins.yourdomain.com

# Cloudflare Tunnel token from Step 2
CLOUDFLARE_TUNNEL_TOKEN=<your-tunnel-token>

# GitHub identity
GITHUB_USERNAME=<your-github-username>
GITHUB_ADMIN_USERNAME=<your-github-username>
GITHUB_ORG=<your-github-org-or-username>

# Jenkins CI App from Step 3
GITHUB_APP_ID=<numeric-app-id>
GITHUB_WEBHOOK_SECRET=<random-secret-matching-app-settings>

# Jenkins Login App from Step 3
GITHUB_OAUTH_CLIENT_ID=<oauth-client-id>
GITHUB_OAUTH_CLIENT_SECRET=<oauth-client-secret>

A fully filled example with every variable configured is available in docs/configuration.md.


Step 5 — Add the Jenkins CI App private key

Copy the .pem file downloaded during Jenkins CI App creation into the repo root:

# Copy the private key downloaded from your GitHub App settings
cp $env:USERPROFILE\Downloads\your-app-name.pem github-app.pem
# Copy the private key downloaded from your GitHub App settings
cp ~/Downloads/your-app-name.pem github-app.pem

github-app.pem is gitignored and never committed.


Step 6 — Choose your services and start the stack

The platform uses Docker Compose profiles to control which services start. The core platform — Jenkins and the Cloudflare tunnel — always starts. Optional service groups are activated via COMPOSE_PROFILES in your .env.

Profile Services When to use
(none — default) Jenkins + Cloudflare tunnel Minimal setup, CI only
reporting + Allure test reporting When you want rich test result dashboards
full Everything above + future services Maximum platform features

Set your preferred profile in .env before starting:

# Start with reporting enabled — adds Allure at localhost:5050
COMPOSE_PROFILES=reporting

Then start the stack:

# Build the Jenkins image and start all configured services in the background
docker compose up --build -d

First build takes a few minutes — it installs all plugins. Subsequent starts are fast.

Verify all services are running:

# Stream logs from all running containers to confirm a clean startup
docker compose logs -f

Wait for Jenkins is fully up and running in the Jenkins log output.

If you started the reporting profile, Allure is available at:

http://localhost:5050/allure-docker-service/projects/default/reports/latest/index.html


Step 7 — Log in

Open http://localhost:8080 (or your public Cloudflare URL).

Log in with your GitHub account via the GitHub OAuth button. Your <your-github-username> account is pre-configured as admin via casc.yml.


Step 8 — Create the GitHub Organization Folder job

This is a one-time manual step. It will be automated in Phase 2 via a seed job — until then, follow these steps.

  1. New Item → name it <your-github-username> → select GitHub Organization
  2. Credentials: select jenkins-ci-app
  3. Owner: <your-github-username>
  4. Behaviors: leave defaults (discovers branches and PRs)
  5. Fork PR trust (security-critical): In BehaviorsDiscover fork pull requests → set Trust to match your JENKINS_FORK_PR_TRUST setting in .env:
Trust value Who can trigger CI on fork PRs When to use
nobody No one — all require manual approval Maximum security
contributors Authors with a previously merged PR Causes a chicken-and-egg problem for first PRs
collaborators Users explicitly added as repo collaborators Recommended — deliberate per-person trust grant
organization All GitHub org members For teams with trusted org membership
everyone Anyone Not recommended — pipelines have credential access
  1. Save — Jenkins scans your account and creates a job for every repo containing a Jenkinsfile

From this point, any new repo with a Jenkinsfile is picked up automatically. If the Cloudflare tunnel drops, Jenkins rescans the org every JENKINS_FOLDER_SCAN_INTERVAL minutes as a fallback. GitHub also retries failed webhook deliveries for up to 3 days — both mechanisms work together to ensure no build is permanently missed.


Step 9 — Verify

Push a commit to any repo that has a Jenkinsfile. You should see: - A build appear in Jenkins within seconds (via webhook) - Build status posted back to the GitHub commit or PR


Updating Jenkins

To apply config changes (plugins, casc.yml, Dockerfile):

# Pull latest config changes and rebuild the Jenkins image
git pull
docker compose up --build -d

Jenkins reloads JCasC config automatically on restart without losing build history (stored in the jenkins_home volume).


Teardown

Stop the stack without losing any data:

# Stop all containers — volumes and data are preserved
docker compose down

Warning — Allure history: Running docker compose down -v permanently destroys the allure_results and allure_reports volumes, which contain all Allure test trend history. Before running -v, configure publishArtifacts() with an artifact backend (S3, Azure Blob, etc.) to preserve history externally. See docs/configuration.md for artifact storage options.

Full wipe including all build history and Allure data:

# Destroys all volumes — jenkins_home, allure_results, allure_reports — irreversible
docker compose down -v