Skip to content

Quick Deploy

Jenkins running from scratch in under 30 minutes.

Prerequisites

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

Step 1: Clone this repo

git clone https://github.com/<your-github-username>/magi.git
cd magi

Step 2: Set up Cloudflare Tunnel

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

Full instructions: Cloudflare Tunnel

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


Step 3: Create GitHub Apps

Two separate GitHub Apps are required:

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

Full instructions: GitHub Apps Setup


Step 4: Configure .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. Minimum required set:

# 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>

Full variable reference: Configuration


Step 5: Add the Jenkins CI App private key

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

cp $env:USERPROFILE\Downloads\your-app-name.pem github-app.pem
cp ~/Downloads/your-app-name.pem github-app.pem

Never commit this file

github-app.pem is gitignored. Keep it that way. Anyone with this key can authenticate as your Jenkins CI App against every repo it has access to.


Step 6: Choose services and start the stack

Services are grouped by Docker Compose profile. Core (Jenkins + tunnel) always starts. Add optional service groups via COMPOSE_PROFILES in .env:

Profile Services When to use
(none: default) Jenkins + Cloudflare tunnel Minimal setup, CI only
reporting + Allure test reporting Rich test result history and trend graphs
full Everything All platform features
# Optional — set a profile before starting
echo "COMPOSE_PROFILES=reporting" >> .env

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

First build

The first up --build takes a few minutes. Jenkins installs all plugins during image build. Subsequent starts are fast.

Stream logs to confirm a clean startup:

docker compose logs -f

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

If you enabled reporting, Allure is 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 GitHub via the OAuth button. The account set as GITHUB_ADMIN_USERNAME is pre-configured as admin via casc.yml.


Step 8: Create the GitHub Organization Folder job

One-time manual step. Will be automated in a future phase via seed job. Until then:

  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: set Discover fork pull requests → Trust to match JENKINS_FORK_PR_TRUST in .env:
Value Who triggers CI on fork PRs Trade-off
nobody No one; all require manual approval Maximum security
contributors Authors with a previously merged PR Chicken-and-egg for first PRs
collaborators Explicitly added repo collaborators Recommended
organization All GitHub org members Good for trusted teams
everyone Anyone Do not use. Pipelines have credential access.
  1. Save. Jenkins scans your account and creates a job for every repo containing a Jenkinsfile.

From here, any new repo with a Jenkinsfile is picked up automatically. If the tunnel drops, Jenkins rescans on the JENKINS_FOLDER_SCAN_INTERVAL schedule as a fallback. GitHub also retries failed webhook deliveries for up to 3 days.


Step 9: Verify

Push a commit to any repo with a Jenkinsfile. Within seconds:

  • A build appears in Jenkins (via webhook)
  • Build status is posted back to the GitHub commit or PR

Updating Jenkins

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

git pull
docker compose up --build -d

Jenkins reloads JCasC automatically on restart. Build history is preserved in the jenkins_home volume.


Teardown

Stop the stack without losing data:

docker compose down

Full wipe: irreversible

docker compose down -v permanently destroys the jenkins_home, allure_results, and allure_reports volumes. All build history and Allure trend data is gone.

Before running -v, configure publishArtifacts() with an external artifact backend (S3, Azure Blob, etc.) to preserve Allure history. See Configuration.

# Destroys everything — build history, test results, Allure trends
docker compose down -v