Skip to content

Vigie reads one YAML file, given by -c/--config-path (./config.yml by default). This page lists every key of the file, with its default and the errors it can raise. The sample file of the repository has an example of each sourceWhere a service reads its endpoints, one of dns, file, url or kubernetes. See Services and sources..

vigie serve ignores the keys it doesn’t know, so a misspelled key silently keeps its default. Run vigie check-config after each change, it refuses them. The errors found while reading the file come from both commands, prefixed by invalid config <path>: for check-config and read config: for serve.

The HTTP endpointsOne IP address and port that a service gives, with its load balancing weight. See HTTP API. of the server are in HTTP API, and what a reloadReading the configuration file again to replace the services, on SIGHUP or POST /reload. See Reload the services. replaces in Reload the services.

server

server

Type object · Required no · Default none

Settings of the HTTP server. A change needs a restart, a reload doesn’t apply it.

:
listen_addr

server.listen_addr

Type string · Required no · Default :8080

Address the server listens on.

: :8080
tls

server.tls

Type object · Required no · Default none

Turns HTTPS on, with the certificate and its key. Without it, the server speaks plain HTTP.

:
cert_file

server.tls.cert_file

Type path · Required with server.tls · Default none

Certificate of the server, in PEM.

: /etc/vigie/vigie.crt
key_file

server.tls.key_file

Type path · Required with server.tls · Default none

Private key of the certificate, in PEM.

: /etc/vigie/vigie.key
basic_auth

server.basic_auth

Type list · Required no · Default empty

Users allowed to call the server. When set, every endpoint but GET /healthz asks for the username and password of one of them.

:
- username

server.basic_auth[].username

Type string · Required with server.basic_auth · Default none

Username of the user, unique among the users.

: flock
password

server.basic_auth[].password

Type string · Required with server.basic_auth · Default none

Password of the user.

: change-me
log

log

Type object · Required no · Default none

Settings of the logs, printed on the standard error.

:
level

log.level

Type string · Required no · Default info

trace, debug, info, warn (or warning), error, fatal or panic.

: info
no_color

log.no_color

Type boolean · Required no · Default false

Prints text without ANSI colours.

: false
in_json

log.in_json

Type boolean · Required no · Default false

Prints one JSON object per line instead of text.

: false
disable_reload_by_request

disable_reload_by_request

Type boolean · Required no · Default false

Removes the POST /reload endpoint.

: false
cache

cache

Type object · Required no · Default none

Settings of the cache kept in front of each source.

:
ttl

cache.ttl

Type duration · Required no · Default 5s

How long vigie reuses the answer of a source, for the services without their own cache_ttl. 0s reads the source on every request.

: 5s
services

services

Type list · Required yes · Default none

Services the server answers for, at least one.

:
- name

services[].name

Type string · Required yes · Default none

Name clients ask for. A request without a name gets the service named default.

: default
default_port

services[].default_port

Type integer · Required no · Default 80

Port of the endpoints that don’t give their own.

: 8080
file

services[].file

Type object · Required one source · Default none

Reads the endpoints from a local file.

:
path

services[].file.path

Type path · Required yes · Default none

File holding one endpoint line per line.

: /etc/vigie/endpoints.txt
KeyTypeRequiredDefaultDescription
serverobjectnononeSettings of the HTTP server. A change needs a restart, a reload doesn’t apply it.
server.listen_addrstringno:8080Address the server listens on.
server.tlsobjectnononeTurns HTTPS on, with the certificate and its key. Without it, the server speaks plain HTTP.
server.tls.cert_filepathwith server.tlsnoneCertificate of the server, in PEM.
server.tls.key_filepathwith server.tlsnonePrivate key of the certificate, in PEM.
server.basic_authlistnoemptyUsers allowed to call the server. When set, every endpoint but GET /healthz asks for the username and password of one of them.
server.basic_auth[].usernamestringwith server.basic_authnoneUsername of the user, unique among the users.
server.basic_auth[].passwordstringwith server.basic_authnonePassword of the user.
logobjectnononeSettings of the logs, printed on the standard error.
log.levelstringnoinfotrace, debug, info, warn (or warning), error, fatal or panic.
log.no_colorbooleannofalsePrints text without ANSI colours.
log.in_jsonbooleannofalsePrints one JSON object per line instead of text.
disable_reload_by_requestbooleannofalseRemoves the POST /reload endpoint.
cacheobjectnononeSettings of the cache kept in front of each source.
cache.ttldurationno5sHow long vigie reuses the answer of a source, for the services without their own cache_ttl. 0s reads the source on every request.
serviceslistyesnoneServices the server answers for, at least one.

