@serve.zone/dcrouter

a traffic router intended to be gating your datacenter.

readme.md for @serve.zone/dcrouter

dcrouter: The all-in-one gateway for your datacenter. πŸš€

A comprehensive traffic routing solution that provides unified gateway capabilities for HTTP/HTTPS, TCP/SNI, email (SMTP), DNS, RADIUS, VPN, and remote edge ingress β€” all from a single process. Designed for enterprises requiring robust traffic management, automatic TLS certificate provisioning, VPN-based access control, distributed edge networking, and enterprise-grade email infrastructure.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Table of Contents

Features

🌐 Universal Traffic Router

πŸ“§ Complete Email Infrastructure (powered by smartmta)

πŸ”’ Enterprise Security

πŸ“‘ RADIUS Server

🌍 Remote Ingress (powered by remoteingress)

πŸ” VPN Access Control (powered by smartvpn)

⚑ High Performance

πŸ’Ύ Persistent Storage & Caching

πŸ–₯️ OpsServer Dashboard

πŸ”§ Programmatic API Client

Installation

pnpm add @serve.zone/dcrouter
# or
npm install @serve.zone/dcrouter

Prerequisites

Quick Start

Basic HTTP/HTTPS Router

import { DcRouter } from '@serve.zone/dcrouter';

const router = new DcRouter({
  smartProxyConfig: {
    routes: [
      {
        name: 'web-app',
        match: { domains: ['example.com', 'www.example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.10', port: 8080 }],
          tls: { mode: 'terminate', certificate: 'auto' }
        }
      }
    ],
    acme: {
      email: 'admin@example.com',
      enabled: true,
      useProduction: true
    }
  }
});

await router.start();

Basic Email Server

import { DcRouter } from '@serve.zone/dcrouter';

const router = new DcRouter({
  emailConfig: {
    ports: [25, 587, 465],
    hostname: 'mail.example.com',
    domains: [
      {
        domain: 'example.com',
        dnsMode: 'external-dns'
      }
    ],
    routes: [
      {
        name: 'process-all',
        match: { recipients: '*@example.com' },
        action: {
          type: 'process',
          process: { scan: true, dkim: true, queue: 'normal' }
        }
      }
    ]
  }
});

await router.start();

Full Stack with Dashboard

import { DcRouter } from '@serve.zone/dcrouter';

const router = new DcRouter({
  // HTTP/HTTPS routing
  smartProxyConfig: {
    routes: [
      {
        name: 'website',
        match: { domains: ['example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.10', port: 80 }],
          tls: { mode: 'terminate', certificate: 'auto' }
        }
      }
    ],
    acme: { email: 'ssl@example.com', enabled: true, useProduction: true }
  },

  // Email system (powered by smartmta)
  emailConfig: {
    ports: [25, 587, 465],
    hostname: 'mail.example.com',
    domains: [{ domain: 'example.com', dnsMode: 'external-dns' }],
    routes: [
      {
        name: 'inbound-mail',
        match: { recipients: '*@example.com' },
        action: { type: 'process', process: { scan: true, dkim: true, queue: 'normal' } }
      }
    ]
  },

  // Authoritative DNS
  dnsNsDomains: ['ns1.example.com', 'ns2.example.com'],
  dnsScopes: ['example.com'],
  publicIp: '203.0.113.1',
  dnsRecords: [
    { name: 'example.com', type: 'A', value: '203.0.113.1' },
    { name: 'www.example.com', type: 'CNAME', value: 'example.com' }
  ],

  // RADIUS authentication
  radiusConfig: {
    authPort: 1812,
    acctPort: 1813,
    clients: [
      { name: 'switch-1', ipRange: '192.168.1.0/24', secret: 'radius-secret', enabled: true }
    ],
    vlanAssignment: {
      defaultVlan: 100,
      allowUnknownMacs: true,
      mappings: [
        { mac: 'aa:bb:cc:dd:ee:ff', vlan: 10, enabled: true },
        { mac: 'aa:bb:cc', vlan: 20, enabled: true }  // OUI prefix
      ]
    },
    accounting: { enabled: true, retentionDays: 30 }
  },

  // Remote Ingress β€” edge nodes tunnel traffic to this hub
  remoteIngressConfig: {
    enabled: true,
    tunnelPort: 8443,
    hubDomain: 'hub.example.com',
  },

  // VPN β€” restrict sensitive routes to VPN clients
  vpnConfig: {
    enabled: true,
    serverEndpoint: 'vpn.example.com',
    clients: [
      { clientId: 'dev-laptop', serverDefinedClientTags: ['engineering'] },
    ],
  },

  // Persistent storage
  storage: { fsPath: '/var/lib/dcrouter/data' },

  // Cache database
  cacheConfig: { enabled: true, storagePath: '~/.serve.zone/dcrouter/tsmdb' },

  // TLS & ACME
  tls: { contactEmail: 'admin@example.com' },
  dnsChallenge: { cloudflareApiKey: process.env.CLOUDFLARE_API_KEY }
});

await router.start();
// OpsServer dashboard available at http://localhost:3000

Architecture

System Overview

graph TB
    subgraph "External Traffic"
        HTTP[HTTP/HTTPS Clients]
        SMTP[SMTP Clients]
        TCP[TCP Clients]
        DNS[DNS Queries]
        RAD[RADIUS Clients]
        EDGE[Edge Nodes]
        VPN[VPN Clients]
    end

    subgraph "DcRouter Core"
        DC[DcRouter Orchestrator]
        SP[SmartProxy Engine<br/><i>Rust-powered</i>]
        ES[smartmta Email Server<br/><i>TypeScript + Rust</i>]
        DS[SmartDNS Server<br/><i>Rust-powered</i>]
        RS[SmartRadius Server]
        RI[RemoteIngress Hub<br/><i>Rust data plane</i>]
        VS[SmartVPN Server<br/><i>Rust data plane</i>]
        CM[Certificate Manager<br/><i>smartacme v9</i>]
        OS[OpsServer Dashboard]
        MM[Metrics Manager]
        SM[Storage Manager]
        CD[Cache Database]
    end

    subgraph "Backend Services"
        WEB[Web Services]
        MAIL[Mail Servers]
        DB[Databases]
        API[Internal APIs]
    end

    HTTP --> SP
    TCP --> SP
    SMTP --> ES
    DNS --> DS
    RAD --> RS
    EDGE --> RI
    VPN --> VS

    DC --> SP
    DC --> ES
    DC --> DS
    DC --> RS
    DC --> RI
    DC --> VS
    DC --> CM
    DC --> OS
    DC --> MM
    DC --> SM
    DC --> CD

    SP --> WEB
    SP --> API
    ES --> MAIL
    ES --> DB
    RI --> SP

    CM -.-> SP
    CM -.-> ES

Core Components

Component Package Description
DcRouter @serve.zone/dcrouter Central orchestrator β€” starts, stops, and coordinates all services
SmartProxy @push.rocks/smartproxy High-performance HTTP/HTTPS and TCP/SNI proxy with route-based config (Rust engine)
UnifiedEmailServer @push.rocks/smartmta Full SMTP server with pattern-based routing, DKIM, queue management (TypeScript + Rust)
DNS Server @push.rocks/smartdns Authoritative DNS with dynamic records and DKIM TXT auto-generation (Rust engine)
SmartAcme @push.rocks/smartacme ACME certificate management with per-domain dedup, concurrency control, and rate limiting
RADIUS Server @push.rocks/smartradius Network authentication with MAB, VLAN assignment, and accounting
RemoteIngress @serve.zone/remoteingress Distributed edge tunneling with Rust data plane and TS management
OpsServer @api.global/typedserver Web dashboard + TypedRequest API for monitoring and management
MetricsManager @push.rocks/smartmetrics Real-time metrics collection (CPU, memory, email, DNS, security)
StorageManager built-in Pluggable key-value storage (filesystem, custom, or in-memory)
CacheDb @push.rocks/smartdb Embedded MongoDB-compatible database (LocalSmartDb) for persistent caching

How It Works

DcRouter acts purely as an orchestrator β€” it doesn't implement protocols itself. Instead, it wires together best-in-class packages for each protocol:

  1. On start(): DcRouter initializes OpsServer (default port 3000, configurable via opsServerPort), then spins up SmartProxy, smartmta, SmartDNS, SmartRadius, RemoteIngress, and SmartVPN based on which configs are provided. Services start in dependency order via ServiceManager.
  2. During operation: Each service handles its own protocol independently. SmartProxy uses a Rust-powered engine for maximum throughput. smartmta uses a hybrid TypeScript + Rust architecture for reliable email delivery. RemoteIngress runs a Rust data plane for edge tunnel networking. SmartVPN runs a Rust data plane for WireGuard and custom transports. SmartAcme v9 handles all certificate operations with built-in concurrency control and rate limiting.
  3. On stop(): All services are gracefully shut down in parallel, including cleanup of HTTP agents and DNS clients.

Rust-Powered Architecture

DcRouter itself is a pure TypeScript orchestrator, but several of its core sub-components ship with compiled Rust binaries for performance-critical paths. At runtime each package detects the platform, unpacks the correct binary, and communicates with TypeScript over IPC/FFI β€” so you get the ergonomics of TypeScript with the throughput of native code.

Component Rust Binary What It Handles
SmartProxy smartproxy-bin All TCP/TLS/HTTP proxy networking, NFTables integration, connection metrics
smartmta mailer-bin SMTP server + client, DKIM/SPF/DMARC, content scanning, IP reputation
SmartDNS smartdns-bin DNS server (UDP + DNS-over-HTTPS), DNSSEC, DNS client resolution
RemoteIngress remoteingress-bin Edge tunnel data plane, multiplexed streams, heartbeat management
SmartVPN smartvpn_daemon WireGuard (boringtun), Noise IK handshake, QUIC/WS transports, userspace NAT (smoltcp)
SmartRadius β€” Pure TypeScript (no Rust component)

Configuration Reference

IDcRouterOptions

interface IDcRouterOptions {
  // ── Base ───────────────────────────────────────────────────────
  /** Base directory for all dcrouter data. Defaults to ~/.serve.zone/dcrouter */
  baseDir?: string;

  // ── Traffic Routing ────────────────────────────────────────────
  /** SmartProxy config for HTTP/HTTPS and TCP/SNI routing */
  smartProxyConfig?: ISmartProxyOptions;

  // ── Email ──────────────────────────────────────────────────────
  /** Unified email server configuration (smartmta) */
  emailConfig?: IUnifiedEmailServerOptions;

  /** Custom email port mapping overrides */
  emailPortConfig?: {
    portMapping?: Record<number, number>;
    portSettings?: Record<number, any>;
    receivedEmailsPath?: string;
  };

