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.
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.
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.
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.
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).
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).
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.
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.
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.
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.
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.