<a id="exp-tunnel-interface"></a>

# Tunnel interface

<!-- @artefact tunnel interface -->

The tunnel interface
enables workshops to share network services with the host system,
and vice versa.
It supports connections over TCP, UDP, and Unix domain sockets.

SDKs advertise their services using tunnel interface slots.
For example, if an SDK installs and advertises a web app,
users can access the app from their usual browser
after creating a tunnel from the host system to the workshop.

SDKs request access to services using tunnel interface plugs.
Some services have dedicated interfaces
(e.g., the [SSH interface](https://ubuntu.com/workshop/docs//explanation/interfaces/ssh-interface.md#exp-ssh-interface)),
which should be used instead.

<a id="exp-tunnel-plug"></a>

## Tunnel interface plug

Most SDKs declare tunnel interface plugs in their SDK definitions,
but the [system SDK](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-system-sdk) has none by default,
so system SDK plugs must be declared in the workshop definition.

A basic structure would include the name of the plug,
the interface (`tunnel`),
and, optionally, an address (`endpoint`).

Plugs designate addresses that clients can connect to.
Regular SDKs are used for clients inside the workshop.
The system SDK is used for clients from the host system.

<a id="exp-tunnel-slot"></a>

## Tunnel interface slot

Most SDKs declare tunnel interface slots in their SDK definitions,
but the [system SDK](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-system-sdk) has none by default,
so system SDK slots must be declared in the workshop definition.

A basic structure would include the name of the slot,
the interface (`tunnel`),
and, optionally, an address (`endpoint`).

Slots designate an address that a service can listen on.
Regular SDKs should make this service available inside the workshop.
The system SDK relies on the user to run this service on the host.

<a id="exp-tunnel-connection"></a>

## Connection

The interface is connected automatically at launch or refresh,
provided that:

- The plug is declared in the system SDK
- The slot is declared in a regular SDK
- The plug listens on `localhost` or a Unix domain socket
- The plug can be matched to the slot by its name,
  or via a `connections` entry in the [definition](https://ubuntu.com/workshop/docs//explanation/workshops/concepts.md#exp-workshop-definition),
  both subject to **Workshop**’s
  [validation rules](https://ubuntu.com/workshop/docs//explanation/interfaces/concepts.md#exp-interfaces-validation).

Otherwise, it isn’t connected automatically,
for security reasons.
The **workshop connect** and **workshop disconnect** commands
can be invoked after the workshop has started:

<!-- @artefact workshop connect -->
<!-- @artefact workshop disconnect -->
```console
$ workshop connect ws/client-sdk:shared
$ workshop disconnect ws/client-sdk:shared
$ workshop connect ws/system:app ws/service-sdk:app
$ workshop disconnect ws/service-sdk:app
```

Establishing a tunnel connection means
that **Workshop** will listen on the plug address,
forwarding incoming network connections to the slot address.

When a system SDK plug is connected to a regular SDK slot,
clients on the host can access services inside the workshop:

When a regular SDK plug is connected to a system SDK slot,
clients in the workshop can access services on the host:

**Workshop** doesn’t support connections within the system SDK
or between regular SDKs.
In these cases clients can connect to services directly,
without the need for a tunnel.

To check if a plug or slot is connected:

<!-- @artefact workshop connections -->
```console
$ workshop connections --all

  INTERFACE  PLUG                  SLOT                NOTES
  ...
  tunnel     ws/client-sdk:shared  ws/system:shared    manual
  tunnel     ws/system:app         ws/service-sdk:app  manual
```

This means that `client-sdk` can access
the `shared` service running on the host,
and the host can access the `app` service
provided by `service-sdk`.

<!-- @artefact workshop info -->
```console
$ workshop info dev

  name:     dev
  base:     ubuntu@22.04
  project:  /home/user/workshop/dev
  status:   ready
  notes:    -
  sdks:
    system:
      tunnels:
        app:
          from:  0.0.0.0:8081/tcp
          to:    127.0.0.1:8080/tcp
    client-sdk:
      tracking:   latest/stable
      installed:  2024-03-02  (1)
      tunnels:
        shared:
          from:  [::1]:1080/tcp
          to:    127.0.0.1:18080/tcp
    service-sdk:
      tracking:   latest/edge
      installed:  2025-06-07  (2)
```

## See also

Explanation:

- [Interface concepts](https://ubuntu.com/workshop/docs//explanation/interfaces/concepts.md#exp-interface-concepts)
- [Plugs and slots](https://ubuntu.com/workshop/docs//explanation/interfaces/concepts.md#exp-plugs-slots)
- [SDK definition](https://ubuntu.com/workshop/docs//explanation/sdks/concepts.md#exp-sdk-definition)
- [Workshop definition](https://ubuntu.com/workshop/docs//explanation/workshops/concepts.md#exp-workshop-definition)

Reference:

- [Tunnel interface](https://ubuntu.com/workshop/docs//reference/sdks.md#ref-tunnel-interface)
- [workshop connect](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-connect)
- [workshop connections](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-connections)
- [workshop disconnect](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-disconnect)
- [workshop info](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-info)
- [workshop launch](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-launch)
- [workshop refresh](https://ubuntu.com/workshop/docs//reference/cli/workshop.md#ref-workshop-refresh)
