tutorial

How to Monitor Direnv-Configured Services with Vigilmon

Direnv is the shell extension that automatically loads and unloads environment variables when you `cd` into a directory. It keeps secrets, API keys, and per-...

Direnv is the shell extension that automatically loads and unloads environment variables when you cd into a directory. It keeps secrets, API keys, and per-project configuration out of your global shell and in .envrc files that are project-local. But when the services those environments configure go down, Direnv won't alert you.

In this tutorial you'll add external uptime monitoring to services whose configuration is managed by Direnv using Vigilmon — free tier, no credit card required.


Why monitor Direnv-configured services?

Direnv is used in local dev and CI to load environment-specific config cleanly. When those services run in staging or production, the usual failure modes appear:

  • Missing or stale environment variables — a .envrc update that isn't sourced leaves a service running with old config, causing silent auth failures or wrong database connections
  • Secret rotation leaves service misconfigured — a credential is rotated in the secrets store but the deployed service's environment wasn't reloaded, causing 401s and 503s
  • Service starts but can't reach its dependencies — the database URL or API key in the environment is wrong and the service degrades silently
  • Process crashes after config change — a bad .envrc variable causes a startup exception that the process supervisor restarts incorrectly

Vigilmon monitors from outside your stack. It catches any of these degradation patterns the moment they affect HTTP responses or port reachability.


What you'll need

  • A service that uses environment variables loaded by Direnv
  • A free Vigilmon account

Step 1: Add a health endpoint that reflects environment state

The most useful health endpoint for a Direnv-managed service shows whether critical environment variables are present and whether downstream dependencies are reachable.

For a Node.js/Express service:

app.get('/health', async (req, res) => {
  const checks = {
    database: false,
    config: !!(process.env.DATABASE_URL && process.env.API_KEY)
  };

  try {
    await db.raw('SELECT 1');
    checks.database = true;
  } catch {
    // database unreachable
  }

  const healthy = Object.values(checks).every(Boolean);
  res.status(healthy ? 200 : 503).json({ status: healthy ? 'ok' : 'degraded', checks });
});

For a Python/FastAPI service:

import os

@app.get("/health")
async def health():
    config_ok = bool(os.getenv("DATABASE_URL") and os.getenv("SECRET_KEY"))
    return {"status": "ok" if config_ok else "degraded", "config": config_ok}

This pattern catches the case where environment variables are missing or empty — a common failure when .envrc changes aren't propagated to a running service.


Step 2: Validate your .envrc before deployment

Add a validation script that Direnv can run (or that your deploy pipeline calls) to assert required variables are present before starting the service:

# .envrc
export DATABASE_URL="postgres://user:pass@localhost:5432/mydb"
export API_KEY="sk-..."
export PORT="3000"

# Validate required vars
_required_vars=(DATABASE_URL API_KEY PORT)
for var in "${_required_vars[@]}"; do
  if [[ -z "${!var}" ]]; then
    echo "ERROR: required env var $var is not set" >&2
    return 1
  fi
done

Run direnv allow . to activate, then direnv exec . env | grep DATABASE_URL to verify the variable is actually in scope before deploying.


Step 3: Set up HTTP monitoring in Vigilmon

Once your service is running at a publicly reachable URL:

  1. Log in to vigilmon.online and go to Monitors → New Monitor
  2. Choose HTTP / HTTPS
  3. Set the URL to your health endpoint, e.g. https://api.example.com/health
  4. Set the check interval to 1 minute
  5. Under Expected response, set:
    • Status code: 200
    • (Optional) Response body contains: "status":"ok"
  6. Save the monitor

A 503 response from the health endpoint — indicating missing config or a failed dependency check — immediately opens a Vigilmon incident.


Step 4: Monitor per-environment services

Direnv shines in multi-environment setups where staging, production, and local dev each have their own .envrc. Map one Vigilmon monitor per environment:

| Environment | .envrc location | Vigilmon monitor | |---|---|---| | Local dev | .envrc | Not monitored (local) | | Staging | .envrc.staging (symlinked) | API — Staging | | Production | Injected by deploy tooling | API — Production |

Use separate alert thresholds per environment: staging might tolerate a 2-minute outage before alerting, while production should alert on the first failed check.


Step 5: Track key metrics

| Metric | What it catches | |---|---| | HTTP response code | Service crash, bad config reload | | HTTP response time | Slow dependency caused by wrong env config | | Response body checks.config | Missing or blank environment variable | | Response body checks.database | Wrong DATABASE_URL or rotated credential |

Set a response-time alert threshold in Vigilmon (e.g. alert if > 2 s) to catch latency regressions caused by a service hitting a wrong — but reachable — database after a config change.


Step 6: Add heartbeat monitoring to your deploy pipeline

When environment variables change (secret rotation, new feature flags), your deploy pipeline should reload or restart the service. Add a Vigilmon heartbeat to confirm the post-deploy health check passes:

  1. In Vigilmon, go to New Monitor → Heartbeat
  2. Name it Deploy + Env Reload — production
  3. Set expected interval to your deploy cadence (e.g. 48 hours)
  4. Copy the ping URL

In your deploy script:

#!/usr/bin/env bash
set -e

# Reload environment and restart service
direnv exec /app /app/scripts/start.sh &

# Wait for health check to pass
for i in $(seq 1 30); do
  if curl -sf http://localhost:3000/health > /dev/null; then
    echo "Service healthy after $i attempts"
    curl -fsS -X POST "$VIGILMON_DEPLOY_HEARTBEAT_URL" --max-time 10
    exit 0
  fi
  sleep 2
done

echo "Service failed to become healthy — aborting"
exit 1

If the service doesn't become healthy after the environment reload, no heartbeat ping is sent and Vigilmon alerts after the grace period.


Step 7: Configure alert channels

  1. Go to Alert Channels → Add Channel
  2. Choose Email or Webhook (Slack, Discord, PagerDuty)
  3. Assign the channel to your HTTP monitors and heartbeat monitors
  4. Set the alert trigger to 1 failed check for production monitors

Vigilmon sends a structured payload you can route in Slack:

{
  "monitor_name": "API — Production",
  "status": "down",
  "url": "https://api.example.com/health",
  "started_at": "2024-06-01T10:00:00Z",
  "duration_seconds": 90
}

Conclusion

Direnv keeps your environment configuration clean, per-project, and explicit. Vigilmon keeps your services observable, ensuring that a stale variable, a rotated credential, or a bad config reload is caught within a minute rather than discovered by a user. Add a health endpoint that validates your critical environment variables, create a one-minute Vigilmon HTTP monitor, and wire up deploy heartbeats — you'll have complete environment-aware monitoring in under ten minutes.

Get started free at vigilmon.online.

Monitor your app with Vigilmon

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

Start free →