Your session expired — please sign in again
NodeMesh / {{ { 'overview': 'Overview', 'analytics': 'Analytics', 'routes': 'Routes', 'webhooks': 'Webhooks', 'tunnels': 'Tunnels', 'tickets': 'Support', 'downloads': 'Downloads', 'security': 'Security', 'apikeys': 'API Keys', 'admin': 'Admin', 'metrics': 'Metrics', 'ipsecurity': 'IP Security', 'webhooklogs': 'Webhook Logs', 'announcements': 'Announcements', 'subdomainpages': 'Subdomain Pages', 'admintickets': 'Tickets', 'admintunnels': 'Tunnels', 'powerserver': 'Power Server', 'adminapikeys': 'API Keys', 'adminsettings': 'Settings' }[currentView] || currentView }}
Maintenance
{{ ann.title }}: {{ ann.message }}

Welcome to NodeMesh — Enterprise Load Balancer!

Manage your routes, tunnels, API keys and platform settings all in one place.

1 Deploy a Route

Go to Routes → click Deploy Route. Set a slug and a target URL.

2 Attach a Domain

Click Domain on your route to assign a NodeMesh subdomain (e.g. myapp.bestdns.qzz.io) or a custom domain.

3 Set Up Webhooks

Get instant alerts when targets go down or rate limits are exceeded. Configure in Webhooks & Alerts.

Active Routes

{{ stats.usage?.current || 0 }}

{{ stats.usage?.current || 0 }} / {{ stats.usage?.max || '—' }} limit

Bandwidth

{{ formatBytes(stats.usage?.bandwidth || 0) }}

Cumulative total

Target Health

{{ Object.values(stats.health || {}).filter(v => v).length }} / {{ Object.keys(stats.health || {}).length }}

{{ Math.round((Object.values(stats.health || {}).filter(v => v).length / Math.max(Object.keys(stats.health || {}).length, 1)) * 100) }}% online

Error Rate

{{ stats.usage?.errorRate || '0.00' }}%

{{ (stats.usage?.errorRate || 0) > 10 ? '⚠ Elevated — check targets' : '✓ Normal' }}

Traffic Analytics

Requests across all routes {{ stats.user.timezone }}

Strategy Mix

Load balancing by route

Recent Activity

Activity will appear here as your routes receive traffic.

{{ activity.message }}

{{ formatTime(activity.timestamp) }}

Quick Guide

1

Deploy a Route

Go to RoutesDeploy Route. Give it a slug like api and a target URL. Routes require a managed subdomain or custom domain to be publicly accessible — attach one via the Domain button.

2

Add Upstream Targets

Add multiple server URLs to a route. NodeMesh load-balances requests across them automatically. Each target shows live health, connections, and response time.

3

Pick a Load Balancing Strategy

Choose from Weighted Round Robin, Least Connections, Least Response Time, IP Hash (sticky sessions), or Random. Change strategy anytime without downtime.

4

Set Up Webhooks

Go to Webhooks & Alerts to receive POST notifications for events like target failures, rate limit hits, or route changes. HMAC-signed for security.

5

Enable 2FA & Copy API Key

In Security, enable Google Authenticator 2FA and copy your Account Key for developer API access via the x-account-key header.

6

Create API Keys

Go to API Keys to create self-service API keys for your protected routes. Set per-key rate limits, daily/total caps, route restrictions, and expiry dates. Clients include the key in the x-api-key header.

Analytics

{{ analyticsData.timezone }}

Traffic, errors, and performance across all your routes

Total Requests

{{ formatNumber(analyticsData.totals?.hits || 0) }}

in {{ chartRange }} window

Bandwidth

{{ formatBytes(analyticsData.totals?.bandwidth || 0) }}

data transferred

Error Rate

{{ analyticsData.totals?.errorRate || '0.00' }}%

{{ formatNumber(analyticsData.totals?.errors || 0) }} errors

Active Routes

{{ analyticsData.totals?.routes || 0 }}

receiving traffic

Request Volume

Requests per {{ chartRange === '24h' ? 'hour' : 'day' }} ({{ analyticsData.timezone }})

{{ formatNumber(analyticsData.totals?.hits || 0) }}

total

{{ analyticsData.timeline?.hits?.length ? Math.round((analyticsData.totals?.hits||0)/analyticsData.timeline.hits.length) : 0 }}

avg/{{ chartRange === '24h' ? 'hr' : 'day' }}

Top Routes

by request volume

{{ idx+1 }}

/{{ r.slug }}

{{ formatNumber(r.hits) }} req
{{ ((r.errors/r.hits)*100).toFixed(1) }}%
No route data yet
/{{ analyticsSlug }} Peak {{ routeAnalytics[analyticsSlug].peakHour.label }}

Route detail view

{{ kpi.value }}

{{ kpi.label }}

Upstream Targets

{{ t.url }} {{ t.connections }} conn {{ t.avgResponseTime ? t.avgResponseTime.toFixed(0)+'ms' : '—' }}

