Reference & troubleshooting

Reference

The look-up tables: what listens on which port and who can reach it, on all three shapes, and where things live on the appliance's two disks.

Port 8080 means two different things On the appliance, port 8080 is the application. On Docker Compose, port 8080 is the object store and the application is on 3000. Same number, different service. Check which shape an instruction is written for before you open a firewall rule or set a public URL.
01

URLs and ports Appliance

Port 80 is the front door and covers most people. The direct ports still exist and are still what generated links use, so they matter for firewalls. Compose and Kubernetes are further down this section.

Your browser and your users' The appliance :80 nginx front door :8080 app the application :5120 console administration :8090 objects traces, artifacts internal use only :5432 postgres loopback :8081 runner :8082 browser open on all NICs /admin → 302
Diagram — what listens where, and who is expected to reach it.
PortWhat answersWho needs it
80 The front door. Serves the application, redirects /admin to the console, and shows the self-refreshing "starting" page while the app is still booting. Everyone
8080 The application, directly. This is what TESTVIBE_PUBLIC_BASE_URL names by default, so emailed links, sign-in callbacks and the runner's artifact upload all use it. Everyone
5120 The administration console — license, mail, single sign-on, AI provider, capacity. A separate service from the app, deliberately. Administrators
8090 The object store. Run artifacts, screenshots and Playwright traces are fetched by the user's browser straight from here. Everyone
5432 PostgreSQL. Genuinely bound to loopback — listen_addresses = 'localhost'. Nothing off the box can open it. Nobody
8081 The test runner. Listening on every interface. The service unit sets Environment=PORT=8081 with no bind address, so Node binds 0.0.0.0. Nobody — but reachable
8082 The generation browser host. Listening on every interface, same reason (Environment=PORT=8082). Nobody — but reachable
Nothing should reach 8081 or 8082 — but nothing stops it Only the application needs those two ports, and it reaches them over 127.0.0.1. They are still open on every interface the VM has, and the appliance ships no inbound firewall. Both services do check a shared key on their data-plane routes, so an unauthenticated caller is refused — but that is the only thing in the way.

Do not expose this VM directly to an untrusted network. Put it on a trusted segment, or add a host firewall of your own that allows only 80, 5120 and 8090 (and 8080 if you use the app's direct port).
Ports 443 and 3000 are not it The appliance serves plain HTTP only — there is no TLS on it and nothing listens on 443. Put a reverse proxy in front of it if you need HTTPS, and then update both public URLs in the console to the proxied address. Port 3000 is the Docker Compose deployment's published port, not the appliance's.

Docker Compose and Kubernetes — ports, volumes and config

A different port map from the appliance. In Compose the three services that each bind 8080 inside their own container are published on different host ports; on the appliance they share one machine, so the ports themselves differ.

ServiceCompose — publishedKubernetesData
web
the application
3000:8080 Service on port 80; ingress optional (ingress.enabled). None — state is in Postgres and the object store.
admin
the console
5120:8080 ClusterIP, no ingress by default. Reach it with kubectl -n testvibe port-forward svc/testvibe-admin 5120:80. None.
blobserver
the object store
8080:8080 Service on port 80. Must be reachable by a user's browser — set blobserver.publicUrl, or the chart's ingress publishes it at /artifacts. Volume testvibe_blobdata at /data
PVC <release>-blobdata
postgres 5432:5432 StatefulSet, Service on 5432, in-cluster only. Volume testvibe_pgdata at /var/lib/postgresql/data
PVC data-<release>-postgresql-0
runner Not published In-cluster only. None kept.
browser Not published In-cluster only. None kept.
migrate Not published A Job. Runs once and exits. None.
Compose publishes your database to the world The shipped docker-compose.yml maps 5432:5432 unconditionally, so PostgreSQL is listening on 0.0.0.0:5432 on the host — protected by TV_PG_PASSWORD and nothing else. Nothing in the stack needs that: the other containers reach it by its service name on the internal network. Unless you connect to it from outside, delete the ports: block from the postgres service, or bind it to loopback with "127.0.0.1:5432:5432".

Where config lives. Compose: .env in the same directory as docker-compose.yml — but only the variables the compose file names are passed into a container. Kubernetes: values.yaml, with the secrets in <release>-secrets (or your own, via secrets.existingSecret).

02

Where things live on the appliance Appliance

PathDiskWhat it is
/etc/testvibe/Data Every configuration and secret file, split so no service reads more than it needs.
/etc/testvibe/testvibe.envData Operator-facing settings: the license, sign-in providers and AI keys. The console never writes this file. The two public URLs are in it as seeds (TV_SEED_TESTVIBE_PUBLIC_BASE_URL, TV_SEED_TV_BLOBSERVER_PUBLIC_URL) — change those at Settings → Addresses in the console, not here.
/etc/testvibe/app-secrets.envData The secret-protection key and the console credentials. The file to back up.
/etc/testvibe/admin-passwordData The generated console password, as printed on the banner.
/var/lib/postgresql/Data The database.
/var/lib/testvibe/blob/Data Run artifacts, screenshots and Playwright traces.
/opt/testvibe/OS The published application, console, object store, migration runner and test runner.
/etc/issueOS The console banner — the durable copy of the address and the generated password.
Do not set the two public URLs in testvibe.env The file's own header says it: those lines are seeds, not settings. The app reads the environment before the console's settings, so a plain TESTVIBE_PUBLIC_BASE_URL= line here locks the matching field in the console — it renders as "locked by environment" and refuses to save.

On an appliance that is a dead end, not an inconvenience: there is no OS login, so the one file that decides the value is unreachable. The moment the address changes, sign-in callbacks fail at your identity provider and every Playwright trace renders as a broken link, permanently, with no route to a fix from either surface you have. The only way out is to rebuild the box.

Use Settings → Addresses in the console. Pin the values here only if a configuration-management tool owns the file and you want the console read-only.

These are listed so you can recognise them in a backup or a rescue mount. You do not need shell access to run the appliance, and it does not offer any.

03

Where to go next

  • The portal — downloads, license activation, the release feed and the full configuration reference.
  • Product documentation — how the application itself works, capacity planning, AI models and licensing.
  • Getting started — the page to send the people who will use the install rather than run it.
  • support@testvibe.com — we would much rather hear from you on day one than on day two.