Nabto Edge TCP Tunnelling Quick Start

This quick start guide will show you how to setup the ready-made Nabto client and device tunnel endpoints to enable TCP remote access to your existing TCP services.

Nabto Cloud Configuration

To use Nabto Edge, you must first create a free account through the Nabto Cloud Console if not done already.

Once you have created an account, create a new Nabto Edge App.

After creating the app, click “edit” and change the “App authentication type” to SCT in the first drop down box (per default an empty grey button with an arrow down). “SCT” means “Server Connect Token” - consider it a self-contained, light weight alternative to the common JWT approach. The applications we will use in this quick start guide are configured to use SCT, hence this step is necessary.

Navigate to the Products page create a new Nabto Edge product.

Under this product under “settings”, add the app previously created from the “apps” tab.

In the “details” tab in the “Client Configuration” section, pick the app added to the product, and press “Generate Configuration”. Note the JSON string shown.

In the “Configured Devices” tab, create a new device. From the device page, note the device configuration JSON string.

You are now ready to start building the Embedded tunnel device application.

Embedded tunnel application

The embedded tunnel application is available as part of the Nabto Edge Embedded SDK. To build the embedded tunnel application, follow the building guide for the general SDK build.

After building, create a config subdirectory in the Nabto Edge home directory. On macOS and Linux, the default home directory is ~/.nabto/edge:

$ mkdir -p ~/.nabto/edge/config

On Windows, it is %APPDATA%\nabto\edge:

c:\$ mkdir %APPDATA%\nabto\edge\config

The default home directory location can be overridden with the tunnel binary’s -H parameter.

In the created config directory, create a file named device.json with the JSON string you noted down from the console device page in the previous step. The file should look like this:

  "ProductId": "pr-aaaaaaaa",
  "DeviceId": "de-bbbbbbbb",
  "Server": "",

The ProductId, DeviceId, and Server fields are used by the device to register with the Nabto Edge Cloud for remote access. The optional Server field can be used to override which Nabto Edge server the device tries to register at.

With the configuration in place, you can now start the device and do the final configuration step (note: on Windows, you may see a firewall popup - if so, you need to allow the tunnel application to listen for incoming connections):

$ ./tcp_tunnel_device
######## Nabto TCP Tunnel Device ########
# Product ID:        pr-aaaaaaaa
# Device ID:         de-bbbbbbbb
# Fingerprint:       b2834abe18f53dd64e009efaffc4294e2a9b59cba17f0e943ca0c0fefda8a1c0
# Pairing password:  uTLdUIAXv3MNgn2wymrN
# Paring SCT:        vrFtMptbLNrqYcpfXhoi
# Version:           5.1.0
# Pairing URL:
######## Configured TCP Services ########
# Id               Type             Host             Port
# ssh              ssh            22
_attacher_attach_start.c:89   ERROR - The server does not recognize the fingerprint of the device. Check that the fingerprint is in sync with the server

As you can see in the last line, we need to register the device’s public key fingerprint with the Nabto Edge Cloud services: Go to the device configuration page in the Nabto Cloud console (first click product, then click the device in question). Then enter the fingerprint from the command line output - the key to look for in the output is Fingerprint, in the example the value is b2834abe18f53dd64e009efaffc4294e2a9b59cba17f0e943ca0c0fefda8a1c0 - copy this value from your own tunnel output to the device fingerprint config on the Nabto Cloud console and save.

Shortly after the fingerprint is saved, the device comes online:

$ ./tcp_tunnel_device
######## Nabto TCP Tunnel Device ########
_attacher_attach_start.c:89   ERROR - The server does not recognize the fingerprint of the device. Check that the fingerprint is in sync with the server
_attacher_attach_start.c:89   ERROR - The server does not recognize the fingerprint of the device. Check that the fingerprint is in sync with the server
_attacher_attach_start.c:89   ERROR - The server does not recognize the fingerprint of the device. Check that the fingerprint is in sync with the server
Attached to the basestation

Client tunnel application

Download Nabto Edge TCP tunnel client from the pre-release artifacts repo at github.

On Linux and macOS, apply execute permission:

chmod a+x tcp_tunnel_client

To configure the client, create the a filed named client.json besides the downloaded executable with the client configuration JSON string you noted down in a previous step. By default, the TCP tunnel client will look for the client.json file in the same directory as the executable, however, the file can be overridden with the -c parameter. The file content should look similar to this:

  "ServerUrl": "",
  "ServerKey": "sk-64fc4987bc60d6c3fae53348b7da33c1"

Like with the device configuration, the ServerUrl is optional, and the ServerKey is used when making remote connections through the Nabto Edge Cloud.

The client must now be paired with the embedded device to be able to connect and establish a tunnel. If client and device are located on the same subnet, local discovery through mDNS (BonJour) can be attempted - if it fails, it is likely because the two peers are not on the same subnet, so just attempt non-local pairing as described below.

Local pairing

To start local pairing, just run the client with the --pair option:

$ ./tcp_tunnel_client --pair
Scanning for local devices for 2 seconds.
Found 1 local devices.
Choose a device for pairing:
[q]: Quit without pairing
[0] ProductId: pr-aaaaaaaa DeviceId: de-bbbbbbbb

If the discovered ids match your device, press 0 and enter:

Connected to device ProductId: pr-aaaaaaaa DeviceId: de-bbbbbbbb
Is this the correct fingerprint of the device b2834abe18f53dd64e009efaffc4294e2a9b59cba17f0e943ca0c0fefda8a1c0 [yn]

If the fingerprint matches your device fingerprint, press y and enter:

Connected to the device
Choose a pairing method
[0] Password
[1] Local

press 1 and enter to make local pairing.

Paired with the device, writing configuration to the configuration file

Picking “Password” as pairing method will make the client ask for the password printet by the device, before pairing succeeds. More information about the pairing methods can be found in the “Pairing guide”.

Non-local pairing

For non-local pairing, the pairing URL output by the device can be used. In the above example, this URL is

You then simply enter this URL as a parameter to the tunnel client - remember the quotes as the ampersands (&) likely confuse your shell:

$ ./tcp_tunnel_client --pair-url ''
Connected to device ProductId: pr-aaaaaaaa DeviceId: de-bbbbbbbb
Paired with the device and wrote config to file tcp_tunnel_client.json

This pairing works equally well locally and remote.

Using the tunnel

Now you can list the available services as provided by the device:

$ ./tcp_tunnel_client  --list-services
Service: ssh, Type: ssh, Host:, Port: 22

Per default, the tunnel supports just the ssh service, see below on how to add another service. You can then start the service as follows:

$ ./tcp_tunnel_client --service ssh
Opened a TCP Tunnel to the service ssh Listening on the local port 52530

Now you can connect an ssh client to localhost port 52530 to access the ssh service running on the same host as the embedded device application.

Access your remote service

The available services to be tunnelled by the device are defined in the configuration file ~/.nabto/edge/config/tcp_tunnel_services.json. To add e.g. a tunnel for an http server running on port 8081, add an entry to this file (note the JSON array syntax):

$ ./tcp_tunnel_client  --list-services
Service: nginx, Type: http, Host:, Port: 8081
Service: ssh, Type: ssh, Host:, Port: 22

So now you can start an http tunnel:

$ ./tcp_tunnel_client  --service nginx
Opened a TCP Tunnel to the service nginx Listening on the local port 52716

And then in another terminal, you can access the TCP service:

$ curl localhost:52716
     <h1>Hello, world!</h1>