  // ── DNS ────────────────────────────────────────────────────────
  /** Nameserver domains β€” get A records automatically */
  dnsNsDomains?: string[];
  /** Domains this server is authoritative for */
  dnsScopes?: string[];
  /** Public IP for NS A records */
  publicIp?: string;
  /** Ingress proxy IPs (hides real server IP) */
  proxyIps?: string[];
  /** Custom DNS records */
  dnsRecords?: Array<{
    name: string;
    type: 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT' | 'NS' | 'SOA';
    value: string;
    ttl?: number;
    useIngressProxy?: boolean;
  }>;

  // ── RADIUS ─────────────────────────────────────────────────────
  /** RADIUS server for network authentication */
  radiusConfig?: {
    authPort?: number;                   // default: 1812
    acctPort?: number;                   // default: 1813
    clients: IRadiusClient[];
    vlanAssignment?: IVlanManagerConfig;
    accounting?: { enabled: boolean; retentionDays?: number };
  };

  // ── Remote Ingress ─────────────────────────────────────────────
  /** Remote Ingress hub for edge tunnel connections */
  remoteIngressConfig?: {
    enabled?: boolean;                   // default: false
    tunnelPort?: number;                 // default: 8443
    hubDomain?: string;                  // External hostname for connection tokens
    tls?: {
      certPath?: string;
      keyPath?: string;
    };
  };

  // ── VPN ───────────────────────────────────────────────────────
  /** VPN server for route-level access control */
  vpnConfig?: {
    enabled?: boolean;                   // default: false
    subnet?: string;                     // default: '10.8.0.0/24'
    wgListenPort?: number;               // default: 51820
    dns?: string[];                      // DNS servers pushed to VPN clients
    serverEndpoint?: string;             // Hostname in generated client configs
    clients?: Array<{                    // Pre-defined VPN clients
      clientId: string;
      serverDefinedClientTags?: string[];
      description?: string;
    }>;
    destinationPolicy?: {                // Traffic routing policy
      default: 'forceTarget' | 'block' | 'allow';
      target?: string;                   // IP for forceTarget (default: '127.0.0.1')
      allowList?: string[];              // Pass through directly
      blockList?: string[];              // Always block (overrides allowList)
    };
  };

  // ── HTTP/3 (QUIC) ────────────────────────────────────────────
  /** HTTP/3 config β€” enabled by default on qualifying HTTPS routes */
  http3?: {
    enabled?: boolean;                   // default: true
    quicSettings?: {
      maxIdleTimeout?: number;           // default: 30000ms
      maxConcurrentBidiStreams?: number;  // default: 100
      maxConcurrentUniStreams?: number;   // default: 100
      initialCongestionWindow?: number;
    };
    altSvc?: {
      port?: number;                     // default: listening port
      maxAge?: number;                   // default: 86400s
    };
    udpSettings?: {
      sessionTimeout?: number;           // default: 60000ms
      maxSessionsPerIP?: number;         // default: 1000
      maxDatagramSize?: number;          // default: 65535
    };
  };

  // ── OpsServer ────────────────────────────────────────────────
  /** Port for the OpsServer web dashboard (default: 3000) */
  opsServerPort?: number;

  // ── TLS & Certificates ────────────────────────────────────────
  tls?: {
    contactEmail: string;
    domain?: string;
    certPath?: string;
    keyPath?: string;
  };
  dnsChallenge?: { cloudflareApiKey?: string };

  // ── Storage & Caching ─────────────────────────────────────────
  storage?: {
    fsPath?: string;
    readFunction?: (key: string) => Promise<string>;
    writeFunction?: (key: string, value: string) => Promise<void>;
  };
  cacheConfig?: {
    enabled?: boolean;                   // default: true
    storagePath?: string;                // default: '~/.serve.zone/dcrouter/tsmdb'
    dbName?: string;                     // default: 'dcrouter'
    cleanupIntervalHours?: number;       // default: 1
    ttlConfig?: {
      emails?: number;                   // default: 30 days
      ipReputation?: number;             // default: 1 day
      bounces?: number;                  // default: 30 days
      dkimKeys?: number;                 // default: 90 days
      suppression?: number;              // default: 30 days
    };
  };
}

HTTP/HTTPS & TCP/SNI Routing

DcRouter uses SmartProxy for all HTTP/HTTPS and TCP/SNI routing. Routes are pattern-matched by domain, port, or both.

HTTPS with Auto-TLS

{
  name: 'api-gateway',
  match: { domains: ['api.example.com'], ports: [443] },
  action: {
    type: 'forward',
    targets: [{ host: '192.168.1.20', port: 8080 }],
    tls: { mode: 'terminate', certificate: 'auto' }
  }
}

TLS Passthrough (SNI Routing)

{
  name: 'secure-backend',
  match: { domains: ['secure.example.com'], ports: [8443] },
  action: {
    type: 'forward',
    targets: [{ host: '192.168.1.40', port: 8443 }],
    tls: { mode: 'passthrough' }
  }
}

TCP Port Range Forwarding

{
  name: 'database-cluster',
  match: { ports: [{ from: 5432, to: 5439 }] },
  action: {
    type: 'forward',
    targets: [{ host: '192.168.1.30', port: 'preserve' }],
    security: { ipAllowList: ['192.168.1.0/24'] }
  }
}

HTTP Redirect

{
  name: 'http-to-https',
  match: { ports: [80] },
  action: { type: 'redirect', redirect: { to: 'https://{domain}{path}' } }
}

HTTP/3 (QUIC) Support

DcRouter ships with HTTP/3 enabled by default πŸš€. All qualifying HTTPS routes on port 443 are automatically augmented with QUIC/H3 configuration β€” no extra setup needed. Under the hood, SmartProxy's native HTTP/3 support (via IRouteQuic) handles QUIC transport, Alt-Svc advertisement, and HTTP/3 negotiation.

How It Works

When DcRouter assembles routes in setupSmartProxy(), it automatically augments qualifying routes with:

Browsers that support HTTP/3 will discover it via the Alt-Svc header on initial TCP responses, then upgrade to QUIC for subsequent requests.

What Gets Augmented

A route qualifies for HTTP/3 augmentation when all of these are true:

Zero-Config (Default Behavior)

// HTTP/3 is ON by default β€” this route automatically gets QUIC/H3:
const router = new DcRouter({
  smartProxyConfig: {
    routes: [{
      name: 'web-app',
      match: { domains: ['example.com'], ports: [443] },
      action: {
        type: 'forward',
        targets: [{ host: '192.168.1.10', port: 8080 }],
        tls: { mode: 'terminate', certificate: 'auto' }
      }
    }]
  }
});

Per-Route Opt-Out

Disable HTTP/3 on a specific route using action.options.http3:

{
  name: 'legacy-app',
  match: { domains: ['legacy.example.com'], ports: [443] },
  action: {
    type: 'forward',
    targets: [{ host: '192.168.1.50', port: 8080 }],
    tls: { mode: 'terminate', certificate: 'auto' },
    options: { http3: false }  // ← This route stays TCP-only
  }
}

Global Opt-Out

Disable HTTP/3 across all routes:

const router = new DcRouter({
  http3: { enabled: false },
  smartProxyConfig: { routes: [/* ... */] }
});

Custom QUIC Settings

Fine-tune QUIC parameters globally:

const router = new DcRouter({
  http3: {
    quicSettings: {
      maxIdleTimeout: 60000,          // 60s idle timeout
      maxConcurrentBidiStreams: 200,   // More parallel streams
      maxConcurrentUniStreams: 50,
    },
    altSvc: {
      maxAge: 3600,                   // 1 hour Alt-Svc cache
    },
    udpSettings: {
      sessionTimeout: 120000,         // 2 min UDP session timeout
      maxSessionsPerIP: 500,
    }
  },
  smartProxyConfig: { routes: [/* ... */] }
});

Programmatic Routes

Routes added at runtime via the Route Management API also get HTTP/3 augmentation automatically β€” the RouteConfigManager applies the same augmentation logic when merging programmatic routes.

Email System

The email system is powered by @push.rocks/smartmta, a TypeScript + Rust hybrid MTA. DcRouter configures and orchestrates smartmta's UnifiedEmailServer, which handles SMTP sessions, route matching, delivery queuing, DKIM signing, and all email processing.

Email Domain Configuration

Domains define infrastructure β€” how DNS and DKIM are handled for each domain:

Forward Mode

Simple forwarding without local DNS management:

{
  domain: 'forwarded.com',
  dnsMode: 'forward',
  dns: { forward: { skipDnsValidation: true, targetDomain: 'mail.target.com' } }
}

Internal DNS Mode

Uses DcRouter's built-in DNS server (requires dnsNsDomains + dnsScopes):

{
  domain: 'mail.example.com',
  dnsMode: 'internal-dns',
  dns: { internal: { mxPriority: 10, ttl: 3600 } },
  dkim: { selector: 'mail2024', keySize: 2048, rotateKeys: true, rotationInterval: 90 }
}

External DNS Mode

Uses existing DNS infrastructure with validation:

{
  domain: 'mail.external.com',
  dnsMode: 'external-dns',
  dns: { external: { requiredRecords: ['MX', 'SPF', 'DKIM', 'DMARC'] } },
  rateLimits: {
    inbound: { messagesPerMinute: 100, connectionsPerIp: 10 },
    outbound: { messagesPerMinute: 200 }
  }
}

Email Route Actions

Routes define behavior β€” what happens when an email matches:

Forward πŸ“€

Routes emails to an external SMTP server:

{
  name: 'forward-to-internal',
  match: { recipients: '*@company.com' },
  action: {
    type: 'forward',
    forward: {
      host: 'internal-mail.company.com',
      port: 25,
      auth: { user: 'relay-user', pass: 'relay-pass' },
      addHeaders: { 'X-Forwarded-By': 'dcrouter' }
    }
  }
}

Process βš™οΈ

Full MTA processing with content scanning and delivery queues:

{
  name: 'process-notifications',
  match: { recipients: '*@notifications.company.com' },
  action: {
    type: 'process',
    process: { scan: true, dkim: true, queue: 'priority' }
  }
}

Deliver πŸ“₯

Local mailbox delivery:

{
  name: 'deliver-local',
  match: { recipients: '*@local.company.com' },
  action: { type: 'deliver' }
}

Reject 🚫

Reject with custom SMTP response code:

{
  name: 'reject-spam-domain',
  match: { senders: '*@spam-domain.com', sizeRange: { min: 1000000 } },
  action: {
    type: 'reject',
    reject: { code: 550, message: 'Message rejected due to policy' }
  }
}

Route Matching

Routes support powerful matching criteria:

// Recipient patterns
match: { recipients: '*@example.com' }           // All addresses at domain
match: { recipients: 'admin@*' }                 // "admin" at any domain
match: { senders: ['*@trusted.com', '*@vip.com'] } // Multiple sender patterns

