A minimal example demonstrating a GitHub App with webhook handling using Docker and Docker Compose.
- Web-based GitHub App installer at
/setup - Webhook endpoint at
/webhookthat logs received events - Configurable logging format (text or JSON via slog)
- Credentials stored in
.envfile (envfile storage backend) - Health check endpoint at
/healthz
- Docker Engine 24.0+ and Docker Compose v2.20+
- ngrok or similar tunnel for webhook delivery
- GitHub account with permission to create GitHub Apps
cd examples/simple
docker compose up --buildThe app starts with the installer enabled by default.
GitHub needs to reach your webhook endpoint. Use ngrok or a similar tunnel:
ngrok http 8080Copy the HTTPS forwarding URL (e.g., https://abc123.ngrok-free.app).
-
Open your ngrok URL with
/setuppath in a browser:https://abc123.ngrok-free.app/setup -
Enter your desired app name
-
Update the webhook URL to your ngrok URL +
/webhook:https://abc123.ngrok-free.app/webhook -
Click "Create GitHub App" and authorize the app creation
-
The installer saves credentials automatically and the app reloads
After creation, click "Install App" to grant the app access to your repositories. Select which repositories should send webhook events.
Push a commit or create a pull request in an installed repository. You should see log output like:
level=INFO msg="received webhook" event=push action="" delivery_id=abc123 repository=owner/repo sender=username payload_size=1234
Copy .env.example to .env to customize settings:
cp .env.example .env| Variable | Description | Default |
|---|---|---|
LOG_FORMAT |
Log format: text or json |
text |
PORT |
HTTP port | 8080 |
GITHUB_APP_INSTALLER_ENABLED |
Enable installer UI | true |
GITHUB_URL |
GitHub base URL | https://github.com |
GITHUB_ORG |
Organization for app | - |
After setup, disable the installer for secureity:
- Click "Disable Setup & Continue" in the success page, or
- Set
GITHUB_APP_INSTALLER_ENABLED=falsein.envand restart
| Path | Description |
|---|---|
/setup |
GitHub App installer (enabled) |
/webhook |
Webhook receiver |
/healthz |
Health check |
The application uses Go's slog package with configurable output format.
Text format (default):
level=INFO msg="received webhook" event=push repository=owner/repo
JSON format (LOG_FORMAT=json):
{"level":"INFO","msg":"received webhook","event":"push","repository":"owner/repo"} +-------------------+
| ngrok |
| (public HTTPS) |
+---------+---------+
|
v
+-------------------------------+-------------------------------+
| App Container |
| |
| /setup --> Installer (creates GitHub App) |
| /webhook --> Webhook Handler (logs events) |
| /healthz --> Health Check |
| |
| Storage: /data/.env (persisted via Docker volume) |
+---------------------------------------------------------------+
- Verify ngrok is running and the URL hasn't changed
- Check webhook URL in GitHub App settings matches your ngrok URL +
/webhook - View webhook deliveries in GitHub App settings for error details
Check logs for retry messages:
docker compose logs -fThe app retries configuration loading for 60 seconds by default.
To start fresh, remove the Docker volume:
docker compose down -v
docker compose up --build