Deploy any Docker/Compose/PM2 service from GitHub webhooks. Drop this in, wire a few env vars, and ship “my-app” with a single push or tag.
- Project-agnostic: Works with any app that can be built/restarted (Docker, Compose, PM2)
- Secure by default: Verifies GitHub HMAC signatures (SHA1 + SHA256)
- Granular deploys: Rebuild/restart exactly one service per webhook
- Ops-friendly: Health, status, structured logs
- Listens on port 3003 (configurable) for GitHub webhooks
- Validates signature, decides if deploy is needed (tags like DEPLOY-1.0.0, branch pushes, or a specific branch)
- Executes one of three strategies against your project folder:
- docker-compose: up -d --build my-app
- docker: build/run a container
- pm2: npm install && pm2 restart my-app
GitHub Repo ──▶ Webhook Service (3003) ──▶ Your Project (Docker/Compose/PM2)
│
└──▶ Status & Health
- Configure
cp env.example .env
DEPLOYMENT_STRATEGY=docker-compose
PROJECT_PATH=/absolute/path/to/my-app
DOCKER_COMPOSE_FILE=docker-compose.yml
DOCKER_SERVICE_NAME=my-app
GITHUB_SECRET=your-webhook-secret- Recommended folder layout (host)
<your-root>/runningServices/
├── my-app/ # your application compose project (git clone)
└── webhook-service/ # this repository (git clone)
- Add to your compose and start Add the webhook service to your top-level compose (see full example below), then:
docker compose up -d --build webhook- Add GitHub webhook
- Payload URL:
http(s)://your-host:3003/webhook/github - Content type:
application/json - Secret: the value of
GITHUB_SECRET - Events: Push and/or Release
| Variable | Description | Example |
|---|---|---|
| PORT | Service port | 3003 |
| GITHUB_SECRET | GitHub webhook secret | super-secret |
| DEPLOYMENT_STRATEGY | docker-compose | docker |
| PROJECT_PATH | Absolute path mounted at /app |
/home/user/my-app |
| DOCKER_COMPOSE_FILE | Compose file (compose strategy) | docker-compose.yml |
| DOCKER_SERVICE_NAME | Service to rebuild/restart | my-app |
| PM2_APP_NAME | PM2 app name/ID (pm2 strategy) | my-app |
| DEPLOY_BRANCH | Restrict to branch (optional) | main |
Notes:
- Use absolute paths for
PROJECT_PATH. - Works with both
docker compose(v2) anddocker-compose(v1).
Depending on the strategy:
docker-compose
git fetch --all
git reset --hard origin/<branch>
docker compose -f <compose-file> up -d --build <service>
docker
git fetch --all
git reset --hard origin/<branch>
docker build -t <image> .
docker stop <container> || true
docker rm <container> || true
docker run -d --name <container> <image>
pm2
git fetch --all
git reset --hard origin/<branch>
npm install --omit=dev
pm2 restart <app>
Branch selection defaults to the webhook ref (e.g., main) or to DEPLOY_BRANCH if set.
- POST
/webhook/github→ receive webhook, validate, maybe deploy - GET
/webhook/status→ deployment status and recent history - GET
/health→ health check
Example webhook response (success):
{
"signature": "OK sha256=...",
"deploy": true,
"deployment": { "success": true, "deploymentId": "deploy-...", "method": "docker-compose" },
"timestamp": "2025-09-07T17:30:00.000Z"
}
Complete example (webhook + my-app) using separate repos/paths:
services:
my-app:
build: ./my-app
image: my-app:latest
ports:
- "8080:8080"
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
retries: 3
webhook:
build: <your-root>/runningServices/webhook-service
image: webhook-service:latest
ports:
- "3003:3003"
environment:
- DEPLOYMENT_STRATEGY=docker-compose
- PROJECT_PATH=/app
- DOCKER_COMPOSE_FILE=docker-compose.yml
- DOCKER_SERVICE_NAME=my-app
- GITHUB_SECRET=your-secret
volumes:
# Mount your compose project (my-app) so the webhook can git pull and compose up it
- <your-root>/runningServices/my-app:/app
# Allow the webhook to control Docker/Compose on the host
- /var/run/docker.sock:/var/run/docker.sock
restart: unless-stopped
Use a systemd unit on your host to bring up your “web” profile services on boot, while the webhook handles upgrades per service. Quick setup pattern:
- System boot:
docker compose --profile web up -d - Deploy one service via webhook:
docker compose up -d --build my-app
- Verifies GitHub HMAC signatures (SHA1 + SHA256)
- Avoids logging secrets
- Optionally restrict deployments to
DEPLOY_BRANCH
curl http://localhost:3003/health
curl http://localhost:3003/webhook/status
docker logs -f webhook-service
If a deploy fails:
- Check webhook logs (invalid signature, missing env, wrong path)
- Verify
PROJECT_PATHand compose project name are consistent - Ensure your app builds locally with the same commands
Made for pragmatic, incremental CI/CD.