From 261fa74ac9aac4fa78a5b37cd48cfeddc208babf Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 17 Nov 2022 13:15:07 +0100 Subject: [PATCH] Add configuration option for the metric server interface (#25) Add a configuration option `interface` to allow configuring where the HTTP metric server should bind to. --- README.md | 5 +++++ config.schema.json | 15 ++++++++++++--- src/adapters/http/api.ts | 5 ++++- src/adapters/http/fastify.ts | 2 +- src/generated/config_boundary.ts | 10 ++++++++-- tests/adapters/http/fastify.test.ts | 1 + 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 26fc9f6..08ee9a6 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,11 @@ Once *Prometheus* is restarted, metrics with the `homebridge_` prefix should sta // TCP port where the Prometheus metrics server listens. Default: 36123 "port": number, + // Interface where the Prometheus metrics server listens. Default: "::" which means "any interface". + // Can be an IP, a hostname, "0.0.0.0" for all IPv4 interfaces, "::1" for all IPv6 interfaces. + // Default is "::" which means any interface + "interface": string, + // How frequently the services should be rediscovered (in seconds). Default: 60 "refresh_interval": number, diff --git a/config.schema.json b/config.schema.json index 9f7078a..835d5d6 100644 --- a/config.schema.json +++ b/config.schema.json @@ -26,12 +26,18 @@ "default": "homebridge" }, "port": { - "title": "Probe server port", - "description": "TCP port for the prometheus probe server to listen to", + "title": "Metrics server port", + "description": "TCP port where the Prometheus metrics server listens", "type": "integer", "required": false, "default": 36123 }, + "interface": { + "title": "Metrics server interface", + "description": "Interface where the Prometheus metrics server listens. Can be an IP, a hostname, \"0.0.0.0\" for all IPv4 interfaces, \"::1\" for all IPv6 interfaces. Default is \"::\" which means \"any interface\"", + "type": "string", + "default": "::" + }, "refresh_interval": { "title": "Service refresh interval", "description": "Discover new services every seconds", @@ -54,17 +60,20 @@ "default": 20 }, "tls_cert_file": { + "title": "TLS cert file", "description": "Path to TLS certificate file (in PEM format)", "type": "string", "required": false }, "tls_key_file": { + "title": "TLS key file", "description": "Path to TLS key file", "type": "string", "required": false }, "basic_auth": { - "description": "Usernames and passwords for basic auth. Key is the username, value is the password. Password must be encoded with bcrypt", + "title": "Basic auth username/password pairs", + "description": "Usernames and passwords for basic auth. Object key is the username, object value is the password. Password must be encoded with bcrypt. Example: {\"joanna\": \"$2a$12$5/mmmRB28wg9yzaXhee5Iupq3UrFr/qMgAe9LvAxGoY5jLcfVGTUq\"}", "type": "object", "additionalProperties": { "type": "string" }, "required": false diff --git a/src/adapters/http/api.ts b/src/adapters/http/api.ts index 83916cd..2b9abfb 100644 --- a/src/adapters/http/api.ts +++ b/src/adapters/http/api.ts @@ -15,7 +15,10 @@ export interface HttpServerController { export type HttpAdapter = (config: HttpServer) => Promise -export type HttpConfig = Pick +export type HttpConfig = Pick< + Config, + 'debug' | 'port' | 'interface' | 'prefix' | 'basic_auth' | 'tls_cert_file' | 'tls_key_file' +> export interface HttpServer { log?: Logger diff --git a/src/adapters/http/fastify.ts b/src/adapters/http/fastify.ts index ac9a9b0..da9f093 100644 --- a/src/adapters/http/fastify.ts +++ b/src/adapters/http/fastify.ts @@ -97,7 +97,7 @@ export const fastifyServe: HttpAdapter = async (server: HttpServer) => { adaptResponseToReply(server.onMetrics(), reply) }) - await listen(fastify, server.config.port, '::') + await listen(fastify, server.config.port, server.config.interface) return { shutdown() { diff --git a/src/generated/config_boundary.ts b/src/generated/config_boundary.ts index 9028d56..34aca84 100644 --- a/src/generated/config_boundary.ts +++ b/src/generated/config_boundary.ts @@ -6,7 +6,13 @@ export const ConfigBoundary = z.object({ pin: z.string().regex(new RegExp('^\\d{3}-\\d{2}-\\d{3}$')).describe('Homebridge PIN for service authentication'), debug: z.boolean().default(false), prefix: z.string().default('homebridge'), - port: z.number().int().describe('TCP port for the prometheus probe server to listen to').default(36123), + port: z.number().int().describe('TCP port where the Prometheus metrics server listens').default(36123), + interface: z + .string() + .describe( + 'Interface where the Prometheus metrics server listens. Can be an IP, a hostname, "0.0.0.0" for all IPv4 interfaces, "::1" for all IPv6 interfaces. Default is "::" which means "any interface"', + ) + .default('::'), refresh_interval: z.number().int().describe('Discover new services every seconds').default(60), request_timeout: z .number() @@ -23,7 +29,7 @@ export const ConfigBoundary = z.object({ basic_auth: z .record(z.string()) .describe( - 'Usernames and passwords for basic auth. Key is the username, value is the password. Password must be encoded with bcrypt', + 'Usernames and passwords for basic auth. Object key is the username, object value is the password. Password must be encoded with bcrypt. Example: {"joanna": "$2a$12$5/mmmRB28wg9yzaXhee5Iupq3UrFr/qMgAe9LvAxGoY5jLcfVGTUq"}', ) .optional(), }) diff --git a/tests/adapters/http/fastify.test.ts b/tests/adapters/http/fastify.test.ts index f7b5d6d..470a6e1 100644 --- a/tests/adapters/http/fastify.test.ts +++ b/tests/adapters/http/fastify.test.ts @@ -17,6 +17,7 @@ function createTestServerWithBasicAuth(basicAuth: Record): { htt const http = createServer() const prometheus = new TestablePrometheusServer({ port: 0, + interface: 'localhost', debug: false, prefix: 'homebridge', basic_auth: basicAuth,