Two things. That's the integration.
Your CI workflow and a compose file — no server config, no registration, no YAML on the VPS.
1. Trigger from CI
Build your image and call RollHook in the same workflow step.
- name: Build & push
uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/you/my-api:${{ github.sha }}
- name: Deploy via RollHook
uses: jkrumm/rollhook-action@v1
with:
url: ${{ secrets.ROLLHOOK_URL }}
token: ${{ secrets.ROLLHOOK_WEBHOOK_TOKEN }}
image_tag: ghcr.io/you/my-api:${{ github.sha }} 2. Use image: ${IMAGE_TAG} and add a healthcheck
RollHook finds the compose file automatically from the running container's labels. No registration needed.
services:
backend:
# IMAGE_TAG is set by RollHook on each deploy.
# The running container's image name is the discovery key —
# RollHook finds it automatically via Docker Compose labels.
image: ${IMAGE_TAG:-ghcr.io/you/my-api:latest}
healthcheck:
test: [CMD, curl, -f, http://localhost:3000/health]
interval: 5s
start_period: 10s
retries: 5
# No ports: — proxy routes via Docker DNS (backend:3000)
# No container_name: — fixed names prevent the scaler from creating a second instance
networks:
- proxy
networks:
proxy:
external: true What it handles
Webhook-Driven
POST /deploy from any CI pipeline. App derived from image_tag. Admin + webhook token roles.
Rolling Updates
TypeScript rolling deploy scales up, health-gates each container, then removes old ones.
Real-Time Logs
SSE stream delivers every log line to CI as it happens.
Job History
SQLite-backed, no external dependencies. Query status and logs any time.
Auto-Discovery
No config file. RollHook finds the compose file and service from Docker Compose labels on the running container.
Notifications
Pushover + configurable webhook on job completion.
What happens on deploy
- 01
CI pushes image, sends POST /deploy
Webhook body carries
{"image_tag": "..."}— CI blocks until deployment completes. Returns HTTP 500 on failure. - 02
Discovers the running container automatically
Matches the image name against running containers, reads Docker Compose labels to find the compose file path and service name. No config file needed.
- 03
Compose file validated, image pulled
Confirms the compose file exists on disk, then pulls the new image from your registry.
- 04
Rolling deploy scales up, waits for health, removes old containers
New container starts alongside the old one. Traffic continues to the old instance.
- 05
Each step waits for healthcheck to pass
Old container removed only after the new one passes its healthcheck. No traffic loss.
- 06
Full log stream via SSE; Pushover fires on completion
CI tails the log stream in real time. Notification sent with full job result on finish.
API Surface
POST /deploy # Trigger a deployment
GET /jobs/:id # Job status + metadata
GET /jobs/:id/logs # SSE log stream
GET /jobs # Deployment history (admin)
GET /health # Health check (no auth) One GitHub Action away.
Add RollHook to your infra compose stack, add
jkrumm/rollhook-action@v1
to your CI workflow, and you're done — no config file needed.