Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 56f41d70b3 | |||
| 8f570ae8a0 | |||
| e58e24a92d | |||
| 12070bc7b5 |
16
changelog.md
16
changelog.md
@@ -1,5 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-02-27 - 10.0.0 - BREAKING CHANGE(remote-ingress)
|
||||
replace tlsConfigured boolean with tlsMode ('custom' | 'acme' | 'self-signed') and compute TLS mode server-side
|
||||
|
||||
- Server: compute remoteIngress.tlsMode = 'custom' when custom certPath/keyPath provided; else attempt to detect ACME by checking stored certs for hubDomain; default to 'self-signed' as fallback.
|
||||
- API: replaced remoteIngress.tlsConfigured:boolean with tlsMode:'custom'|'acme'|'self-signed' — this is a breaking change for consumers of the config API.
|
||||
- UI: ops view updated to display TLS Mode as a badge instead of a boolean "TLS Configured" field.
|
||||
- Action required: update clients and integrations to read remoteIngress.tlsMode instead of tlsConfigured.
|
||||
|
||||
## 2026-02-26 - 9.3.0 - feat(remoteingress)
|
||||
add TLS certificate resolution and passthrough for RemoteIngress tunnel
|
||||
|
||||
- Resolve TLS certs for the RemoteIngress tunnel with priority: explicit certPath/keyPath files → stored ACME cert for hubDomain → fallback to self-signed
|
||||
- Expose tls option on ITunnelManagerConfig and forward certPem/keyPem into hub.start so the hub can use the provided TLS materials
|
||||
- Add logging for cert selection and file read failures
|
||||
- Bump dependency @serve.zone/remoteingress from ^4.2.0 to ^4.3.0
|
||||
|
||||
## 2026-02-26 - 9.2.0 - feat(remoteingress)
|
||||
expose connected edge IPs and detected public IP; resolve proxy IPs from SmartProxy and improve ops UI
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@serve.zone/dcrouter",
|
||||
"private": false,
|
||||
"version": "9.2.0",
|
||||
"version": "10.0.0",
|
||||
"description": "A multifaceted routing service handling mail and SMS delivery functions.",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
@@ -57,7 +57,7 @@
|
||||
"@push.rocks/smartunique": "^3.0.9",
|
||||
"@serve.zone/catalog": "^2.5.0",
|
||||
"@serve.zone/interfaces": "^5.3.0",
|
||||
"@serve.zone/remoteingress": "^4.2.0",
|
||||
"@serve.zone/remoteingress": "^4.3.0",
|
||||
"@tsclass/tsclass": "^9.3.0",
|
||||
"lru-cache": "^11.2.6",
|
||||
"uuid": "^13.0.0"
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -99,8 +99,8 @@ importers:
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0
|
||||
'@serve.zone/remoteingress':
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0
|
||||
specifier: ^4.3.0
|
||||
version: 4.3.0
|
||||
'@tsclass/tsclass':
|
||||
specifier: ^9.3.0
|
||||
version: 9.3.0
|
||||
@@ -1344,8 +1344,8 @@ packages:
|
||||
'@serve.zone/interfaces@5.3.0':
|
||||
resolution: {integrity: sha512-venO7wtDR9ixzD9NhdERBGjNKbFA5LL0yHw4eqGh0UpmvtXVc3SFG0uuHDilOKMZqZ8bttV88qVsFy1aSTJrtA==}
|
||||
|
||||
'@serve.zone/remoteingress@4.2.0':
|
||||
resolution: {integrity: sha512-VJsWAaTuNGtschbvnDP3PciZ5CGE8KLwrTXC8GN3tcDa2wGj7mJQ+JFlTaQRVoRLtCEMkxMYnLIrhJwal9yEYg==}
|
||||
'@serve.zone/remoteingress@4.3.0':
|
||||
resolution: {integrity: sha512-yk14uS6oWIP83Zpem4hGf8zi3W9pefnxijtSWp45WvZ+u9XTXIADQNaUZBSTCId8CYkfPkfRGaaaARunVdjFXg==}
|
||||
|
||||
'@sindresorhus/is@5.6.0':
|
||||
resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
|
||||
@@ -6827,7 +6827,7 @@ snapshots:
|
||||
'@push.rocks/smartlog-interfaces': 3.0.2
|
||||
'@tsclass/tsclass': 9.3.0
|
||||
|
||||
'@serve.zone/remoteingress@4.2.0':
|
||||
'@serve.zone/remoteingress@4.3.0':
|
||||
dependencies:
|
||||
'@push.rocks/qenv': 6.1.3
|
||||
'@push.rocks/smartrust': 1.3.1
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '9.2.0',
|
||||
version: '10.0.0',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
@@ -1714,10 +1714,42 @@ export class DcRouter {
|
||||
const currentRoutes = this.options.smartProxyConfig?.routes || [];
|
||||
this.remoteIngressManager.setRoutes(currentRoutes as any[]);
|
||||
|
||||
// Resolve TLS certs for tunnel: explicit paths > ACME for hubDomain > self-signed (Rust default)
|
||||
const riCfg = this.options.remoteIngressConfig;
|
||||
let tlsConfig: { certPem: string; keyPem: string } | undefined;
|
||||
|
||||
// Priority 1: Explicit cert/key file paths
|
||||
if (riCfg.tls?.certPath && riCfg.tls?.keyPath) {
|
||||
try {
|
||||
const certPem = plugins.fs.readFileSync(riCfg.tls.certPath, 'utf8');
|
||||
const keyPem = plugins.fs.readFileSync(riCfg.tls.keyPath, 'utf8');
|
||||
tlsConfig = { certPem, keyPem };
|
||||
logger.log('info', 'Using explicit TLS cert/key for RemoteIngress tunnel');
|
||||
} catch (err) {
|
||||
logger.log('warn', `Failed to read RemoteIngress TLS cert/key files: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Priority 2: Existing cert from SmartProxy cert store for hubDomain
|
||||
if (!tlsConfig && riCfg.hubDomain) {
|
||||
try {
|
||||
const stored = await this.storageManager.getJSON(`/proxy-certs/${riCfg.hubDomain}`);
|
||||
if (stored?.publicKey && stored?.privateKey) {
|
||||
tlsConfig = { certPem: stored.publicKey, keyPem: stored.privateKey };
|
||||
logger.log('info', `Using stored ACME cert for RemoteIngress tunnel TLS: ${riCfg.hubDomain}`);
|
||||
}
|
||||
} catch { /* no stored cert, fall through */ }
|
||||
}
|
||||
|
||||
if (!tlsConfig) {
|
||||
logger.log('info', 'No TLS cert configured for RemoteIngress tunnel — using auto-generated self-signed');
|
||||
}
|
||||
|
||||
// Create and start the tunnel manager
|
||||
this.tunnelManager = new TunnelManager(this.remoteIngressManager, {
|
||||
tunnelPort: this.options.remoteIngressConfig.tunnelPort ?? 8443,
|
||||
tunnelPort: riCfg.tunnelPort ?? 8443,
|
||||
targetHost: '127.0.0.1',
|
||||
tls: tlsConfig,
|
||||
});
|
||||
await this.tunnelManager.start();
|
||||
|
||||
|
||||
@@ -179,11 +179,25 @@ export class ConfigHandler {
|
||||
// --- Remote Ingress ---
|
||||
const riCfg = opts.remoteIngressConfig;
|
||||
const connectedEdgeIps = dcRouter.tunnelManager?.getConnectedEdgeIps() || [];
|
||||
|
||||
// Determine TLS mode: custom certs > ACME from cert store > self-signed fallback
|
||||
let tlsMode: 'custom' | 'acme' | 'self-signed' = 'self-signed';
|
||||
if (riCfg?.tls?.certPath && riCfg?.tls?.keyPath) {
|
||||
tlsMode = 'custom';
|
||||
} else if (riCfg?.hubDomain) {
|
||||
try {
|
||||
const stored = await dcRouter.storageManager.getJSON(`/proxy-certs/${riCfg.hubDomain}`);
|
||||
if (stored?.publicKey && stored?.privateKey) {
|
||||
tlsMode = 'acme';
|
||||
}
|
||||
} catch { /* no stored cert */ }
|
||||
}
|
||||
|
||||
const remoteIngress: interfaces.requests.IConfigData['remoteIngress'] = {
|
||||
enabled: !!dcRouter.remoteIngressManager,
|
||||
tunnelPort: riCfg?.tunnelPort || null,
|
||||
hubDomain: riCfg?.hubDomain || null,
|
||||
tlsConfigured: !!(riCfg?.tls?.certPath && riCfg?.tls?.keyPath),
|
||||
tlsMode,
|
||||
connectedEdgeIps,
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@ import type { RemoteIngressManager } from './classes.remoteingress-manager.js';
|
||||
export interface ITunnelManagerConfig {
|
||||
tunnelPort?: number;
|
||||
targetHost?: string;
|
||||
tls?: {
|
||||
certPem?: string;
|
||||
keyPem?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,6 +65,7 @@ export class TunnelManager {
|
||||
await this.hub.start({
|
||||
tunnelPort: this.config.tunnelPort ?? 8443,
|
||||
targetHost: this.config.targetHost ?? '127.0.0.1',
|
||||
tls: this.config.tls,
|
||||
});
|
||||
|
||||
// Send allowed edges to the hub
|
||||
|
||||
@@ -69,7 +69,7 @@ export interface IConfigData {
|
||||
enabled: boolean;
|
||||
tunnelPort: number | null;
|
||||
hubDomain: string | null;
|
||||
tlsConfigured: boolean;
|
||||
tlsMode: 'custom' | 'acme' | 'self-signed';
|
||||
connectedEdgeIps: string[];
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '9.2.0',
|
||||
version: '10.0.0',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ export class OpsViewConfig extends DeesElement {
|
||||
const fields: IConfigField[] = [
|
||||
{ key: 'Tunnel Port', value: ri.tunnelPort },
|
||||
{ key: 'Hub Domain', value: ri.hubDomain },
|
||||
{ key: 'TLS Configured', value: ri.tlsConfigured, type: 'boolean' },
|
||||
{ key: 'TLS Mode', value: ri.tlsMode, type: 'badge' },
|
||||
{ key: 'Connected Edge IPs', value: ri.connectedEdgeIps?.length > 0 ? ri.connectedEdgeIps : null, type: 'pills' },
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user