Repository navigation
Closed Network Install
Index · Team Server · CI-CD Pipeline Setup · Closed Network Install - 2026-11-15
Running QASight on a network with no internet (air-gapped), with a self-hosted GitLab and, optionally, an AI model inside the network. You pack everything on a machine that has internet, carry one file in, and install it there.
Once installed, nothing does. The web UI is inside the Python package (qasight_api/ui_dist) and its fonts are bundled, so pages load nothing from a CDN, and QASight sends no telemetry. The one outbound call is the daily "is a newer qasight out?" check against PyPI, already off in CI; set TESTO_NO_UPDATE_CHECK=1 everywhere else.
Getting it in is the part that needs internet:
| Piece | Normally from | On a closed network |
|---|---|---|
The CLI (pip install qasight) |
PyPI | The bundle's wheels/, or your PyPI mirror (Nexus, Artifactory, devpi) |
| Team server images |
ghcr.io/arieleven, Docker Hub (postgres) |
The bundle's images/, pushed to your registry |
| GitLab CI template |
include: project: arieleven/qasight and python:3.11-slim
|
The bundle's gitlab/qasight.gitlab-ci.yml, committed into your project, with your own image |
qasight init CI jobs |
uv from astral.sh, then PyPI |
An image that already has qasight (the jobs then download nothing) |
| AI summaries | OpenAI, Anthropic, Gemini | Any OpenAI-compatible model inside the network |
From a clone of the repository, checked out at the release tag:
scripts/offline/bundle.sh # this checkout's version, linux/amd64
scripts/offline/bundle.sh --python 3.11 --extras api,db,bdd --runner
scripts/offline/bundle.sh --no-images # the CLI only; no Docker neededIt writes dist-offline/qasight-offline-<version>-linux-<arch>.tar.gz with:
-
wheels/:qasight[<extras>]and every dependency as wheels for the target's Python versions (--python, default3.11,3.12,3.13) and CPU (--arch amd64|arm64), not this machine's, so a Mac can pack for a Linux server. -
images/:qasight-server,qasight-runnerandpostgres:16-alpine(docker save), plusqasight-runner-servicewith--runner. -
gitlab/qasight.gitlab-ci.yml,install.sh,bundle.env(what was packed) andSHA256SUMS.
The published server image has no Chromium, so the Report page offers PowerPoint, Excel and HTML but not PDF or PNG. For those, build Dockerfile.qasight-server with --build-arg TESTO_REPORT_PDF=1 on the machine with internet and docker save it next to the others.
tar -xzf qasight-offline-1.7.0-linux-amd64.tar.gz && cd qasight-offline-1.7.0-linux-amd64
./install.sh # checks SHA256SUMS, CLI into ./venv, docker load
./install.sh --registry registry.example.local/qa # and tags + pushes each image there--no-venv installs into the current Python, --no-cli / --no-images skip a half. pip runs with --no-index, so it never tries the network. At the end it prints the .env lines for the team server.
venv/bin/qasight server init qasight-server # compose file and .env with fresh secrets
cd qasight-server
cat >> .env <<'EOF'
TESTO_REGISTRY=registry.example.local/qa
TESTO_SERVER_TAG=1.7.0
TESTO_POSTGRES_IMAGE=registry.example.local/qa/postgres:16-alpine
TESTO_NO_UPDATE_CHECK=1
EOF
docker compose up -dWithout --registry, the images are already in that machine's Docker: set TESTO_SERVER_TAG to the version and leave TESTO_REGISTRY out. Everything else (accounts, backups, retention, the variables) is in Team Server. For sign-in, GitLab itself can be the single sign-on provider: add an application in GitLab (scopes openid, email, profile) with the redirect URL https://<your server>/api/v1/auth/oidc/callback, then set TESTO_AUTH=accounts and TESTO_OIDC_ISSUER=https://<your gitlab> with the id and secret (Single sign-on).
Commit gitlab/qasight.gitlab-ci.yml into your project and include it locally; include: project: works too once the QASight repository is mirrored into your GitLab.
include:
- local: .gitlab/qasight.gitlab-ci.yml
variables:
TESTO_CYCLE: smoke
TESTO_IMAGE: registry.example.local/qa/python-qasight:3.11 # has qasight: nothing is downloaded
# or keep a plain Python image and install from your mirror:
# TESTO_IMAGE: registry.example.local/python:3.11-slim
# PIP_INDEX_URL: https://nexus.example.local/repository/pypi/simpleThe template installs TESTO_PACKAGE only when the image has no qasight (TESTO_INSTALL: auto). An image with it baked in, built inside from the bundle:
FROM registry.example.local/python:3.11-slim
COPY wheels /tmp/wheels
RUN pip install --no-index --find-links /tmp/wheels "qasight[api,db]" && rm -rf /tmp/wheelsJobs that qasight init --ci gitlab writes run your tests in your language's image and record them after; they skip installing when qasight is already on the image's PATH, so add the same pip install --no-index line to that image. To upload every pipeline to the team server, add qasight ingest --server https://<your server> --token "$TESTO_API_TOKEN" (Upload from CI).
The merge request comment goes to your GitLab's own API (CI_API_V4_URL, set by GitLab), never gitlab.com; add a TESTO_GITLAB_TOKEN CI/CD variable with api scope.
Any server that answers OpenAI's POST /v1/chat/completions works: vLLM, Ollama, LiteLLM, TGI, LocalAI. On the team server, in .env:
TESTO_AI_PROVIDER=openai_compatible
TESTO_AI_BASE_URL=http://llm.example.local:8000/v1
TESTO_AI_MODEL=qwen2.5-coder-32b
OPENAI_COMPATIBLE_API_KEY=... # only if the model asks for oneor pick "OpenAI-compatible" on the Settings › AI page and type the URL. CI jobs take the same TESTO_AI_* variables (qasight ai). Since the model is yours, turning on "share the failing test's source" sends nothing outside.
If internal services use certificates from your own CA, give it to both HTTP stacks: SSL_CERT_FILE=/path/ca.pem (AI calls) and REQUESTS_CA_BUNDLE=/path/ca.pem (GitLab comments, uploads), or add the CA to the image's trust store.
These need GitHub or the internet and are simply unused on a closed network; nothing else depends on them:
-
qasight issues(GitHub issues for flaky tests),qasight try --from-github, history backfill from GitHub, and the setup pull request (gh). - The GitHub Action and
npx qasight(npm). - Scorecard tools that download their own databases (Trivy, Semgrep rules): bring their offline databases or leave them off (Release Scorecard).
- The docs site: the same notes are in
docs/in the repository.
Pack the new version, carry it in, run ./install.sh again and bump TESTO_SERVER_TAG. The server upgrades its database schema in place when it starts (Team Server § Storage).
Generated from docs/Processes & Guides/Closed Network Install.md. Edit it there; changes made in the wiki are overwritten.
Architecture
CLI Commands
Processes & Guides
- CI-CD Pipeline Setup
- Closed Network Install
- E2E Harness Operations Guide
- GitLab Pages Demo
- Publishing Docker Images
- Publishing to Artifactory
- Publishing to PyPI
- Setup Snippets
- Shared Resource Pools
- Stability and Deprecation Policy
- Team Server
Prompts & Snippets
Roadmap & Strategy
- Feature Gaps and Quick Wins - 2026-10-31
- New User Journey Audit - 2026-11-01
- Paid Features to Offer Free - 2026-10-31
- Product Roadmap
Specs & ADRs
- Adoption Blockers - 2026-11-12
- Affected Test Selection - 2026-10-30
- Alerts Where Developers Look - 2026-10-22
- Architecture Consolidation - 2026-10-06
- Architecture Review - 2026-10-31
- Automation and Unification - 2026-11-12
- BehaveX Reports - 2026-10-21
- Better Flaky Signal - 2026-11-01
- CLI-Only Bug Hunt - 2026-11-15
- Closed Network Install - 2026-11-15
- Command Adapter and JUnit Import - 2026-09-25
- Config JSON Schema - 2026-10-22
- Crash Detection - 2026-10-31
- Delta Comparison Policy
- Docs Site - 2026-10-19
- Docs Vault and Wiki Sync - 2026-10-07
- Easy Setup - 2026-11-01
- Engine Fixes - 2026-11-01
- Engineering Health Review - 2026-10-31
- Exporting Results - 2026-11-01
- External Audit Tools - 2026-11-11
- Flaky Test Issues - 2026-11-01
- Flaky Test Quarantine - 2026-10-22
- Free Copies of Paid Features - 2026-11-01
- GitHub Action PR Comment - 2026-10-19
- Human-Run Resource Provider - 2026-10-30
- Importer and Integration Bug Hunt - 2026-10-31
- Ingest and Team Server - 2026-10-22
- Interview Readiness Fixes - 2026-10-07
- Library Packaging
- Lifecycle Fixes - 2026-11-02
- MCP Server - 2026-11-01
- Menu by Question - 2026-11-12
- New User Journey Automation - 2026-11-01
- Open Source Features - 2026-10-19
- OpenTelemetry Export - 2026-10-30
- Phase 3 Delta Comparison Engine Plan
- Phase 3 Unified Dashboard Plan
- Phase 4 BYOK and Failure Analysis
- Phase 5 UI Redesign - Cycles-First Navigation
- Playwright Adapter - 2026-10-19
- Playwright JSON Import - 2026-10-22
- Plug and Play - 2026-11-12
- Plugin API - 2026-10-19
- Product Roadmap Work - 2026-10-25
- Product to Ten - 2026-10-25
- Project Health - 2026-10-26
- QASight Logo - 2026-11-05
- Qualflare Follow-ups - 2026-10-26
- Quarantine From the UI - 2026-11-01
- Specs & ADRs
- Release Gate - 2026-11-12
- Release Scorecard - 2026-11-12
- Rename to QASight - 2026-11-04
- Repository Pattern - Database-Agnostic Refactor
- Resource Lifecycle Hooks - 2026-10-26
- Resource Pools and Leases - 2026-10-26
- Run Deletion and Stop - 2026-11-02
- Runner Coverage - 2026-10-26
- Scale Runs and Stages - 2026-10-24
- Scorecard on MegaLinter - 2026-11-12
- Security and Install Review - 2026-10-31
- Standards Compliance - 2026-11-12
- Switchable Team Features - 2026-10-24
- Test Delivery Metrics - 2026-11-02
- Test Labels, Environments and Releases - 2026-11-02
- Test Source in AI Summaries - 2026-11-01
- Throwaway Stage Containers - 2026-10-24
- Tidy Cards and Demo Examples - 2026-11-05
- UI Design Review - 2026-10-31
- UI Polish - 2026-11-08
- UI Restyle - 2026-10-19
- UI Review Fixes - 2026-11-01
Testing Workflows
Vault