Docker
Use a repository checkout for the local demo. Production Compose downloads immutable assets and published images, so the server needs no checkout.
The Compose service name
redis and the REDIS_URL variable keep the protocol
name for compatibility.
Compose topology commands
Topology is selected by files, not by an environment switch:SCHEDULER_DRIVER=none; both worker topologies set
SCHEDULER_DRIVER=temporal. An environment value never adds or removes a
service. The bundled topology owns its namespace retention. The external
topology validates its namespace but never creates it or changes its policy.
How the stack starts
The deployment overlays contain nobuild: entries. Add compose.build.yaml
to build web and worker from source. The migration job uses the same web image.
The default stack starts PostgreSQL, Valkey, db-migrations, and the web app.
The one-shot migration service runs npm run db:migrate. It applies the Prisma
tree, then active deploy-blocking data migrations. No operator migration job is
required. The server, worker, and /api/v1/health require finished rows with
exact manifest checksums. With DEMO_FIXED_OTP=1, migrations also seed local
demo data.
Compose uses the version-pinned Docker Hub web image for migrations and the app.
For source testing, override complete references with BISIBILITY_IMAGE and
BISIBILITY_WORKER_IMAGE.
If a migration fails partway, run npm run db:migrate again. Completed steps
are skipped; only the failed step retries. Docker Compose keeps the app and
worker stopped until the one-shot migration service exits successfully.
services.migrations: "ready" requires all bundled Prisma migrations, finished
active data migrations with expected checksums, and the public ID database
contract. Run npx prisma migrate status in the deployed environment for
detailed Prisma status.
This default mode supports manual rank checks. For scheduled checks, choose a
worker topology from Compose topology commands.
The bundled topology adds Temporal Server 1.31.2 and the pinned Docker Hub
worker image. Add --profile temporal-ui to expose Temporal Web UI at
http://localhost:8233. An idempotent Admin Tools job creates or upgrades both schemas and
the namespace before worker startup. For source testing, add
-f compose.build.yaml --build; it builds both images and runs migrations from
the web image.
Use /api/v1/liveness for restarts and /api/v1/readiness for traffic; see
Health endpoint exposure.
Worker or Temporal failures can return 503 while web reads continue. The
APP_REVISION build argument identifies the public commit; omitting it
reports "unknown".
Local demo
bootstrap-local.sh writes generated secrets to a new .env. It sets
DEMO_FIXED_OTP=1 and DEMO_INSTANCE_INSECURE_AUTH_ACK=1. Sign-in then accepts
and displays a fixed code. Migrations seed demo data.
Open http://localhost:3000 and sign in with demo@acme.dev and code 000000,
also described under demo login.
The script refuses to run when .env already exists, so it cannot overwrite a
configured install.
Seeded rank history is synthetic. Connect a SERP provider from Integrations
before running a live check.
Production Compose
Download the immutable assets for one exact release into an empty directory. Do not runbootstrap-local.sh - it exists to enable demo mode in a repository
checkout.
.env. It creates independent secrets, sets
both public origins, and sets DEPLOYMENT_ENV=production. Replace
https://rank.example.com with the final origin, then review .env:
- Secrets. Back up
BETTER_AUTH_SECRETandBISIBILITY_SECRETS_KEY; see Application secrets. - Public URL. Confirm
SITE_URLandBETTER_AUTH_URLare the final public origin. The template leaves both blank and Compose fails before starting if the generator has not filled them. - Deployment stage. Keep
DEPLOYMENT_ENV=production; see Operations. - Email. Set
EMAIL_PROVIDERandEMAIL_FROMso sign-in codes can be delivered. See Email delivery. - Demo variables stay unset. See Fixed OTP.
- Client IP. See Trusted client IP.
/setup. Create the
instance admin, then connect a SERP
provider from Integrations.
Work through the production checklist before pointing
real users at the instance.
For scheduled checks with the bundled server, add both scheduling overlays:
docker-compose.self-host.yml remains a one-minor compatibility asset for the
former --profile scheduled command.
Verify and troubleshoot startup
Check every service, the one-shot migration result, and the anonymous traffic probe before configuring a reverse proxy:/api/v1/health diagnostics.
For symptom-first diagnosis of startup failures, readiness, auth redirects,
worker loops, schedules, client IP, and email delivery, see the canonical
Troubleshooting runbook.
Use the CLI with this instance
Install the CLI on the workstation where you use bisibility:baseUrl is the REST API root.
cloudUrl is the app origin for OAuth discovery and consent.
SITE_URL and BETTER_AUTH_URL. Route
/api/auth/* and /api/v1/* through the proxy. Run login on a workstation with
a browser. On a headless host, provide a project API key or personal access
token through the environment:
Access services from the host
The default stack publishes only the app on127.0.0.1:3000; PostgreSQL and
Valkey are internal to the Compose network. See
Public port exposure. Core does
not start the Temporal or worker overlays; the optional temporal-ui profile
exposes the Web UI at 127.0.0.1:8233.
For deliberate PostgreSQL or Valkey access from the Docker host, apply the
opt-in debug override:
127.0.0.1:5432 and Valkey to
127.0.0.1:6379. Change those loopback ports, or the app port, in .env when a
port is already taken:
docker-compose.override.yml.
Set a new app port in SITE_URL and BETTER_AUTH_URL, such as
http://localhost:3100. A mismatch breaks auth callbacks and absolute links;
Google sign-in and Search Console redirect URIs must use the same port.
Give each local instance unique ports and a Compose project name, such as
docker compose -p bisibility-staging up --build. Project names namespace
volumes and keep databases separate.
Stop or reset the stack
down preserves the PostgreSQL volume, so the next up continues with the same
data and applies only new migrations. down -v cannot be undone; use it when
you want a clean install.