web {} block
Generated Markdown for references/entity_web_block.md.
Open book page Back to the skill graph
# web {} block
_wcl block_
Declares an HTTP UI served inside a guest, proxied into the web console as a sandboxed iframe tab — with the guest app's own login handled by the proxy.
A `web {}` block on a `vm {}` or `container {}` (which must have at least one
NIC) publishes a guest-served HTTP UI to the [web console](../references/concept_web_console.md):
the page appears as a launch card on the lab overview, opens as an in-app tab,
and all open pages aggregate under the sidebar's **Web** entry. The proxy
reaches the guest through a loopback host→guest forward, strips frame-blocking
headers, and rewrites HTML/CSS URLs and redirects so everything stays under
`/web/{lab}/{kind}/{machine}/{page}/…`.
```wcl
vm "nas" {
template = "x86_64/linux-modern"
nic { segment = "corp" }
web "admin" { port = 8080 path = "/manage" } // http://<guest>:8080/manage
}
container "grafana" {
image = "grafana/grafana:11.2.0"
profile = "container"
memory = 512MiB
nic { segment = "corp" }
web "dash" {
port = 3000
auth { method = :form username = "admin" password = "admin"
login_path = "/login" login_body = "{\"user\":\"{user}\",\"password\":\"{pass}\"}"
login_content_type = "application/json" }
}
}
```
The optional `auth {}` child holds credentials the proxy injects so the guest
app's own login never prompts: `:basic`, `:bearer` (`token`), `:header`
(`header` + `value`), `:ntlm` (IIS/AD integrated; optional `domain`), or
`:form` (a login request from `login_path`/`login_body` with `{user}`/`{pass}`
substituted; captured cookies are replayed, and `fail_redirect` marks a
redirect target that means "not logged in"). Credentials are plaintext in the
lab config, like everything else there.
Console access to `/web/*` is guarded separately by a path-scoped cookie the
UI mints per session — see the [API reference](../references/fact_web_api.md).
Guest pages are **sandboxed away from the console origin**: the iframe carries
`sandbox="allow-scripts allow-forms allow-popups allow-downloads"` with no
`allow-same-origin`, and the proxy sends its own
`Content-Security-Policy: frame-ancestors 'self'; sandbox …`. A hostile guest
page therefore cannot reach the console's session. The cost is real and
visible: because the page runs in an opaque origin, guest script gets no
`document.cookie` and no `localStorage`, so apps that need either will
misbehave in the tab (open them directly through the forward instead).
Deliberately out of scope in v1: WebSockets/SSE and SPAs that build absolute
URLs in JS; the proxy suits admin-style UIs, not bulk downloads.
## Related
- [vm {} block](../references/entity_vms.md)
- [container {} block](../references/entity_container_block.md)
- [The web console](../references/concept_web_console.md)
- [vmlab-web](../references/entity_vmlab_web.md)
- [The vmlab.wcl schema](../references/fact_schema_reference.md)
[← Back to SKILL.md](../SKILL.md)