Prerequisites
- Syft installed on your pipeline host (
anchore/syftbinary or Docker image) - A web service framework available on the host (examples use Python/FastAPI and shell scripts)
- A free account at vigilmon.online
Part 1: Understanding what to monitor in a Syft pipeline
Syft itself is a CLI tool — it does not expose an HTTP endpoint. Monitoring therefore happens at the wrapping layer: the service, script, or CI job that invokes Syft and handles its output.
There are three failure modes worth monitoring:
| Failure | Symptom | Detection method |
|---------|---------|-----------------|
| Syft binary missing or broken | Exit code non-zero, no SBOM written | Health endpoint that invokes syft version |
| Registry unreachable | Syft hangs or errors on image pull | Separate HTTP monitor on the registry URL |
| Output store full or unreachable | SBOM not persisted | Health endpoint that checks last write timestamp |
We will build a small HTTP health service that covers all three.
Part 2: Build a Syft health endpoint
Create a minimal FastAPI service that exposes a /health endpoint. Run this alongside your Syft pipeline on each scanner host.
Install dependencies
pip install fastapi uvicorn
Create sbom_health.py
import subprocess
import time
import os
from fastapi import FastAPI, Response
app = FastAPI()
SBOM_OUTPUT_DIR = os.environ.get("SBOM_OUTPUT_DIR", "/var/sbom")
MAX_STALENESS_SEC = int(os.environ.get("SBOM_MAX_STALENESS_SEC", "3600"))
@app.get("/health")
def health(response: Response):
checks = {}
try:
result = subprocess.run(
["syft", "version"],
capture_output=True,
text=True,
timeout=10,
)
checks["syft_binary"] = "ok" if result.returncode == 0 else "error"
except Exception as e:
checks["syft_binary"] = f"error: {e}"
if os.path.isdir(SBOM_OUTPUT_DIR) and os.access(SBOM_OUTPUT_DIR, os.W_OK):
checks["output_dir"] = "ok"
else:
checks["output_dir"] = "error: missing or not writable"
try:
files = [
os.path.join(SBOM_OUTPUT_DIR, f)
for f in os.listdir(SBOM_OUTPUT_DIR)
if f.endswith(".json") or f.endswith(".spdx")
]
if files:
latest_mtime = max(os.path.getmtime(f) for f in files)
age_sec = time.time() - latest_mtime
checks["last_sbom_age_sec"] = int(age_sec)
checks["pipeline_staleness"] = "warning" if age_sec > MAX_STALENESS_SEC else "ok"
else:
checks["pipeline_staleness"] = "no_sboms_found"
except Exception as e:
checks["pipeline_staleness"] = f"error: {e}"
all_ok = all(v == "ok" for v in checks.values() if isinstance(v, str))
response.status_code = 200 if all_ok else 503
return {"status": "ok" if all_ok else "degraded", "checks": checks}
Run the health service
uvicorn sbom_health:app --host 0.0.0.0 --port 8090
Verify the endpoint
curl http://localhost:8090/health
Expected response when healthy:
{
"status": "ok",
"checks": {
"syft_binary": "ok",
"output_dir": "ok",
"last_sbom_age_sec": 312,
"pipeline_staleness": "ok"
}
}
Part 3: Set up HTTP monitoring in Vigilmon
Monitor the Syft health endpoint
- Log in to vigilmon.online and click Add Monitor.
- Choose HTTP(S) monitor.
- Enter:
http://your-scanner-host:8090/health - Set interval to 5 minutes.
- Add a keyword check: must contain
"status":"ok". - Add your alert channel.
- Click Save.
The keyword check catches the case where the endpoint returns HTTP 200 but with "status":"degraded" — which means Syft is reachable but the pipeline has a problem.
Monitor the container registry Syft pulls from
Syft needs to pull image manifests from your registry. If the registry is down, all SBOM generation silently fails. Add a separate monitor:
- Add a new HTTP(S) monitor.
- Enter your registry health endpoint:
- Docker Hub:
https://index.docker.io/v2/ - GitHub Container Registry:
https://ghcr.io/v2/ - Private registry:
https://registry.example.com/v2/
- Docker Hub:
- Set interval to 1 minute.
- Add the same alert channel.
Part 4: Monitor Syft in CI/CD
If Syft runs inside GitHub Actions, add a reporting step so your status endpoint reflects the last run outcome:
# .github/workflows/sbom.yml
name: Generate SBOM
on:
push:
branches: [main]
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Syft
run: curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- name: Generate SBOM
id: syft
run: |
syft "${{ env.IMAGE_REF }}" -o spdx-json > sbom.spdx.json
echo "exit_code=$?" >> $GITHUB_OUTPUT
- name: Report pipeline status
if: always()
run: |
STATUS="ok"
if [ "${{ steps.syft.outputs.exit_code }}" != "0" ]; then STATUS="failed"; fi
curl -s -X POST "${{ secrets.STATUS_API_URL }}/api/sbom-status" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.STATUS_API_KEY }}" \
-d "{\"status\": \"$STATUS\", \"image\": \"${{ env.IMAGE_REF }}\"}"
Part 5: Webhook alerts for pipeline failures
Configure Vigilmon to call a webhook when the Syft health endpoint goes down:
from fastapi import FastAPI, Request
import logging
app = FastAPI()
logger = logging.getLogger(__name__)
@app.post("/webhook/vigilmon")
async def vigilmon_alert(request: Request):
payload = await request.json()
status = payload.get("status")
monitor_name = payload.get("monitor_name")
if status == "down":
logger.error("SBOM pipeline DOWN", extra={"monitor": monitor_name})
await notify_security_team(monitor_name)
elif status == "up":
logger.info("SBOM pipeline recovered", extra={"monitor": monitor_name})
return {"received": True}
Vigilmon sends this payload on status transitions:
{
"monitor_id": "mon_syft01",
"monitor_name": "Syft SBOM Pipeline Health",
"status": "down",
"url": "http://scanner.internal:8090/health",
"checked_at": "2026-07-02T09:00:00Z",
"response_code": 503,
"response_time_ms": 1204
}
Part 6: SSL monitoring for SBOM stores
If you store SBOMs in an HTTPS endpoint or OCI registry:
- In Vigilmon, click Add Monitor.
- Choose SSL monitor.
- Enter each HTTPS host your Syft pipeline writes to:
sbom-store.example.comregistry.example.com
- Set alert threshold to 14 days before expiry.
- Add your alert channel.
Part 7: Systemd service for the health endpoint
Keep the health service running across reboots:
# /etc/systemd/system/sbom-health.service
[Unit]
Description=Syft SBOM pipeline health endpoint
After=network.target
[Service]
User=sbomscanner
WorkingDirectory=/opt/sbom-health
ExecStart=/usr/local/bin/uvicorn sbom_health:app --host 0.0.0.0 --port 8090
Restart=on-failure
RestartSec=5
Environment=SBOM_OUTPUT_DIR=/var/sbom
Environment=SBOM_MAX_STALENESS_SEC=3600
[Install]
WantedBy=multi-user.target
sudo systemctl enable sbom-health
sudo systemctl start sbom-health
Summary
Your Syft SBOM pipeline now has layered monitoring:
- Binary health endpoint — confirms Syft is installed and the output directory is writable, polled every 5 minutes by Vigilmon.
- Registry monitor — catches upstream registry failures before they silently block SBOM generation.
- CI pipeline status — reports success/failure after each Syft run so Vigilmon alerts on consecutive failures.
- SSL monitors — alerts before certificate expiry breaks SBOM writes or registry pulls.
Vigilmon handles check scheduling, multi-region polling, and alert routing. You get notified within minutes of any failure in the Syft pipeline — not after your next compliance audit.
Monitor your SBOM generation pipeline free at vigilmon.online
#syft #sbom #containersecurity #devops #monitoring