Safe Online Exam
Deploy the application

Deploy the application

Install a verified Safe Online Exam release on Cloud Run or Docker Compose, then preserve the migration, cleanup, backup, and recovery contract.

Safe Online Exam is distributed as a nonroot Node.js container. A supported production installation also needs PostgreSQL 17 or newer, a stable public HTTPS origin, protected configuration, a migration job before new traffic, scheduled cleanup, backups with restore drills, monitoring, and a tested Canvas/SEB workflow.

For a new public installation, use a published GitHub Release bundle rather than a source checkout. The bundle is version-matched to an immutable image digest and contains the installer, upgrade helper, and self-contained command reference for that exact release.

Verify the release before installation

Stable images are published at:

ghcr.io/jsb2010/safe-online-exam

Stable releases publish X.Y.Z, X.Y, X, and latest tags, plus a multi-architecture (linux/amd64 and linux/arm64) manifest, SBOM, provenance, GitHub attestation, and both deployment bundles. Tags help discovery; production must use the exact @sha256:... digest recorded in the GitHub Release.

Review and download the exact release

Read the changelog and release notes. Download the bundle and its adjacent .sha256 file from the releases page.

Verify the archive

Run the release-note checksum command before extraction. For example:

sha256sum --check "safe-online-exam-X.Y.Z-compose.tar.gz.sha256"

Verify the image provenance

Use the exact gh attestation verify command printed in the release notes. It binds the digest to JSB2010/safe-online-exam, the release workflow, source commit, and tag.

Publishing a GitHub Release never deploys an institution's service automatically. Record the release version, digest, verification result, and approver in the institution's change record.

Choose an operating model

Other container platforms can run the image, but their manifests are not maintained here. They must preserve the same contract: immutable image digest, PostgreSQL 17+, protected runtime values, a pre-traffic migration job, scheduled db:cleanup --drain, /ready gating, stable HTTPS, backups, monitoring, and schema-aware rollback.

First-install order

The two maintained bundles deliberately stop for Canvas at the points where Canvas must supply values:

  1. Verify the release and start the guided installer.
  2. Create or validate PostgreSQL, protected values, the stable URL, and the SEB client identity (when using certificate encryption).
  3. Create the Canvas API OAuth Developer Key for the final callback URL.
  4. Let the installer deploy a first revision using bootstrap-pending LTI IDs.
  5. Create the Canvas LTI Developer Key from ${TOOL_URL}/lti/config, install the app, and record the real client and deployment IDs.
  6. Finalize those IDs, load the Canvas theme loader, deploy the client identity where applicable, and complete end-to-end acceptance.

See Setup overview for the full handoff checklist and Canvas setup for the Canvas portion.

Invariants after go-live

  • Run a migration from the exact new image before it receives traffic.
  • Run bounded cleanup at least daily; expiry is a cleanup job, not database TTL.
  • Keep public app and database ports private behind the approved HTTPS ingress.
  • Preserve the version, digest, migration result, secret-version record, and release notes for every deploy.
  • Test Classic Quiz, New Quiz, administrator, instructor, student, detector, certificate decryption when enabled, Config Key proof, tools, and exit after a meaningful change.
  • Take and validate a backup before a high-risk upgrade. An application rollback does not reverse PostgreSQL migrations.

Next: Google Cloud Run or Docker Compose.

On this page