tutorial

How to Monitor Frizbee with Vigilmon (Pin Verification, Dependency Drift + Alerts)

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 m...

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@latest or 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:

  1. Go to Monitors → New Monitor
  2. Choose Heartbeat
  3. Name: Frizbee Pin Audit
  4. Grace period: 45 minutes (gives one missed beat before alerting)
  5. Copy the generated heartbeat URL and paste it into the VIGILMON_HEARTBEAT_URL variable in your probe script
  6. 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

  1. Go to Monitors → New Monitor
  2. Choose HTTP / HTTPS
  3. URL: https://hub.docker.com
  4. Interval: 2 minutes
  5. Expected status: 200
  6. Save as Docker Hub Reachability

GitHub Container Registry (GHCR)

  1. New monitor → HTTP / HTTPS
  2. URL: https://ghcr.io
  3. Interval: 2 minutes
  4. Expected status: 200
  5. Save as GHCR Reachability

Private registry

If you run a private Harbor, Nexus, or similar registry that Frizbee queries:

  1. New monitor → HTTP / HTTPS
  2. URL: https://registry.yourcompany.com/v2/ (OCI v2 API root)
  3. Expected status: 200 or 401 (unauthenticated v2 root returns 401 by design)
  4. 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.

  1. New monitor → HTTP / HTTPS
  2. URL: https://api.github.com/zen (GitHub's lightweight health endpoint — returns a random zen aphorism with 200)
  3. Interval: 1 minute
  4. Expected status: 200
  5. 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-alerts or #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.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →