This guide provides a reference for configuring Vigil v1.28.6. The configuration file uses INI-style format with environment variable interpolation. All sections, options, and best practices for production deployments are covered.
Configuration File: /etc/vigil/config.cfg (native) or /etc/vigil.cfg (Docker)
Version: v1.28.6 (November 2025)
Vigil uses INI-style configuration with the following conventions:
[section_name]key = "value" or key = number#${VARIABLE_NAME} syntax[ "value1", "value2" ]true or false (unquoted)[server]
log_level = "info"
inet = "[::]:8080"
[branding]
page_title = "Service Status"
[metrics]
poll_interval = 120
[notify]
startup_notification = true
[probe]
[[probe.service]]
id = "api"
label = "API Service"
Configures the Vigil server process, authentication, and runtime behavior.
[server]
log_level = "info"
inet = "[::]:8080"
workers = 4
mcp_server = false
manager_token = "${VIGIL_MANAGER_TOKEN}"
reporter_token = "${VIGIL_REPORTER_TOKEN}"
| Option | Type | Default | Description |
|---|---|---|---|
log_level |
String | "error" |
Logging level: debug, info, warn, error |
inet |
String | "[::1]:8080" |
Bind address and port (IPv4/IPv6) |
workers |
Integer | 4 |
Number of worker threads |
mcp_server |
Boolean | false |
Enable MCP server for AI Agents (v1.28.0+) |
manager_token |
String | Required | Secret token for Manager API authentication |
reporter_token |
String | Required | Secret token for Reporter API authentication |
"info" or "warn" (avoid "debug" in production)[::]:8080 for IPv4+IPv6 or 127.0.0.1:8080 for localhost only# 32-character hex token
openssl rand -hex 32
# URL-safe base64 token
openssl rand -base64 32 | tr -d '\n+/='
Configures the path to static assets (CSS, JavaScript, images).
[assets]
path = "./res/assets/"
| Option | Type | Default | Description |
|---|---|---|---|
path |
String | "./res/assets/" |
Directory path for static assets |
Configures the public status page appearance, logos, colors, and URLs.
[branding]
page_title = "Crisp Status"
page_url = "https://status.crisp.chat/"
company_name = "Crisp IM SAS"
icon_color = "#1972F5"
icon_url = "https://valeriansaliou.github.io/vigil/images/crisp-icon.png"
logo_color = "#1972F5"
logo_url = "https://valeriansaliou.github.io/vigil/images/crisp-logo.svg"
website_url = "https://crisp.chat/"
support_url = "mailto:support@crisp.chat"
custom_html = ""
| Option | Type | Default | Description |
|---|---|---|---|
page_title |
String | "Status Page" |
HTML page title and header |
page_url |
String | "" |
Canonical URL of the status page |
company_name |
String | "" |
Company/organization name |
icon_color |
String | "#3B82F6" |
Primary color for icons (hex) |
icon_url |
String | "" |
URL to favicon/icon image |
logo_color |
String | "#1E40AF" |
Primary color for logo (hex) |
logo_url |
String | "" |
URL to logo image (SVG recommended) |
website_url |
String | "" |
Link to main company website |
support_url |
String | "" |
Support contact URL or mailto: |
custom_html |
String | "" |
Custom HTML injected in <head> |
#RRGGBB)mailto:support@example.com for email or full URL for help desk[branding]
custom_html = """
<script async src="https://umami.example.com/script.js" data-website-id="xxx"></script>
<meta name="robots" content="index, follow">
"""
Configures health check polling intervals, thresholds, and performance settings.
[metrics]
poll_interval = 120
poll_retry = 2
poll_retry_wait = 500
poll_http_status_healthy_above = 200
poll_http_status_healthy_below = 400
poll_delay_dead = 10
poll_delay_sick = 5
poll_parallelism = 4
push_delay_dead = 20
push_system_cpu_sick_above = 0.90
push_system_ram_sick_above = 0.90
script_interval = 300
script_parallelism = 2
local_delay_dead = 40
| Option | Type | Default | Description |
|---|---|---|---|
poll_interval |
Integer | 120 |
Time between poll probes (seconds) |
poll_retry |
Integer | 2 |
Number of retries before marking dead |
poll_retry_wait |
Integer | 500 |
Wait time between retries (milliseconds) |
poll_http_status_healthy_above |
Integer | 200 |
Minimum HTTP status for healthy |
poll_http_status_healthy_below |
Integer | 400 |
Maximum HTTP status for healthy |
poll_delay_dead |
Integer | 10 |
Response time threshold for dead status (seconds) |
poll_delay_sick |
Integer | 5 |
Response time threshold for sick status (seconds) |
poll_parallelism |
Integer | 4 |
Maximum parallel poll threads |
push_delay_dead |
Integer | 20 |
Time without push report before dead (seconds) |
push_system_cpu_sick_above |
Float | 0.90 |
CPU load threshold for sick status (0.0-1.0) |
push_system_ram_sick_above |
Float | 0.90 |
RAM usage threshold for sick status (0.0-1.0) |
script_interval |
Integer | 300 |
Time between script probe runs (seconds) |
script_parallelism |
Integer | 2 |
Maximum parallel script threads |
local_delay_dead |
Integer | 40 |
Time without Local report before dead (seconds) |
| Scenario | Recommendation |
|---|---|
| High-traffic services | Reduce poll_interval to 60s, increase poll_parallelism to 8 |
| Low-priority services | Increase poll_interval to 300s to reduce load |
| Unstable networks | Increase poll_retry to 3-5, increase poll_retry_wait to 1000ms |
| Strict SLA monitoring | Reduce poll_delay_sick to 3s, poll_delay_dead to 5s |
| Resource-constrained | Reduce poll_parallelism to 2, increase intervals |
Healthy: response_time < poll_delay_sick AND status in range
Sick: poll_delay_sick <= response_time < poll_delay_dead OR CPU/RAM > threshold
Dead: response_time >= poll_delay_dead OR no response after retries
Configures RabbitMQ queue monitoring integration.
[plugins.rabbitmq]
api_url = "http://127.0.0.1:15672"
auth_username = "rabbitmq-administrator"
auth_password = "RABBITMQ_ADMIN_PASSWORD"
virtualhost = "crisp"
queue_ready_healthy_below = 500
queue_nack_healthy_below = 100
queue_ready_dead_above = 20000
queue_nack_dead_above = 5000
queue_loaded_retry_delay = 500
| Option | Type | Default | Description |
|---|---|---|---|
api_url |
String | Required | RabbitMQ Management API URL |
auth_username |
String | Required | RabbitMQ username |
auth_password |
String | Required | RabbitMQ password |
virtualhost |
String | "/" |
RabbitMQ virtual host |
queue_ready_healthy_below |
Integer | 500 |
Messages in queue threshold for healthy |
queue_nack_healthy_below |
Integer | 100 |
NACKed messages threshold for healthy |
queue_ready_dead_above |
Integer | 20000 |
Messages in queue threshold for dead |
queue_nack_dead_above |
Integer | 5000 |
NACKed messages threshold for dead |
queue_loaded_retry_delay |
Integer | 500 |
Retry delay on error (milliseconds) |
Add to probe configuration:
[[probe.service.node]]
id = "rabbitmq-queue"
label = "Main Queue"
mode = "poll"
rabbitmq_queue = "my-queue"
rabbitmq_queue_nack_healthy_below = 50
rabbitmq_queue_nack_dead_above = 500
Global notification behavior and reminder settings.
[notify]
startup_notification = true
reminder_interval = 300
reminder_backoff_function = "linear"
reminder_backoff_limit = 3
| Option | Type | Default | Description |
|---|---|---|---|
startup_notification |
Boolean | false |
Send test notification on startup |
reminder_interval |
Integer | 300 |
Time between status reminders (seconds) |
reminder_backoff_function |
String | "none" |
Backoff algorithm: none, linear, square, cubic |
reminder_backoff_limit |
Integer | 3 |
Maximum backoff multiplier |
| Function | Behavior | Use Case |
|---|---|---|
none |
No backoff, constant interval | Critical services |
linear |
Interval × 1, × 2, × 3 | Standard services |
square |
Interval × 1, × 4, × 9 | Low-priority services |
cubic |
Interval × 1, × 8, × 27 | Very low-priority services |
Vigil supports 11+ notification channels. Configure at least one for production deployments.
[notify.email]
from = "vigil@example.com"
to = "ops@example.com"
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_username = "vigil"
smtp_password = "${SMTP_PASSWORD}"
smtp_encrypt = true
reminders_only = false
| Option | Description |
|---|---|
from |
Sender email address |
to |
Recipient email address |
smtp_host |
SMTP server hostname |
smtp_port |
SMTP port (587 for STARTTLS, 465 for SSL) |
smtp_username |
SMTP authentication username |
smtp_password |
SMTP authentication password |
smtp_encrypt |
Enable TLS/SSL encryption |
reminders_only |
Only send reminders, not initial alerts |
[notify.twilio]
to = [ "+1234567890", "+0987654321" ]
service_sid = "ZSxxxx"
account_sid = "ACxxxx"
auth_token = "${TWILIO_AUTH_TOKEN}"
reminders_only = true
| Option | Description |
|---|---|
to |
Array of phone numbers to notify |
service_sid |
Twilio Messaging Service SID |
account_sid |
Twilio Account SID |
auth_token |
Twilio authentication token |
reminders_only |
Only send reminders |
[notify.slack]
hook_url = "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX"
mention_channel = true
reminders_only = false
| Option | Description |
|---|---|
hook_url |
Slack Incoming Webhook URL |
mention_channel |
Mention @channel on alerts |
reminders_only |
Only send reminders |
[notify.zulip]
bot_email = "bot@example.zulipchat.com"
bot_api_key = "${ZULIP_BOT_KEY}"
channel = "alerts"
api_url = "https://domain.zulipchat.com/api/v1/"
reminders_only = false
| Option | Description |
|---|---|
bot_email |
Zulip bot email address |
bot_api_key |
Zulip bot API key |
channel |
Target channel/stream name |
api_url |
Zulip API base URL |
reminders_only |
Only send reminders |
[notify.telegram]
bot_token = "${TELEGRAM_BOT_TOKEN}"
chat_id = "@channelname"
message_thread_id = "123"
reminders_only = false
| Option | Description |
|---|---|
bot_token |
Telegram Bot API token |
chat_id |
Channel/group username or ID |
message_thread_id |
Thread ID for topics-enabled groups (v1.28.0+) |
reminders_only |
Only send reminders |
[notify.pushover]
app_token = "${PUSHOVER_APP_TOKEN}"
user_keys = [ "user-key-1", "user-key-2" ]
reminders_only = false
| Option | Description |
|---|---|
app_token |
Pushover application token |
user_keys |
Array of user keys to notify |
reminders_only |
Only send reminders |
[notify.gotify]
app_url = "https://push.gotify.net"
app_token = "${GOTIFY_APP_TOKEN}"
reminders_only = false
| Option | Description |
|---|---|
app_url |
Gotify server URL |
app_token |
Gotify application token |
reminders_only |
Only send reminders |
[notify.xmpp]
from = "vigil@jabber.org"
to = "ops@jabber.org"
xmpp_password = "${XMPP_PASSWORD}"
reminders_only = false
| Option | Description |
|---|---|
from |
Vigil XMPP account JID |
to |
Recipient JID |
xmpp_password |
XMPP account password |
reminders_only |
Only send reminders |
Note: Requires libstrophe-dev package and notifier-xmpp feature compiled.
[notify.matrix]
homeserver_url = "https://matrix.org"
access_token = "${MATRIX_ACCESS_TOKEN}"
room_id = "!abc123:matrix.org"
reminders_only = false
| Option | Description |
|---|---|
homeserver_url |
Matrix homeserver URL |
access_token |
Matrix access token |
room_id |
Target room ID |
reminders_only |
Only send reminders |
[notify.webex]
endpoint_url = "https://webexapis.com/v1/messages"
token = "${WEBEX_TOKEN}"
room_id = "Y2lzY29zcGFyazov..."
reminders_only = false
| Option | Description |
|---|---|
endpoint_url |
Webex API endpoint |
token |
Webex bot access token |
room_id |
Target room ID |
reminders_only |
Only send reminders |
[notify.webhook]
hook_url = "https://example.com/webhooks/vigil"
| Option | Description |
|---|---|
hook_url |
Custom webhook URL |
Webhook Payload Example:
{
"type": "changed",
"status": "dead",
"time": "08:58:28 UTC+0200",
"replicas": ["web:core:tcp://edge-3.pool.net.example.com:80"],
"page": {
"title": "Example Status",
"url": "https://status.example.com/"
}
}
Define services and nodes to monitor with different probe modes.
| Mode | Description | Use Case |
|---|---|---|
poll |
Active HTTP/TCP/SSH/ICMP polling | External services, APIs, websites |
push |
Application-reported health | Internal services with Vigil Reporter |
script |
Custom shell script execution | Complex health checks, external dependencies |
local |
Vigil Local daemon reports | Services behind firewalls, remote networks |
[probe]
[[probe.service]]
id = "api"
label = "API Service"
[[probe.service.node]]
id = "api-health"
label = "API Health Check"
mode = "poll"
replicas = ["https://api.example.com/health"]
http_method = "GET"
http_headers = { "Authorization" = "Bearer xxx" }
http_body_healthy_match = "healthy"
reveal_replica_name = false
link_url = "https://status.example.com/api-details"
link_label = "View Details"
[[probe.service.node]]
id = "unique-node-id"
label = "Human-Readable Label"
mode = "poll"
replicas = [
"https://replica1.example.com/health",
"https://replica2.example.com/health"
]
http_method = "GET"
http_headers = { "User-Agent" = "Vigil/1.28" }
http_body = "{\"test\":true}"
http_body_healthy_match = "OK"
reveal_replica_name = false
link_url = "https://example.com/details"
link_label = "Details"
| Option | Description |
|---|---|
id |
Unique node identifier (alphanumeric + hyphens) |
label |
Human-readable service name |
mode |
Probe mode: poll, push, script, local |
replicas |
Array of URLs to probe |
http_method |
HTTP method: GET, HEAD, POST, PUT, PATCH |
http_headers |
Custom HTTP headers (key-value pairs) |
http_body |
Request body for POST/PUT requests |
http_body_healthy_match |
Regex pattern to match in response body |
reveal_replica_name |
Show replica URL in public status |
link_url |
Custom link for more details |
link_label |
Link label text |
| Protocol | Format | Example |
|---|---|---|
| HTTP/HTTPS | http(s)://host[:port]/path |
https://api.example.com/health |
| TCP | tcp://host:port |
tcp://db.example.com:5432 |
| SSH | ssh://host[:port] |
ssh://server.example.com:22 |
| ICMP | icmp://host |
icmp://router.example.com |
[[probe.service.node]]
id = "app-push"
label = "Application Service"
mode = "push"
reveal_replica_name = true
rabbitmq_queue = "app-queue"
rabbitmq_queue_nack_healthy_below = 50
rabbitmq_queue_nack_dead_above = 500
| Option | Description |
|---|---|
reveal_replica_name |
Show replica name in status |
rabbitmq_queue |
RabbitMQ queue name for health tracking |
rabbitmq_queue_nack_healthy_below |
NACK threshold for healthy |
rabbitmq_queue_nack_dead_above |
NACK threshold for dead |
[[probe.service.node]]
id = "plugin-health"
label = "Plugins Health"
mode = "script"
link_url = "https://status.example.com/plugins"
link_label = "Plugin Details"
scripts = [
'''
status=$(curl --silent --connect-timeout 3 https://plugins.example.com/status)
if [ -z "$status" ]; then exit 2 fi
if [ "$status" = "healthy" ]; then exit 0 fi
exit 1
'''
]
| Option | Description |
|---|---|
scripts |
Array of shell scripts to execute |
Script Return Codes:
exit 0: Healthyexit 1: Sick (degraded)exit 2+: Dead (unreachable)[[probe.service.node]]
id = "internal-gateway"
label = "Internal Gateway"
mode = "local"
Local mode requires Vigil Local daemon running on remote network.
Use environment variables for sensitive data with ${VARIABLE_NAME} syntax.
| Variable | Description | Usage |
|---|---|---|
VIGIL_MANAGER_TOKEN |
Manager API authentication | [server] manager_token |
VIGIL_REPORTER_TOKEN |
Reporter API authentication | [server] reporter_token |
SMTP_PASSWORD |
Email password | [notify.email] smtp_password |
TWILIO_AUTH_TOKEN |
Twilio authentication | [notify.twilio] auth_token |
TELEGRAM_BOT_TOKEN |
Telegram bot token | [notify.telegram] bot_token |
ZULIP_BOT_KEY |
Zulip bot API key | [notify.zulip] bot_api_key |
PUSHOVER_APP_TOKEN |
Pushover app token | [notify.pushover] app_token |
GOTIFY_APP_TOKEN |
Gotify app token | [notify.gotify] app_token |
XMPP_PASSWORD |
XMPP account password | [notify.xmpp] xmpp_password |
MATRIX_ACCESS_TOKEN |
Matrix access token | [notify.matrix] access_token |
WEBEX_TOKEN |
Webex bot token | [notify.webex] token |
RABBITMQ_ADMIN_PASSWORD |
RabbitMQ password | [plugins.rabbitmq] auth_password |
In configuration file:
[server]
manager_token = "${VIGIL_MANAGER_TOKEN}"
reporter_token = "${VIGIL_REPORTER_TOKEN}"
[notify.email]
smtp_password = "${SMTP_PASSWORD}"
With Docker:
docker run -d \
-e VIGIL_MANAGER_TOKEN="your-token" \
-e VIGIL_REPORTER_TOKEN="your-token" \
-e SMTP_PASSWORD="your-password" \
valeriansaliou/vigil:v1.28.6
With Docker Compose:
services:
vigil:
env_file:
- .env
.env file:
VIGIL_MANAGER_TOKEN=your-manager-token
VIGIL_REPORTER_TOKEN=your-reporter-token
SMTP_PASSWORD=your-smtp-password
With Ansible:
environment:
VIGIL_MANAGER_TOKEN: "{{ vigil_manager_token }}"
VIGIL_REPORTER_TOKEN: "{{ vigil_reporter_token }}"
[server]
log_level = "info"
inet = "[::]:8080"
manager_token = "${VIGIL_MANAGER_TOKEN}"
reporter_token = "${VIGIL_REPORTER_TOKEN}"
[branding]
page_title = "Service Status"
page_url = "https://status.example.com"
[metrics]
poll_interval = 120
poll_delay_dead = 10
poll_delay_sick = 5
[notify.email]
from = "vigil@example.com"
to = "ops@example.com"
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_username = "vigil"
smtp_password = "${SMTP_PASSWORD}"
smtp_encrypt = true
[probe]
[[probe.service]]
id = "website"
label = "Website"
[[probe.service.node]]
id = "website-health"
label = "Website Health"
mode = "poll"
replicas = ["https://www.example.com/health"]
[server]
log_level = "warn"
inet = "[::]:8080"
workers = 8
mcp_server = false
manager_token = "${VIGIL_MANAGER_TOKEN}"
reporter_token = "${VIGIL_REPORTER_TOKEN}"
[branding]
page_title = "Example Corp Status"
page_url = "https://status.example.com"
company_name = "Example Corp"
icon_color = "#3B82F6"
logo_color = "#1E40AF"
logo_url = "https://status.example.com/logo.svg"
website_url = "https://www.example.com"
support_url = "mailto:support@example.com"
[metrics]
poll_interval = 120
poll_retry = 2
poll_retry_wait = 500
poll_delay_dead = 10
poll_delay_sick = 5
poll_parallelism = 8
[notify]
startup_notification = true
reminder_interval = 300
reminder_backoff_function = "linear"
[notify.email]
from = "status@example.com"
to = "ops@example.com"
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_username = "status"
smtp_password = "${SMTP_PASSWORD}"
smtp_encrypt = true
[notify.slack]
hook_url = "${SLACK_WEBHOOK_URL}"
mention_channel = true
[probe]
[[probe.service]]
id = "api"
label = "API Services"
[[probe.service.node]]
id = "api-v1"
label = "API v1"
mode = "poll"
replicas = [
"https://api-v1.example.com/health",
"https://api-v1-backup.example.com/health"
]
http_method = "GET"
http_body_healthy_match = "healthy"
[[probe.service.node]]
id = "api-v2"
label = "API v2"
mode = "poll"
replicas = ["https://api-v2.example.com/health"]
[[probe.service]]
id = "database"
label = "Database"
[[probe.service.node]]
id = "postgres-primary"
label = "PostgreSQL Primary"
mode = "poll"
replicas = ["tcp://db-primary.example.com:5432"]
[[probe.service.node]]
id = "postgres-replica"
label = "PostgreSQL Replica"
mode = "poll"
replicas = ["tcp://db-replica.example.com:5432"]
[[probe.service]]
id = "infrastructure"
label = "Infrastructure"
[[probe.service.node]]
id = "load-balancer"
label = "Load Balancer"
mode = "poll"
replicas = [
"tcp://lb1.example.com:443",
"tcp://lb2.example.com:443"
]
[[probe.service.node]]
id = "dns"
label = "DNS Resolution"
mode = "poll"
replicas = ["icmp://dns.example.com"]
vigil -c /path/to/config.cfg --check
vigil -c /path/to/config.cfg
Enable startup notification and restart:
[notify]
startup_notification = true
sudo systemctl restart vigil
# Or for Docker:
docker compose restart vigil
# Test HTTP probe manually
curl -v https://api.example.com/health
# Test TCP probe
nc -zv db.example.com 5432
# Test ICMP probe
ping -c 3 router.example.com
# Test script probe
bash /path/to/script.sh
echo $? # Should be 0 for healthy
# Native installation
journalctl -u vigil -f
# Docker
docker compose logs -f vigil
# Tail specific log level
journalctl -u vigil -f | grep -E "(ERROR|WARN|INFO)"
Any questions?
Feel free to contact us. Find all contact information on our contact page.