// IP-based matching (CIDR)
match: { clientIp: '192.168.0.0/16' }
match: { clientIp: ['10.0.0.0/8', '172.16.0.0/12'] }

// Authentication state
match: { authenticated: true }

// Header matching
match: { headers: { 'X-Priority': 'high', 'Subject': /urgent|emergency/i } }

// Size and content
match: { sizeRange: { min: 1000, max: 5000000 }, hasAttachments: true }
match: { subject: /invoice|receipt/i }

Email Security Stack

Email Deliverability

DNS Server

DcRouter includes an authoritative DNS server built on smartdns. It handles standard UDP DNS on port 53 and DNS-over-HTTPS via SmartProxy socket handler.

Enabling DNS

DNS is activated when both dnsNsDomains and dnsScopes are configured:

const router = new DcRouter({
  dnsNsDomains: ['ns1.example.com', 'ns2.example.com'],
  dnsScopes: ['example.com'],
  publicIp: '203.0.113.1',
  dnsRecords: [
    { name: 'example.com', type: 'A', value: '203.0.113.1' },
    { name: 'www.example.com', type: 'CNAME', value: 'example.com' },
    { name: 'example.com', type: 'MX', value: '10:mail.example.com' },
    { name: 'example.com', type: 'TXT', value: 'v=spf1 a mx ~all' }
  ]
});

Automatic DNS Records

DcRouter auto-generates:

Ingress Proxy Support

When proxyIps is configured, A records with useIngressProxy: true (default) will use the proxy IP instead of the real server IP β€” hiding your origin:

{
  proxyIps: ['198.51.100.1', '198.51.100.2'],
  dnsRecords: [
    { name: 'example.com', type: 'A', value: '203.0.113.1' },  // Will resolve to 198.51.100.1
    { name: 'ns1.example.com', type: 'A', value: '203.0.113.1', useIngressProxy: false }  // Stays real IP
  ]
}

RADIUS Server

DcRouter includes a RADIUS server for network access control, built on smartradius.

Configuration

const router = new DcRouter({
  radiusConfig: {
    authPort: 1812,
    acctPort: 1813,
    clients: [
      {
        name: 'core-switch',
        ipRange: '192.168.1.0/24',
        secret: 'shared-secret',
        enabled: true
      }
    ],
    vlanAssignment: {
      defaultVlan: 100,
      allowUnknownMacs: true,
      mappings: [
        { mac: 'aa:bb:cc:dd:ee:ff', vlan: 10, enabled: true },   // Exact MAC
        { mac: 'aa:bb:cc', vlan: 20, enabled: true },             // OUI prefix
      ]
    },
    accounting: {
      enabled: true,
      retentionDays: 30
    }
  }
});

Components

Component Purpose
RadiusServer Main RADIUS server handling auth + accounting requests
VlanManager MAC-to-VLAN mapping with exact, OUI, and wildcard patterns
AccountingManager Session tracking, traffic metering, start/stop/interim updates

OpsServer API

RADIUS is fully manageable at runtime via the OpsServer API:

Remote Ingress

DcRouter can act as a hub for distributed edge nodes using @serve.zone/remoteingress. Edge nodes accept incoming traffic at remote locations and tunnel it back to the hub over a single multiplexed connection. This is ideal for scenarios where you need to accept traffic at multiple geographic locations but process it centrally.

Enabling Remote Ingress

const router = new DcRouter({
  remoteIngressConfig: {
    enabled: true,
    tunnelPort: 8443,
    hubDomain: 'hub.example.com',  // Embedded in connection tokens
  },
  // Routes tagged with remoteIngress are auto-derived to edge listen ports
  smartProxyConfig: {
    routes: [
      {
        name: 'web-via-edge',
        match: { domains: ['app.example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.10', port: 8080 }],
          tls: { mode: 'terminate', certificate: 'auto' }
        },
        remoteIngress: { enabled: true }  // Edges will listen on port 443
      }
    ]
  }
});

await router.start();

Edge Registration

Edges are registered via the OpsServer API (or dashboard UI). Each edge gets a unique ID and secret:

// Via TypedRequest API
const createReq = new TypedRequest<IReq_CreateRemoteIngress>(
  'https://hub:3000/typedrequest', 'createRemoteIngress'
);
const { edge } = await createReq.fire({
  identity,
  name: 'edge-nyc-01',
  autoDerivePorts: true,
  tags: ['us-east'],
});
// edge.secret is returned only on creation β€” save it!

Connection Tokens πŸ”‘

Instead of configuring edges with four separate values (hubHost, hubPort, edgeId, secret), DcRouter can generate a single connection token β€” an opaque base64url string that encodes everything:

// Via TypedRequest API
const tokenReq = new TypedRequest<IReq_GetRemoteIngressConnectionToken>(
  'https://hub:3000/typedrequest', 'getRemoteIngressConnectionToken'
);
const { token } = await tokenReq.fire({ identity, edgeId: 'edge-uuid' });
// token = "eyJoIjoiaHViLmV4YW1wbGUuY29tIiwicCI6ODQ0MywiZSI6I..."

// On the edge side, just pass the token:
const edge = new RemoteIngressEdge({ token });
await edge.start();

The token is generated using remoteingress.encodeConnectionToken() and contains { hubHost, hubPort, edgeId, secret }. The hubHost comes from remoteIngressConfig.hubDomain (or can be overridden per-request).

In the OpsServer dashboard, click "Copy Token" on any edge row to copy the connection token to your clipboard.

Auto-Derived Ports

When routes have remoteIngress: { enabled: true }, edges with autoDerivePorts: true (default) automatically pick up those routes' ports. You can also use edgeFilter to restrict which edges get which ports:

{
  name: 'web-route',
  match: { ports: [443] },
  action: { /* ... */ },
  remoteIngress: {
    enabled: true,
    edgeFilter: ['us-east', 'edge-uuid-123']  // Only edges with matching id or tags
  }
}

Dashboard Actions

The OpsServer Remote Ingress view provides:

Action Description
Create Edge Node Register a new edge with name, ports, tags
Enable / Disable Toggle an edge on or off
Edit Modify name, manual ports, auto-derive setting, tags
Regenerate Secret Issue a new secret (invalidates the old one)
Copy Token Generate and copy a base64url connection token to clipboard
Delete Remove the edge registration

VPN Access Control

DcRouter integrates @push.rocks/smartvpn to provide VPN-based route access control. VPN clients connect via standard WireGuard or native WebSocket/QUIC transports, receive an IP from a configurable subnet, and can then access routes that are restricted to VPN-only traffic.

How It Works

  1. SmartVPN daemon runs inside dcrouter with a Rust data plane (WireGuard via boringtun, custom protocol via Noise IK)
  2. Clients connect and get assigned an IP from the VPN subnet (e.g. 10.8.0.0/24)
  3. Smart split tunnel β€” generated WireGuard configs auto-include the VPN subnet plus DNS-resolved IPs of VPN-gated domains. Domains from routes with vpn.enabled are resolved at config generation time, so clients route only the necessary traffic through the tunnel
  4. Routes with vpn: { enabled: true } get security.ipAllowList dynamically injected (re-computed on every client change). With mandatory: true (default), the allowlist is replaced; with mandatory: false, VPN IPs are appended to existing rules
  5. When allowedServerDefinedClientTags is set, only matching client IPs are injected (not the whole subnet)
  6. SmartProxy enforces the allowlist β€” only authorized VPN clients can access protected routes
  7. All VPN traffic is forced through SmartProxy via userspace NAT with PROXY protocol v2 β€” no root required

Destination Policy

By default, VPN client traffic is redirected to localhost (SmartProxy) via forceTarget. You can customize this with a destination policy:

// Default: all traffic β†’ SmartProxy
destinationPolicy: { default: 'forceTarget', target: '127.0.0.1' }

// Allow direct access to a backend subnet
destinationPolicy: {
  default: 'forceTarget',
  target: '127.0.0.1',
  allowList: ['192.168.190.*'],     // direct access to this subnet
  blockList: ['192.168.190.1'],     // except the gateway
}

// Block everything except specific IPs
destinationPolicy: {
  default: 'block',
  allowList: ['10.0.0.*', '192.168.1.*'],
}

Configuration

const router = new DcRouter({
  vpnConfig: {
    enabled: true,
    subnet: '10.8.0.0/24',            // VPN client IP pool (default)
    wgListenPort: 51820,               // WireGuard UDP port (default)
    serverEndpoint: 'vpn.example.com', // Hostname in generated client configs
    dns: ['1.1.1.1', '8.8.8.8'],      // DNS servers pushed to clients

    // Pre-define VPN clients with server-defined tags
    clients: [
      { clientId: 'alice-laptop', serverDefinedClientTags: ['engineering'], description: 'Dev laptop' },
      { clientId: 'bob-phone', serverDefinedClientTags: ['engineering', 'mobile'] },
      { clientId: 'carol-desktop', serverDefinedClientTags: ['finance'] },
    ],

    // Optional: customize destination policy (default: forceTarget β†’ localhost)
    // destinationPolicy: { default: 'forceTarget', target: '127.0.0.1', allowList: ['192.168.1.*'] },
  },
  smartProxyConfig: {
    routes: [
      // πŸ” VPN-only: any VPN client can access
      {
        name: 'internal-app',
        match: { domains: ['internal.example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.50', port: 8080 }],
          tls: { mode: 'terminate', certificate: 'auto' },
        },
        vpn: { enabled: true },
      },
      // πŸ” VPN + tag-restricted: only 'engineering' tagged clients
      {
        name: 'eng-dashboard',
        match: { domains: ['eng.example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.51', port: 8080 }],
          tls: { mode: 'terminate', certificate: 'auto' },
        },
        vpn: { enabled: true, allowedServerDefinedClientTags: ['engineering'] },
        // β†’ alice + bob can access, carol cannot
      },
      // 🌐 Public: no VPN
      {
        name: 'public-site',
        match: { domains: ['example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.10', port: 80 }],
          tls: { mode: 'terminate', certificate: 'auto' },
        },
      },
    ],
  },
});

Client Tags

SmartVPN distinguishes between two types of client tags:

Tag Type Set By Purpose
serverDefinedClientTags Admin (via config or API) Trusted β€” used for route access control
clientDefinedClientTags Connecting client Informational β€” displayed in dashboard, never used for security

Routes with allowedServerDefinedClientTags only permit VPN clients whose admin-assigned tags match. Clients cannot influence their own server-defined tags.

Client Management via OpsServer

The OpsServer dashboard and API provide full VPN client lifecycle management:

Standard WireGuard clients on any platform (iOS, Android, macOS, Windows, Linux) can connect using the generated .conf file or by scanning the QR code β€” no custom VPN software needed.

