Service Discovery

Service Discovery

A discovery provider reads proxy definitions from an external system and adds them to the proxy list. When a definition changes, r3v3rs3 updates the routes without a restart.

This page is the reference. To build a working setup with Docker labels, follow Proxies from Docker.

Discovered Proxies

Provider Status

The proxy list shows the state of each provider, the number of proxies that it added and the definitions that did not become a proxy. The admin API returns the same data at GET /api/discovery.

StateMeaning
connectingThe provider has not read its resources yet.
runningThe provider has read its resources and watches them for changes.
errorThe provider cannot read its resources. The proxies of its last read stay active.

When the deployment platform runs, the list also holds the provider platform, which publishes the proxies of the deployed apps.

An issue names the resource and the reason, for example web-1: http.app: port not found: https.

Labels

Docker labels, Consul tags and key-value entries use the same keys. Each key has this form:

r3v3rs3.<protocol>.<name>.<field>=<value>

Proxy Keys

KeyValue
r3v3rs3.enabletrue selects the resource when the provider does not read every resource. Any other value, for example false, skips the resource, also with exposed_by_default = true.
portsRequired. Port names or port ids, separated by commas.
nameThe name in the proxy list. The default is <name>.
activefalse adds the proxy as inactive. The default is true.
portThe port of the upstream server on the address of the resource.
schemehttp or https for port of an HTTP proxy. The default is http.
acmeThe id of an ACME entry that orders a certificate for the vhosts of an HTTP proxy. See ACME Certificates.

Values

HTTP Proxies

port and scheme define one route to / with one server. They cannot be used together with routes.

r3v3rs3.http.app.ports=https
r3v3rs3.http.app.vhosts=app.example.com
r3v3rs3.http.app.port=8080

A route can also use port and scheme. They cannot be used together with servers or response of the same route.

r3v3rs3.http.app.ports=http,https
r3v3rs3.http.app.vhosts=app.example.com
r3v3rs3.http.app.routes.0.path=/
r3v3rs3.http.app.routes.0.port=8080
r3v3rs3.http.app.routes.1.path=/api
r3v3rs3.http.app.routes.1.port=9443
r3v3rs3.http.app.routes.1.scheme=https

A server can have an explicit URL and a weight:

r3v3rs3.http.app.routes.0.servers.0.url=http://10.0.0.5:8080
r3v3rs3.http.app.routes.0.servers.1.url=http://10.0.0.6:8080
r3v3rs3.http.app.routes.0.servers.1.weight=3
r3v3rs3.http.app.load_balancing=round_robin

The other fields use the names of the admin API:

r3v3rs3.http.app.upgrade_insecure=true
r3v3rs3.http.app.ip_filter.allow=10.0.0.0/8,192.168.0.0/16
r3v3rs3.http.app.rate_limit.requests=100
r3v3rs3.http.app.rate_limit.per=minute
r3v3rs3.http.app.rate_limit.burst=20
r3v3rs3.http.app.timeouts.connect=3s
r3v3rs3.http.app.timeouts.request=30s
r3v3rs3.http.app.health_check.interval=10s
r3v3rs3.http.app.health_check.path=/healthz
r3v3rs3.http.app.compression.algorithms=br,gzip
r3v3rs3.http.app.cache.enabled=true
r3v3rs3.http.app.cache.default_ttl=1m
r3v3rs3.http.app.headers.response.0.action=set
r3v3rs3.http.app.headers.response.0.name=X-Frame-Options
r3v3rs3.http.app.headers.response.0.value=DENY
r3v3rs3.http.app.auth.type=basic
r3v3rs3.http.app.auth.realm=Staff
r3v3rs3.http.app.auth.users.0.username=alice
r3v3rs3.http.app.auth.users.0.password=change-me

r3v3rs3 replaces plain text passwords and tokens with hashes before it uses the proxy. The source still holds the plain text value, so prefer password_hash and token_hash in labels.

TCP and UDP Proxies

port defines one upstream server on the address of the resource. It cannot be used together with upstream_servers.

r3v3rs3.tcp.db.ports=postgres
r3v3rs3.tcp.db.port=5432

r3v3rs3.udp.dns.ports=dns
r3v3rs3.udp.dns.upstream_servers.0.addr=/ip4/10.0.0.53/udp/53
r3v3rs3.udp.dns.session_idle_timeout=30s

