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.
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.
| Port | What answers | Who 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 |
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).
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.
| Service | Compose — published | Kubernetes | Data |
|---|---|---|---|
| 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
/dataPVC <release>-blobdata |
| postgres | 5432:5432 |
StatefulSet, Service on 5432, in-cluster only. | Volume testvibe_pgdata at
/var/lib/postgresql/dataPVC 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. |
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).
Where things live on the appliance Appliance
| Path | Disk | What it is |
|---|---|---|
/etc/testvibe/ | Data | Every configuration and secret file, split so no service reads more than it needs. |
/etc/testvibe/testvibe.env | Data | 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.env | Data | The secret-protection key and the console credentials. The file to back up. |
/etc/testvibe/admin-password | Data | 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/issue | OS | The console banner — the durable copy of the address and the generated password. |
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.
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.