Certificate Management

DcRouter uses @push.rocks/smartacme v9 for ACME certificate provisioning. smartacme v9 brings significant improvements over previous versions:

How It Works

When a dnsChallenge is configured (e.g. with a Cloudflare API key), DcRouter creates a SmartAcme instance that handles DNS-01 challenges for automatic certificate provisioning. SmartProxy calls the certProvisionFunction whenever a route needs a TLS certificate, and SmartAcme takes care of the rest.

const router = new DcRouter({
  smartProxyConfig: {
    routes: [
      {
        name: 'secure-app',
        match: { domains: ['app.example.com'], ports: [443] },
        action: {
          type: 'forward',
          targets: [{ host: '192.168.1.10', port: 8080 }],
          tls: { mode: 'terminate', certificate: 'auto' }  // ← triggers ACME provisioning
        }
      }
    ],
    acme: { email: 'admin@example.com', enabled: true, useProduction: true }
  },
  tls: { contactEmail: 'admin@example.com' },
  dnsChallenge: { cloudflareApiKey: process.env.CLOUDFLARE_API_KEY }
});

smartacme v9 Features

Feature Description
Per-domain deduplication Concurrent requests for the same domain share a single ACME operation
Global concurrency cap Default 5 parallel ACME operations to prevent overload
Account rate limiting Sliding window (250 orders / 3 hours) to stay within ACME provider limits
Structured errors AcmeError with isRetryable, isRateLimited, retryAfter fields
Clean shutdown stop() properly destroys HTTP agents and DNS clients

Per-Domain Backoff

DcRouter's CertProvisionScheduler adds per-domain exponential backoff on top of smartacme's built-in protections. If a DNS-01 challenge fails for a domain:

  1. The failure is recorded (persisted to storage)
  2. The domain enters backoff: min(failuresΒ² Γ— 1 hour, 24 hours)
  3. Subsequent requests for that domain are rejected until the backoff expires
  4. On success, the backoff is cleared

This prevents hammering ACME servers for domains with persistent issues (e.g. missing DNS delegation).

Fallback to HTTP-01

If DNS-01 fails, the certProvisionFunction returns 'http01' to tell SmartProxy to fall back to HTTP-01 challenge validation. This provides a safety net for domains where DNS-01 isn't viable.

Certificate Storage

Certificates are persisted via the StorageBackedCertManager which uses DcRouter's StorageManager. This means certs survive restarts and don't need to be re-provisioned unless they expire.

Dashboard

The OpsServer includes a Certificates view showing:

Storage & Caching

StorageManager

Provides a unified key-value interface with three backends:

// Filesystem backend
storage: { fsPath: '/var/lib/dcrouter/data' }

// Custom backend (Redis, S3, etc.)
storage: {
  readFunction: async (key) => await redis.get(key),
  writeFunction: async (key, value) => await redis.set(key, value)
}

// In-memory (development only β€” data lost on restart)
// Simply omit the storage config

Used for: TLS certificates, DKIM keys, email routes, bounce/suppression lists, IP reputation data, domain configs, cert backoff state, remote ingress edge registrations.

Cache Database

An embedded MongoDB-compatible database (via smartdata + smartdb) for persistent caching with automatic TTL cleanup:

cacheConfig: {
  enabled: true,
  storagePath: '~/.serve.zone/dcrouter/tsmdb',
  dbName: 'dcrouter',
  cleanupIntervalHours: 1,
  ttlConfig: {
    emails: 30,         // days
    ipReputation: 1,    // days
    bounces: 30,        // days
    dkimKeys: 90,       // days
    suppression: 30     // days
  }
}

Cached document types: CachedEmail, CachedIPReputation.

Security Features

IP Reputation Checking

Automatic IP reputation checks on inbound connections with configurable caching:

// IP reputation is checked automatically for inbound SMTP connections.
// Results are cached according to cacheConfig.ttlConfig.ipReputation.

Rate Limiting

Hierarchical rate limits with three levels of specificity:

// Global defaults (via emailConfig.defaults.rateLimits)
defaults: {
  rateLimits: {
    inbound: { messagesPerMinute: 50, connectionsPerIp: 5, recipientsPerMessage: 50 },
    outbound: { messagesPerMinute: 100 }
  }
}

// Per-domain overrides (in domain config)
{
  domain: 'high-volume.com',
  rateLimits: {
    outbound: { messagesPerMinute: 500 }  // Override for this domain
  }
}

Precedence: Domain-specific > Pattern-specific > Global

Content Scanning

action: {
  type: 'process',
  options: {
    contentScanning: true,
    scanners: [
      { type: 'spam', threshold: 5.0, action: 'tag' },
      { type: 'virus', action: 'reject' },
      { type: 'attachment', blockedExtensions: ['.exe', '.bat', '.scr'], action: 'reject' }
    ]
  }
}

OpsServer Dashboard

The OpsServer provides a web-based management interface served on port 3000 by default (configurable via opsServerPort). It's built with modern web components using @design.estate/dees-catalog.

Dashboard Views

View Description
πŸ“Š Overview Real-time server stats, CPU/memory, connection counts, email throughput
🌐 Network Active connections, top IPs, throughput rates, SmartProxy metrics
πŸ“§ Email Queue monitoring (queued/sent/failed), bounce records, security incidents
πŸ›£οΈ Routes Merged route list (hardcoded + programmatic), create/edit/toggle/override routes
πŸ”‘ API Tokens Token management with scopes, create/revoke/roll/toggle
πŸ” Certificates Domain-centric certificate overview, status, backoff info, reprovisioning, import/export
🌍 RemoteIngress Edge node management, connection status, token generation, enable/disable
πŸ” VPN VPN client management, server status, create/toggle/export/rotate/delete clients
πŸ“‘ RADIUS NAS client management, VLAN mappings, session monitoring, accounting
πŸ“œ Logs Real-time log viewer with level filtering and search
βš™οΈ Configuration Read-only view of current system configuration
πŸ›‘οΈ Security IP reputation, rate limit status, blocked connections

API Endpoints

All management is done via TypedRequest over HTTP POST to /typedrequest:

// Authentication
'adminLoginWithUsernameAndPassword'   // Login with credentials β†’ returns JWT identity
'verifyIdentity'                       // Verify JWT token validity
'adminLogout'                          // End admin session

// Statistics & Health
'getServerStatistics'                  // Uptime, CPU, memory, connections
'getHealthStatus'                      // System health check
'getCombinedMetrics'                   // All metrics in one call

// Email Operations
'getAllEmails'                          // List all emails (queued/sent/failed)
'getEmailDetail'                       // Full detail for a specific email
'resendEmail'                          // Re-queue a failed email

// Certificates
'getCertificateOverview'               // Domain-centric certificate status
'reprovisionCertificate'               // Reprovision by route name (legacy)
'reprovisionCertificateDomain'         // Reprovision by domain (preferred)
'importCertificate'                    // Import a certificate
'exportCertificate'                    // Export a certificate
'deleteCertificate'                    // Delete a certificate

// Remote Ingress
'getRemoteIngresses'                   // List all edge registrations
'createRemoteIngress'                  // Register a new edge
'updateRemoteIngress'                  // Update edge settings
'deleteRemoteIngress'                  // Remove an edge
'regenerateRemoteIngressSecret'        // Issue a new secret
'getRemoteIngressStatus'               // Runtime status of all edges
'getRemoteIngressConnectionToken'      // Generate a connection token for an edge

// Route Management (JWT or API token auth)
'getMergedRoutes'                      // List all routes (hardcoded + programmatic)
'createRoute'                          // Create a new programmatic route
'updateRoute'                          // Update a programmatic route
'deleteRoute'                          // Delete a programmatic route
'toggleRoute'                          // Enable/disable a programmatic route
'setRouteOverride'                     // Override a hardcoded route
'removeRouteOverride'                  // Remove a hardcoded route override

// API Token Management (admin JWT only)
'createApiToken'                       // Create API token β†’ returns raw value once
'listApiTokens'                        // List all tokens (without secrets)
'revokeApiToken'                       // Delete an API token
'rollApiToken'                         // Regenerate token secret
'toggleApiToken'                       // Enable/disable a token

// Configuration (read-only)
'getConfiguration'                     // Current system config

// Logs
'getRecentLogs'                        // Retrieve system logs with filtering
'getLogStream'                         // Stream live logs

// VPN
'getVpnClients'                        // List all registered VPN clients
'getVpnStatus'                         // VPN server status (running, subnet, port, keys)
'createVpnClient'                      // Create client β†’ returns WireGuard config (shown once)
'deleteVpnClient'                      // Remove a VPN client
'enableVpnClient'                      // Enable a disabled client
'disableVpnClient'                     // Disable a client
'rotateVpnClientKey'                   // Generate new keys (invalidates old ones)
'exportVpnClientConfig'                // Export WireGuard (.conf) or SmartVPN (.json) config
'getVpnClientTelemetry'                // Per-client bytes sent/received, keepalives

// RADIUS
'getRadiusSessions'                    // Active RADIUS sessions
'getRadiusClients'                     // List NAS clients
'getRadiusStatistics'                  // RADIUS stats
'setRadiusClient'                      // Add/update NAS client
'removeRadiusClient'                   // Remove NAS client
'getVlanMappings'                      // List VLAN mappings
'setVlanMapping'                       // Add/update VLAN mapping
'removeVlanMapping'                    // Remove VLAN mapping
'testVlanAssignment'                   // Test what VLAN a MAC gets

API Client

DcRouter ships with a typed, object-oriented API client for programmatic management of a running instance. Install it separately or import from the main package:

pnpm add @serve.zone/dcrouter-apiclient
# or import from the main package:
# import { DcRouterApiClient } from '@serve.zone/dcrouter/apiclient';

Quick Example

import { DcRouterApiClient } from '@serve.zone/dcrouter/apiclient';

const client = new DcRouterApiClient({ baseUrl: 'https://dcrouter.example.com' });
await client.login('admin', 'password');

// OO resource instances with methods
const { routes } = await client.routes.list();
await routes[0].toggle(false);

// Builder pattern for creation
const newRoute = await client.routes.build()
  .setName('api-gateway')
  .setMatch({ ports: 443, domains: ['api.example.com'] })
  .setAction({ type: 'forward', targets: [{ host: 'backend', port: 8080 }] })
  .setTls({ mode: 'terminate', certificate: 'auto' })
  .save();

// Manage certificates
const { certificates, summary } = await client.certificates.list();
await certificates[0].reprovision();

// Create API tokens with builder
const token = await client.apiTokens.build()
  .setName('ci-token')
  .setScopes(['routes:read', 'routes:write'])
  .setExpiresInDays(90)
  .save();