Select a route to see details

No analytics data yet

Analytics data appears once your routes start receiving traffic.

Routes & Load Balancer

Each route is an ingress endpoint that proxies traffic to one or more upstream targets

Domain-Only Routing: Routes are no longer accessible via /slug/path on the system domain. Every route must have a Managed Subdomain or Custom Domain attached to be publicly reachable.

Managed Subdomain — assign one of NodeMesh's domains (e.g. myapp.bestdns.qzz.io) to any route. Click Domain on your route card.

Custom Domain — point your own domain via Cloudflare DNS to NodeMesh, then attach it. Both subdomain and custom domain can work simultaneously.

Power Server Relay — enable per-route relay to forward traffic through a private backend server. Configure the relay in Admin → Power Server Relay, then enable it per route in Configure.

No routes deployed yet

A route is an ingress endpoint that proxies traffic to one or more upstream targets using load balancing.

/{{ route.slug }}
{{ route.subdomain }} {{ route.customDomain }} {{ formatStrategyName(route.loadBalancingStrategy) }} Protected Sticky Paused No Rate Limit Power Relay {{ tag }}

{{ route.description }}

Limit: {{ route.rateLimit || 60 }}/min Timeout: {{ route.timeout }}ms Updated: {{ formatTime(route.updated) }} Visit Visit Domain Required QR Code

Load Balancer Targets

● Healthy ● Down

{{ target.url }}

{{ target.internalPath || '/' }} Weight: {{ target.weight }} {{ target.currentConnections }} conn {{ target.responseTime }}ms

Webhooks & Alerts

Configure notifications for system events and route activities

How Webhooks Work — NodeMesh sends an HTTP POST request to your URL when a subscribed event fires. Payloads are HMAC-SHA256 signed using the webhook secret for security verification.

Retries — Failed deliveries are retried up to 3 times with exponential backoff. Check Webhook Logs (admin) for delivery history.

Test — Use the send button on any webhook to fire a test event immediately to verify your endpoint is receiving correctly.

No webhooks configured

Webhooks send real-time POST notifications to a URL when system events occur (e.g. target down, rate limit exceeded).

{{ webhook.name }}

{{ webhook.url }}

{{ webhook.enabled ? 'Active' : 'Disabled' }}
{{ formatEventName(event) }}
Last triggered: {{ formatTime(webhook.lastTriggered) }} Never triggered

Available Events

Subscribe to any combination of these events when creating a webhook.

{{ event.name }}

{{ event.description }}

Hosted Sites

Deploy static HTML/CSS/JS projects on a managed subdomain — free CDN included.

Account storage — shared across all your sites:  Free 50 MB  ·  Pro 500 MB  ·  Enterprise 10 GB
/ {{ currentSite.name }} {{ currentSite.enabled !== false ? 'Online' : 'Offline' }} {{ currentSite.fullDomain }}
Subdomain: {{ currentSite.subdomain }}.{{ currentSite.domain || 'bestdns.qzz.io' }} Custom domain:
Account storage:
· {{ (siteStats.hits||0).toLocaleString() }} hits · {{ siteStats.bandwidthMb }} MB served
{{ siteSelectedFiles.length }} selected
{{ siteUploadProgress }}
{{ siteFileSearchResults.length }} result{{ siteFileSearchResults.length !== 1 ? 's' : '' }}
{{ f.filePath }}
Files ({{ currentSite.files?.length || 0 }})

No files yet. Upload to make the site live.

{{ file.filePath }} {{ (file.size/1024).toFixed(1) }}k
{{ siteEditorFile.path }} ● unsaved

Click any file to edit it

HTML, CSS, JS, JSON, Markdown and other text files open in the editor. Binary files can be downloaded.

No hosted sites yet

Deploy a static site in seconds — upload your HTML/CSS/JS and get a public URL instantly.

{{ site.name }}

{{ site.enabled !== false ? 'Live' : 'Paused' }}
{{ site.fullDomain }}

{{ site.description }}

{{ site.usedMb }} MB this site {{ (site.hits||0).toLocaleString() }} hits

Teams

Collaborate with others — share routes, tunnels, and access with role-based permissions.

{{ currentTeam.name }}

{{ currentTeam.plan || 'free' }}

{{ currentTeam.memberCount }} member{{ currentTeam.memberCount !== 1 ? 's' : '' }} · ID: {{ currentTeam.teamId }}

Members

{{ m.username.substring(0,2) }}

{{ m.username }}

Joined {{ formatTime(m.joinedAt) }}

Owner

No teams yet

Create a team to collaborate with colleagues. Share routes, tunnels, and manage access with roles.

{{ team.name.substring(0,1).toUpperCase() }}

{{ team.name }}

{{ team.myRole }}

{{ team.memberCount }} member{{ team.memberCount !== 1 ? 's' : '' }} · Created {{ formatTime(team.createdAt) }}

Developer API

