Чому webhook-и GitHub упираються в таймаут під час звернення до Jenkins за VPN
GitHub надсилає webhook-и всередину, тому VPN, що захищає Jenkins, їх відхиляє. Пробросіть доставку назовні через relay або замініть webhook агентом, який опитує.
Сторінка доставки показує таймаут, а Jenkins нічого не записує в журнал — це ознака з’єднання, яке так і не надійшло. GitHub надсилає webhook як вихідний HTTP POST зі своєї інфраструктури на налаштований вами payload URL. VPN захищає Jenkins, відхиляючи саме такий тип з’єднання. Ні з одного боку нічого не зламано. Проблема в напрямку запиту.
Що насправді намагається зробити доставка
GitHub розв’язує ім’я хоста в payload URL і підключається до нього з публічного інтернету. Якщо цей URL указує на приватну адресу або на ім’я, яке розв’язується лише всередині вашої мережі, спроба провалюється ще до надсилання будь-якого запиту. Якщо він указує на публічне ім’я, яке відкидає ваш край, спроба натомість упирається в таймаут.
Ця різниця важлива для діагностики. Збій DNS і відфільтрований порт виглядають однаково — ніби на боці Jenkins нічого не сталося, — і обидва відображаються в GitHub як невдала доставка з іншою приєднаною причиною. Прочитайте цю причину, перш ніж змінювати URL.
Тунель, який дзвонить назовні, не створює слухача. Саме цієї частини люди чекають іншої поведінки.
Три способи виправити напрямок з’єднання
Кожне рішення змінює того, хто ініціює з’єднання, і існує лише три форми.
| 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 |
Опитування — найменш елегантне й найпростіше в експлуатації. Relay забезпечує майже миттєвий зворотний зв’язок, не відкриваючи порт. Runner зазвичай правильна відповідь, коли конфіденційність payload виключає третю сторону, бо завдання може виконуватися на машині, яка вже перебуває всередині мережі.
Обирайте за тим, чим можете керувати, а не за тим, що звучить сучасно.
Пробросіть доставку назовні за допомогою smee
Створіть канал у сервісі relay і збережіть його URL. Усередині мережі встановіть клієнт і пересилайте доставки на шлях, якого чекає Jenkins. Payload URL у налаштуваннях репозиторію стає URL каналу, а тип вмісту встановлюється як application/json.
sudo npm install --global smee-client
smee -u CHANNEL_URL --path /github-webhook/ --port 8080Три деталі вирішують, чи це працюватиме. Шлях має збігатися з тим, чого Jenkins чекає для подій GitHub, а за замовчуванням це /github-webhook/. Jenkins має слухати порт, який ви дали клієнту. І налаштований у завданні Jenkins URL має узгоджуватися з цим шляхом, інакше подія надходить і потім відкидається.
Незбіг завершальної скісної риски дає 404, який читається як збій доставки, але ним не є.
Запуск так, щоб це пережило тиждень
Клієнт на передньому плані помирає разом із терміналом, і webhook-и працюють день, а потім зупиняються. Дайте йому unit із Restart=always, запустіть його від користувача Jenkins і прочитайте журнал після першої реальної доставки. Саме цей останній крок відрізняє робочий relay від налаштованого.
[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.targetТестуйте справжнім push, а не кнопкою повтору. Повтор проганяє збережений payload relay, а не шлях від GitHub до вашого каналу, тому він може пройти, поки жива доставка все ще збоїть.
Сповіщайте, коли unit зупиняється. Relay, що впав, мовчить за своєю конструкцією, і тиша — це саме те, що ви вже налагоджуєте.
Що relay може бачити і коли його краще не використовувати
Relay термінує payload, тому бачить назви репозиторіїв, дані commit і все інше, що несе подія. Ставтеся до URL каналу як до публічної кінцевої точки. Тримайте секретний token Jenkins налаштованим, щоб підроблені доставки відхилялися, і обмежте token, який використовує Jenkins, необхідним мінімумом.
Якщо конфіденційність payload це виключає, self-hosted runner або автентифікований зворотний тунель — це відповідь.
Relay тепер інфраструктура, і він заслуговує на такий самий огляд, як build, який він запускає. Змінюйте канал, якщо він протік, і записуйте дату, коли ви востаннє перевіряли живу доставку. Поставте цю дату в runbook поруч з URL каналу. Relay, який ніхто не перевіряв рік, — це публічна кінцева точка, якою ніхто не володіє.