How to use multiple workshops in a project¶
Workshops← Multi-workshop patterns|Status diagrams →
A project may require different toolchains for different components,
such as a Go backend and a Node.js frontend.
Instead of putting everything into a single workshop definition,
you can define multiple workshops in the same project directory.
Each workshop is an independent environment
with its own base image, SDKs, and actions;
at the same time, the workshops share a single project directory
mounted at /project/.
Set up definitions¶
When a project uses multiple workshops,
store their definitions in the .workshop/ subdirectory
instead of a single workshop.yaml in the project root.
Each file must be named after its workshop,
so the name field matches the file name
(without the .yaml extension).
Here is a project layout with two workshop definitions and a shared in-project SDK:
my-project/
├── .workshop/
│ ├── frontend.yaml
│ ├── backend.yaml
│ └── common-tools/
│ └── sdk.yaml
├── web/
└── api/
The frontend workshop uses the node SDK
for the browser-facing part of the project:
name: frontend
base: ubuntu@24.04
sdks:
- name: node
channel: 24
actions:
build: |
npm run build
The backend workshop uses the go SDK
for the server-side code:
name: backend
base: ubuntu@22.04
sdks:
- name: go
channel: 1.26
actions:
test: |
go test ./...
Each workshop can use a different base image, a different set of SDKs, and its own actions, all while sharing the project directory.
What’s more, you can share in-project SDKs across workshops, as described in a section below.
Note
You cannot mix a root-level workshop.yaml
with files in .workshop/.
If Workshop finds both,
it reports an error.
Launch and manage workshops¶
Launch both workshops at once:
$ workshop launch frontend backend
When a project has multiple workshops, the workshop name is required in every command; you cannot omit it as you would with a single-workshop project.
Check the status of both workshops:
$ workshop list
WORKSHOP STATUS NOTES
frontend Ready -
backend Ready -
Run an action in a specific workshop:
$ workshop run frontend -- build
$ workshop run backend -- test
Shell into one of the workshops:
$ workshop shell backend
Execute a one-off command:
$ workshop exec frontend -- node --version
Stop and start workshops independently:
$ workshop stop frontend
$ workshop start frontend
Or stop both at once:
$ workshop stop frontend backend
To see the status of workshops in the current project, use the workshop list command without arguments:
$ workshop list
WORKSHOP STATUS NOTES
frontend Ready -
backend Ready -
To see the status of workshops across all projects on the system,
use the --global flag:
$ workshop list --global
PROJECT WORKSHOP STATUS NOTES
/home/user/my-project frontend Ready -
/home/user/my-project backend Ready -
/home/user/other-project dev Ready -
When you no longer need the workshops, remove them:
$ workshop remove frontend backend
Cross-workshop networking¶
Workshops in the same project can reach each other directly by hostname.
For instance, given a running backend workshop,
the frontend counterpart can reach it by the short form backend.
If backend exposes an API on port 8080,
reach it directly from frontend:
$ workshop exec frontend -- curl http://backend:8080
Note
Direct access works only if the service listens on all interfaces
(for example, 0.0.0.0:8080) rather than only on loopback.
Any device that can reach the workshopbr0 bridge
can resolve the workshop’s *.wp hostname through it and connect too,
so restrict such a service with a firewall if it isn’t meant to be shared.
From outside the project,
use the full hostname shown by workshop info backend
(usually backend.<PROJECT>.wp, otherwise backend.<PROJECT-ID>.wp).
For SSH-based tools,
Workshop also generates an OpenSSH configuration on the host
that trusts workshop host keys signed by its per-user authority
and authorizes your user to connect,
so tools such as ssh and VS Code Remote-SSH
reach a workshop by its hostname
without a host-key or password prompt.
See How to connect your local VS Code to a workshop for a worked example.
Use hostname-based access for anything TCP or HTTP between workshops in the same project; it needs no setup. Use the tunnel interface instead to expose a service to the host itself, to reach a workshop in a different project, or when you need workshop connect-level control over who can reach the port.
You cannot connect a plug in one workshop to a slot in another; workshop connect rejects such attempts. However, all workshops on the same machine share a common host, and the tunnel interface can bridge through it.
The idea is to compose two independent tunnels: one that exposes a service from the backend workshop to the host, and another that lets the frontend workshop reach that host port. This is different from a regular intraworkshop connection, where a single tunnel links a plug to a slot inside the same workshop. Here, the host sits in the middle, and each workshop configures its own half of the bridge.
The backend workshop exposes its API on the host
by pairing a system plug with a regular SDK slot:
name: backend
base: ubuntu@22.04
sdks:
- name: go
channel: 1.26
slots:
api:
interface: tunnel
endpoint: localhost:8080 # service inside the workshop
- name: system
plugs:
api:
interface: tunnel
endpoint: localhost:8080 # port on the host
The frontend workshop reaches the host port
by pairing a regular SDK plug with a system slot:
name: frontend
base: ubuntu@24.04
sdks:
- name: node
channel: 24
plugs:
api:
interface: tunnel
endpoint: localhost:8080 # where the client connects
- name: system
slots:
api:
interface: tunnel
endpoint: localhost:8080 # host-side port (bridged from backend)
Launch both workshops.
The backend tunnel auto-connects
because its plug is on the system SDK with a matching name,
but the frontend tunnel requires a manual step:
$ workshop launch frontend backend
$ workshop connect frontend/node:api
Verify the connection:
$ workshop connections frontend
INTERFACE PLUG SLOT NOTES
tunnel frontend/node:api frontend/system:api manual
After this, any service listening on port 8080 inside the backend workshop
is reachable at localhost:8080 from within the frontend workshop.
Note
The host port must be free before launching the backend workshop, or the tunnel will fail to activate. If you need several cross-workshop tunnels, use a different port for each. See How to forward ports with tunneling for tunnel basics and troubleshooting.
See also¶
Explanation:
How-to guides:
Reference: