Frizbee is an open-source tool that pins GitHub Actions and container image references to their immutable SHA digests, eliminating the supply-chain risk of mutable tags like latest or v1. In regulated or security-conscious environments, Frizbee runs as a pre-commit hook or CI gate to enforce that every action and image reference is pinned before code merges.
But Frizbee's effectiveness depends on infrastructure staying healthy: the OCI registries it queries must respond, the GitHub API must be reachable, and the CI pipelines running Frizbee must not silently fail. In this tutorial you'll set up external monitoring for your Frizbee-enforced supply chain using Vigilmon — free tier, no credit card required.
Why Frizbee-enforced workflows need external monitoring
Frizbee runs at commit or CI time, not continuously. That creates a window where your enforcement infrastructure can break without anyone noticing until a developer hits a confusing error or — worse — a pinned check silently passes on stale data.
The failure modes that external monitoring catches:
- Registry API timeouts — Frizbee resolves digests by querying Docker Hub, GHCR, or your private registry; if the registry is slow, Frizbee times out and CI fails with unhelpful errors
- GitHub API rate limiting — Frizbee uses the GitHub API to resolve action SHAs; hitting rate limits causes every pipeline in your org to fail simultaneously
- Stale pin detection gap — if your scheduled Frizbee audit job stops running (cron misconfiguration, runner shutdown), unpinned references accumulate without triggering any alert
- Pre-commit hook drift — developers may uninstall or bypass the pre-commit hook; the only reliable signal is whether Frizbee is still catching violations in CI
- Digest verification failures — an image re-tagged to a different digest creates a gap between what Frizbee validated at pin time and what actually runs
External monitoring closes these gaps because it tests what your pipelines actually see from a neutral vantage point.
What you'll need
- Frizbee installed (
go install github.com/stacklok/frizbee/cmd/frizbee@latestor the Docker image) - At least one GitHub Actions workflow or Dockerfile using pinned references
- A free Vigilmon account — sign up takes 30 seconds
Step 1: Expose a Frizbee health endpoint
Frizbee doesn't ship an HTTP server, so the simplest approach is a small probe script that runs Frizbee and reports results to Vigilmon via heartbeat.
Create a probe script that verifies your pinned references are still valid:
#!/usr/bin/env bash
# frizbee-probe.sh — verify pins and report to Vigilmon
REPO_DIR="${REPO_DIR:-/opt/repos/myapp}"
HEARTBEAT_URL="${VIGILMON_HEARTBEAT_URL:-https://vigilmon.online/heartbeat/YOUR_HEARTBEAT_ID}"
REPORT_FILE="/tmp/frizbee-report-$(date +%Y%m%d-%H%M%S).txt"
cd "$REPO_DIR" || { echo "Repo not found"; exit 1; }
# Run Frizbee in check mode — exits non-zero if unpinned references found
frizbee ghactions check --dir . > "$REPORT_FILE" 2>&1
GH_STATUS=$?
frizbee image check --dir . >> "$REPORT_FILE" 2>&1
IMG_STATUS=$?
if [ $GH_STATUS -ne 0 ] || [ $IMG_STATUS -ne 0 ]; then
echo "Frizbee detected unpinned references:"
cat "$REPORT_FILE"
exit 1
fi
# All references are pinned — send heartbeat to Vigilmon
curl -s -o /dev/null -w "%{http_code}" "$HEARTBEAT_URL"
echo "Frizbee probe passed — all references pinned"
Make it executable and test it:
chmod +x /opt/scripts/frizbee-probe.sh
/opt/scripts/frizbee-probe.sh
# Frizbee probe passed — all references pinned
Step 2: Monitor pin audit health with a Vigilmon heartbeat
Schedule the probe to run every 30 minutes and set up a Vigilmon heartbeat to alert if it stops:
*/30 * * * * /opt/scripts/frizbee-probe.sh >> /var/log/frizbee-probe.log 2>&1
In Vigilmon:
- Go to Monitors → New Monitor
- Choose Heartbeat
- Name:
Frizbee Pin Audit - Grace period: 45 minutes (gives one missed beat before alerting)
- Copy the generated heartbeat URL and paste it into the
VIGILMON_HEARTBEAT_URLvariable in your probe script - Save the monitor
Now if your audit job stops running — because the runner machine rebooted, the cron entry was deleted, or Frizbee itself failed to install — Vigilmon alerts you within 45 minutes.
Step 3: Monitor registry reachability
Frizbee resolves digests from OCI registries. If those registries are unreachable or slow, Frizbee silently fails or produces misleading errors. Monitor the registries directly.
Docker Hub
- Go to Monitors → New Monitor
- Choose HTTP / HTTPS
- URL:
https://hub.docker.com - Interval: 2 minutes
- Expected status:
200 - Save as
Docker Hub Reachability
GitHub Container Registry (GHCR)
- New monitor → HTTP / HTTPS
- URL:
https://ghcr.io - Interval: 2 minutes
- Expected status:
200 - Save as
GHCR Reachability
Private registry
If you run a private Harbor, Nexus, or similar registry that Frizbee queries:
- New monitor → HTTP / HTTPS
- URL:
https://registry.yourcompany.com/v2/(OCI v2 API root) - Expected status:
200or401(unauthenticated v2 root returns 401 by design) - Save as
Private Registry API
Step 4: Monitor GitHub API availability
Frizbee uses the GitHub API to resolve action commit SHAs. Monitor the GitHub API health endpoint so you know when rate limiting or outages are affecting your pipelines before developers start filing tickets.
- New monitor → HTTP / HTTPS
- URL:
https://api.github.com/zen(GitHub's lightweight health endpoint — returns a random zen aphorism with200) - Interval: 1 minute
- Expected status:
200 - Save as
GitHub API Health
For more granular GitHub status:
# Check GitHub API rate limit remaining from a CI machine
curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/rate_limit | jq '.rate.remaining'
Create a probe that alerts when rate limit drops below a threshold:
#!/usr/bin/env bash
# github-ratelimit-probe.sh
THRESHOLD=100
REMAINING=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
https://api.github.com/rate_limit | jq -r '.rate.remaining')
if [ -z "$REMAINING" ] || [ "$REMAINING" -lt "$THRESHOLD" ]; then
echo "GitHub API rate limit critically low: $REMAINING remaining"
exit 1
fi
curl -s "$VIGILMON_HEARTBEAT_URL"
Step 5: Monitor CI workflow integrity
The most important signal is whether Frizbee's CI gate is actually running and catching violations. Set up a Vigilmon heartbeat that your CI pipeline sends on every successful Frizbee check run.
Add this step to your GitHub Actions workflow:
# .github/workflows/frizbee-check.yml
name: Frizbee Pin Verification
on:
push:
branches: [main, develop]
pull_request:
schedule:
# Run daily audit even without code changes
- cron: '0 6 * * *'
jobs:
verify-pins:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae1 # v4.1.1
- name: Install Frizbee
run: |
go install github.com/stacklok/frizbee/cmd/frizbee@latest
- name: Check GitHub Actions pins
run: frizbee ghactions check --dir .
- name: Check container image pins
run: frizbee image check --dir .
- name: Report success to Vigilmon
if: success()
run: |
curl -s -o /dev/null \
"${{ secrets.VIGILMON_FRIZBEE_HEARTBEAT_URL }}"
In Vigilmon, create a Heartbeat monitor:
- Name:
Frizbee CI Gate - Grace period: 25 hours (catches missed daily runs)
If your CI pipeline stops running Frizbee — because a workflow file was accidentally deleted, a branch protection rule was removed, or the runner fleet is down — Vigilmon alerts you before any unpinned code can sneak through.
Step 6: Set up alerts
Go to Alerts in Vigilmon and configure notifications for all your Frizbee monitors:
- Email: instant alerts to your security team
- Slack: post to
#supply-chain-alertsor#ci-health - PagerDuty: for 24/7 on-call when the pin audit heartbeat goes silent
Recommended alert policy:
| Monitor | Alert after | Recovery notification | |---|---|---| | Frizbee Pin Audit heartbeat | 1 missed beat | Yes | | Docker Hub Reachability | 2 minutes down | Yes | | GHCR Reachability | 2 minutes down | Yes | | GitHub API Health | 3 minutes down | Yes | | Frizbee CI Gate heartbeat | 25 hours silent | Yes |
Step 7: Dependency drift detection with scheduled reports
Pin staleness is a slower failure mode — your pins are technically valid but months out of date, accumulating CVEs without your awareness. Set up a weekly probe that reports digest age:
#!/usr/bin/env bash
# frizbee-freshness-check.sh — check if pinned digests are still current
REPO_DIR="${REPO_DIR:-/opt/repos/myapp}"
MAX_DRIFT_DAYS=30
HEARTBEAT_URL="$VIGILMON_FRESHNESS_HEARTBEAT_URL"
cd "$REPO_DIR" || exit 1
# Generate a full pin report
frizbee ghactions pin --dry-run --dir . > /tmp/current-pins.txt 2>&1
# Compare with what's committed
if git diff --quiet HEAD -- .github/; then
echo "All GitHub Actions pins match latest digests"
else
CHANGED=$(git diff --name-only HEAD -- .github/ | wc -l)
echo "WARNING: $CHANGED workflow files have drifted from latest digests"
if [ "$CHANGED" -gt 5 ]; then
echo "Drift exceeds threshold — not sending heartbeat"
exit 1
fi
fi
curl -s "$HEARTBEAT_URL"
Schedule weekly:
0 9 * * 1 /opt/scripts/frizbee-freshness-check.sh >> /var/log/frizbee-freshness.log 2>&1
Create a corresponding Vigilmon heartbeat with an 8-day grace period to alert if the weekly check stops running.
Interpreting Vigilmon alerts for Frizbee
| Alert | Likely cause | First action |
|---|---|---|
| Pin Audit heartbeat silent | Cron not running, probe script error, Frizbee install missing | SSH to runner, check /var/log/frizbee-probe.log |
| Docker Hub or GHCR down | Registry outage | Check registry status page; Frizbee will fail until resolved |
| GitHub API health down | GitHub outage or rate limit | Check api.github.com/rate_limit; rotate or refresh token |
| CI Gate heartbeat silent | Workflow deleted, branch protection removed, runner down | Check GitHub Actions tab for the repository |
| Freshness heartbeat silent | Weekly check failed, high drift detected | Run frizbee ghactions check --dir . manually to see drift |
What's next
Once Frizbee monitoring is in place:
- Add image signing verification — integrate Cosign or Sigstore to verify signed digests, then monitor the verification step as a separate heartbeat
- Multi-repo coverage — run the probe script against multiple repositories and report aggregate health to a single Vigilmon heartbeat group
- Slack digest reports — use Vigilmon's webhook integration to post weekly freshness summaries to Slack
- SBOM generation — export a software bill of materials after every successful Frizbee audit and archive it; monitor the archival step as a heartbeat
Frizbee makes your supply chain safer by eliminating mutable references. Vigilmon makes Frizbee's own infrastructure observable, so you know when the safety net has a hole in it.