VM Role Reference
vm_workload_showroom turns a RHEL/Fedora host (bastion, lab VM, etc.) into a Showroom instance using rootless Podman.
What It Does
-
System preparation — installs OS and Python dependencies, allows unprivileged ports for rootless containers.
-
User and SSH setup — creates a dedicated
showroomuser (UID 1888), enables rootless Podman via systemd, configures SSH access for lab users. -
Content pipeline — clones your Antora/AsciiDoc content repo, optionally injects
user_dataas Antora attributes, renders HTML via an Antora container. -
Service orchestration — generates a Podman Compose file for Traefik + Showroom + optional tab services, installs a
showroom.servicesystemd unit. -
TLS and verification — obtains and renews certificates via Traefik ACME, verifies TLS with OpenSSL, publishes the final lab URL.
Architecture
┌─────────────────────────────────────────────────────────┐
│ Host System (RHEL/Fedora) │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ Systemd Service (showroom.service) │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Rootless Podman (showroom user) │ │ │
│ │ │ │ │ │
│ │ │ ┌──────────┐ ┌───────────────┐ │ │ │
│ │ │ │ Traefik │──│ Showroom HTTPD │ │ │ │
│ │ │ │ (proxy) │ │ (content) │ │ │ │
│ │ │ └──────────┘ └───────────────┘ │ │ │
│ │ │ │ │ │ │
│ │ │ Optional tab services: │ │ │
│ │ │ ┌──────────┐ ┌──────────┐ │ │ │
│ │ │ │ Wetty │ │ CodeSrvr │ │ │ │
│ │ │ │(terminal)│ │ Parasol │ │ │ │
│ │ │ └──────────┘ └──────────┘ │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ /opt/showroom/content cloned git repo │
│ /opt/showroom/build rendered HTML │
│ /opt/showroom/orchestration compose + acme.json │
└─────────────────────────────────────────────────────────┘
Core Variables
| Variable | Type | Default | Description |
|---|---|---|---|
|
boolean |
|
Guard for the whole role. Set to |
|
string |
(derived from AgnosticD) |
Public hostname for the Showroom instance. Used in TLS and user-facing URLs. |
|
string |
Git repo with Antora/AsciiDoc content. |
|
|
string |
|
Branch, tag, or commit to check out. |
|
string |
|
Antora site file. When set to the default, the role auto-detects between |
TLS and ACME
Traefik handles certificate issuance and renewal automatically.
| Variable | Type | Default | Description |
|---|---|---|---|
|
string |
|
|
|
string |
|
ACME account email (required unless |
|
integer |
|
Host port for HTTP (also used for ZeroSSL HTTP-01 challenge). |
|
integer |
|
Host port for HTTPS. |
ZeroSSL (default)
Uses HTTP-01 challenge. Requires External Account Binding (EAB) credentials:
| Variable | Type | Default | Description |
|---|---|---|---|
|
string |
|
EAB key ID from ZeroSSL. |
|
string |
|
EAB HMAC key from ZeroSSL. |
Tab Services
Tab services add terminals, editors, and other tools alongside the lab content.
They are controlled by showroom_tab_services:
showroom_tab_services:
- single_terminal
- second_terminal
Available Tab Services
| Service | Description |
|---|---|
|
A Wetty web terminal connected to a host via SSH. |
|
A second Wetty terminal, typically connected to a different host. |
|
A VS Code editor (Code Server) running in the browser. |
|
The Parasol service for AI-related labs. |
Terminal SSH Configuration
When using single_terminal:
| Variable | Type | Default | Description |
|---|---|---|---|
|
string |
|
|
|
string |
|
SSH target host. Use |
|
string |
(from user_data) |
SSH username. |
|
string |
(from user_data) |
SSH password (when method is |
|
integer |
|
SSH port. |
When using second_terminal, the same pattern applies with showroom_terminal2_* variables:
showroom_terminal2_ssh_host: worker.example.com
showroom_terminal2_ssh_username: lab-user
showroom_terminal2_ssh_password: "{{ common_password }}"
User, Paths, and Images
| Variable | Type | Default | Description |
|---|---|---|---|
|
string |
|
System user that owns content and runs rootless containers. |
|
string |
|
Base directory for all Showroom files. |
|
string |
|
Git checkout of the content repo. |
|
string |
|
Antora HTML output mounted into the HTTPD container. |
|
string |
|
Generated compose file and |
|
string |
|
Antora builder image. |
|
string |
|
Antora image tag. |
|
string |
|
Traefik reverse proxy image. |
|
string |
|
Showroom HTTPD content server image. |
UI Configuration
| Variable | Type | Default | Description |
|---|---|---|---|
|
string |
|
UI type. |
|
string |
nookbag v0.3.0 ZIP URL |
URL of the zero-touch UI bundle. |
Dev Mode
Dev mode enables diagnostic features in the Antora build, including an Attributes reference page and unlisted pages in the navigation.
| Variable | Type | Default | Description |
|---|---|---|---|
|
boolean |
|
Enable the Antora dev-mode extension. |
showroom_antora_enable_dev_mode: true
Lab User Configuration
| Variable | Type | Default | Description |
|---|---|---|---|
|
list |
|
OS accounts created or adjusted for lab SSH access. |
|
string |
|
SSH authentication method for lab users: |
Examples
Minimal HTTP-only deployment
- hosts: bastion
become: true
roles:
- role: agnosticd.showroom.vm_workload_showroom
vars:
showroom_tls_provider: none
showroom_http_port: 8080
showroom_host: bastion.example.com
showroom_git_repo: https://github.com/myorg/my-lab.git
HTTPS with ZeroSSL
- hosts: bastion
become: true
roles:
- role: agnosticd.showroom.vm_workload_showroom
vars:
showroom_host: lab.example.com
showroom_tls_provider: zerossl
showroom_acme_email: admin@example.com
showroom_acme_zerossl_eab_kid: "{{ lookup('env', 'ZEROSSL_EAB_KID') }}"
showroom_acme_zerossl_eab_hmac_key: "{{ lookup('env', 'ZEROSSL_EAB_HMAC') }}"
showroom_git_repo: https://github.com/myorg/my-lab.git
With terminal and Code Server
showroom_git_repo: https://github.com/myorg/my-lab.git
showroom_git_ref: main
showroom_host: "{{ bastion_public_hostname }}"
showroom_tls_provider: none
showroom_tab_services:
- single_terminal
- codeserver
showroom_ssh_method: password
showroom_ssh_host: host.containers.internal
showroom_ssh_username: lab-user
showroom_ssh_password: "{{ common_password }}"
AgnosticV integration (CNV bastion)
post_software_final_workloads:
bastions:
- agnosticd.showroom.vm_workload_showroom
showroom_git_repo: https://github.com/myorg/my-lab.git
showroom_git_ref: vm-example
showroom_tls_provider: none
showroom_host: "{{ bastion_public_hostname }}"
showroom_tab_services:
- single_terminal
- second_terminal
showroom_ssh_method: password
showroom_ssh_host: host.containers.internal
showroom_ssh_username: "{{ bastion_student_user_name }}"
showroom_ssh_password: "{{ common_password }}"
showroom_terminal2_ssh_host: worker.sandbox-{{ guid }}-ocp4-cluster.svc.cluster.local
showroom_terminal2_ssh_username: "{{ bastion_student_user_name }}"
showroom_terminal2_ssh_password: "{{ common_password }}"