Catalog

Services and how they attach

Each appliance is independently useful. The lab’s job is to wire them, publish them, and tell a client how to reach them. Default-profile dests 10053, 3389/3636, 1025, and 20490 are residual (policy is IANA 53, 389/636, 25, 2049, HTTPS 443 for LabSSO). TacLab is already native. LabSSO is dest-443. LabMITM is a forward proxy, not dest 443.

LabDNS

v1.4.1

Authoritative lab DNS with overrides, wildcards, suffix forwarding, bounded chaos, and an operator console. Over-length names answer on management resolve/explain only; do not add them to lab.test..

Connect. dig @<lab-host> -p 10053 ns1.lab.test (residual dest; native policy is 53) — console at :18080/, REST at :18080/v1, MCP at :18080/mcp.

Configure. profiles/<name>/labdns/bootstrap.yaml. Mutations via MCP are ephemeral; dns_state_reset restores the file. Reload: make reload APP=labdns. Remote console Origins go in spec.management.allowedOrigins.

Auth. Bearer in secrets/labdns-token for the management plane. Data plane is plain DNS.

10053 residual · 18080go-lab-dns

LabLDAP

v0.7.0

Native Go directory (labldapd) plus a control plane. Native is the default engine.

Connect. ldaps://<lab-host>:3636 (residual; native dests are 389/636; SAN directory plus LAB_PUBLIC_HOST as DNS or IP) or LDAP + StartTLS. UI at https://<lab-host>:8443/.

Configure. profiles/<name>/labldap/scenario.yaml. Native engine, lab CA, mutation and password MCP tools enabled. Reload: make reload APP=labldap (re-seeds ephemeral /data).

Auth. Control plane: token-admin. Bind as uid=alice,ou=people,dc=example,dc=test.

3389 / 3636 residual · 8443go-lab-ldap-mcp

TacLab

v1.6.0

TACACS+ (legacy + TLS 1.3) and RADIUS.

Connect. TACACS+ :49 / TLS :300. RADIUS udp :1812/:1813. Control http://<lab-host>:18049/.

Configure. Generated by labgen (YAML and PKI). Profile owns TACLAB_* ports. In LAB_DEV_MODE=true, mcplab secrets pins lab-user passwords and AAA shared secrets from dev-credentials.yaml. Reload: make reload APP=labtacacs.

Auth. Control bearer from api_admin_token. RADIUS shared secret for lab_switches. PASSWORDS.txt for lab users.

49 / 300 · 1812 / 1813 · 18049go-lab-tacacs-mcp

LabMail

v1.0.0-rc.4

Receive-only SMTP sink. Compose service name stays maildev. Relay keys are rejected fail-closed.

Connect. SMTP <lab-host>:1025 (residual; native dest is 25). UI / /email / /v1 / MCP at <lab-host>:1080.

Configure. profiles/<name>/labmail/bootstrap.yaml. Default originAllowlist: ["*"] so remote inbox JS loads. Reload: make reload APP=maildev (wipes the inbox).

Auth. Web Basic user admin (frozen). Password and MCP bearer minted by mcplab secrets (maildev-web-password, labmail-token, both 0o644).

1025 residual · 1080go-lab-maildev

LabMITM

v1.7.2

Laboratory HTTP(S) intercepting forward proxy. Data plane is unauthenticated; HTTPS intercept is :443 only (CONNECT to LabLDAP/TacLab TLS is tunnel-not-decrypt). Native /v1 catalog 31 (includes features.get); GET /v1/features is the 11-row hop/accept catalog. SOCKS / inspectFrames / httpAuth are present in the overlay and stay off.

Connect. HTTP proxy <lab-host>:18888 (forward proxy — SUT sets HTTP_PROXY; not dest 443). Inspector / /v1 / MCP at <lab-host>:18088.

Configure. profiles/<name>/labmitm/bootstrap.yaml. Exact Origins (no "*"). Reload: make reload APP=labmitm (wipes captured flows; generate-mode CA rotates; does not re-register).

