[{"data":1,"prerenderedAt":1157},["ShallowReactive",2],{"content-query-UM2Y9GyA9F":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"layout":10,"author":11,"tags":12,"categories":20,"date":22,"faq":23,"image":45,"excerpt":46,"body":92,"_type":1150,"_id":1151,"_source":1152,"_file":1153,"_stem":1154,"_extension":1155,"sitemap":1156},"/blog/jenkins-webhooks","blog",false,"","Jenkins Webhooks: The Complete Setup Guide (GitHub, Bitbucket, GitLab, Gitea)","Every Jenkins webhook URL in one place — /github-webhook/, /bitbucket-hook/, /project/NAME, /gitea-webhook/post — plus how to fix 403 no valid crumb and receive webhooks when Jenkins has no public IP.","post","Karolis Rusenas",[13,14,15,16,17,18,19],"jenkins","github","bitbucket","gitlab","gitea","webhooks","ci-cd",[21],"automation","2026-08-19 10:00:00",[24,27,30,33,36,39,42],{"q":25,"a":26},"What is the Jenkins GitHub webhook URL?","It is http://JENKINS_URL/github-webhook/ — for example http://localhost:8080/github-webhook/. The trailing slash matters: posting to /github-webhook without it commonly returns a 403 'No valid crumb was included in the request' error. This endpoint is provided by the Jenkins GitHub plugin and is exempt from CSRF crumb checks, which is why the exact path must be used.",{"q":28,"a":29},"What is the Jenkins Bitbucket webhook URL?","It is http://JENKINS_URL/bitbucket-hook/, provided by the Jenkins Bitbucket plugin. As with GitHub, keep the trailing slash. On Bitbucket Server you need a webhook plugin and must create a Post-Webhook rather than a plain Webhook.",{"q":31,"a":32},"What is the Jenkins GitLab webhook URL?","It is http://JENKINS_URL/project/PROJECT_NAME (or /project/FOLDER/PROJECT_NAME for jobs inside folders), provided by the Jenkins GitLab plugin. Do not point GitLab at /job/PROJECT_NAME/build — that bypasses the plugin entirely.",{"q":34,"a":35},"How do I fix '403 No valid crumb was included in the request' in Jenkins?","This means the request reached a Jenkins path that is not exempt from CSRF protection. Almost always the webhook URL is wrong — a missing trailing slash on /github-webhook/, or the sender appending an extra path segment such as /ghprbhook onto your configured destination. Verify the exact final URL Jenkins receives, including the trailing slash and any path the sender adds.",{"q":37,"a":38},"Why does Jenkins return 200 but no build starts?","Jenkins accepted the webhook but could not match it to a job. It uses the repository URL in the webhook payload to decide what to poll, so the repository configured in your job's Source Code Management section must exactly match the repository the webhook came from. Check the Jenkins system log for 'No SCM configuration was found!'.",{"q":40,"a":41},"Can I receive Jenkins webhooks without a public IP?","Yes. Run the Webhook Relay agent next to Jenkins — it opens an outbound connection and streams incoming webhooks to your internal Jenkins URL, so GitHub, Bitbucket, GitLab or Gitea only ever talk to a public Webhook Relay endpoint. No inbound firewall ports, no public IP, and no exposing Jenkins to the internet.",{"q":43,"a":44},"Do I need a plugin for every Git provider?","No. If you would rather not install a provider-specific plugin, the Generic Webhook Trigger plugin accepts any HTTP request at /generic-webhook-trigger/invoke and lets you extract values from the payload with JSONPath. It is the usual answer for Gitea, Forgejo and self-hosted or in-house tools.","/images/blog/jenkins-guide/interstellar-jenkins.jpg",{"type":47,"children":48},"root",[49,59,87],{"type":50,"tag":51,"props":52,"children":53},"element","p",{},[54],{"type":50,"tag":55,"props":56,"children":58},"img",{"alt":57,"src":45},"Jenkins webhooks setup guide",[],{"type":50,"tag":51,"props":60,"children":61},{},[62,65,71,73,78,80,85],{"type":63,"value":64},"text","Jenkins can start a build the instant someone pushes, instead of waking up every few minutes to poll. That is what webhooks are for. But almost every Jenkins webhook question comes down to one of three things: ",{"type":50,"tag":66,"props":67,"children":68},"strong",{},[69],{"type":63,"value":70},"which URL do I point the provider at",{"type":63,"value":72},", ",{"type":50,"tag":66,"props":74,"children":75},{},[76],{"type":63,"value":77},"why am I getting a 403",{"type":63,"value":79},", and ",{"type":50,"tag":66,"props":81,"children":82},{},[83],{"type":63,"value":84},"how does any of this work when Jenkins sits on a private network with no public IP",{"type":63,"value":86},".",{"type":50,"tag":51,"props":88,"children":89},{},[90],{"type":63,"value":91},"This guide answers all three, for GitHub, Bitbucket, GitLab and Gitea.",{"type":47,"children":93,"toc":1135},[94,100,119,123,130,135,306,311,407,413,418,423,442,450,455,499,505,510,694,699,707,733,761,768,773,841,847,853,858,912,918,943,951,963,969,988,994,999,1005,1106,1112,1117,1129],{"type":50,"tag":51,"props":95,"children":96},{},[97],{"type":50,"tag":55,"props":98,"children":99},{"alt":57,"src":45},[],{"type":50,"tag":51,"props":101,"children":102},{},[103,104,108,109,113,114,118],{"type":63,"value":64},{"type":50,"tag":66,"props":105,"children":106},{},[107],{"type":63,"value":70},{"type":63,"value":72},{"type":50,"tag":66,"props":110,"children":111},{},[112],{"type":63,"value":77},{"type":63,"value":79},{"type":50,"tag":66,"props":115,"children":116},{},[117],{"type":63,"value":84},{"type":63,"value":86},{"type":50,"tag":51,"props":120,"children":121},{},[122],{"type":63,"value":91},{"type":50,"tag":124,"props":125,"children":127},"h2",{"id":126},"jenkins-webhook-urls-all-in-one-place",[128],{"type":63,"value":129},"Jenkins webhook URLs, all in one place",{"type":50,"tag":51,"props":131,"children":132},{},[133],{"type":63,"value":134},"Each Jenkins plugin registers its own endpoint. Point your provider at the matching one:",{"type":50,"tag":136,"props":137,"children":138},"table",{},[139,163],{"type":50,"tag":140,"props":141,"children":142},"thead",{},[143],{"type":50,"tag":144,"props":145,"children":146},"tr",{},[147,153,158],{"type":50,"tag":148,"props":149,"children":150},"th",{},[151],{"type":63,"value":152},"Provider",{"type":50,"tag":148,"props":154,"children":155},{},[156],{"type":63,"value":157},"Jenkins webhook URL",{"type":50,"tag":148,"props":159,"children":160},{},[161],{"type":63,"value":162},"Plugin",{"type":50,"tag":164,"props":165,"children":166},"tbody",{},[167,198,225,252,279],{"type":50,"tag":144,"props":168,"children":169},{},[170,176,186],{"type":50,"tag":171,"props":172,"children":173},"td",{},[174],{"type":63,"value":175},"GitHub",{"type":50,"tag":171,"props":177,"children":178},{},[179],{"type":50,"tag":180,"props":181,"children":183},"code",{"className":182},[],[184],{"type":63,"value":185},"http://JENKINS_URL/github-webhook/",{"type":50,"tag":171,"props":187,"children":188},{},[189],{"type":50,"tag":190,"props":191,"children":195},"a",{"href":192,"rel":193},"https://plugins.jenkins.io/github/",[194],"nofollow",[196],{"type":63,"value":197},"GitHub plugin",{"type":50,"tag":144,"props":199,"children":200},{},[201,206,215],{"type":50,"tag":171,"props":202,"children":203},{},[204],{"type":63,"value":205},"Bitbucket",{"type":50,"tag":171,"props":207,"children":208},{},[209],{"type":50,"tag":180,"props":210,"children":212},{"className":211},[],[213],{"type":63,"value":214},"http://JENKINS_URL/bitbucket-hook/",{"type":50,"tag":171,"props":216,"children":217},{},[218],{"type":50,"tag":190,"props":219,"children":222},{"href":220,"rel":221},"https://plugins.jenkins.io/bitbucket/",[194],[223],{"type":63,"value":224},"Bitbucket plugin",{"type":50,"tag":144,"props":226,"children":227},{},[228,233,242],{"type":50,"tag":171,"props":229,"children":230},{},[231],{"type":63,"value":232},"GitLab",{"type":50,"tag":171,"props":234,"children":235},{},[236],{"type":50,"tag":180,"props":237,"children":239},{"className":238},[],[240],{"type":63,"value":241},"http://JENKINS_URL/project/PROJECT_NAME",{"type":50,"tag":171,"props":243,"children":244},{},[245],{"type":50,"tag":190,"props":246,"children":249},{"href":247,"rel":248},"https://plugins.jenkins.io/gitlab-plugin/",[194],[250],{"type":63,"value":251},"GitLab plugin",{"type":50,"tag":144,"props":253,"children":254},{},[255,260,269],{"type":50,"tag":171,"props":256,"children":257},{},[258],{"type":63,"value":259},"Gitea",{"type":50,"tag":171,"props":261,"children":262},{},[263],{"type":50,"tag":180,"props":264,"children":266},{"className":265},[],[267],{"type":63,"value":268},"http://JENKINS_URL/gitea-webhook/post",{"type":50,"tag":171,"props":270,"children":271},{},[272],{"type":50,"tag":190,"props":273,"children":276},{"href":274,"rel":275},"https://plugins.jenkins.io/gitea/",[194],[277],{"type":63,"value":278},"Gitea plugin",{"type":50,"tag":144,"props":280,"children":281},{},[282,287,296],{"type":50,"tag":171,"props":283,"children":284},{},[285],{"type":63,"value":286},"Anything else",{"type":50,"tag":171,"props":288,"children":289},{},[290],{"type":50,"tag":180,"props":291,"children":293},{"className":292},[],[294],{"type":63,"value":295},"http://JENKINS_URL/generic-webhook-trigger/invoke",{"type":50,"tag":171,"props":297,"children":298},{},[299],{"type":50,"tag":190,"props":300,"children":303},{"href":301,"rel":302},"https://plugins.jenkins.io/generic-webhook-trigger/",[194],[304],{"type":63,"value":305},"Generic Webhook Trigger",{"type":50,"tag":51,"props":307,"children":308},{},[309],{"type":63,"value":310},"Three details cause most of the failures:",{"type":50,"tag":312,"props":313,"children":314},"ol",{},[315,342,376],{"type":50,"tag":316,"props":317,"children":318},"li",{},[319,340],{"type":50,"tag":66,"props":320,"children":321},{},[322,324,330,332,338],{"type":63,"value":323},"The trailing slash on ",{"type":50,"tag":180,"props":325,"children":327},{"className":326},[],[328],{"type":63,"value":329},"/github-webhook/",{"type":63,"value":331}," and ",{"type":50,"tag":180,"props":333,"children":335},{"className":334},[],[336],{"type":63,"value":337},"/bitbucket-hook/",{"type":63,"value":339}," is required.",{"type":63,"value":341}," Drop it and you are no longer hitting the plugin's CSRF-exempt endpoint, which surfaces as a 403.",{"type":50,"tag":316,"props":343,"children":344},{},[345,350,352,358,360,366,368,374],{"type":50,"tag":66,"props":346,"children":347},{},[348],{"type":63,"value":349},"GitLab's URL contains the job name",{"type":63,"value":351},", not a fixed path — ",{"type":50,"tag":180,"props":353,"children":355},{"className":354},[],[356],{"type":63,"value":357},"/project/my-job",{"type":63,"value":359},", or ",{"type":50,"tag":180,"props":361,"children":363},{"className":362},[],[364],{"type":63,"value":365},"/project/my-folder/my-job",{"type":63,"value":367}," for a job inside a folder. Pointing GitLab at ",{"type":50,"tag":180,"props":369,"children":371},{"className":370},[],[372],{"type":63,"value":373},"/job/PROJECT_NAME/build",{"type":63,"value":375}," skips the plugin and will not behave as documented.",{"type":50,"tag":316,"props":377,"children":378},{},[379,390,392,398,400,406],{"type":50,"tag":66,"props":380,"children":381},{},[382,388],{"type":50,"tag":180,"props":383,"children":385},{"className":384},[],[386],{"type":63,"value":387},"JENKINS_URL",{"type":63,"value":389}," is whatever Jenkins is reachable at",{"type":63,"value":391},", including any context path. If Jenkins runs under ",{"type":50,"tag":180,"props":393,"children":395},{"className":394},[],[396],{"type":63,"value":397},"/jenkins",{"type":63,"value":399},", the GitHub endpoint is ",{"type":50,"tag":180,"props":401,"children":403},{"className":402},[],[404],{"type":63,"value":405},"http://host/jenkins/github-webhook/",{"type":63,"value":86},{"type":50,"tag":124,"props":408,"children":410},{"id":409},"the-problem-jenkins-usually-is-not-on-the-public-internet",[411],{"type":63,"value":412},"The problem: Jenkins usually is not on the public internet",{"type":50,"tag":51,"props":414,"children":415},{},[416],{"type":63,"value":417},"Jenkins has broad access to your infrastructure, so it normally lives behind a firewall, inside a VPC, or on a NAT'd network. That is the right call for security — and it is exactly what breaks webhooks, because GitHub and friends can only POST to a public URL.",{"type":50,"tag":51,"props":419,"children":420},{},[421],{"type":63,"value":422},"The usual workarounds are all bad: exposing Jenkins to the internet, maintaining IP allowlists that the provider keeps changing, or falling back to polling and accepting the delay plus the API rate limiting that comes with it.",{"type":50,"tag":51,"props":424,"children":425},{},[426,433,435,440],{"type":50,"tag":190,"props":427,"children":430},{"href":428,"rel":429},"https://my.webhookrelay.com/register",[194],[431],{"type":63,"value":432},"Webhook Relay",{"type":63,"value":434}," solves it from the other direction. You run a small agent next to Jenkins; it makes an ",{"type":50,"tag":66,"props":436,"children":437},{},[438],{"type":63,"value":439},"outbound",{"type":63,"value":441}," connection and streams incoming webhooks to your internal Jenkins URL. The provider only ever sees a public Webhook Relay endpoint.",{"type":50,"tag":51,"props":443,"children":444},{},[445],{"type":50,"tag":55,"props":446,"children":449},{"alt":447,"src":448},"Receiving GitHub webhooks on Jenkins without a public IP","/images/tutorials/jenkins/github-webhooks-jenkins.png",[],{"type":50,"tag":51,"props":451,"children":452},{},[453],{"type":63,"value":454},"A few properties that matter for a team setup:",{"type":50,"tag":456,"props":457,"children":458},"ul",{},[459,469,479,489],{"type":50,"tag":316,"props":460,"children":461},{},[462,467],{"type":50,"tag":66,"props":463,"children":464},{},[465],{"type":63,"value":466},"No inbound ports.",{"type":63,"value":468}," Nothing about your firewall changes.",{"type":50,"tag":316,"props":470,"children":471},{},[472,477],{"type":50,"tag":66,"props":473,"children":474},{},[475],{"type":63,"value":476},"One agent, many Jenkins servers.",{"type":63,"value":478}," A single agent can relay to any number of internal hosts it can reach.",{"type":50,"tag":316,"props":480,"children":481},{},[482,487],{"type":50,"tag":66,"props":483,"children":484},{},[485],{"type":63,"value":486},"The public endpoint is stable.",{"type":63,"value":488}," Reprovision the machine behind it and the provider configuration stays the same.",{"type":50,"tag":316,"props":490,"children":491},{},[492,497],{"type":50,"tag":66,"props":493,"children":494},{},[495],{"type":63,"value":496},"Webhooks stay uni-directional.",{"type":63,"value":498}," Responses are not returned to the sender, so Jenkins is not probeable through the endpoint.",{"type":50,"tag":124,"props":500,"children":502},{"id":501},"setting-it-up",[503],{"type":63,"value":504},"Setting it up",{"type":50,"tag":51,"props":506,"children":507},{},[508],{"type":63,"value":509},"Install the agent and create a forwarding rule pointing at the endpoint for your provider:",{"type":50,"tag":511,"props":512,"children":516},"pre",{"code":513,"language":514,"meta":7,"className":515,"style":7},"# install (Linux x86-64; see the docs for other platforms)\nsudo wget -O /usr/local/bin/relay \\\n  https://storage.googleapis.com/webhookrelay/downloads/relay-linux-amd64\nsudo chmod +wx /usr/local/bin/relay\n\n# authenticate with a token key/secret from https://my.webhookrelay.com/tokens\nrelay login -k YOUR_TOKEN_KEY -s YOUR_TOKEN_SECRET\n\n# create the public endpoint and start forwarding\nrelay forward --bucket jenkins http://localhost:8080/github-webhook/\n","bash","language-bash shiki shiki-themes github-dark",[517],{"type":50,"tag":180,"props":518,"children":519},{"__ignoreMap":7},[520,532,564,573,596,606,615,649,657,666],{"type":50,"tag":521,"props":522,"children":525},"span",{"class":523,"line":524},"line",1,[526],{"type":50,"tag":521,"props":527,"children":529},{"style":528},"--shiki-default:#6A737D",[530],{"type":63,"value":531},"# install (Linux x86-64; see the docs for other platforms)\n",{"type":50,"tag":521,"props":533,"children":535},{"class":523,"line":534},2,[536,542,548,554,559],{"type":50,"tag":521,"props":537,"children":539},{"style":538},"--shiki-default:#B392F0",[540],{"type":63,"value":541},"sudo",{"type":50,"tag":521,"props":543,"children":545},{"style":544},"--shiki-default:#9ECBFF",[546],{"type":63,"value":547}," wget",{"type":50,"tag":521,"props":549,"children":551},{"style":550},"--shiki-default:#79B8FF",[552],{"type":63,"value":553}," -O",{"type":50,"tag":521,"props":555,"children":556},{"style":544},[557],{"type":63,"value":558}," /usr/local/bin/relay",{"type":50,"tag":521,"props":560,"children":561},{"style":550},[562],{"type":63,"value":563}," \\\n",{"type":50,"tag":521,"props":565,"children":567},{"class":523,"line":566},3,[568],{"type":50,"tag":521,"props":569,"children":570},{"style":544},[571],{"type":63,"value":572},"  https://storage.googleapis.com/webhookrelay/downloads/relay-linux-amd64\n",{"type":50,"tag":521,"props":574,"children":576},{"class":523,"line":575},4,[577,581,586,591],{"type":50,"tag":521,"props":578,"children":579},{"style":538},[580],{"type":63,"value":541},{"type":50,"tag":521,"props":582,"children":583},{"style":544},[584],{"type":63,"value":585}," chmod",{"type":50,"tag":521,"props":587,"children":588},{"style":544},[589],{"type":63,"value":590}," +wx",{"type":50,"tag":521,"props":592,"children":593},{"style":544},[594],{"type":63,"value":595}," /usr/local/bin/relay\n",{"type":50,"tag":521,"props":597,"children":599},{"class":523,"line":598},5,[600],{"type":50,"tag":521,"props":601,"children":603},{"emptyLinePlaceholder":602},true,[604],{"type":63,"value":605},"\n",{"type":50,"tag":521,"props":607,"children":609},{"class":523,"line":608},6,[610],{"type":50,"tag":521,"props":611,"children":612},{"style":528},[613],{"type":63,"value":614},"# authenticate with a token key/secret from https://my.webhookrelay.com/tokens\n",{"type":50,"tag":521,"props":616,"children":618},{"class":523,"line":617},7,[619,624,629,634,639,644],{"type":50,"tag":521,"props":620,"children":621},{"style":538},[622],{"type":63,"value":623},"relay",{"type":50,"tag":521,"props":625,"children":626},{"style":544},[627],{"type":63,"value":628}," login",{"type":50,"tag":521,"props":630,"children":631},{"style":550},[632],{"type":63,"value":633}," -k",{"type":50,"tag":521,"props":635,"children":636},{"style":544},[637],{"type":63,"value":638}," YOUR_TOKEN_KEY",{"type":50,"tag":521,"props":640,"children":641},{"style":550},[642],{"type":63,"value":643}," -s",{"type":50,"tag":521,"props":645,"children":646},{"style":544},[647],{"type":63,"value":648}," YOUR_TOKEN_SECRET\n",{"type":50,"tag":521,"props":650,"children":652},{"class":523,"line":651},8,[653],{"type":50,"tag":521,"props":654,"children":655},{"emptyLinePlaceholder":602},[656],{"type":63,"value":605},{"type":50,"tag":521,"props":658,"children":660},{"class":523,"line":659},9,[661],{"type":50,"tag":521,"props":662,"children":663},{"style":528},[664],{"type":63,"value":665},"# create the public endpoint and start forwarding\n",{"type":50,"tag":521,"props":667,"children":669},{"class":523,"line":668},10,[670,674,679,684,689],{"type":50,"tag":521,"props":671,"children":672},{"style":538},[673],{"type":63,"value":623},{"type":50,"tag":521,"props":675,"children":676},{"style":544},[677],{"type":63,"value":678}," forward",{"type":50,"tag":521,"props":680,"children":681},{"style":550},[682],{"type":63,"value":683}," --bucket",{"type":50,"tag":521,"props":685,"children":686},{"style":544},[687],{"type":63,"value":688}," jenkins",{"type":50,"tag":521,"props":690,"children":691},{"style":544},[692],{"type":63,"value":693}," http://localhost:8080/github-webhook/\n",{"type":50,"tag":51,"props":695,"children":696},{},[697],{"type":63,"value":698},"That prints a public endpoint:",{"type":50,"tag":511,"props":700,"children":702},{"code":701},"https://vlndyzsibcil98gdte7yp1.hooks.webhookrelay.com -> http://localhost:8080/github-webhook/\n",[703],{"type":50,"tag":180,"props":704,"children":705},{"__ignoreMap":7},[706],{"type":63,"value":701},{"type":50,"tag":51,"props":708,"children":709},{},[710,712,717,718,723,725,731],{"type":63,"value":711},"Put that URL into your provider's webhook settings. Swap the destination for ",{"type":50,"tag":180,"props":713,"children":715},{"className":714},[],[716],{"type":63,"value":337},{"type":63,"value":72},{"type":50,"tag":180,"props":719,"children":721},{"className":720},[],[722],{"type":63,"value":357},{"type":63,"value":724}," or ",{"type":50,"tag":180,"props":726,"children":728},{"className":727},[],[729],{"type":63,"value":730},"/gitea-webhook/post",{"type":63,"value":732}," depending on which provider you are wiring up.",{"type":50,"tag":51,"props":734,"children":735},{},[736,738,744,746,752,754,760],{"type":63,"value":737},"For anything long-lived, run the agent as a service so it survives reboots — pass ",{"type":50,"tag":180,"props":739,"children":741},{"className":740},[],[742],{"type":63,"value":743},"--no-agent",{"type":63,"value":745}," to create the configuration without starting a foreground agent, then install it via Docker (",{"type":50,"tag":180,"props":747,"children":749},{"className":748},[],[750],{"type":63,"value":751},"--restart always",{"type":63,"value":753},") or as a background OS service. Both are covered step by step in the ",{"type":50,"tag":190,"props":755,"children":757},{"href":756},"/docs/tutorials/cicd/jenkins-github/",[758],{"type":63,"value":759},"Jenkins and GitHub tutorial",{"type":63,"value":86},{"type":50,"tag":762,"props":763,"children":765},"h3",{"id":764},"per-provider-walkthroughs",[766],{"type":63,"value":767},"Per-provider walkthroughs",{"type":50,"tag":51,"props":769,"children":770},{},[771],{"type":63,"value":772},"The full production setups, with screenshots and shared-secret configuration, live in the docs:",{"type":50,"tag":456,"props":774,"children":775},{},[776,786,797,808,819,830],{"type":50,"tag":316,"props":777,"children":778},{},[779,784],{"type":50,"tag":190,"props":780,"children":781},{"href":756},[782],{"type":63,"value":783},"Jenkins and GitHub",{"type":63,"value":785}," — GitHub plugin, shared secret, Blue Ocean pipeline",{"type":50,"tag":316,"props":787,"children":788},{},[789,795],{"type":50,"tag":190,"props":790,"children":792},{"href":791},"/docs/tutorials/cicd/jenkins-bitbucket/",[793],{"type":63,"value":794},"Jenkins and Bitbucket",{"type":63,"value":796}," — Bitbucket plugin, including Bitbucket Server Post-Webhooks",{"type":50,"tag":316,"props":798,"children":799},{},[800,806],{"type":50,"tag":190,"props":801,"children":803},{"href":802},"/docs/tutorials/cicd/jenkins-plugin/",[804],{"type":63,"value":805},"Jenkins plugin for Webhook Relay",{"type":63,"value":807}," — subscribe to buckets from inside Jenkins, no separate agent",{"type":50,"tag":316,"props":809,"children":810},{},[811,817],{"type":50,"tag":190,"props":812,"children":814},{"href":813},"/docs/tutorials/cicd/jenkins-plugin-multibranch/",[815],{"type":63,"value":816},"Multibranch pipelines",{"type":63,"value":818}," — branch and pull-request discovery",{"type":50,"tag":316,"props":820,"children":821},{},[822,828],{"type":50,"tag":190,"props":823,"children":825},{"href":824},"/blog/webhooks-to-jenkins-on-kubernetes/",[826],{"type":63,"value":827},"Jenkins on Kubernetes",{"type":63,"value":829}," — agent as a sidecar container",{"type":50,"tag":316,"props":831,"children":832},{},[833,839],{"type":50,"tag":190,"props":834,"children":836},{"href":835},"/blog/automated-github-pull-request-builds-on-jenkins/",[837],{"type":63,"value":838},"Automated PR builds",{"type":63,"value":840}," — building GitHub pull requests",{"type":50,"tag":124,"props":842,"children":844},{"id":843},"troubleshooting",[845],{"type":63,"value":846},"Troubleshooting",{"type":50,"tag":762,"props":848,"children":850},{"id":849},"_403-no-valid-crumb-was-included-in-the-request",[851],{"type":63,"value":852},"403 No valid crumb was included in the request",{"type":50,"tag":51,"props":854,"children":855},{},[856],{"type":63,"value":857},"The request landed on a Jenkins path that is not exempt from CSRF protection. Check, in order:",{"type":50,"tag":312,"props":859,"children":860},{},[861,885],{"type":50,"tag":316,"props":862,"children":863},{},[864,869,871,876,878,884],{"type":50,"tag":66,"props":865,"children":866},{},[867],{"type":63,"value":868},"Trailing slash.",{"type":63,"value":870}," ",{"type":50,"tag":180,"props":872,"children":874},{"className":873},[],[875],{"type":63,"value":329},{"type":63,"value":877},", not ",{"type":50,"tag":180,"props":879,"children":881},{"className":880},[],[882],{"type":63,"value":883},"/github-webhook",{"type":63,"value":86},{"type":50,"tag":316,"props":886,"children":887},{},[888,893,895,901,903,910],{"type":50,"tag":66,"props":889,"children":890},{},[891],{"type":63,"value":892},"An extra path segment.",{"type":63,"value":894}," Some integrations append a path (",{"type":50,"tag":180,"props":896,"children":898},{"className":897},[],[899],{"type":63,"value":900},"/ghprbhook",{"type":63,"value":902},", for instance) to whatever destination you configured, producing a final URL Jenkins does not recognise. Look at the actual request path in your ",{"type":50,"tag":190,"props":904,"children":907},{"href":905,"rel":906},"https://my.webhookrelay.com/logs",[194],[908],{"type":63,"value":909},"Webhook Relay logs",{"type":63,"value":911}," and make sure it is exactly the endpoint you expect.",{"type":50,"tag":762,"props":913,"children":915},{"id":914},"_400-signature-was-expected-but-not-provided",[916],{"type":63,"value":917},"400 Signature was expected, but not provided",{"type":50,"tag":51,"props":919,"children":920},{},[921,923,928,930,935,937,942],{"type":63,"value":922},"Jenkins is configured with a shared secret but the incoming request has no signature — the secret is missing on the provider side, or the two do not match. Set the same secret in both places. On GitHub that is the webhook's ",{"type":50,"tag":66,"props":924,"children":925},{},[926],{"type":63,"value":927},"Secret",{"type":63,"value":929}," field; in Jenkins it goes under the GitHub section → ",{"type":50,"tag":66,"props":931,"children":932},{},[933],{"type":63,"value":934},"Advanced",{"type":63,"value":936}," → ",{"type":50,"tag":66,"props":938,"children":939},{},[940],{"type":63,"value":941},"Shared secrets",{"type":63,"value":86},{"type":50,"tag":51,"props":944,"children":945},{},[946],{"type":50,"tag":55,"props":947,"children":950},{"alt":948,"src":949},"Jenkins shared secret configuration","/images/tutorials/jenkins/jenkins-shared-secret.png",[],{"type":50,"tag":51,"props":952,"children":953},{},[954,956,962],{"type":63,"value":955},"Generate one with ",{"type":50,"tag":180,"props":957,"children":959},{"className":958},[],[960],{"type":63,"value":961},"openssl rand -base64 32",{"type":63,"value":86},{"type":50,"tag":762,"props":964,"children":966},{"id":965},"jenkins-returns-200-but-nothing-builds",[967],{"type":63,"value":968},"Jenkins returns 200 but nothing builds",{"type":50,"tag":51,"props":970,"children":971},{},[972,974,979,981,987],{"type":63,"value":973},"Jenkins accepted the webhook and could not match it to a job. It reads the repository URL out of the payload and looks for a job configured against that repository, so the URL in your job's ",{"type":50,"tag":66,"props":975,"children":976},{},[977],{"type":63,"value":978},"Source Code Management",{"type":63,"value":980}," section has to match exactly. Check the Jenkins system log for ",{"type":50,"tag":180,"props":982,"children":984},{"className":983},[],[985],{"type":63,"value":986},"No SCM configuration was found!",{"type":63,"value":86},{"type":50,"tag":762,"props":989,"children":991},{"id":990},"everything-shows-as-received-but-never-forwarded",[992],{"type":63,"value":993},"Everything shows as \"received\" but never \"forwarded\"",{"type":50,"tag":51,"props":995,"children":996},{},[997],{"type":63,"value":998},"The agent is not running. Webhook Relay stored the request but had nothing to deliver it to. Start the agent — and if this happens intermittently, install it as a service rather than running it in a shell.",{"type":50,"tag":124,"props":1000,"children":1002},{"id":1001},"which-approach-should-you-use",[1003],{"type":63,"value":1004},"Which approach should you use?",{"type":50,"tag":136,"props":1006,"children":1007},{},[1008,1024],{"type":50,"tag":140,"props":1009,"children":1010},{},[1011],{"type":50,"tag":144,"props":1012,"children":1013},{},[1014,1019],{"type":50,"tag":148,"props":1015,"children":1016},{},[1017],{"type":63,"value":1018},"Situation",{"type":50,"tag":148,"props":1020,"children":1021},{},[1022],{"type":63,"value":1023},"Use",{"type":50,"tag":164,"props":1025,"children":1026},{},[1027,1040,1053,1071,1087],{"type":50,"tag":144,"props":1028,"children":1029},{},[1030,1035],{"type":50,"tag":171,"props":1031,"children":1032},{},[1033],{"type":63,"value":1034},"Jenkins has a public IP and you are happy exposing it",{"type":50,"tag":171,"props":1036,"children":1037},{},[1038],{"type":63,"value":1039},"Provider webhook straight to the Jenkins endpoint",{"type":50,"tag":144,"props":1041,"children":1042},{},[1043,1048],{"type":50,"tag":171,"props":1044,"children":1045},{},[1046],{"type":63,"value":1047},"Jenkins is behind a firewall, NAT or in a private network",{"type":50,"tag":171,"props":1049,"children":1050},{},[1051],{"type":63,"value":1052},"Webhook Relay agent forwarding to the internal URL",{"type":50,"tag":144,"props":1054,"children":1055},{},[1056,1061],{"type":50,"tag":171,"props":1057,"children":1058},{},[1059],{"type":63,"value":1060},"You would rather not run a separate agent",{"type":50,"tag":171,"props":1062,"children":1063},{},[1064,1069],{"type":50,"tag":190,"props":1065,"children":1066},{"href":802},[1067],{"type":63,"value":1068},"Jenkins plugin",{"type":63,"value":1070}," subscribing to a bucket",{"type":50,"tag":144,"props":1072,"children":1073},{},[1074,1079],{"type":50,"tag":171,"props":1075,"children":1076},{},[1077],{"type":63,"value":1078},"Jenkins runs in Kubernetes",{"type":50,"tag":171,"props":1080,"children":1081},{},[1082],{"type":50,"tag":190,"props":1083,"children":1084},{"href":824},[1085],{"type":63,"value":1086},"Agent as a sidecar",{"type":50,"tag":144,"props":1088,"children":1089},{},[1090,1095],{"type":50,"tag":171,"props":1091,"children":1092},{},[1093],{"type":63,"value":1094},"Provider has no Jenkins plugin",{"type":50,"tag":171,"props":1096,"children":1097},{},[1098,1100],{"type":63,"value":1099},"Generic Webhook Trigger at ",{"type":50,"tag":180,"props":1101,"children":1103},{"className":1102},[],[1104],{"type":63,"value":1105},"/generic-webhook-trigger/invoke",{"type":50,"tag":124,"props":1107,"children":1109},{"id":1108},"wrapping-up",[1110],{"type":63,"value":1111},"Wrapping up",{"type":50,"tag":51,"props":1113,"children":1114},{},[1115],{"type":63,"value":1116},"Most Jenkins webhook problems are URL problems. Get the endpoint exactly right — trailing slash included — make sure the repository in the job matches the repository in the payload, and set the shared secret on both sides.",{"type":50,"tag":51,"props":1118,"children":1119},{},[1120,1122,1128],{"type":63,"value":1121},"The part that genuinely needs infrastructure is receiving webhooks at all when Jenkins is not publicly reachable, which is the normal case for a company CI server. An outbound agent handles that without opening a single port. ",{"type":50,"tag":190,"props":1123,"children":1125},{"href":428,"rel":1124},[194],[1126],{"type":63,"value":1127},"Start forwarding for free",{"type":63,"value":86},{"type":50,"tag":1130,"props":1131,"children":1132},"style",{},[1133],{"type":63,"value":1134},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":7,"searchDepth":566,"depth":566,"links":1136},[1137,1138,1139,1142,1148,1149],{"id":126,"depth":534,"text":129},{"id":409,"depth":534,"text":412},{"id":501,"depth":534,"text":504,"children":1140},[1141],{"id":764,"depth":566,"text":767},{"id":843,"depth":534,"text":846,"children":1143},[1144,1145,1146,1147],{"id":849,"depth":566,"text":852},{"id":914,"depth":566,"text":917},{"id":965,"depth":566,"text":968},{"id":990,"depth":566,"text":993},{"id":1001,"depth":534,"text":1004},{"id":1108,"depth":534,"text":1111},"markdown","content:blog:jenkins-webhooks.md","content","blog/jenkins-webhooks.md","blog/jenkins-webhooks","md",{"loc":4},1787128253557]