Without server.tls, the server speaks plain HTTP. With it, the server speaks HTTPS only.

With server.basic_auth, a request without the username and password of one of the users gets 401, see Require a password. Basic authentication sends the password in clear on each request, so set server.tls too when the network isn’t trusted.

ErrorCause
services is emptyservices is empty or missing.
server tls: cert_file and key_file are requiredserver.tls is set with an empty cert_file or key_file.
server basic_auth: username and password are requiredA user of server.basic_auth has an empty username or password.
server basic_auth: username <name> is given twiceTwo users of server.basic_auth have the same username.
cache ttl is negativecache.ttl is below 0s.
KeyTypeRequiredDefaultDescription
namestringyesnoneName clients ask for. A request without a name gets the service named default.
default_portintegerno80Port of the endpoints that don’t give their own.
cache_ttldurationnocache.ttlHow long vigie reuses the answer of this service’s source. 0s reads the source on every request.
dnsobjectone sourcenoneReads the endpoints from DNS.
fileobjectone sourcenoneReads the endpoints from a local file.
urlobjectone sourcenoneReads the endpoints from an HTTP endpoint.
kubernetesobjectone sourcenoneReads the endpoints from a Kubernetes Service.

Give each service one source. When a service has several, the first of kubernetes, url, file and dns wins, and vigie ignores the others.

vigie keeps the answer of each source for cache_ttl (cache.ttl, 5 seconds by default), then reads the source again on the next request. A change to the DNS records, the file, the remote list or the Kubernetes endpoints shows within that time, without a reload. Requests arriving while the answer has expired wait for a single read of the source, so many clients polling together cost one read. A source that fails isn’t cached, the next request reads it again. A reload starts with an empty cache. Durations are written like 500ms, 5s or 1m.

ErrorCause
service name is emptyname is empty.
service dns, file, url and kubernetes are empty, you must specify one of themThe service has no source.
service <name> cache_ttl is negativecache_ttl is below 0s.

A missing default_port only logs a warning and takes 80.

services

services

Type list · Required yes · Default none

Services the server answers for, at least one.

:
- name

services[].name

Type string · Required yes · Default none

Name clients ask for. A request without a name gets the service named default.

: api
default_port

services[].default_port

Type integer · Required no · Default 80

Port of the endpoints that don’t give their own.

: 8080
dns

services[].dns

Type object · Required one source · Default none

Reads the endpoints from DNS.

:
name

services[].dns.name

Type string · Required yes · Default none

DNS name to look up.

: api.example.com
type

services[].dns.type

Type string · Required no · Default IP

IP, SRV or TXT, in any case.

: SRV
srv_service

services[].dns.srv_service

Type string · Required no · Default http with SRV

Service part of the SRV lookup.

: http
srv_proto

services[].dns.srv_proto

Type string · Required no · Default tcp with SRV

Protocol part of the SRV lookup.

: tcp
KeyTypeRequiredDefaultDescription
namestringyesnoneDNS name to look up.
typestringnoIPIP, SRV or TXT, in any case.
srv_servicestringnohttp with SRVService part of the SRVA DNS record giving the host, port and weight of one instance of a service. See Read endpoints from DNS. lookup.
srv_protostringnotcp with SRVProtocol part of the SRV lookup.
resolverhost:portnoemptyDNS server to query instead of the resolverThe DNS server a dns source queries over TCP instead of the resolver of the system. See Read endpoints from DNS. of the system, such as 127.0.0.1:8600. An IPv6 address goes in brackets, [::1]:8600.

vigie builds the SRV name from the three keys, so name: api.example.com with srv_service: http and srv_proto: tcp looks up _http._tcp.api.example.com.

With resolver set, every lookup of the service goes to that server over TCP, the lookups of the SRV targets included, and each request gives up after 8 seconds. TCP keeps a long answer whole, where a UDP answer can be cut. Without resolver, vigie uses the resolver of the system.