console.log(token.tokenValue); // only available at creation

// Remote ingress edges
const edge = await client.remoteIngress.build()
  .setName('edge-nyc-01')
  .setListenPorts([80, 443])
  .save();
const connToken = await edge.getConnectionToken();

// Read-only managers
const health = await client.stats.getHealth();
const config = await client.config.get();
const { logs } = await client.logs.getRecent({ level: 'error', limit: 50 });

Resource Managers

Manager Operations
client.routes list(), create(), build() β†’ Route: update(), delete(), toggle(), setOverride(), removeOverride()
client.certificates list(), import() β†’ Certificate: reprovision(), delete(), export()
client.apiTokens list(), create(), build() β†’ ApiToken: revoke(), roll(), toggle()
client.remoteIngress list(), getStatuses(), create(), build() β†’ RemoteIngress: update(), delete(), regenerateSecret(), getConnectionToken()
client.stats getServer(), getEmail(), getDns(), getSecurity(), getConnections(), getQueues(), getHealth(), getNetwork(), getCombined()
client.config get(section?)
client.logs getRecent(), getStream()
client.emails list() β†’ Email: getDetail(), resend()
client.radius .clients, .vlans, .sessions sub-managers + getStatistics(), getAccountingSummary()

See the full API client documentation for detailed usage of every manager, builder, and resource class.

API Reference

DcRouter Class

import { DcRouter } from '@serve.zone/dcrouter';

const router = new DcRouter(options: IDcRouterOptions);

Methods

Method Description
start(): Promise<void> Start all configured services
stop(): Promise<void> Gracefully stop all services
updateSmartProxyConfig(config): Promise<void> Hot-update SmartProxy routes
updateEmailConfig(config): Promise<void> Hot-update email configuration
updateEmailRoutes(routes): Promise<void> Update email routing rules at runtime
updateRadiusConfig(config): Promise<void> Hot-update RADIUS configuration
getStats(): any Get real-time statistics from all services

Properties

Property Type Description
options IDcRouterOptions Current configuration
smartProxy SmartProxy SmartProxy instance
smartAcme SmartAcme SmartAcme v9 certificate manager instance
emailServer UnifiedEmailServer Email server instance (from smartmta)
dnsServer DnsServer DNS server instance
radiusServer RadiusServer RADIUS server instance
remoteIngressManager RemoteIngressManager Edge registration CRUD manager
tunnelManager TunnelManager Tunnel lifecycle and status manager
vpnManager VpnManager VPN server lifecycle and client CRUD manager
storageManager StorageManager Storage backend
opsServer OpsServer OpsServer/dashboard instance
metricsManager MetricsManager Metrics collector
cacheDb CacheDb Cache database instance
certProvisionScheduler CertProvisionScheduler Per-domain backoff scheduler for cert provisioning
certificateStatusMap Map<string, ...> Domain-keyed certificate status from SmartProxy events

Re-exported Types

DcRouter re-exports key types for convenience:

import {
  DcRouter,
  IDcRouterOptions,
  UnifiedEmailServer,
  type IUnifiedEmailServerOptions,
  type IEmailRoute,
  type IEmailDomainConfig,
  type IHttp3Config,
} from '@serve.zone/dcrouter';

Sub-Modules

DcRouter is published as a monorepo with separately-installable interface and web packages:

Package Description Install
@serve.zone/dcrouter Main package β€” the full router pnpm add @serve.zone/dcrouter
@serve.zone/dcrouter-interfaces TypedRequest interfaces for the OpsServer API pnpm add @serve.zone/dcrouter-interfaces
@serve.zone/dcrouter-apiclient OO API client with builder pattern pnpm add @serve.zone/dcrouter-apiclient
@serve.zone/dcrouter-web Web dashboard components pnpm add @serve.zone/dcrouter-web

You can also import directly from the main package:

import { data, requests } from '@serve.zone/dcrouter/interfaces';
import { DcRouterApiClient } from '@serve.zone/dcrouter/apiclient';

Testing

DcRouter includes a comprehensive test suite covering all system components:

# Run all tests
pnpm test

# Run a specific test file
tstest test/test.jwt-auth.ts --verbose

# Run with extended timeout
tstest test/test.opsserver-api.ts --verbose --timeout 60

Test Coverage

Test File Area Tests
test.apiclient.ts API client instantiation, builders, resource hydration, exports 18
test.contentscanner.ts Content scanning (spam, phishing, malware, attachments) 13
test.dcrouter.email.ts Email config, domain and route setup 4
test.dns-server-config.ts DNS record parsing, grouping, extraction 5
test.dns-socket-handler.ts DNS socket handler and route generation 6
test.errors.ts Error classes, handler, retry utilities 5
test.http3-augmentation.ts HTTP/3 route augmentation, qualification, opt-in/out, QUIC settings 20
test.ipreputationchecker.ts IP reputation, DNSBL, caching, risk classification 10
test.jwt-auth.ts JWT login, verification, logout, invalid credentials 8
test.opsserver-api.ts Health, statistics, configuration, log APIs 8
test.protected-endpoint.ts Admin auth, identity verification, public endpoints 8
test.storagemanager.ts Memory, filesystem, custom backends, concurrency 8

Docker / OCI Container Deployment

DcRouter ships with a production-ready Dockerfile and supports environment-variable-driven configuration for OCI container deployments. The container image includes tini as PID 1 (via the base image), proper health checks, and configurable resource limits. When DCROUTER_MODE=OCI_CONTAINER is set, DcRouter automatically reads configuration from environment variables (and optionally from a JSON config file).

Running with Docker

docker run -d \
  --ulimit nofile=65536:65536 \
  -e DCROUTER_TLS_EMAIL=admin@example.com \
  -e DCROUTER_PUBLIC_IP=203.0.113.1 \
  -e DCROUTER_DNS_NS_DOMAINS=ns1.example.com,ns2.example.com \
  -e DCROUTER_DNS_SCOPES=example.com \
  -p 80:80 -p 443:443 -p 25:25 -p 587:587 -p 465:465 \
  -p 53:53/udp -p 3000:3000 -p 8443:8443 \
  code.foss.global/serve.zone/dcrouter:latest

⚑ Production tip: Always set --ulimit nofile=65536:65536 for production deployments. DcRouter will log a warning at startup if the file descriptor limit is below 65536.

Environment Variables

Variable Description Default Example
DCROUTER_MODE Container mode (set automatically in image) OCI_CONTAINER β€”
DCROUTER_CONFIG_PATH Path to JSON config file (env vars override) β€” /config/dcrouter.json
DCROUTER_BASE_DIR Base data directory ~/.serve.zone/dcrouter /data/dcrouter
DCROUTER_TLS_EMAIL ACME contact email β€” admin@example.com
DCROUTER_TLS_DOMAIN Primary TLS domain β€” example.com
DCROUTER_PUBLIC_IP Public IP for DNS records β€” 203.0.113.1
DCROUTER_PROXY_IPS Comma-separated ingress proxy IPs β€” 198.51.100.1,198.51.100.2
DCROUTER_DNS_NS_DOMAINS Comma-separated nameserver domains β€” ns1.example.com,ns2.example.com
DCROUTER_DNS_SCOPES Comma-separated authoritative domains β€” example.com,other.com
DCROUTER_EMAIL_HOSTNAME SMTP server hostname β€” mail.example.com
DCROUTER_EMAIL_PORTS Comma-separated email ports β€” 25,587,465
DCROUTER_CACHE_ENABLED Enable/disable cache database true false
DCROUTER_HEAP_SIZE Node.js V8 heap size in MB 512 1024
DCROUTER_MAX_CONNECTIONS Global max concurrent connections 50000 100000
DCROUTER_MAX_CONNECTIONS_PER_IP Max connections per source IP 100 200
DCROUTER_CONNECTION_RATE_LIMIT Max new connections/min per IP 600 1200

Exposed Ports

The container exposes all service ports:

Port(s) Protocol Service
80, 443 TCP HTTP/HTTPS (SmartProxy)
25, 587, 465 TCP SMTP, Submission, SMTPS
53 TCP/UDP DNS
1812, 1813 UDP RADIUS auth/acct
3000 TCP OpsServer dashboard
8443 TCP Remote ingress tunnels
51820 UDP WireGuard VPN
29000–30000 TCP Dynamic port range

Building the Image

pnpm run build:docker    # Build the container image
pnpm run release:docker  # Push to registry

The Docker build supports multi-platform (linux/amd64, linux/arm64) via tsdocker.

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH
Registered at District Court Bremen HRB 35230 HB, Germany

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

changelog.md for @serve.zone/dcrouter

2026-03-31 - 11.23.5 - fix(config)

correct VPN mandatory flag default handling in route config manager

2026-03-31 - 11.23.4 - fix(deps)

bump @push.rocks/smartvpn to 1.17.1

2026-03-31 - 11.23.3 - fix(ts_web)

update appstate to import interfaces from source TypeScript module path

2026-03-31 - 11.23.2 - fix(repo)

no changes to commit

2026-03-31 - 11.23.1 - fix(repo)

no changes to commit

2026-03-31 - 11.23.0 - feat(vpn)

support optional non-mandatory VPN route access and align route config with enabled semantics

2026-03-31 - 11.22.0 - feat(vpn)

add VPN client editing and connected client visibility in ops server

2026-03-31 - 11.21.5 - fix(routing)

apply VPN route allowlists dynamically after VPN clients load

2026-03-31 - 11.21.4 - fix(deps)

bump @push.rocks/smartvpn to 1.16.4

2026-03-31 - 11.21.3 - fix(deps)

bump @push.rocks/smartvpn to 1.16.3

2026-03-31 - 11.21.2 - fix(deps)

bump @push.rocks/smartvpn to 1.16.2

2026-03-31 - 11.21.1 - fix(vpn)

resolve VPN-gated route domains into per-client AllowedIPs with cached DNS lookups

2026-03-31 - 11.21.0 - feat(vpn)

add tag-aware WireGuard AllowedIPs for VPN-gated routes

2026-03-31 - 11.20.1 - fix(vpn-manager)

persist WireGuard private keys for valid client exports and QR codes

2026-03-30 - 11.20.0 - feat(vpn-ui)

add QR code export for WireGuard client configurations

2026-03-30 - 11.19.1 - fix(vpn)

configure SmartVPN client exports with explicit server endpoint and split-tunnel allowed IPs

2026-03-30 - 11.19.0 - feat(vpn)

document tag-based VPN access control, declarative clients, and destination policy options

2026-03-30 - 11.18.0 - feat(vpn-ui)

add format selection for VPN client config exports

2026-03-30 - 11.17.0 - feat(vpn)

expand VPN operations view with client management and config export actions

2026-03-30 - 11.16.0 - feat(vpn)