Auth. Management bearer in secrets/labmitm-token (0o644). Proxy data plane has no Proxy-Authorization (HTTP 407 is opt-in YAML, off here).

18888 · 18088go-lab-mitmproxy

LabNTP

v1.0.0-rc.3

Laboratory NTPv3/v4 unicast with per-IP virtual clocks. Data plane is plain NTP (no MAC in this profile). First-match CIDR filters. Host-published UDP is SNAT'd (NAT collision); compose-network + ntp_views_preview stay reliable. No Go userland-proxy probe.

Connect. NTP UDP <lab-host>:10123 (ADR 0014 default; privileged 123 is opt-in). Operator console / /v1 / MCP at <lab-host>:18123.

Configure. profiles/<name>/labntp/bootstrap.yaml. allowedOrigins deny-all (no "*"). Reload: make reload APP=labntp (does not re-register).

Auth. Management bearer in secrets/labntp-token (0o644). NTP data plane has no secret.

10123 · 18123go-lab-ntp

LabSSO

v1.0.0-rc.4

Laboratory OIDC/OAuth2 and SAML IdP (generic clothes). Dedicated CA under secrets/labsso-tls/. SAML-on requires the RSA signing key. Loopback management is unauthenticated admin; remote peers need the bearer. No allowedOrigins yet. No labgraph fan-out.

Connect. HTTPS dest-443 issuer https://<lab-host> (no :443 in catalog URLs). Operator console / /v1 / MCP at <lab-host>:18443.

Configure. profiles/<name>/labsso/bootstrap.yaml. Issuer must match the derived issuer. Reload: make reload APP=labsso (does not re-register).

Auth. Management bearer in secrets/labsso-token (0o644). Alice password in secrets/labsso-users/alice.password. Trust secrets/labsso-tls/ca.crt.

443 · 18443go-lab-sso

ratarmount-rs

v0.1.34

Writable archive-backed userspace NFSv3 export (empty-root .tar.zst, 15m overlay commit). Remount after commit does not reindex the whole TAR. NFSv4.1 is in the package, this lab stays on v3.

Connect. mount -t nfs -o vers=3,tcp,nolock,port=20490,mountport=20490 <lab-host>:/ /mnt (residual; native dest is 2049).

Configure. NFS_ARCHIVE_DIR and NFS_DATA_DIR in profile.env. Reload: make reload APP=nfs.

Auth. AUTH_SYS. No credential.

20490 residualratarmount-rs

labgraph

First-party LabScenario orchestrator. Applies profile YAML across appliances via native plan/apply/reset. Named packs: broken-bind, expired-cert, split-horizon-dns, mitm-intercept-extra-port (labgraph://fixtures/{id}, fixture.apply). Empty default scenario is a no-op. LabLDAP control-plane disableUser is allowed; any labldap key besides operations/reason/expectedRevision and TacLab apply fail closed.

Connect. Operator console / REST / MCP at <lab-host>:18091.

Configure. profiles/<name>/labgraph/bootstrap.yaml and scenarios/*.yaml. Reload: make reload APP=labgraph (drops the journal).

Auth. Bearer in secrets/labgraph-token (0o644). SPA uses cookie + CSRF after POST /v1/session.

labinfo + MCPJungle

Service directory MCP plus the single client gateway. MCPJungle pinned 0.4.6. Operator dashboard is GET / in development mode only (enterprise 404s).

Connect. Gateway http://<lab-host>:8080/mcp or /v0/groups/integration/mcp. labinfo at :18090.

Configure. labinfo/services.yaml and mcpjungle/servers/*.json. Catalog reload: make reload APP=labinfo. Gateway JSON: make register. Gateway container: make reload APP=mcpjungle (re-registers).

Auth. Enterprise (default): secrets/mcp-client-token. Development: open. labinfo /mcp always requires a non-empty bearer; secrets only in dev mode.

8080 · 18090mcpjungle/MCPJungle