typeLookupEndpoints
IPA and AAAA records of nameEach address, on default_port.
SRVSRV records of nameEach address of each target, on the port of the record or default_port when it’s 0, with the weight of the record.
TXTTXT records of nameEach record starting with eds=, followed by an endpoint lineOne line of a file, a remote list or a TXT record, written host[:port][#weight]. See Endpoint lines. as described in endpoint lines. Other records are skipped.
ErrorCause
service dns name is emptyname is empty.
service dns lookup is invalid, valid are IP, TXT, SRVtype is none of the three values.
service dns resolver is invalid: <err>resolver isn’t a host:port with both parts.

Consul answers DNS for its services, so the dns source reads them without a Consul-specific source. Point resolver at the DNS port of a Consul agent, or have the host forward the .consul domain to it and leave resolver empty.

services

services

Type list · Required yes · Default none

Services the server answers for, at least one.

:
- name

services[].name

Type string · Required yes · Default none

Name clients ask for. A request without a name gets the service named default.

: api
default_port

services[].default_port

Type integer · Required no · Default 80

Port of the endpoints that don’t give their own.

: 8080
dns

services[].dns

Type object · Required one source · Default none

Reads the endpoints from DNS.

:
name

services[].dns.name

Type string · Required yes · Default none

DNS name to look up.

: service.consul
type

services[].dns.type

Type string · Required no · Default IP

IP, SRV or TXT, in any case.

: SRV
srv_service

services[].dns.srv_service

Type string · Required no · Default http with SRV

Service part of the SRV lookup.

: api
srv_proto

services[].dns.srv_proto

Type string · Required no · Default tcp with SRV

Protocol part of the SRV lookup.

: tcp
resolver

services[].dns.resolver

Type host:port · Required no · Default empty

DNS server to query instead of the resolver of the system, such as 127.0.0.1:8600. An IPv6 address goes in brackets, [::1]:8600.

: 127.0.0.1:8600

This looks up _api._tcp.service.consul, Consul’s RFC 2782 form. Each instance gives one endpoint, with the port it registered and its weight Weights.Passing, which is 1 when the instance registered none.

  • To keep only the instances with a tag, put the tag in place of tcp: srv_proto: primary looks up _api._primary.service.consul.
  • To query another datacenter, put it in the name: name: service.dc1.consul.

Two settings of the Consul agent (dns_config) matter here:

  • only_passing = true. By default, Consul DNS leaves out the instances whose checks are critical but keeps those in warning, and vigie would hand them to its clients.
  • enable_truncate = true, when vigie goes through the resolver of the system rather than resolver. Over UDP, Consul cuts a long answer to a few records without telling the client, so a service with many instances would lose some of them. With resolver, vigie asks over TCP and gets every record.
services

services

Type list · Required yes · Default none

Services the server answers for, at least one.

:
- name

services[].name

Type string · Required yes · Default none

Name clients ask for. A request without a name gets the service named default.

: web
default_port

services[].default_port

Type integer · Required no · Default 80

Port of the endpoints that don’t give their own.

: 8080
file

services[].file

Type object · Required one source · Default none

Reads the endpoints from a local file.

:
path

services[].file.path

Type path · Required yes · Default none

File holding one endpoint line per line.

: /etc/vigie/web-endpoints.txt
KeyTypeRequiredDefaultDescription
pathpathyesnoneFile holding one endpoint line per line.
services

services

Type list · Required yes · Default none

Services the server answers for, at least one.

:
- name

services[].name

Type string · Required yes · Default none

Name clients ask for. A request without a name gets the service named default.

: db
default_port

services[].default_port

Type integer · Required no · Default 80

Port of the endpoints that don’t give their own.

: 5432
url

services[].url

Type object · Required one source · Default none

Reads the endpoints from an HTTP endpoint.

:
url

services[].url.url

Type URL · Required yes · Default none

Endpoint answering a GET with one endpoint line per line.

: https://inventory.example.com/db-endpoints.txt
basic_auth

services[].url.basic_auth

Type object · Required no · Default none

Credentials sent to the remote server with HTTP basic authentication.

:
username

services[].url.basic_auth.username

Type string · Required no · Default empty

User name for HTTP basic authentication. Sent only with password.

: vigie
password

services[].url.basic_auth.password

Type string · Required no · Default empty

Password for HTTP basic authentication. Sent only with username.

: change-me
insecure_skip_verify

services[].url.insecure_skip_verify

Type boolean · Required no · Default false

Skips the TLS check of the remote server.

: false
KeyTypeRequiredDefaultDescription
urlURLyesnoneEndpoint answering a GET with one endpoint line per line.
basic_authobjectnononeCredentials sent to the remote server with HTTP basic authentication.
basic_auth.usernamestringnoemptyUser name for HTTP basic authentication. Sent only with password.
basic_auth.passwordstringnoemptyPassword for HTTP basic authentication. Sent only with username.
insecure_skip_verifybooleannofalseSkips the TLS check of the remote server.

The request times out after 8 seconds. An answer other than 200 fails the request with `bad status code: ,

`.
ErrorCause
service url is emptyurl is empty.
service url is invalid: <err>url isn’t a valid URL.
services

services

Type list · Required yes · Default none

Services the server answers for, at least one.

:
- name

services[].name

Type string · Required yes · Default none

Name clients ask for. A request without a name gets the service named default.

: web
default_port

services[].default_port

Type integer · Required no · Default 80

Port of the endpoints that don’t give their own.

: 8080
kubernetes

services[].kubernetes

Type object · Required one source · Default none

Reads the endpoints from a Kubernetes Service.

:
namespace

services[].kubernetes.namespace

Type string · Required no · Default default

Namespace of the Service.

: shop
service

services[].kubernetes.service

Type string · Required yes · Default none

Name of the Kubernetes Service.

: web
port_name

services[].kubernetes.port_name

Type string · Required no · Default empty

Name of the port to use, among the ports of the Service.

: http
kubeconfig

services[].kubernetes.kubeconfig

Type path · Required no · Default empty

Kubeconfig to connect with. A leading ~/ is the home directory.

: ~/.kube/config
context

services[].kubernetes.context

Type string · Required no · Default empty

Context of the kubeconfig. Empty means its current context.

: prod
KeyTypeRequiredDefaultDescription
servicestringyesnoneName of the Kubernetes Service.
namespacestringnodefaultNamespace of the Service.
port_namestringnoemptyName of the port to use, among the ports of the Service.
kubeconfigpathnoemptyKubeconfig to connect with. A leading ~/ is the home directory.
contextstringnoemptyContext of the kubeconfig. Empty means its current context.

Without kubeconfig, vigie looks for $KUBECONFIG, then ~/.kube/config, then the service account of the pod it runs in.

vigie reads the Service, then its EndpointSlicesThe Kubernetes object that lists the pods behind a Kubernetes Service, read by the kubernetes source. See Read Kubernetes Services., and gives each address of each ready endpoint. An endpoint without a ready condition counts as ready, as in Kubernetes. Endpoints that aren’t ready, terminating pods for instance, are left out. A dual-stack Service gives each pod once per address family, and slices of host names (FQDN) are skipped.

  • The port is the one named port_name. Without port_name, it’s the port of the Service when it has only one, else default_port.
  • The weight is 0, Kubernetes has no weight per endpoint.

vigie loads the kubeconfig when the services load, at start and on each reload, and connects to the cluster each time the cache of the service expires, with an 8 second timeout. Each read sends two requests to the Kubernetes API, with no rate limit on the vigie side, so the limits of the API server apply. A kubeconfig that can’t be loaded stops vigie at start, and keeps the previous services on reload. check-config doesn’t load the kubeconfig, so it can’t catch that.

In a cluster, the service account of vigie needs to read the Service and list its EndpointSlices:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: vigie
namespace: shop
rules:
- apiGroups: [""]
resources: [services]
verbs: [get]
- apiGroups: [discovery.k8s.io]
resources: [endpointslices]
verbs: [list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: vigie
namespace: shop
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: vigie
subjects:
- kind: ServiceAccount
name: vigie
namespace: vigie
ErrorCause
service kubernetes service is emptyservice is empty.
load kubernetes client config: <err>At load, the kubeconfig or its context can’t be loaded, or vigie runs outside a cluster without a kubeconfig.
get service <namespace>/<service>: <err>On a request, the Service doesn’t exist, or the cluster can’t be reached or refuses vigie.
port <port_name> not found in service <namespace>/<service>On a request, the Service has no port named port_name.

A Service that exists without any ready endpoint answers 200 with [].

Files, remote lists and eds= TXT records hold one endpoint per line:

# web servers
10.0.0.5
10.0.0.6:8081
10.0.0.7:8080#3
http://10.0.0.8:8080#1
  • The form is host[:port][#weight], with an optional scheme:// in front, which vigie ignores.
  • Without a port, the endpoint takes default_port. Without a weight, its weight is 0.
  • Empty lines and lines starting with # are skipped.
  • vigie doesn’t resolve host names, so write IP addresses. The flock agent refuses an endpoint whose ip isn’t an IP address.

A line with a weight or a port that isn’t a number fails the whole request with invalid weight or invalid port.