add destination-based VPN routing policy and standardize socket proxy forwarding

2026-03-30 - 11.15.0 - feat(vpn)

add tag-based VPN route access control and support configured initial VPN clients

2026-03-30 - 11.14.0 - feat(docs)

document VPN access control and add OpsServer VPN navigation

2026-03-30 - 11.13.0 - feat(vpn)

add VPN server management and route-based VPN access control

2026-03-27 - 11.12.4 - fix(acme)

use X509 certificate expiry when reporting ACME certificate validity

2026-03-27 - 11.12.3 - fix(dcrouter)

re-trigger auto certificate provisioning after SmartAcme becomes ready

2026-03-27 - 11.12.2 - fix(dcrouter)

guard auto certificate reprovisioning against unnamed routes

2026-03-27 - 11.12.1 - fix(dcrouter)

retry auto certificate provisioning after SmartAcme becomes ready

2026-03-27 - 11.12.0 - feat(web-ui)

pause dashboard polling, sockets, and chart updates when the tab is hidden

2026-03-26 - 11.11.0 - feat(docker,cache,proxy)

improve container runtime defaults and add configurable connection limits

2026-03-26 - 11.10.7 - fix(sms)

update sms service to use async ProjectInfo initialization

2026-03-26 - 11.10.6 - fix(typescript)

tighten TypeScript null safety and error handling across backend and ops UI

2026-03-26 - 11.10.5 - fix(build)

rename smart tooling config to .smartconfig.json and update package references

2026-03-24 - 11.10.4 - fix(monitoring)

handle multiple protocol cache entries per backend in metrics output

2026-03-23 - 11.10.3 - fix(deps)

bump tstest, smartmetrics, and taskbuffer to latest patch releases

2026-03-23 - 11.10.2 - fix(deps)

bump @api.global/typedserver to ^8.4.6 and @push.rocks/smartproxy to ^26.2.1

2026-03-23 - 11.10.1 - fix(deps)

bump @push.rocks/smartproxy to ^26.2.0

2026-03-23 - 11.10.0 - feat(monitoring)

add backend protocol metrics to network stats and ops dashboard

2026-03-21 - 11.9.1 - fix(lifecycle)

clean up service subscriptions, proxy retries, and stale runtime state on shutdown

2026-03-20 - 11.9.0 - feat(dcrouter)

add service manager lifecycle orchestration and health-based ops status reporting

2026-03-20 - 11.8.11 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.10

2026-03-20 - 11.8.10 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.9

2026-03-20 - 11.8.9 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.8

2026-03-20 - 11.8.8 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.7

2026-03-20 - 11.8.7 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.4

2026-03-20 - 11.8.6 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.3

2026-03-20 - 11.8.5 - fix(deps)

bump @push.rocks/smartproxy to ^25.17.1

2026-03-20 - 11.8.4 - fix(deps)

bump @serve.zone/remoteingress to ^4.14.0

2026-03-20 - 11.8.3 - fix(deps)

bump @serve.zone/remoteingress to ^4.13.2

2026-03-19 - 11.8.2 - fix(deps)

bump smartproxy and remoteingress dependencies

2026-03-19 - 11.8.1 - fix(dcrouter)

use constructor routes for remote ingress setup and bump smartproxy dependency

2026-03-19 - 11.8.0 - feat(remoteingress)

add UDP listen port derivation and edge configuration support

2026-03-19 - 11.7.1 - fix(deps)

bump @push.rocks/smartproxy to ^25.16.0

2026-03-19 - 11.7.0 - feat(readme)

document HTTP/3 QUIC support and configuration options

2026-03-19 - 11.6.0 - feat(http3)

add automatic HTTP/3 route augmentation for qualifying HTTPS routes

2026-03-19 - 11.5.1 - fix(project)

no changes to commit

2026-03-19 - 11.5.0 - feat(opsserver)

add configurable OpsServer port and update related tests and documentation

2026-03-19 - 11.4.0 - feat(docs)

document OCI container deployment and enable verbose docker build scripts

2026-03-18 - 11.3.0 - feat(docker)

add OCI container startup configuration and migrate Docker release pipeline to tsdocker

2026-03-18 - 11.2.56 - fix(deps)

bump @serve.zone/remoteingress to ^4.9.0

2026-03-17 - 11.2.55 - fix(deps)

bump @serve.zone/catalog to ^2.7.0 and @serve.zone/remoteingress to ^4.8.18

2026-03-17 - 11.2.54 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.16

2026-03-17 - 11.2.53 - fix(deps)

bump @push.rocks/smartproxy and @serve.zone/remoteingress patch versions

2026-03-17 - 11.2.52 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.13

2026-03-17 - 11.2.51 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.12

2026-03-17 - 11.2.50 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.11

2026-03-17 - 11.2.49 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.10

2026-03-17 - 11.2.48 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.9

2026-03-17 - 11.2.47 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.23

2026-03-17 - 11.2.46 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.22

2026-03-17 - 11.2.45 - fix(deps)

bump @push.rocks/smartproxy and @serve.zone/remoteingress dependencies

2026-03-17 - 11.2.44 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.3

2026-03-17 - 11.2.43 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.2

2026-03-17 - 11.2.42 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.1

2026-03-17 - 11.2.41 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.20

2026-03-17 - 11.2.40 - fix(deps)

bump @serve.zone/remoteingress to ^4.8.0

2026-03-17 - 11.2.39 - fix(repository)

no changes to commit

2026-03-17 - 11.2.38 - fix(deps)

bump @serve.zone/remoteingress to ^4.7.2

2026-03-16 - 11.2.37 - fix(deps)

bump @serve.zone/remoteingress to ^4.7.0

2026-03-16 - 11.2.36 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.19

2026-03-16 - 11.2.35 - fix(deps)

bump @push.rocks/smartproxy, @serve.zone/catalog, and @serve.zone/remoteingress dependencies

2026-03-16 - 11.2.34 - fix(deps)

bump @push.rocks/smartproxy and @serve.zone/catalog patch versions

2026-03-16 - 11.2.33 - fix(deps)

bump smartproxy and remoteingress dependencies

2026-03-16 - 11.2.32 - fix(deps)

bump smartproxy and remoteingress dependencies

2026-03-16 - 11.2.31 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.11

2026-03-16 - 11.2.30 - fix(deps)

bump @push.rocks/smartproxy and @serve.zone/catalog dependencies

2026-03-16 - 11.2.29 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.9

2026-03-16 - 11.2.28 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.8

2026-03-16 - 11.2.27 - fix(deps)

bump smartproxy and remoteingress dependencies

2026-03-16 - 11.2.26 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.5

2026-03-16 - 11.2.25 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.8

2026-03-16 - 11.2.24 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.7

2026-03-16 - 11.2.23 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.6

2026-03-16 - 11.2.22 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.5

2026-03-15 - 11.2.21 - fix(deps)

bump @push.rocks/smartproxy to ^25.11.4

2026-03-15 - 11.2.20 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.4

2026-03-15 - 11.2.19 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.3

2026-03-15 - 11.2.18 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.2

2026-03-15 - 11.2.17 - fix(repo)

no changes to commit

2026-03-15 - 11.2.16 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.1

2026-03-15 - 11.2.15 - fix(deps)

bump @serve.zone/remoteingress to ^4.5.0

2026-03-15 - 11.2.14 - fix(deps)

bump smartproxy and remoteingress patch dependencies

2026-03-15 - 11.2.13 - fix(deps)

bump runtime dependencies to latest compatible patch and minor versions

2026-03-12 - 11.2.12 - fix(deps)

bump @push.rocks/smartproxy to ^25.10.7

2026-03-12 - 11.2.11 - fix(deps)

bump @push.rocks/smartproxy to ^25.10.6

2026-03-12 - 11.2.10 - fix(deps)

bump @push.rocks/smartproxy to ^25.10.5

2026-03-12 - 11.2.9 - fix(deps)

bump @push.rocks/smartproxy to ^25.10.4

2026-03-12 - 11.2.8 - fix(deps)

bump @design.estate/dees-element and @push.rocks/smartproxy patch versions

2026-03-12 - 11.2.7 - fix(deps)

bump @design.estate/dees-catalog and @push.rocks/smartproxy patch versions

2026-03-12 - 11.2.6 - fix(deps)

bump @design.estate/dees-catalog and @push.rocks/smartproxy patch versions

2026-03-12 - 11.2.5 - fix(repo)

no changes to commit

2026-03-12 - 11.2.4 - fix(repo)

no changes to commit

2026-03-12 - 11.2.3 - fix(deps)

bump package dependencies to latest compatible patch and minor releases

2026-03-11 - 11.2.2 - fix(deps)

update dependencies and devDependencies to newer patch/minor versions

2026-03-08 - 11.2.1 - fix(deps)

bump devDependency @git.zone/tstest to ^3.3.0 and dependency @push.rocks/smartproxy to ^25.9.2

2026-03-06 - 11.2.0 - feat(apiclient)

add typed, object-oriented API client documentation and interfaces; document builders, resource managers, and new programmatic endpoints

2026-03-06 - 11.1.0 - feat(apiclient)

add TypeScript API client (ts_apiclient) with resource managers and package exports

2026-03-05 - 11.0.51 - fix(build)

include HTML files in tsbundle output and bump tsbuild/tsbundle devDependencies

2026-03-05 - 11.0.50 - fix(devDependencies)

bump @git.zone/tsbuild to ^4.2.4

2026-03-05 - 11.0.49 - fix(dcrouter)

no changes detected

2026-03-05 - 11.0.48 - fix(deps)

bump @git.zone/tsbuild to ^4.2.3

2026-03-05 - 11.0.47 - fix(dcrouter)

no code changes; nothing to release

2026-03-05 - 11.0.46 - fix(none)

no changes detected

2026-03-05 - 11.0.45 - fix(deps)

bump @git.zone/tsbuild to ^4.2.2

2026-03-05 - 11.0.44 - fix(dev-deps)

bump @git.zone/tsbuild devDependency to ^4.2.1

2026-03-05 - 11.0.43 - fix(dcrouter)

no changes detected; nothing to release

2026-03-05 - 11.0.42 - fix(dcrouter)

empty commit β€” no changes

2026-03-05 - 11.0.41 - fix(deps)

bump devDependency @git.zone/tsbuild to ^4.2.0

2026-03-05 - 11.0.40 - fix(deps)

bump @git.zone/tsbuild devDependency to ^4.1.26

2026-03-05 - 11.0.39 - fix(devDependencies)

bump @git.zone/tsbuild devDependency to ^4.1.25

2026-03-05 - 11.0.38 - fix(deps)

bump @git.zone/tsbuild to ^4.1.24

2026-03-05 - 11.0.37 - fix(dcrouter)

bump patch version (no changes detected)