Manage tunnels, routes, and analytics programmatically using /v1/* with scoped developer keys.

Base URL https://nodemesh.qzz.io/v1
{{ scope.name }} {{ scope.label }}

Copy your key now — shown only once!

{{ newDevKeySecret.rawKey || newDevKeySecret }}

No developer keys yet

Create a scoped API key to manage your NodeMesh resources programmatically from CI/CD, scripts, or apps.

{{ key.name }}

{{ key.enabled !== false ? 'Active' : 'Revoked' }} Expires {{ formatTime(key.expiresAt) }}
{{ s }}
{{ key.keyId }} {{ (key.totalHits || 0).toLocaleString() }} hits {{ key.rateLimit || 120 }} req/min Last used {{ formatTime(key.lastUsedAt) }}

Profile Settings

Display name, timezone & country — used for timezone-aware analytics

Chart time labels on your dashboard will display in this timezone. Must be a valid IANA zone string.

{{ profileMsg.text }}

Two-Factor Authentication

Protect your account with Google Authenticator (TOTP)

Active Not enabled

2FA is Active

Your account is protected. You'll need your authenticator app to sign in.

Using 2FA adds an extra layer of security. Highly recommended for all admins.

You'll need Google Authenticator or any TOTP-compatible app installed on your phone.

1. Scan QR Code

Open Google Authenticator and scan this QR code or enter the secret manually:

{{ twoFactorSetup.secret }}

2. Enter Verification Code

Enter the 6-digit code from your authenticator app:

Account Security

Account Key

For API access — keep this secret

Last Login

{{ formatTime(user.lastLogin) }}

Change Password

{{ passwordMsg.text }}

API Keys

Create and manage API keys to authenticate requests to your protected routes.

How API Keys Work

Attach an API key to any protected route. Clients include your key via the x-api-key header (configurable by admin). Keys can have per-day and total request caps, plus RPM rate limits. You can restrict a key to specific routes.

No API keys yet

Create an API key to control programmatic access to your protected routes.

{{ key.name }}

{{ key.enabled ? 'Active' : 'Disabled' }} Expired
{{ key.keyPrefix }}••••••••
{{ (key.totalHits || 0).toLocaleString() }} total hits {{ (key.dailyHits || 0).toLocaleString() }} today Cap: {{ key.totalHits || 0 }}/{{ key.totalCap }} Daily: {{ key.dailyHits || 0 }}/{{ key.dailyCap }} {{ key.rpm || 60 }} RPM Expires {{ formatTime(key.expiresAt) }}
Routes: /{{ r }}
Total usage {{ Math.min(Math.round(((key.totalHits||0)/key.totalCap)*100),100) }}%

Admin Dashboard

Platform-wide overview, user management, and route controls.

Total Users

{{ adminLiveDashboard.totalUsers }}

Total Routes

{{ adminLiveDashboard.totalRoutes }}

{{ adminLiveDashboard.relayedRoutes }} relayed

Open Tickets

{{ adminLiveDashboard.openTickets }}

{{ adminLiveDashboard.overdueTickets }} overdue

Tunnels Live

{{ adminLiveDashboard.connectedTunnels }}

Power relay active

Users

{{ adminUsers.length }} total
UserPlanRoutesJoinedStatusActions
{{ u.username }}{{ u.email }} {{ u.routeCount || 0 }} {{ formatTime(u.createdAt) }} {{ u.suspended ? 'Suspended' : 'Active' }}

Loading users...

All Routes

{{ adminRoutes.length }} total
RouteOwnerDomainStrategyStatusActions
/{{ route.slug }} {{ route.owner }} {{ route.customDomain || route.subdomain || '—' }} {{ formatStrategyName(route.loadBalancingStrategy) }} {{ route.enabled !== false ? 'Active' : 'Paused' }}

Loading routes...

System Metrics

Live server performance — CPU, memory, connections, and cache.

Uptime

{{ formatUptime(systemMetrics.uptime) }}

Heap Used

{{ systemMetrics.memory?.process?.heapUsedMB || '—' }} MB

of {{ systemMetrics.memory?.process?.heapTotalMB || '—' }} MB total

CPU Cores

{{ systemMetrics.cpu?.cores || '—' }}

Load: {{ systemMetrics.cpu?.loadAvg?.['1m'] || '0' }} (1m)

Live Tunnels

{{ systemMetrics.cache?.liveTunnels ?? '—' }}

{{ systemMetrics.cache?.downTargets ?? 0 }} down targets

Memory Usage

Process heap — used vs free

CPU Usage

Per-core breakdown (or load avg if unavailable)

Connections Over Time

Active WebSocket + proxy connections (simulated)

Node.js Process Info

Node Version

{{ systemMetrics.node?.version || '—' }}

Platform

{{ systemMetrics.node?.platform || '—' }} / {{ systemMetrics.node?.arch || '—' }}

PID

{{ systemMetrics.node?.pid || '—' }}

IP Security

Manage blocked IPs and review scanner/bot activity.

Blocked IPs

{{ blockedIPs.length }} active blocks

No blocked IPs

IP AddressReasonBlocked AtExpires
{{ ip.ip }} {{ ip.reason }} {{ formatTime(ip.blockedAt) }} {{ ip.expiresAt ? formatTime(ip.expiresAt) : 'Permanent' }}

Scanner / Bot Hits

No scanner hits recorded

IPPathHitsLast Seen
{{ hit.ip }} {{ hit.path }} {{ hit.count }} {{ formatTime(hit.lastSeen) }}

Announcements & Maintenance

Broadcast system messages and toggle maintenance mode.

Maintenance Mode

{{ maintenanceStatus.enabled ? 'ACTIVE' : 'Off' }}

When enabled, all non-admin requests return a 503 maintenance response with the message below.

Active Announcements

No active announcements

{{ ann.title }}

{{ ann.message }}

{{ formatTime(ann.createdAt) }}

Subdomain Pages

Map subdomains on your base domain to static HTML files in the public/ folder of the server.

How it works: Drop any .html file into the public/ directory on the server, then create a mapping here. The subdomain will immediately start serving that file.

Example: map statusstatus.html to serve a status page at status.nodemesh.qzz.io.

The public/ folder is also a full static web server — any file placed there is instantly accessible without a mapping.

No subdomain mappings yet

Create a mapping to serve a static page at a custom subdomain on your base domain.

Active Mappings

{{ subdomainPages.length }} mapping{{ subdomainPages.length !== 1 ? 's' : '' }}
Subdomain URL File in public/ Title Status Created
{{ page.subdomain }}.nodemesh.qzz.io public/{{ page.file }} {{ page.title || '—' }} {{ page.active !== false ? 'Active' : 'Disabled' }} {{ formatTime(page.createdAt) }}

All Tunnels

Platform-wide tunnel list across all users.

No tunnels found across the platform.

URL / DomainOwnerStatusHitsCreated
{{ t.url || t.fullDomain }} {{ t.customDomain }} {{ t.owner || t.username }} {{ t.status }} {{ t.hits || 0 }} {{ formatTime(t.createdAt) }}

API Key Admin

Platform-wide visibility and management of all API keys.

{{ key.name }} {{ key.enabled ? 'Active' : 'Disabled' }} Expired
{{ key.owner || key.ownerUsername }} {{ (key.totalHits||0).toLocaleString() }} hits Cap: {{ key.totalCap }} {{ key.rpm || 60 }} RPM

No API keys found

{{ adminApiKeyAnalytics.totalKeys || 0 }}

Total Keys

{{ adminApiKeyAnalytics.enabledKeys || 0 }}

Active Keys

{{ (adminApiKeyAnalytics.totalHitsToday || 0).toLocaleString() }}

Hits Today

{{ (adminApiKeyAnalytics.totalHitsAllTime || 0).toLocaleString() }}

Total Hits

Loading analytics...

{{ adminApiKeyDetail.name }}

Owner

{{ adminApiKeyDetail.owner || adminApiKeyDetail.ownerUsername }}

Key Prefix

{{ adminApiKeyDetail.keyPrefix }}••••••••

Total Hits

{{ (adminApiKeyDetail.totalHits||0).toLocaleString() }} / {{ adminApiKeyDetail.totalCap }}

Today

{{ (adminApiKeyDetail.dailyHits||0).toLocaleString() }} / {{ adminApiKeyDetail.dailyCap }}

Allowed Routes: /{{ r }}

Platform Settings

Dynamic platform-wide configuration — changes take effect immediately.

API Key Enforcement

Controls how API keys are validated on proxied requests.

Enable API Key Enforcement

When disabled, protected routes skip key validation entirely.

The HTTP header clients must include (default: x-api-key).

Fallback RPM for API keys without their own rate limit.

Support Ticket Settings

Configure ticket spam protection and limits.

Users hitting this limit receive a 429 Too Many Requests response.

{{ settingsSaveMsg.text }}

Tunnels

Expose a local server to the internet via a WebSocket-backed public URL — no port forwarding needed.

How to Connect Your Local App

1

Create a tunnel above

Choose a domain and optional custom subdomain prefix. Click New Tunnel.

2

Download the client script

On your server, run one of the following:

curl -O https://nodemesh.qzz.io/tunnel/client/nodemesh-client.js curl -O https://nodemesh.qzz.io/tunnel/client/nodemesh-client.py

Node.js: install npm install ws • Python: no deps needed

3

Run the client with your tunnel token

Replace YOUR_TOKEN with the token from your tunnel card below, and 3000 with your local port:

node nodemesh-client.js --token=YOUR_TOKEN --port=3000 --gateway=wss://nodemesh.qzz.io
4

Your tunnel is live! 🎉

Once the client connects, the tunnel status turns Connected. Your public URL is ready to use.

No tunnels yet

Create a tunnel to expose your local application at a public URL.

{{ tunnel.url }} Connected Waiting for client Disabled

{{ tunnel.description }}

{{ tunnel.hits || 0 }} hits {{ tunnel.rateLimit }}/min Connected {{ formatTime(tunnel.clientConnectedAt) }}

Connect Commands

node $ {{ tunnel.connect?.node || `node nodemesh-client.js --token=${tunnel.tunnelToken} --port=3000 --gateway=wss://nodemesh.qzz.io` }}
py $ {{ tunnel.connect?.python || `python nodemesh-client.py --token ${tunnel.tunnelToken} --port 3000 --gateway wss://nodemesh.qzz.io` }}
Token: {{ tunnel.tunnelToken }}
NodeMesh {{ tunnel.url || tunnel.fullDomain }} Always active
Custom
{{ formatBytes(tunnel.bandwidth) }} relayed total {{ tunnel.pendingRequests }} pending

Support Tickets

Report issues, request features, or contact support. Our team will respond in your ticket thread.

{{ ticketSummary.total || 0 }}

Total Tickets

{{ ticketSummary.open || 0 }}

Open

{{ ticketSummary.in_progress || 0 }}

In Progress

{{ ticketSummary.resolved || 0 }}

Resolved

{{ ticketSummary.closed || 0 }}

Closed

Programmatic Error Reporting

Use the built-in SDK to automatically submit error reports from your app. Tickets are created instantly with full stack trace context.

// Quick usage — POST /api/tickets/code-report
const sdk = require('./nodemesh-sdk')({ token: 'YOUR_TOKEN' });
sdk.report(err, { route: '/api', severity: 'critical' });

No tickets submitted yet

Having a problem or a feature idea? Open a ticket and our team will look into it.

{{ ticket.ticketId }} {{ ticket.status.replace(/_/g, ' ') }} {{ ticket.priority }} {{ ticket.category.replace(/_/g,' ') }}

{{ ticket.subject }}

{{ formatTime(ticket.updatedAt) }}

{{ currentTicket.subject }}

{{ currentTicket.ticketId }} {{ currentTicket.status.replace(/_/g,' ') }}

Original Description

{{ currentTicket.description }}

{{ currentTicket.errorDetails }}

{{ reply.isAdmin ? 'SU' : reply.author.substring(0,2).toUpperCase() }}

{{ reply.isAdmin ? 'Support Team' : reply.author }} • {{ formatTime(reply.createdAt) }}

{{ reply.message }}

This ticket is closed.

Downloads & SDKs

Client libraries, starter templates, and setup scripts.

Tunnel Clients

Install a client to connect your local application through a NodeMesh tunnel.

Node.js Client

nodemesh-client.js

WebSocket-based tunnel client for Node.js. Works without any filesystem dependencies.

node nodemesh-client.js --token YOUR_TOKEN
Download Client

Python Client

nodemesh-client.py

Native Python tunnel client. Requires only the standard library — no pip install needed.

python nodemesh-client.py --token YOUR_TOKEN
Download Client

Error Reporting SDKs

Drop these into your app to auto-submit error reports as support tickets. Token is pre-filled when authenticated.

JS Error Reporter SDK

const sdk = require('./nodemesh-sdk')({
  token: 'YOUR_TOKEN'
});
// Automatic — catches unhandled exceptions
sdk.attach();
Download SDK

Python Error Reporter SDK

from nodemesh_sdk import NodeMeshSDK
sdk = NodeMeshSDK(
  token="YOUR_TOKEN"
)
sdk.attach() # auto-hooks sys.excepthook
Download SDK

Programmatic Reports via API

POST to /api/tickets/code-report with { message, stack, severity, metadata } and your Authorization header to create a ticket programmatically without the SDK.

Ticket Management

Manage all support tickets, add notes, labels, and track SLA compliance.

{{ selectedTicketIds.length }} selected
{{ ticket.ticketId }} {{ ticket.status.replace(/_/g,' ') }} {{ ticket.priority }} SLA {{ label }}

{{ ticket.subject }}

{{ ticket.username }} · {{ formatTime(ticket.updatedAt) }}

No tickets found

Overdue Tickets

These tickets have been open for more than 48 hours with no admin reply. They may have SLA breaches.

{{ ticket.ticketId }} Overdue SLA Breached

{{ ticket.subject }}

{{ ticket.username }} · Open since {{ formatTime(ticket.createdAt) }}

No overdue tickets — great work!

{{ slaStats.totalTickets || 0 }}

Total Tickets

{{ slaStats.slaCompliant || 0 }}

SLA Compliant

{{ slaStats.slaBreached || 0 }}

SLA Breached

{{ slaStats.complianceRate || '—' }}%

Compliance Rate

Avg First Response Time

{{ slaStats.avgFirstResponseHours }}h

Loading SLA stats...

{{ ticket.ticketId }} {{ ticket.status.replace(/_/g,' ') }}

{{ ticket.subject }}

{{ ticket.username }} · {{ formatTime(ticket.updatedAt) }}

No tickets assigned to you

{{ adminCurrentTicket.subject }}

{{ adminCurrentTicket.ticketId }} {{ adminCurrentTicket.status?.replace(/_/g,' ') }} SLA Breached {{ label }}
First reply: {{ formatTime(adminCurrentTicket.firstResponseAt) }}
No first reply yet

Original Description by {{ adminCurrentTicket.username }}

{{ adminCurrentTicket.description }}

{{ adminCurrentTicket.errorDetails }}

User Rating: {{ '★'.repeat(adminCurrentTicket.satisfactionRating) }}{{ '☆'.repeat(5 - adminCurrentTicket.satisfactionRating) }} — {{ adminCurrentTicket.satisfactionComment }}

Internal Note — {{ reply.author }} · {{ formatTime(reply.createdAt) }}

{{ reply.message }}

Internal Note (never shown to user)

Power Server Relay

POOL MODE ⚡ GLOBAL RELAY ON

Forward route traffic to backend nodes. V33: circuit breakers, 5 LB strategies, global relay mode, site sync.

Global Relay Mode — {{ globalRelayMode ? 'ENABLED' : 'Disabled' }}

ALL route traffic is being forwarded to the backend pool. This node acts as a pure edge. Hosted sites still served locally. Only routes with Power Server Relay enabled are forwarded. Toggle ON to relay every route without per-route config.

Pool Mode (V32+): Add multiple backends — NodeMesh load-balances using your chosen strategy. Pool takes precedence over the legacy single URL.

V33 Strategies: Round Robin · Least Connections · Least Response Time · Random · IP Hash (sticky sessions)

Circuit Breaker (V33): Each backend has an independent circuit breaker. After consecutive failures it opens (backend skipped) then retries after a cooldown. Reset manually below.

Site Sync (V33): When global relay is active, hosted site files are auto-pushed to all pool backends. Use Sync Sites to force a full re-push after adding a new backend.

Injected Headers: x-relay-source, x-relay-slug, x-relay-secret

Backend Pool {{ powerServerPool.length }} server{{ powerServerPool.length !== 1 ? 's' : '' }} {{ powerServerPool.filter(s=>!s.healthy).length }} down

Load-balanced across healthy backends. Pool takes precedence over the legacy single URL.

{{ server.url }}

⚡ Circuit Open ⟳ Half-Open (retrying) {{ server.lastError }} Checked {{ formatTime(server.lastCheck) }}

No servers in pool

Add backend servers above to enable pool-based load balancing.

Strategy: {{ { 'round-robin':'Round Robin','least-connections':'Least Conn','least-response-time':'Least Resp Time','random':'Random','ip-hash':'IP Hash' }[powerPoolStrategy] || powerPoolStrategy }} {{ powerServerPool.filter(s => s.healthy).length }}/{{ powerServerPool.length }} healthy {{ powerServerPool.filter(s => s.circuitState === 'open').length }} circuit(s) open

Circuit Breakers

{{ cb.index }} {{ cb.url }} {{ cb.circuitState === 'open' ? '⚡ OPEN' : cb.circuitState === 'half-open' ? '⟳ HALF-OPEN' : '✓ Closed' }} {{ cb.circuitFailures }} failures {{ Math.ceil(cb.msUntilHalfOpen/1000) }}s until retry

Legacy Single-URL Config (fallback when pool is empty)

Relay URL

{{ powerServerConfig.url }}

Active

{{ powerServerConfig.relayedRoutes.length }} route(s) using this relay

{{ powerServerTestResult.msg }}

No legacy URL configured.

API Reference

{{ep.m}} {{ep.p}} {{ep.n}}

V32/V33 Pool Management

{{ep.m}} {{ep.p}} {{ep.n}}

V33 Circuit Breakers

{{ep.m}} {{ep.p}} {{ep.n}}

V33 Global Relay & Site Sync

{{ep.m}} {{ep.p}} {{ep.n}}

Per-Route Backend Pin (V33)

{{ep.m}} {{ep.p}} {{ep.n}}

Hosted Sites Admin

Platform-wide view of all user-hosted sites.

No hosted sites found.

Site / DomainOwnerFilesStorageHitsStatus

{{ s.name }}

{{ s.fullDomain }}
{{ s.owner }} {{ s.files || 0 }} {{ ((s.totalSize || 0) / 1024 / 1024).toFixed(1) }} / {{ ((s.storageQuota || 0) / 1024 / 1024).toFixed(0) }} MB {{ (s.hits || 0).toLocaleString() }} {{ s.enabled !== false ? 'Online' : 'Offline' }}

Teams Admin

Platform-wide team management.

No teams found.

TeamCreatorMembersPlanStatusCreated

{{ t.name }}

{{ t.teamId }}
{{ t.createdBy }} {{ t.memberCount }} {{ t.plan || 'free' }} {{ t.suspended ? 'Suspended' : 'Active' }} {{ formatTime(t.createdAt) }}

Abuse Reports

Report illegal or abusive content to the NodeMesh team.

No reports submitted yet.

Use the button above to report abusive content or sites.

Report IDTargetCategoryStatusPrioritySubmittedAction Taken
{{ r.reportId }} {{ r.targetType }} {{ r.targetId }} {{ (r.category || '').replace(/_/g,' ') }} {{ r.status }} {{ r.priority }} {{ formatTime(r.createdAt) }} {{ r.actionTaken || '—' }}

Security Center

Bot detection, DDoS burst activity, firewall overview, and IP management.

Blocked IPs
{{ adminSecurityOverview.blockedIPs?.total || 0 }}
Suspicious Bots
{{ adminSecurityOverview.suspiciousBots?.total || 0 }}
Burst Activity
{{ adminSecurityOverview.burstActivity?.total || 0 }}
Pending Reports
{{ adminSecurityOverview.pendingReports || 0 }}

Blocked IPs

No blocked IPs
IPReasonExpires
{{ ip.ip }} {{ (ip.reason || '').replace(/_/g,' ') }} {{ ip.remainingSeconds > 0 ? Math.ceil(ip.remainingSeconds/3600) + 'h' : 'Expired' }}

Suspicious Bot Activity

IPScoreSignalsLast Seen
{{ bot.ip }} {{ bot.score }}/100 {{ (bot.signals || []).join(', ') }} {{ formatTime(bot.lastSeen) }}

DDoS Burst Activity

RouteIPRequest Count
{{ b.slug }} {{ b.ip }} {{ b.count }}

Active Route Firewalls ({{ adminSecurityOverview.firewalls.total }})

RouteOwnerModeRulesBot ProtectionBurst Limit
{{ fw.slug }} {{ fw.owner }} {{ fw.mode }} {{ fw.ruleCount }} {{ fw.botProtection ? '✓ On' : '—' }} {{ fw.burstLimit || '—' }}

Click Refresh to load security data.

Abuse Reports

Review and action abuse reports submitted by users.

Report: {{ currentAdminReport.reportId }}

Target{{ currentAdminReport.targetType }}: {{ currentAdminReport.targetId }}
Category{{ (currentAdminReport.category || '').replace(/_/g,' ') }}
Reported By{{ currentAdminReport.reportedBy || 'Anonymous' }}
Status{{ currentAdminReport.status }}
Priority{{ currentAdminReport.priority }}
Description

{{ currentAdminReport.description }}

No abuse reports found.

IDTargetCategoryReporterPriorityStatusSubmitted
{{ r.reportId.slice(0,12) }} {{ r.targetType }}{{ r.targetId }} {{ (r.category || '').replace(/_/g,' ') }} {{ r.reportedBy || 'Anon' }} {{ r.priority }} {{ r.status }} {{ formatTime(r.createdAt) }}

Tunnel Domain Settings

Your NodeMesh URL (always active)

{{ tunnelDomainTarget?.url || tunnelDomainTarget?.fullDomain }}

This URL is always live — you don't need your own domain. The custom domain below is optional and works alongside this URL.

Optional: Add your own domain

Cloudflare DNS Setup Required

  1. 1 Log in to Cloudflare → select your domain → go to DNS → Records.
  2. 2

    Add an A record:

    TypeNameIPv4 AddressProxy
    A{{ tunnelDomainForm.domain || 'tunnel.yourdomain.com' }}45.131.65.51 Proxied ON
  3. 3 Make sure the Proxy toggle is ON (orange cloud, not grey). Save the record, wait ~1 minute, then attach below.
Both your NodeMesh URL and custom domain will work at the same time.

{{ routeModalMode === 'create' ? 'Deploy New Route' : 'Route Settings' }}

/

Tags appear as colored badges on the route card

After saving, use the Domain button on the route card for step-by-step DNS setup instructions.

Default: 30000ms (30 seconds)

Same client IP always hits the same target

Requires x-route-key header

Enforce req/min limit above

Per-route CORS headers (Access-Control-Allow-Origin)

Automatically detect and remove unhealthy targets from rotation

Forward this route's traffic through the configured Power Server. Requires Power Server Relay to be set up in Admin.

Leave blank to forward the original request path.

When pinned, this route always hits the same backend regardless of the pool strategy.

Track hits, bandwidth, and response times per route

Load Balancing Strategy

Select a strategy for route: /{{ strategyForm.slug }}

{{ webhookModalMode === 'create' ? 'Create Webhook' : 'Edit Webhook' }}

Supports Discord, Slack, or any HTTP POST endpoint

Create Tunnel

Your local app will be proxied to a public URL. Run nodemesh-client.js on your server after creating.
.{{ tunnelForm.domain }}

Open Support Ticket

Rate limit: Max 5 tickets per hour. Please include as much detail as possible to avoid re-submitting.

Domain Settings

/{{ routeSubdomainForm.slug }}
No domain? No problem. We'll give your route a free public URL on one of our NodeMesh domains — no DNS setup required.
Current: {{ routeSubdomainForm.currentDomain }}
.{{ routeSubdomainForm.domain }}

Result: {{ routeSubdomainForm.subdomain || 'auto' }}.{{ routeSubdomainForm.domain }}

Have your own domain? Point it to NodeMesh using Cloudflare DNS and we'll route traffic from your domain directly to this route.
Current: {{ routeSubdomainForm.currentCustomDomain }}

Cloudflare DNS Setup (Required)

  1. 1 In your Cloudflare dashboard, go to your domain's DNS → Records tab.
  2. 2

    Add a new A record:

    TypeNameIPv4 AddressProxy Status
    A{{ routeCustomDomainInput || 'app.yourdomain.com' }}45.131.65.51 Proxied
  3. 3 Ensure the Proxy status is set to Proxied (orange cloud icon) — not DNS only.
  4. 4 Save and wait ~1 minute, then click Attach Domain below.

Configure Power Server Relay

Enter the URL of your private backend server (must be reachable from this gateway). The shared secret is injected as x-relay-secret on every forwarded request.

Must be reachable from the gateway (e.g. internal LAN, VPC, or local IP).

Your backend should validate this header to accept relayed requests.

{{ apiKeyModalMode === 'create' ? 'Create API Key' : 'Edit API Key' }}

Copy your API key now — it won't be shown again!

{{ newApiKeySecret }}

Close Ticket

Click to rate (optional) Poor experience Neutral Good Excellent!

Send Message to User

A support ticket will be created on behalf of the user with your message. They will see it in their Support Tickets section.

Traffic Distribution

Live per-target breakdown for {{ distributionRoute?.slug }}

No distribution data yet

Traffic data becomes available once requests are proxied through this route.

{{ t.url }}
{{ (t.pct || 0).toFixed(1) }}% {{ t.health ? 'Healthy' : 'Down' }}

{{ (t.hits || 0).toLocaleString() }}

Total Hits

{{ (t.errors || 0).toLocaleString() }}

Errors ({{ (t.errorPct||0).toFixed(1) }}%)

{{ t.connections || 0 }}

Active Conns

{{ t.avgResponseMs ? t.avgResponseMs.toFixed(0) + 'ms' : '—' }}

Avg Response

Request Inspector

{{ inspectorTunnel?.url }}

{{ tunnelRequests.length }} request{{ tunnelRequests.length !== 1 ? 's' : '' }}

No requests captured

Send traffic through the tunnel or click Go Live to stream in real-time.

{{ req.method || '?' }} {{ req.path || req.url || '/' }}
{{ req.status }} pending {{ req.duration }}ms
{{ currentInspectorRequest.method }} {{ currentInspectorRequest.path || currentInspectorRequest.url }}
{{ currentInspectorRequest.status }} Status
{{ currentInspectorRequest.duration }}ms Duration
{{ formatBytes(currentInspectorRequest.responseSize) }} Response Size
Request Headers
{{ key }} {{ val }}

No headers captured

Request Body
{{ currentInspectorRequest.bodyPreview || currentInspectorRequest.body }}
Response Headers
{{ key }} {{ val }}
Response Body Preview
{{ currentInspectorRequest.responseBodyPreview }}

Reassign Route

/{{ assignForm.slug }}
This transfers full ownership of the route to the new user. They will be able to manage, edit and delete it.

Set Route Limit

{{ limitForm.username }}

Set how many routes this user can create. Overrides their plan default.

Block IP Address

Use 8760 for 1 year. The block expires automatically.

Create Announcement

Create Subdomain Page

Map a subdomain (e.g. status.nodemesh.qzz.io) to a static HTML file in the public/ directory.
.nodemesh.qzz.io

The file must exist in your public/ directory on the server.

Create Hosted Site

Create a site to get a public URL. Upload your HTML/CSS/JS files afterward to make it live.
.bestdns.qzz.io

{{ siteMsg.text }}

Create Team

{{ teamMsg.text }}

Invite Member

An invite link will be generated. Share it with the person you want to add. It expires in 7 days.

Create Developer Key

Copy now — won't be shown again!

{{ newDevKeySecret.rawKey || newDevKeySecret }}

{{ devKeyMsg.text }}

Add Extra Domain

Adding an extra domain routes traffic through the same tunnel client. Your primary URL stays active.
.{{ addTunnelDomainForm.domain }}

Route Firewall — {{ firewallRoute }}

No rules yet
{{ rule.type }} {{ rule.ip }} {{ rule.hits || 0 }} hits

Submit Abuse Report

Change Subdomain

The old URL will stop working immediately. Update any links, DNS records, or API integrations pointing to the current subdomain.
.{{ currentSite?.domain || 'bestdns.qzz.io' }}

3–50 chars, letters/numbers/hyphens only, no leading or trailing hyphen.

{{ subdomainMsg.text }}