Waarom GitHub-webhooks time-out lopen tegen een Jenkins achter een VPN
GitHub stuurt webhooks naar binnen, dus een VPN die Jenkins beschermt weigert ze. Leid de levering naar buiten via een relay, of vervang de webhook door een agent die pollt.
De leveringspagina toont een time-out en Jenkins logt niets, wat het kenmerk is van een verbinding die nooit aankwam. GitHub stuurt een webhook als een uitgaande HTTP POST vanuit zijn eigen infrastructuur naar de payload-URL die je hebt geconfigureerd. Een VPN beschermt Jenkins door precies dat soort verbinding te weigeren. Aan geen van beide kanten is iets kapot. Het probleem is de richting van het verzoek.
Wat de levering werkelijk probeert
GitHub lost de hostnaam in de payload-URL op en maakt vanaf het openbare internet verbinding. Als die URL naar een privéadres wijst, of naar een naam die alleen binnen je netwerk oplost, mislukt de poging voordat er een verzoek wordt gedaan. Als hij naar een openbare naam wijst die je edge laat vallen, loopt de poging juist time-out.
Dat onderscheid is belangrijk voor de diagnose. Een DNS-fout en een gefilterde poort zien er beide uit alsof er aan de Jenkins-kant niets is gebeurd, en beide verschijnen in GitHub als een mislukte levering met een andere reden erbij. Lees die reden voordat je de URL wijzigt.
Een tunnel die naar buiten belt maakt geen luisteraar. Dat is het deel waarvan mensen verwachten dat het anders werkt.
Drie manieren om de richting van de verbinding te herstellen
Elke oplossing verandert wie de verbinding start, en er zijn maar drie vormen.
| Approach | Who initiates | What you give up |
|---|---|---|
| Relay service | An outbound client inside the network | A third party sees every payload |
| Reverse tunnel or ingress | The public edge, into a controlled listener | An inbound surface you must secure |
| Runner or polling | The agent, outbound to GitHub | Instant delivery, replaced by a schedule |
Pollen is het minst elegant en het eenvoudigst te beheren. Een relay houdt bijna directe feedback zonder een poort te openen. Een runner is meestal het juiste antwoord wanneer payload-vertrouwelijkheid een derde partij uitsluit, omdat de taak kan draaien op een machine die al binnen het netwerk staat.
Kies op basis van wat je kunt beheren, niet op basis van wat modern klinkt.
Leid een levering naar buiten met smee
Maak een kanaal aan op de relaydienst en bewaar de URL. Binnen het netwerk installeer je de client en stuurt leveringen door naar het pad dat Jenkins verwacht. De payload-URL in de repository-instellingen wordt de kanaal-URL, met het inhoudstype ingesteld op application/json.
sudo npm install --global smee-client
smee -u CHANNEL_URL --path /github-webhook/ --port 8080Drie details bepalen of het werkt. Het pad moet overeenkomen met wat Jenkins voor GitHub-gebeurtenissen verwacht, namelijk standaard /github-webhook/. Jenkins moet luisteren op de poort die je de client hebt gegeven. En de Jenkins-URL die in de job is geconfigureerd moet met dat pad overeenkomen, anders komt de gebeurtenis aan en wordt die daarna weggegooid.
Een afwijkende slash aan het eind levert een 404 op die leest als een mislukte levering en dat niet is.
Draaien zodat het de week overleeft
Een client op de voorgrond sterft met de terminal, en de webhooks werken een dag en stoppen dan. Geef hem een unit met Restart=always, draai hem als de Jenkins-gebruiker en lees het journal na de eerste echte levering. Die laatste stap is wat een werkende relay scheidt van een geconfigureerde.
[Unit]
Description=smee webhook relay
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=2
User=jenkins
ExecStart=/usr/bin/smee -u CHANNEL_URL --path /github-webhook/ --port 8080
[Install]
WantedBy=multi-user.targetTest met een echte push in plaats van een replay-knop. Een replay oefent de opgeslagen payload van de relay, niet het pad van GitHub naar je kanaal, dus hij kan slagen terwijl live levering nog steeds mislukt.
Alarmeer wanneer de unit stopt. Een relay die plat ligt is stil door zijn constructie, en die stilte is precies wat je al aan het debuggen bent.
Wat de relay kan zien, en wanneer je er geen moet gebruiken
Een relay beëindigt de payload, dus hij ziet reponamen, commitgegevens en al het andere dat de gebeurtenis draagt. Behandel de kanaal-URL als een openbaar eindpunt. Houd het geheime token van Jenkins geconfigureerd zodat vervalste leveringen worden geweigerd, en beperk het token dat Jenkins gebruikt tot het noodzakelijke minimum.
Als payload-vertrouwelijkheid dat uitsluit, is een zelfgehoste runner of een geauthenticeerde omgekeerde tunnel het antwoord.
Een relay is nu infrastructuur, en verdient dezelfde beoordeling als de build die hij uitlokt. Roteer het kanaal als het lekt, en noteer de datum waarop je voor het laatst een live levering hebt geverifieerd. Zet die datum in het runbook naast de kanaal-URL. Een relay die niemand een jaar lang heeft beoordeeld is een openbaar eindpunt dat niemand bezit.