tutorial

Monitoring Nickel Configuration Pipelines with Vigilmon

Nickel brings typed contracts to configuration — but when the pipelines evaluating your configs go quiet, you won't know until something breaks downstream. Here's how to monitor Nickel-driven workflows with Vigilmon.

Nickel is a modern configuration language from Tweag that brings gradual typing, contracts, and lazy evaluation to the configuration problem that Nix and Dhall also tackle. Teams use it to generate NixOS module options, Terraform variables, and application configs. Like CUE and Dhall, Nickel itself is a build-time tool — it has no runtime daemon to observe. Vigilmon provides that missing runtime layer: heartbeat monitors for Nickel evaluation jobs, HTTP monitors for services wrapping Nickel evaluation, and alerts when the pipeline stops producing output.

What You'll Set Up

  • Cron heartbeat monitors for scheduled Nickel evaluation and export jobs
  • HTTP monitors for services that use Nickel for runtime config generation
  • Contract validation endpoint monitoring
  • Alerting for silent pipeline failures

Prerequisites

  • Nickel 1.x installed (nickel --version)
  • At least one scheduled job or service that runs nickel export
  • A free Vigilmon account

Step 1: Add a Heartbeat Monitor for Nickel Export Jobs

The typical Nickel failure is an evaluation that succeeds locally but silently stops running in CI, or a cron job whose schedule drifts until it never fires. Vigilmon's heartbeat catches this: if the expected ping doesn't arrive within the configured window, you get an alert.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Select Cron Heartbeat.
  3. Set the expected ping interval to match your export schedule (e.g. 60 minutes).
  4. Copy the heartbeat URL (e.g. https://vigilmon.online/heartbeat/abc123).

Update your Nickel export script to ping on success:

#!/bin/bash
set -e

# Export Nickel config to JSON
nickel export config/main.ncl --format json > dist/config.json

# Validate the output is well-formed
python3 -c "import json, sys; json.load(open('dist/config.json'))"

# Generate environment-specific overrides
nickel export config/env/production.ncl --format json > dist/production.json

# Signal successful completion
curl -s https://vigilmon.online/heartbeat/abc123

echo "Nickel export pipeline completed."

If nickel export exits non-zero (contract violation, import error, type mismatch), the script halts before the heartbeat ping.

For a GitHub Actions workflow, add the ping step explicitly:

- name: Export Nickel configs
  run: nickel export config/main.ncl --format json > dist/config.json

- name: Export production overrides
  run: nickel export config/env/production.ncl --format json > dist/production.json

- name: Ping Vigilmon
  if: success()
  run: curl -s https://vigilmon.online/heartbeat/abc123

Step 2: Write Nickel Contracts with Observable Failure

Nickel's contract system validates data against schemas at merge time. Wrap your evaluation in a script that surfaces contract failures clearly so alerts are actionable:

# config/contracts.ncl
let Port = std.contract.from_predicate (fun p =>
  std.is_number p && p >= 1 && p <= 65535
) in

let ServiceConfig = {
  host | String,
  port | Port,
  tls_enabled | Bool,
  health_path | String | default = "/health",
}
in

{
  api_server | ServiceConfig = {
    host = "api.example.com",
    port = 8443,
    tls_enabled = true,
  }
}

Wrap the evaluation in a script that surfaces contract failures:

#!/bin/bash
if ! nickel export config/main.ncl --format json > dist/config.json 2>nickel_errors.txt; then
  echo "Nickel contract violation:"
  cat nickel_errors.txt
  # Do NOT ping Vigilmon — let the heartbeat expire and alert
  exit 1
fi

curl -s https://vigilmon.online/heartbeat/abc123

Step 3: Monitor a Nickel HTTP Config Service

Some infrastructure teams build a small HTTP service that evaluates Nickel on demand — a webhook that validates incoming JSON, or an API that returns environment-specific configs. Monitor this service with an HTTP check:

  1. Click Add Monitor in Vigilmon.
  2. Set Type to HTTP / HTTPS.
  3. Enter the service URL: https://config-service.example.com/health.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

Add a health endpoint to your Nickel config service that verifies the evaluator is available:

from fastapi import FastAPI, HTTPException
import subprocess

app = FastAPI()

@app.get("/health")
def health():
    try:
        result = subprocess.run(
            ["nickel", "export", "--format", "json"],
            input='{ status = "ok" }',
            capture_output=True,
            text=True,
            timeout=10,
        )
        if result.returncode != 0:
            raise RuntimeError(result.stderr)
        return {"status": "ok", "nickel": "responsive"}
    except Exception as e:
        raise HTTPException(status_code=503, detail=str(e))

Step 4: Contract Validation Endpoint Monitoring

Expose Nickel contract validation as a dedicated endpoint and use Vigilmon to probe it with a known-valid payload:

@app.post("/validate")
def validate(payload: dict):
    nickel_expr = f"""
    let Schema = {{
      host | String,
      port | Number,
      tls  | Bool,
    }} in
    Schema & {{
      host = "{payload.get('host', '')}",
      port = {payload.get('port', 0)},
      tls = {str(payload.get('tls', False)).lower()}
    }}
    """
    result = subprocess.run(
        ["nickel", "export", "--format", "json"],
        input=nickel_expr,
        capture_output=True,
        text=True,
        timeout=10,
    )
    if result.returncode != 0:
        return {"valid": False, "error": result.stderr}, 400
    return {"valid": True}

In Vigilmon, add an HTTP monitor for POST /validate with a known-valid JSON body and check for "valid":true in the response. Any configuration drift that breaks contract validation triggers an alert before it reaches a deployment.


Step 5: Track Config Generation Across Multiple Environments

Large deployments evaluate Nickel configs per environment. Use separate Vigilmon heartbeats for each:

#!/bin/bash
set -e

VIGILMON_BASE="https://vigilmon.online/heartbeat"

for env in staging production; do
  echo "Generating config for $env..."
  nickel export "config/envs/$env.ncl" --format json > "dist/$env.json"
  curl -s "${VIGILMON_BASE}/${env}_heartbeat_id"
done

Create one heartbeat monitor per environment in Vigilmon so you get per-environment visibility rather than a single aggregate signal. A failure in the staging config generator is a warning; a failure in production is a critical incident.


Step 6: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add Slack, email, or a webhook.
  2. For heartbeat monitors, set Consecutive failures before alert to 1 — a missed Nickel export is always worth investigating immediately.
  3. For HTTP service monitors, set it to 2 to absorb brief restarts.
  4. Name each monitor clearly (e.g. "Nickel export — production") so alerts are immediately actionable without opening a dashboard.

Summary

| Monitor | Type | What It Catches | |---|---|---| | Nickel export job | Cron heartbeat | Contract violations stopping pipeline, cron failure | | Per-environment export | Cron heartbeat | Missing environment config, silent skip | | Config HTTP service | HTTP | Service crash, Nickel evaluator errors | | Contract validator endpoint | HTTP | Schema drift breaking validation |

Nickel enforces type and contract correctness at evaluation time — Vigilmon enforces that the evaluation actually runs. Together they guarantee that your configuration pipeline is both correct and alive.

Monitor your app with Vigilmon

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

Start free →