2026-03-05 - 11.0.36 - fix(repo)

no changes detected; no release necessary

2026-03-05 - 11.0.35 - fix(dev-deps)

bump @git.zone/tsbuild devDependency to ^4.1.23

2026-03-05 - 11.0.34 - fix(dcrouter)

empty diff β€” no changes detected; no version bump suggested

2026-03-05 - 11.0.33 - fix(build)

bump @git.zone/tsbuild to ^4.1.22

2026-03-05 - 11.0.32 - fix(dev-deps)

bump @git.zone/tsbuild devDependency to ^4.1.21

2026-03-05 - 11.0.31 - fix(deps)

bump @git.zone/tsbuild devDependency to ^4.1.20

2026-03-05 - 11.0.30 - fix(devDependencies)

bump @git.zone/tsbuild devDependency to ^4.1.19

2026-03-05 - 11.0.29 - fix(build)

bump @git.zone/tsbuild devDependency to ^4.1.18

2026-03-05 - 11.0.28 - fix(devDependencies)

bump @git.zone/tsbuild devDependency to ^4.1.17

2026-03-05 - 11.0.27 - fix(deps)

bump @git.zone/tsbuild to ^4.1.16

2026-03-05 - 11.0.26 - fix(devDependencies)

bump @git.zone/tsbuild devDependency to ^4.1.15

2026-03-05 - 11.0.25 - fix(logger)

remove build verification comment from logger export

2026-03-05 - 11.0.24 - fix(dcrouter)

no changes detected β€” no release necessary

2026-03-05 - 11.0.23 - fix(deps)

bump @git.zone/tsbuild devDependency to ^4.1.14

2026-03-05 - 11.0.22 - fix(deps)

bump @git.zone/tsbuild devDependency to ^4.1.13

2026-03-05 - 11.0.21 - fix()

no changes detected

2026-03-05 - 11.0.20 - fix(logger)

annotate singleton logger export comment for build verification

2026-03-05 - 11.0.19 - fix(dcrouter)

no changes

2026-03-05 - 11.0.18 - fix(dcrouter)

no changes detected; no version bump required

2026-03-05 - 11.0.17 - fix(dcrouter)

no changes detected in diff; no code or documentation updates

2026-03-05 - 11.0.16 - fix(dcrouter)

noop commit: no changes detected

2026-03-05 - 11.0.15 - fix()

no changes detected; no version bump necessary

2026-03-05 - 11.0.14 - fix(dcrouter)

no changes detected

2026-03-05 - 11.0.13 - fix()

no code changes

2026-03-05 - 11.0.12 - fix(dcrouter)

no changes detected β€” nothing to commit

2026-03-05 - 11.0.11 - fix(deps)

bump @git.zone/tsbuild devDependency to ^4.1.9

2026-03-05 - 11.0.10 - fix(playwright-mcp)

remove committed Playwright artifacts and add .playwright-mcp/ to .gitignore

2026-03-05 - 11.0.9 - fix(devDependencies)

bump @git.zone/tsbuild devDependency to ^4.1.4

2026-03-05 - 11.0.8 - fix()

no changes detected

2026-03-05 - 11.0.7 - fix(deps)

bump @git.zone/tsbuild to ^4.1.3 and @push.rocks/lik to ^6.3.1

2026-03-04 - 11.0.5 - fix(none)

no changes detected; nothing to release

2026-03-04 - 11.0.4 - fix()

no changes

2026-03-04 - 11.0.3 - fix()

no changes detected

2026-03-04 - 11.0.2 - fix(dcrouter)

no changes detected; no files were modified

2026-03-04 - 11.0.1 - fix(auth)

treat expired JWTs as no identity, improve logout and token verification flow, and bump deps

2026-03-03 - 11.0.0 - BREAKING CHANGE(opsserver)

Require authentication for OpsServer endpoints, split handlers into authenticated view/admin routers, and make identity required on many TypedRequest interfaces

2026-03-03 - 10.1.9 - fix(deps)

bump @push.rocks/smartproxy to ^25.9.1

2026-03-03 - 10.1.8 - fix(deps)

bump dependencies: @push.rocks/smartmetrics to ^3.0.2, @push.rocks/smartproxy to ^25.9.0, @serve.zone/remoteingress to ^4.4.0

2026-03-03 - 10.1.7 - fix(ops-view-apitokens)

use correct lucide icon name for roll/rotate actions in API tokens view

2026-03-02 - 10.1.6 - fix(ts_web)

use actionContext for dispatches in web state actions and bump @push.rocks/smartstate to ^2.2.0

2026-03-02 - 10.1.5 - fix(monitoring)

use a per-second ring buffer for DNS query metrics, improve DNS logging rate limiting and security event aggregation, and bump smartmta dependency

2026-03-02 - 10.1.4 - fix(no-changes)

no changes detected; no version bump required

2026-03-02 - 10.1.3 - fix(deps)

bump @api.global/typedrequest to ^3.2.7

2026-03-01 - 10.1.2 - fix(core)

improve shutdown cleanup, socket/stream robustness, and memory/cache handling

2026-02-27 - 10.1.1 - fix(ops-view-apitokens)

replace lucide:refresh-cw with lucide:rotate-cw for Roll action icon

2026-02-27 - 10.1.0 - feat(api-tokens)

add ability to roll (regenerate) API token secrets and UI to display the newly generated token once

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

2026-02-26 - 9.3.0 - feat(remoteingress)

add TLS certificate resolution and passthrough for RemoteIngress tunnel

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

2026-02-26 - 9.1.10 - fix(deps)

bump @push.rocks/smartproxy to ^25.8.5

2026-02-26 - 9.1.9 - fix(deps(smartmta))

bump @push.rocks/smartmta to ^5.3.0

2026-02-26 - 9.1.8 - fix(deps)

bump @serve.zone/remoteingress to ^4.1.0

2026-02-26 - 9.1.7 - fix(dcrouter)

bump @push.rocks/smartproxy to ^25.8.4 and remove custom smartProxy timeout/connection lifetime settings from dcrouter

2026-02-26 - 9.1.6 - fix(cleanup)

prevent event listener and log stream leaks, tighten smartProxy connection timeouts, and improve graceful shutdown behavior

2026-02-26 - 9.1.5 - fix(remoteingress)

Reconcile tunnel manager edge statuses with authoritative Rust hub periodically; update active tunnel counts and heartbeats, add missed edges, remove stale entries, and clear reconcile interval on stop

2026-02-25 - 9.1.4 - fix(deps)

bump @push.rocks/smartproxy to ^25.8.1

2026-02-24 - 9.1.3 - fix(deps)

bump @api.global/typedserver to ^8.4.0 and @push.rocks/smartproxy to ^25.8.0

2026-02-24 - 9.1.2 - fix(deps)

bump dependency versions for build and runtime packages

2026-02-23 - 9.1.1 - fix(dcrouter)

no changes detected β€” no files modified, no release necessary

2026-02-23 - 9.1.0 - feat(ops-dashboard)

add lucide icons to Ops dashboard view tabs

2026-02-23 - 9.0.0 - BREAKING CHANGE(opsserver)

Return structured configuration (IConfigData) from opsserver and update UI to render detailed config sections

2026-02-23 - 8.1.0 - feat(route-management)

add programmatic route management API with API tokens and admin UI

2026-02-22 - 8.0.0 - BREAKING CHANGE(email-ops)

migrate email operations to catalog-compatible email model and simplify UI/router

2026-02-21 - 7.4.3 - fix(logging)

add adaptive rate-limited DNS query logging, flush pending DNS logs on shutdown, and enhance email delivery logging

2026-02-21 - 7.4.2 - fix(monitoring,remoteingress,web)

Prune old metrics buckets periodically, clear metrics caches on shutdown, simplify edge disconnect handling, and optimize network view data updates

2026-02-21 - 7.4.1 - fix(dcrouter)

replace console logging with structured logger, improve metrics logging, add terminal-ready wait in ops UI, bump dees-catalog patch

2026-02-21 - 7.4.0 - feat(opsserver)

add real-time log push to ops dashboard and recent DNS query tracking

2026-02-20 - 7.3.0 - feat(dcrouter)

Wire DNS server 'query' events to MetricsManager for time-series tracking and bump @push.rocks/smartdns to ^7.9.0

2026-02-20 - 7.2.0 - feat(logs)

replace custom logs list with dees-chart-log component and push logs to chart, add log mapping and lifecycle sync, and bump smartlog dependency

2026-02-19 - 7.1.0 - feat(ops/monitoring)

add in-memory log buffer, metrics time-series and ops UI integration

2026-02-19 - 7.0.1 - fix(monitoring)

Use smartMetrics cpuPercentage for cpuUsage.user and update smartmetrics and smartproxy dependencies

2026-02-19 - 7.0.0 - BREAKING CHANGE(deps)

bump dependencies: @serve.zone/remoteingress to ^4.0.0 (breaking), @push.rocks/smartproxy to ^25.7.6, @types/node to ^25.3.0

2026-02-19 - 6.13.2 - fix(runtime)

prevent memory leaks and improve shutdown/stream handling across services

2026-02-18 - 6.13.1 - fix(dcrouter)

enable PROXY protocol v1 handling for SmartProxy when remoteIngress is enabled to preserve client IPs

2026-02-18 - 6.13.0 - feat(remoteingress)

include listenPorts for allowed edges sent to the Rust hub and always resync allowed edges when edge properties change

2026-02-18 - 6.12.0 - feat(remote-ingress)

add Remote Ingress hub integration, OpsServer UI, APIs, and docs

2026-02-18 - 6.11.0 - feat(remoteingress)

add ability to generate remote ingress connection tokens and UI copy action; add hubDomain config option; update remoteingress dependency to ^3.1.1

2026-02-17 - 6.10.0 - feat(ops-view-certificates)

Make Export and Delete actions available inline (inRow) as well as in the context menu; bump @design.estate/dees-catalog to ^3.43.0

2026-02-17 - 6.9.0 - feat(certificates)

add certificate import, export, and deletion support (server handlers, request types, and UI)

2026-02-17 - 6.8.0 - feat(remote-ingress)

support auto-deriving ports for remote ingress edges and expose manual/derived port breakdown in API and UI

2026-02-17 - 6.7.0 - feat(remote-ingress)

Support auto-derived effective listen ports, make listenPorts optional, add toggle action and refine remote ingress creation/management UI

2026-02-17 - 6.6.1 - fix(icons)

standardize icon identifiers to lucide-prefixed names across operational views

2026-02-17 - 6.6.0 - feat(remoteingress)

derive effective remote ingress listen ports from route configs and expose them via ops API

2026-02-16 - 6.5.0 - feat(ops-view-remoteingress)

add 'Create Edge Node' header action to remote ingress table and remove duplicate createNewAction