ACME Certificates

acme names an existing ACME entry of the certificate list. r3v3rs3 orders a certificate for the virtual hosts of the proxy with the account, the challenge and the DNS provider of the entry.

r3v3rs3.http.app.ports=https
r3v3rs3.http.app.vhosts=app.example.com,www.example.com
r3v3rs3.http.app.port=8080
r3v3rs3.http.app.acme=abc-def

Docker

The Docker provider reads the labels of the running containers through the Docker Engine API. It follows the container events, so a started, stopped or changed container updates the proxies within about one second.

Settings

Fill in "Docker Service Discovery" in "Settings", or edit config.toml:

[discovery.docker]
enabled = true
endpoint = "unix:///var/run/docker.sock"
network = "proxy"
exposed_by_default = false
SettingMeaning
enabledStarts the provider.
endpointunix://<path>, tcp://<host>:<port>, http://<host>:<port> or https://<host>:<port>. The default is unix:///var/run/docker.sock.
client_certThe id of a client certificate that r3v3rs3 sends to an https endpoint. A system root certificate or a root certificate in r3v3rs3 must sign the server certificate.
networkThe Docker network of the upstream addresses. Leave it empty when each container is on one network. A container that is not on this network, or that is on more than one network while the setting is empty, is an issue.
exposed_by_defaulttrue reads every container that has r3v3rs3. labels. false reads only the containers with r3v3rs3.enable=true.

A change of the settings restarts the provider without a server restart. The proxies and certificates of the provider are removed at once and return with its first read. Turning the provider off removes them. A certificate that the provider uses cannot be deleted.

Containers

Compose Example

r3v3rs3 runs on the host and reads /var/run/docker.sock. The Compose file holds the labeled containers:

services:
  whoami:
    image: traefik/whoami
    networks: [proxy]
    labels:
      r3v3rs3.enable: "true"
      r3v3rs3.http.whoami.ports: http
      r3v3rs3.http.whoami.vhosts: whoami.example.com
      r3v3rs3.http.whoami.port: "80"

networks:
  proxy:
    name: proxy

Add a port with the name http in "Ports", enable the provider with the network proxy, and start the stack. Compose adds the project name to a network name unless the network sets name.

etcd

The etcd provider reads the keys under a prefix through the etcd v3 HTTP API. It follows the changes with a watch stream, so a changed key updates the proxies within about one second.

Settings

Fill in "etcd Service Discovery" in "Settings", or edit config.toml:

[discovery.etcd]
enabled = true
endpoints = ["http://10.0.0.1:2379", "http://10.0.0.2:2379"]
username = "r3v3rs3"
password = "<password>"
prefix = "r3v3rs3"
SettingMeaning
enabledStarts the provider.
endpointsThe HTTP API addresses of the cluster members: http://<host>:<port>, https://<host>:<port> or unix://<path>. When a connection fails, r3v3rs3 connects to the next address. The default is http://127.0.0.1:2379.
client_certThe id of a client certificate that r3v3rs3 sends to an https endpoint.
usernameThe user of etcd authentication. Leave it empty when authentication is off.
passwordThe password of the user. Set it together with username.
prefixThe key prefix. The default is r3v3rs3.

endpoints needs at least one address, and prefix cannot be empty.

The admin API does not return the password. GET /api/config returns password_set: true when a password is saved. A PUT /api/config without password keeps the saved password, and "password": "" removes it. config.toml holds the password as plain text, so allow only the r3v3rs3 user to read the config directory.

With authentication, r3v3rs3 requests a token with the user name and the password. When etcd rejects an expired token, r3v3rs3 requests a new token and sends the request again. The user needs a role with the read permission on the prefix:

etcdctl role add r3v3rs3-reader
etcdctl role grant-permission r3v3rs3-reader --prefix=true read r3v3rs3/
etcdctl user add r3v3rs3
etcdctl user grant-role r3v3rs3 r3v3rs3-reader

Keys

etcdctl put r3v3rs3/http/app/ports https
etcdctl put r3v3rs3/http/app/vhosts app.example.com
etcdctl put r3v3rs3/http/app/routes/0/servers/0/url http://10.0.0.5:8080