signalk-edge-link
v3.1.0
Published
SignalK Edge Link. Secure UDP link for data exchange.
Maintainers
Readme
Signal K Edge Link
Signal K Edge Link is a Signal K plugin that transfers vessel deltas between Signal K servers over encrypted UDP.
It is designed for links where latency, packet loss, and bandwidth usage matter (cellular, satellite, and other unstable WAN paths).

Why use it?
- Secure transport using AES-256-GCM
- Bandwidth optimization with Brotli compression (plus optional MessagePack and path dictionary)
- Two operating modes:
- Client: subscribes to local deltas and sends packets
- Server: receives packets, decrypts, and forwards to local Signal K
- Advanced mode features for difficult links:
- ACK/NAK-based reliability
- congestion control
- optional primary/backup bonding
- monitoring and alerting endpoints
- values snapshot replay on subscribe, retry, and socket recovery
- optional server-triggered full-state request on restart (
requestFullStatusOnRestart) - Signal K path metadata transport (units, descriptions, zones)
- Multi-connection support on one Signal K instance
How data flows
Client Signal K
-> subscribe + batch deltas
-> optional path dictionary + MessagePack
-> Brotli compress
-> AES-256-GCM encrypt
-> UDP send
Server Signal K
<- UDP receive
<- AES-256-GCM decrypt
<- Brotli decompress
<- optional MessagePack + path decode
<- inject into local Signal KRequirements
- Two Signal K instances (source and destination)
- UDP reachability from client to server on your chosen port
- Shared encryption key on both ends (32-character ASCII, 64-character hex, or 44-character base64)
- Node.js 20.9.0+ (if installing from source: dev dependencies including TypeScript are installed automatically via
npm install)
Installation
Option A: Signal K Plugin Manager
Install Signal K Edge Link from your Signal K plugin catalog.
Option B: Manual install from source
cd ~/.signalk/node_modules
git clone https://github.com/KEGustafsson/signalk-edge-link.git
cd signalk-edge-link
npm install
npm run buildRestart Signal K after installation.
Quick start
1) Configure the destination (Server mode)
In Signal K Admin UI:
- Open
Server -> Plugin Config -> Signal K Edge Link - Click Add Server
- Set:
Connection Name(for exampleshore-server)UDP Port(default4446)Encryption Key(same shared secret used by client)Protocol— select Advanced (v3, recommended) for new deployments; select Basic (v1) only for stable local links
- Save
2) Configure the source (Client mode)
On the sending Signal K instance:
- Open
Server -> Plugin Config -> Signal K Edge Link - Click Add Client
- Set:
Connection Name(for examplevessel-client)Server Address(destination host/IP)UDP Port(must match server)Encryption Key(must match server)Protocol— select Advanced (v3, recommended) for new deployments; select Basic (v1) only for stable local links
- Save
3) Verify traffic
Open the runtime UI:
http://<signalk-host>:3000/plugins/signalk-edge-link/
Check that:
- client
Deltas Sentincreases - server
Deltas Receivedincreases - encryption/decryption errors remain stable at zero
Protocol guidance
| Mode | Numeric | Use when | Notes | | ------------ | ------- | ---------------------------------------- | ------------------------------------------------------------------------ | | Basic | v1 | stable local links, simplest setup | lower overhead, no ACK/NAK reliability, no metadata transport | | Advanced | v3 | packet loss, variable latency, WAN links | retransmission, congestion control, bonding, metadata, HMAC control auth |
Use Advanced for any new deployment on a WAN or unreliable link. Use Basic only for stable local links where simplicity and minimum overhead matter.
Runtime UI and API
- Runtime UI:
/plugins/signalk-edge-link/ - API base path:
/plugins/signalk-edge-link - Default API rate limit: 120 requests/minute/IP
For a walkthrough of the configuration panel (progressive-disclosure connection
cards) and the runtime dashboard panels for server and client, see
docs/web-ui.md.
Most used endpoints:
GET /metricsGET /network-metricsGET /monitoring/alertsGET /connectionsGET /instancesGET /instances/:idGET /connections/:id/metricsGET /connections/:id/network-metricsGET /bondingPOST /bonding
For full endpoint details, use docs/api-reference.md
Configuration model (summary)
Configuration is an array of independent connections:
{
"connections": [
{
"name": "shore-server",
"serverType": "server",
"udpPort": 4446,
"secretKey": "<32-byte key>",
"protocolVersion": 3,
"requestFullStatusOnRestart": false
},
{
"name": "sat-client",
"serverType": "client",
"udpPort": 4447,
"udpAddress": "10.0.0.1",
"secretKey": "<32-byte key>",
"protocolVersion": 3
}
]
}- Each connection runs independently.
- Legacy single-object config is auto-normalized to one connection.
- Client runtime JSON files (
delta_timer.json,subscription.json,sentence_filter.json) are stored per connection and can be edited via API. requestFullStatusOnRestart(server mode, v3, defaultfalse): when enabled, the server sends aFULL_STATUS_REQUESTto each client on first contact after a (re)start; the client immediately replays its complete values snapshot so the server rebuilds state without waiting for incremental deltas. Client-side rate-limited to 10 s to prevent replay floods across rapid restarts.
For complete setting definitions and ranges, use docs/configuration-reference.md.
Schema and migration helpers:
- The runtime schema is defined inline as
plugin.schemainsrc/index.tsand served to the Signal K admin UI.docs/configuration-reference.mdis the authoritative human-readable reference. src/scripts/migrate-config.ts(convert legacy flat config toconnections[])npm run migrate:config -- <input.json> [output.json]
Security notes
- Uses AES-256-GCM authenticated encryption.
- Keys must match exactly and can be entered as 32-character ASCII, 64-character hex, or 44-character base64 (standard or URL-safe).
- Restrict UDP ingress to trusted source addresses whenever possible.
authenticatedHeaders(v3, default on, both ends must match) adds an HMAC tag binding each DATA/METADATA packet header to its encrypted payload, preventing on-path header tampering. Set tofalseon both peers only to interoperate with a peer that cannot enable it. Seedocs/security.md.
Example key generation:
openssl rand -hex 32Troubleshooting
Common checks:
- Verify
udpAddress,udpPort, andsecretKeymatch both ends. - Confirm server UDP port is reachable and not already in use.
- If link quality is poor, switch to Advanced (
protocolVersion: 3) when both peers can upgrade together.
testAddress is only supported on v1 clients after upgrading to Advanced mode
The fields testAddress, testPort, and pingIntervalTime belong to the Basic (v1) ping monitor and are not used by Advanced (v3) clients (which derive RTT from HEARTBEAT exchanges instead). If these fields are present in a connection with protocolVersion: 3 the validator will reject the config.
Remove them from the affected connection:
{
"name": "my-client",
"serverType": "client",
"protocolVersion": 3,
"udpAddress": "...",
"heartbeatInterval": 25000
}The plugin strips these fields automatically on startup, but if you see the error when saving via the SignalK admin UI you need to remove them from the stored config JSON manually once.
For issue-oriented diagnostics, use docs/troubleshooting.md.
Developer commands
npm run build
npm run dev
npm test
npm run test:v2
npm run test:integration
npm run lint
npm run lint:fix
npm run cli -- help
npm run cli -- instances list --token=$EDGE_LINK_TOKEN --state=running --limit=10 --page=1 --format=table
npm run cli -- instances show alpha --token=$EDGE_LINK_TOKEN --format=table
npm run cli -- instances create --config ./new-instance.json --token=$EDGE_LINK_TOKEN
npm run cli -- instances update alpha --patch '{"udpAddress":"10.0.0.2"}' --token=$EDGE_LINK_TOKEN
npm run cli -- instances delete alpha --token=$EDGE_LINK_TOKEN
npm run cli -- bonding status --token=$EDGE_LINK_TOKEN --format=table
npm run cli -- bonding update --patch '{"failoverThreshold":300}' --token=$EDGE_LINK_TOKEN
npm run cli -- status --token=$EDGE_LINK_TOKEN --format=tableManagement API security
Set managementApiToken in plugin options (or the environment variable SIGNALK_EDGE_LINK_MANAGEMENT_TOKEN). Protected routes include:
/instances,/bonding,/status,/plugin-config/config/*,/connections/:id/config/*/connections/:id/metrics,/connections/:id/network-metrics/connections/:id/bonding,/connections/:id/congestion/connections/:id/monitoring/*,/monitoring/alerts/capture/*,/delta-timer
Send the token as either:
X-Edge-Link-Token: <token>Authorization: Bearer <token>
CLI commands support --token=<token> or the SIGNALK_EDGE_LINK_MANAGEMENT_TOKEN environment variable.
Web UI token injection
Management pages automatically attach auth headers when a token is available. Token sources are checked in this order:
window.__EDGE_LINK_AUTH__.token— injected global (preferred for server-side injection)- URL query parameter
?edgeLinkToken=<token>— disabled by default; opt in withincludeTokenInQuery: true. Avoid it: tokens in URLs leak via browser history, server access logs, andRefererheaders. localStorage.setItem("signalkEdgeLinkManagementToken", "<token>")
The UI sends both X-Edge-Link-Token and Authorization: Bearer <token> by default. Override with:
window.__EDGE_LINK_AUTH__ = {
token: "<token>",
queryParam: "edgeLinkToken",
localStorageKey: "signalkEdgeLinkManagementToken",
headerMode: "both" // "both" | "authorization" | "x-edge-link-token"
};Documentation map
docs/README.md(documentation index)docs/architecture-overview.md(system architecture and lifecycle)docs/configuration-reference.md(settings and defaults)docs/api-reference.mddocs/protocol-v3.md(Basic/Advanced protocol operational overview)docs/protocol-v3-spec.md(RFC-style wire specification with authenticated control plane)docs/bonding.md(bonding concepts and API usage)docs/congestion-control.md(congestion-control behavior and tuning)docs/metrics.md(metrics and monitoring reference)docs/management-tools.md(instance/bonding API + CLI operations)docs/security.md(security guidance and deployment hardening)docs/performance-tuning.md(deployment tuning recommendations by hardware profile)docs/troubleshooting.md(issue-oriented diagnostics)samples/(example JSON configurations for minimal/dev/bonding setups)src/scripts/migrate-config.ts(legacy config migration utility)src/bin/edge-link-cli.ts(CLI wrapper for migration and instance/bonding management)
License
MIT. See LICENSE.