2026-02-16 - 6.4.5 - fix(remoteingress)

mark remote ingress data actions as row actions and bump @design.estate/dees-catalog dependency

2026-02-16 - 6.4.4 - fix(deps)

bump @push.rocks/smartproxy to ^25.7.3

2026-02-16 - 6.4.3 - fix(deps)

bump @push.rocks/smartproxy to ^25.7.2

2026-02-16 - 6.4.2 - fix(smartproxy)

bump @push.rocks/smartproxy to ^25.7.1

2026-02-16 - 6.4.1 - fix(deps)

bump dependencies: @push.rocks/smartproxy to ^25.7.0 and @serve.zone/remoteingress to ^3.0.2

2026-02-16 - 6.4.0 - feat(remoteingress)

add Remote Ingress hub and management for edge tunnel nodes, including backend managers, tunnel hub integration, opsserver handlers, typedrequest APIs, and web UI

2026-02-16 - 6.3.0 - feat(dcrouter)

add configurable baseDir and centralized path resolution; use resolved data paths for storage, cache and DNS

2026-02-16 - 6.2.4 - fix(deps)

bump @push.rocks/smartproxy to ^25.5.0

2026-02-16 - 6.2.3 - fix(dcrouter)

persist proxy certificate validity dates and improve certificate status initialization

2026-02-16 - 6.2.2 - fix(certs)

Populate certificate status for cert-store-loaded certificates after SmartProxy startup and check proxy-certs in opsserver certificate handler

2026-02-16 - 6.2.1 - fix(smartacme,storage)

Respect wildcard domain requests when retrieving certificates and treat empty/whitespace storage values as null in getJSON

2026-02-16 - 6.2.0 - feat(ts_web)

add Certificate Management documentation and ops-view-certificates reference

2026-02-16 - 6.1.0 - feat(certs)

integrate smartacme v9 for ACME certificate provisioning and add certificate management features, docs, dashboard views, API endpoints, and per-domain backoff scheduler

2026-02-15 - 6.0.0 - BREAKING CHANGE(certs)

Introduce domain-centric certificate provisioning with per-domain exponential backoff and a staggered serial scheduler; add domain-based reprovision API and UI backoff display; change certificate overview API to be domain-first and include backoff info; bump related deps.

2026-02-14 - 5.5.0 - feat(certs)

persist ACME certificates in StorageManager, add storage-backed cert manager, default storage to filesystem, and improve certificate status reporting

2026-02-14 - 5.4.6 - fix(deps)

bump @push.rocks/smartproxy dependency to ^25.2.2

2026-02-14 - 5.4.5 - fix(dcrouter)

bump patch for release pipeline consistency - no code changes

2026-02-14 - 5.4.4 - fix(deps)

bump @push.rocks/smartproxy to ^25.2.0

2026-02-14 - 5.4.3 - fix(dependencies)

bump @push.rocks/smartproxy to ^25.1.0

2026-02-13 - 5.4.2 - fix(dcrouter)

improve domain pattern matching to support routing-glob and wildcard patterns and use matching logic when resolving routes

2026-02-13 - 5.4.1 - fix(network,dcrouter)

Always register SmartProxy certificate event handlers and include total bytes + improved connection metrics in network stats/UI

2026-02-13 - 5.4.0 - feat(certificates)

include certificate source/issuer and Rust-side status checks; pass eventComms into certProvisionFunction and record expiry information

2026-02-13 - 5.3.0 - feat(certificates)

add certificate overview and reprovisioning in ops UI and API; track SmartProxy certificate events

2026-02-13 - 5.2.0 - feat(monitoring)

add throughput metrics and expose them in ops UI

2026-02-13 - 5.1.0 - feat(acme)

Integrate SmartAcme DNS-01 handling and add certificate provisioning for SmartProxy

2026-02-13 - 5.0.7 - fix(deps)

bump @push.rocks/smartdns to ^7.8.1 and @push.rocks/smartmta to ^5.2.2

2026-02-12 - 5.0.6 - fix(deps)

bump @push.rocks/smartproxy to ^23.1.4

2026-02-12 - 5.0.5 - fix(dcrouter)

remove legacy handling of emailConfig.routes that added domain-based routes

2026-02-12 - 5.0.4 - fix(cache)

use user-writable ~/.serve.zone/dcrouter for TsmDB and centralize data path logic

2026-02-12 - 5.0.3 - fix(packaging)

add files whitelist to package.json and remove Playwright-generated screenshots

2026-02-12 - 5.0.2 - fix(docs)

update documentation and packaging configuration: document smartmta/smartdns integrations, adjust API method names, and add release registry info

2026-02-11 - 5.0.1 - fix(deps/tests)

bump two dependencies and disable cache in tests

2026-02-11 - 5.0.0 - BREAKING CHANGE(mta)

migrate internal MTA to @push.rocks/smartmta and remove legacy mail/deliverability implementation

2026-02-10 - 4.1.1 - fix(smartproxy)

upgrade @push.rocks/smartproxy to ^23.1.0 and adapt code/tests for its async getStatistics() API

2026-02-10 - 4.1.0 - feat(cache)

add persistent smartdata-backed cache with LocalTsmDb, cache cleaner, and DcRouter integration

2026-02-03 - 4.0.0 - BREAKING CHANGE(config)

convert configuration management to read-only; remove updateConfiguration endpoint and client-side editing

2026-02-02 - 3.1.0 - feat(web)

determine initial UI view from URL and wire selected view to appdash; add interface and web README files; bump various dependencies

2026-02-01 - 3.0.0 - BREAKING CHANGE(deps)

upgrade major dependencies, migrate action.target to action.targets (array), adapt to SmartRequest API changes, and add RADIUS server support

2026-02-01 - 2.13.0 - feat(radius)

add RADIUS server with MAC authentication (MAB), VLAN assignment, accounting and OpsServer API handlers

2026-02-01 - 2.12.6 - fix(tests)

update tests and test helpers to current email/DNS APIs, use non-privileged ports, and improve robustness and resilience

2026-02-01 - 2.12.5 - fix(mail)

migrate filesystem helpers to fsUtils, update DKIM and mail APIs, harden SMTP client, and bump dependencies

2025-01-29 - 2.13.0 - feat(socket-handler)

Implement socket-handler mode for DNS and email services, enabling direct socket passing from SmartProxy

2025-05-16 - 2.12.0 - feat(smartproxy)

Update documentation and configuration guides to adopt new route-based SmartProxy architecture

2025-05-16 - 2.11.2 - fix(dependencies)

Update dependency versions and adjust test imports to use new packages

2025-05-08 - 2.11.1 - fix(platform)

Update commit info with no functional changes; regenerated commit information.

2025-05-08 - 2.11.0 - feat(platformservice)

Expose DcRouter and update package visibility. Changed package.json 'private' flag from true to false to allow public publication, and added export of DcRouter in ts/index.ts for improved API accessibility.

2025-05-08 - 2.10.0 - feat(config): Implement standardized configuration system

Create a comprehensive configuration system with validation, defaults, and documentation

2025-05-08 - 2.9.0 - feat(errors): Implement comprehensive error handling system

Enhance error handling with structured errors, consistent patterns, and improved logging

2025-05-08 - 2.8.9 - fix(types)

Fix TypeScript build errors and improve API type safety across platformservice interfaces

2025-05-08 - 2.8.8 - fix(types): Fix TypeScript build errors and improve API interfaces

Fix TypeScript build errors caused by interface placement and improve API type alignment

2025-05-08 - 2.8.7 - feat(types): Add comprehensive TypeScript interfaces for API types

Improve type safety across the platform by adding detailed TypeScript interfaces for APIs

2025-05-08 - 2.8.6 - fix(tests)

fix: Improve test stability by handling race conditions in SenderReputationMonitor and IPWarmupManager. Disable filesystem operations and external DNS lookups during tests by checking NODE_ENV, add proper cleanup of singleton instances and active timeouts to ensure consistent test environment.

2025-05-08 - 2.8.5 - fix(tests): Improve test stability by fixing race conditions

Enhance the SenderReputationMonitor tests to prevent race conditions and make tests more reliable

2025-05-08 - 2.8.4 - fix(mail)

refactor(mail): Remove Mailgun references from PlatformService. Update keywords, error messages, and documentation to use MTA exclusively.

2025-05-08 - 2.8.3 - refactor(mail): Remove Mailgun references

Remove all Mailgun references from the codebase since it's no longer used as an email provider

2025-05-08 - 2.8.2 - fix(tests)

Fix outdated import paths in test files for dcrouter and ratelimiter modules

2025-05-08 - 2.8.1 - fix(readme)

Update readme with consolidated email system improvements and modular directory structure

Clarify that the platform now organizes email functionality into distinct directories (mail/core, mail/delivery, mail/routing, mail/security, mail/services) and update the diagram and key features list accordingly. Adjust code examples to reflect explicit module imports and the use of SzPlatformService.

2025-05-08 - 2.8.0 - feat(docs)

Update documentation to include consolidated email handling and pattern‑based routing details

2025-05-08 - 2.7.0 - feat(dcrouter)

Implement unified email configuration with pattern‐based routing and consolidated email processing. Migrate SMTP forwarding and store‐and‐forward into a single, configuration-driven system that supports glob pattern matching in domain rules.

2025-05-08 - 2.7.0 - feat(dcrouter)

Implement consolidated email configuration with pattern-based routing

2025-05-07 - 2.6.0 - feat(dcrouter)

Implement integrated DcRouter with comprehensive SmartProxy configuration, enhanced SMTP processing, and robust store‐and‐forward email routing

2025-05-07 - 2.5.0 - feat(dcrouter)

Enhance DcRouter configuration and update documentation

2025-05-07 - 2.4.2 - fix(tests)

Update test assertions and singleton instance references in DMARC, integration, and IP warmup manager tests

2025-05-07 - 2.4.1 - fix(tests)

Update test assertions and refine service interfaces

2025-05-07 - 2.4.0 - feat(email)

Enhance email integration by updating @push.rocks/smartmail to ^2.1.0 and improving the entire email stack including validation, DKIM verification, templating, MIME conversion, and attachment handling.

2025-05-04 - 1.0.10 to 1.0.8 - core

Applied core fixes across several versions on this day.

2024-04-01 - 1.0.7 - core

Applied a core fix.

2024-03-19 - 1.0.6 - core

Applied a core fix.

2024-02-16 - 1.0.5 to 1.0.2 - core

Applied multiple core fixes in a contiguous range of versions.

2024-02-15 - 1.0.1 - core

Applied a core fix.

––––––––––––––––––––––– Note: Versions that only contained version bumps (for example, 1.0.11 and the plain "1.0.x" commits) have been omitted from individual entries and are implicitly included in the version ranges above.