diff --git a/backend/package-lock.json b/backend/package-lock.json index dfe150fce..d1bf11995 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -2669,22 +2669,23 @@ } }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -2699,11 +2700,40 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2812,6 +2842,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -3685,20 +3716,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express/node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4249,6 +4266,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -6023,11 +6041,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -6065,19 +6084,49 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -7209,7 +7258,11 @@ } }, "rust-gbt": { - "version": "0.0.1" + "name": "gbt", + "version": "3.0.1", + "engines": { + "node": ">= 12" + } } }, "dependencies": { @@ -9077,22 +9130,22 @@ } }, "body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "requires": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -9103,10 +9156,27 @@ "ms": "2.0.0" } }, + "http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "requires": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" } } }, @@ -9795,14 +9865,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "requires": { - "side-channel": "^1.1.0" - } } } }, @@ -11417,11 +11479,11 @@ "dev": true }, "qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", "requires": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" } }, "queue-microtask": { @@ -11436,14 +11498,33 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "dependencies": { + "http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "requires": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + } + }, + "statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==" + } } }, "react-is": { diff --git a/backend/src/api/backend-info.ts b/backend/src/api/backend-info.ts index c9a82def4..4a907a067 100644 --- a/backend/src/api/backend-info.ts +++ b/backend/src/api/backend-info.ts @@ -30,6 +30,7 @@ class BackendInfo { lightning: config.LIGHTNING.ENABLED, backend: config.MEMPOOL.BACKEND, coreVersion: '?', + osVersion: `${os.type()} ${os.release()}`, }; this.timer = setInterval(async () => { diff --git a/backend/src/api/bitcoin/esplora-api.ts b/backend/src/api/bitcoin/esplora-api.ts index 3cb0ad93b..475aae8b4 100644 --- a/backend/src/api/bitcoin/esplora-api.ts +++ b/backend/src/api/bitcoin/esplora-api.ts @@ -30,6 +30,7 @@ interface FailoverHost { electrs?: string, ssr?: string, core?: string, + os?: string, lastUpdated: number, } } @@ -324,6 +325,9 @@ class FailoverRouter { if (response.data?.coreVersion) { host.hashes.core = response.data.coreVersion; } + if (response.data?.osVersion) { + host.hashes.os = response.data.osVersion; + } } catch (e) { // failed to get backend build hash - do nothing } diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts index 1f7ffdd1f..a0888bb50 100644 --- a/backend/src/mempool.interfaces.ts +++ b/backend/src/mempool.interfaces.ts @@ -505,6 +505,7 @@ export interface IBackendInfo { version: string; lightning: boolean; coreVersion: string; + osVersion: string; backend: 'esplora' | 'electrum' | 'none'; } diff --git a/frontend/src/app/components/server-health/server-health.component.html b/frontend/src/app/components/server-health/server-health.component.html index 7026ff848..a6e799026 100644 --- a/frontend/src/app/components/server-health/server-health.component.html +++ b/frontend/src/app/components/server-health/server-health.component.html @@ -25,6 +25,7 @@ Electrs SSR Core + OS {{ i + 1 }} @@ -34,13 +35,13 @@ {{ (host.rtt / 1000) | number : '1.1-1' }} {{ host.rtt == null ? '' : 's'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }} {{ host.rtt | number : '1.0-0' }} {{ host.rtt == null ? '' : 'ms'}} {{ !host.checked ? '⏳' : (host.unreachable ? '🔥' : '✅') }} {{ host.latestHeight }} {{ !host.checked ? '⏳' : (host.outOfSync ? '🚫' : (host.latestHeight && host.latestHeight < maxHeight ? '🟧' : '✅')) }} - - - @if (type !== 'core' && host.hashes?.[type]) { + + + @if (type !== 'core' && type !== 'os' && host.hashes?.[type]) { {{ host.hashes[type].slice(0, 8) || '?' }} } @else if (host.hashes?.[type]) { {{ host.hashes[type] || '?' }} - {{ host.hashes[type]?.slice(9) || '?' }} + {{ shortenVersion(host.hashes[type]) || '?' }} } @else { ? } diff --git a/frontend/src/app/components/server-health/server-health.component.scss b/frontend/src/app/components/server-health/server-health.component.scss index 883ef22dc..bb5fd1a84 100644 --- a/frontend/src/app/components/server-health/server-health.component.scss +++ b/frontend/src/app/components/server-health/server-health.component.scss @@ -13,10 +13,12 @@ margin: auto; padding: 1em; background: var(--box-bg); + overflow-x: auto; } .status-table { - width: 100%; + width: max-content; + min-width: 100%; td, th { padding: 0.25em; @@ -45,6 +47,7 @@ &.host { width: 100%; max-width: 0; + min-width: 130px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/frontend/src/app/components/server-health/server-health.component.ts b/frontend/src/app/components/server-health/server-health.component.ts index 7c5ed75ba..399e42d2e 100644 --- a/frontend/src/app/components/server-health/server-health.component.ts +++ b/frontend/src/app/components/server-health/server-health.component.ts @@ -1,6 +1,6 @@ import { Component, OnInit, ChangeDetectionStrategy, SecurityContext, ChangeDetectorRef } from '@angular/core'; import { WebsocketService } from '@app/services/websocket.service'; -import { Observable, Subject, map, tap } from 'rxjs'; +import { Observable, map, tap } from 'rxjs'; import { StateService } from '@app/services/state.service'; import { HealthCheckHost } from '@interfaces/websocket.interface'; import { DomSanitizer } from '@angular/platform-browser'; @@ -17,6 +17,7 @@ export class ServerHealthComponent implements OnInit { maxHeight: number; interval: number; now: number = Date.now(); + colors: Record> = {}; repoMap = { frontend: 'mempool', @@ -59,6 +60,31 @@ export class ServerHealthComponent implements OnInit { for (const host of hosts) { newMaxHeight = Math.max(newMaxHeight, host.latestHeight); } + + const sortedCoreVersions = [...new Set( + hosts.map(h => this.parseVersion(h.hashes?.core)).filter(Boolean) + )].sort((a, b) => this.compareVersions(a, b)); + + const sortedOsVersions = [...new Set( + hosts.map(h => this.parseOsVersion(h.hashes?.os)).filter(Boolean) + )].sort((a, b) => this.compareVersions(a, b)); + + this.colors = {}; + for (const host of hosts) { + this.colors[host.host] = {}; + for (const type of ['hybrid', 'frontend', 'backend', 'electrs', 'ssr', 'core', 'os']) { + if (type === 'core') { + const version = this.parseVersion(host.hashes?.core); + this.colors[host.host][type] = version ? this.getVersionColor(version, sortedCoreVersions) : ''; + } else if (type === 'os') { + const version = this.parseOsVersion(host.hashes?.os); + this.colors[host.host][type] = version ? this.getVersionColor(version, sortedOsVersions) : ''; + } else { + const hash = host.hashes?.[type]; + this.colors[host.host][type] = hash ? '#' + hash.slice(0, 6) : ''; + } + } + } }) ); this.websocketService.want(['mempool-blocks', 'stats', 'blocks', 'tomahawk']); @@ -99,4 +125,50 @@ export class ServerHealthComponent implements OnInit { return ''; } } + + private parseVersion(subver: string): string | undefined { + if (subver) { + const match = subver.match(/:(\d+\.\d+\.\d+)/); + return match ? match[1] : null; + } + } + + private parseOsVersion(osVersion: string): string | undefined { + if (osVersion) { + const match = osVersion.match(/(\d+)\.(\d+)(?:\.(\d+))?/); + return match ? `${match[1]}.${match[2]}.${match[3] ?? 0}` : null; + } + } + + public shortenVersion(version: string): string { + return version.match(/\d+\.\d+(?:\.\d+)?/)?.[0] ?? ''; + } + + private compareVersions(a: string, b: string): number { + const partsA = a.split('.').map(Number); + const partsB = b.split('.').map(Number); + for (let i = 0; i < 3; i++) { + if (partsA[i] !== partsB[i]) { + return partsA[i] - partsB[i]; + } + } + return 0; + } + + private getVersionColor(version: string, sortedVersions: string[]): string { + if (!version || sortedVersions.length === 0) { + return ''; + } + const index = sortedVersions.indexOf(version); + if (index === -1) { + return ''; + } + + if (sortedVersions.length === 1) { + return 'hsl(120, 70%, 35%)'; + } + + const hue = (index / (sortedVersions.length - 1)) * 120; + return `hsl(${hue}, 70%, 35%)`; + } } diff --git a/frontend/src/app/interfaces/websocket.interface.ts b/frontend/src/app/interfaces/websocket.interface.ts index 9281f0fc7..d22061259 100644 --- a/frontend/src/app/interfaces/websocket.interface.ts +++ b/frontend/src/app/interfaces/websocket.interface.ts @@ -151,7 +151,11 @@ export interface HealthCheckHost { frontend?: string; backend?: string; electrs?: string; - } + hybrid?: string; + ssr?: string; + core?: string; + os?: string; + }; } export interface StratumJob { diff --git a/frontend/src/resources/liquid/liquid-network-preview.png b/frontend/src/resources/liquid/liquid-network-preview.png index a66e9bb7a..9b076eda6 100644 Binary files a/frontend/src/resources/liquid/liquid-network-preview.png and b/frontend/src/resources/liquid/liquid-network-preview.png differ diff --git a/production/nginx-cache-warmer-ssr b/production/nginx-cache-warmer-ssr index 4907e4e12..29ebc9883 100755 --- a/production/nginx-cache-warmer-ssr +++ b/production/nginx-cache-warmer-ssr @@ -1,7 +1,7 @@ #!/usr/bin/env zsh delay=0.15 hostname=$(hostname) -services_host="" +#services_host="" protocol="https" base_domain="mempool.space" list_refresh_interval=60