Contributing a new lab¶
Two contribution paths share the same SSH gateway VM and upstream Ansible per-lab coordinator setup, but differ in what the lab must support and which runners execute CI. This page summarizes both so a new contributor picks the minimum setup for the target workflow.
1. Shared foundation¶
Every contributed lab uses:
- A local labgrid-coordinator on each lab host (loopback :20408), deployed by the upstream Ansible playbook. The SSH gateway VM (
global-coordinatorhostname) provides SSH jump access for CI runners and developers. - A WireGuard tunnel between the lab host and the SSH gateway VM (for SSH transport).
- A single inventory in openwrt-tests
labnet.yamllisting labs, devices, maintainers, and access lists (SSH keys are fetched from GitHub at deploy time). - The openwrt-tests
playbook_labgrid.ymlapplied to the lab host: userlabgrid-dev, gateway SSH key inauthorized_keys,labgrid-coordinator,labgrid-exporter,labgrid-switch-abstractionvia pipx, TFTP, PDUDaemon, netplan, dnsmasq.
The infrastructure is the same; what changes between paths is which CI runner executes tests and which suite expects which resources.
flowchart LR
subgraph shared [Shared upstream]
sshgw[SSH gateway VM]
labnet[labnet.yaml<br/>aparcar/openwrt-tests]
end
subgraph labHost [Lab host]
coord[labgrid-coordinator<br/>loopback :20408]
exporter[labgrid-exporter]
switchVlan[switch-vlan CLI<br/>optional]
duts[DUTs]
end
subgraph scenarioA [A base openwrt-tests]
runnerA[GitHub-hosted runners<br/>ubuntu-latest]
suiteA[openwrt-tests suite]
end
subgraph scenarioB [B libremesh mesh]
runnerB[self-hosted runner<br/>testbed-fcefyn or yours]
suiteB[libremesh-tests suite]
end
exporter -->|gRPC loopback| coord
runnerA -->|"LG_PROXY (via SSH gateway)"| exporter
runnerB -->|LG_PROXY| exporter
suiteA --> runnerA
suiteB --> runnerB
runnerA -.->|reads| labnet
runnerB -.->|reads| labnet
switchVlan --> duts
exporter --> duts
2. Scenario A: base openwrt-tests lab¶
Goal: contribute DUTs so upstream aparcar/openwrt-tests CI can flash OpenWrt and run vanilla healthchecks on them. Single-node tests. Managed switch and VLAN switching are optional: if the lab has no managed switch, everything still works on a static topology.
Audience: lab owners who want upstream openwrt-tests coverage on their hardware.
Runners: GitHub-hosted runners (ubuntu-latest) that reach the lab via the SSH gateway VM. No self-hosted runner required.
Steps:
- Follow openwrt-tests onboarding: WireGuard, GitHub usernames in
access:, PR againstaparcar/openwrt-testswithlabnet.yamlentry,ansible/files/exporter/<lab>/*, lab doc. - Apply
playbook_labgrid.ymlon the lab host (gateway SSH key, coordinator, exporter, TFTP, PDUDaemon, dnsmasq, netplan). The playbook now also installslabgrid-switch-abstractionvia pipx; labs without a managed switch can ignore the CLI. - Optional: if the lab has a managed switch and wants dynamic VLAN switching in upstream tests, configure
switch.confanddut-config.yamlon the host and opt in per test run withVLAN_SWITCH_ENABLED=1+LG_MULTI_PLACES. See switch-abstraction.md on the PR branch once PR #218 is merged.
Nothing else is required on the lab side. Upstream CI will start scheduling jobs when labnet.yaml lists the lab.
3. Scenario B: libremesh-capable lab¶
Goal: run the libremesh-tests suite (single-node LibreMesh, multi-node mesh, virtual mesh) against DUTs in the lab. Requires a managed switch that can move DUT ports between isolated VLANs and the mesh VLAN (200 by default).
Audience: labs that want their DUTs covered by LibreMesh test matrices.
Runners: a self-hosted GitHub runner under the lab's control (not the aparcar runners). The FCEFyN lab uses testbed-fcefyn; other labs should register their own runner so tests run physically close to the DUTs.
Steps:
- Complete Scenario A (same upstream onboarding; the inventory, exporter, per-lab coordinator,
playbook_labgrid.ymlare shared). - Managed switch must be configured. On the lab host:
- Credentials in
/etc/switch.conf(system-wide, group-readable so any SSH user can runswitch-vlan; see switch-config.md#multi-user-setup). - DUT-to-port map in
/etc/testbed/dut-config.yaml(or setSWITCH_DUT_CONFIG). DUT names in that file must match the suffix of labgrid place names (see place-to-DUT mapping below). - Confirm
switch-vlan --helpworks as the SSH user. - Register a self-hosted GitHub Actions runner on the lab host (or on another machine with lab access) and label it for the lime-packages CI workflow. The runner should expose the labels
[self-hosted, testbed-fcefyn](or your lab equivalent) — these match theruns-on:ofpi-lime-packages/.github/workflows/build-firmware.yml. See CI runner config for details. - The active CI orchestrator is
pi-lime-packages/.github/workflows/build-firmware.yml. Each lab declares its hardware inpi-lime-packages/.github/ci/targets.yml(per-targettest_places:/test_firmware:/image_format:keys). The legacylibremesh-testsdaily/pull_requests workflows were retired in May 2026; only the lint workflowformal.ymlremains in that repo. - Local development against the lab:
LG_PROXY=labgrid-<lab>,LG_MESH_PLACES=labgrid-<lab>-<dut1>,labgrid-<lab>-<dut2>,PLACE_PREFIX=labgrid-<lab>-(or leave empty for the second-hyphen fallback). See libremesh-tests CONTRIBUTING_LAB.md.
Place-to-DUT mapping¶
Both suites derive DUT names from labgrid place names by stripping a prefix. Defaults differ:
| Suite | Default | Override |
|---|---|---|
| openwrt-tests (PR #218) | up to the second hyphen | PLACE_PREFIX |
| libremesh-tests | labgrid-fcefyn- |
PLACE_PREFIX |
Set PLACE_PREFIX=labgrid-mylab- when contributing a lab named mylab; PLACE_PREFIX="" disables the default and reverts to the second-hyphen strip.
4. Decision matrix¶
| Requirement | Scenario A | Scenario B |
|---|---|---|
| WireGuard tunnel to SSH gateway VM | required | required |
labnet.yaml entry in openwrt-tests |
required | required |
playbook_labgrid.yml applied |
required | required |
| Self-hosted GitHub runner | not needed | required |
| Managed switch | optional | required |
switch.conf and dut-config.yaml on lab host |
optional | required |
| Target YAML in libremesh-tests | no | per board that runs LibreMesh |
| Test suite | openwrt-tests | libremesh-tests (+ optional openwrt-tests) |
A lab can contribute to both paths at once: the infrastructure is shared. Scenario A is a prerequisite for Scenario B.
5. Related pages¶
- openwrt-tests onboarding - full walkthrough of Scenario A (WireGuard, SSH, Ansible, sequence diagram).
- Ansible and Labgrid - what upstream vs FCEFyN playbooks deploy.
- Switch - VLAN layout,
switch.confmulti-user setup,switch-vlaninvocation. - Lab architecture - per-lab coordinator, VLAN scheduling, locking.
- CI runner - self-hosted runner setup (Scenario B).