> ## Documentation Index
> Fetch the complete documentation index at: https://docs.safeonlineexam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Safe Online Exam Deployment: Choosing Your Platform

> Compare Cloud Run, Docker Compose, and container modes, understand image pinning and release trust, and review operational requirements before starting.

Safe Online Exam is distributed as a single nonroot Node.js container image published to `ghcr.io/jsb2010/safe-online-exam`. This page helps infrastructure teams choose the right deployment mode, understand release trust and image verification, and satisfy the operational requirements that every supported installation shares before moving to a platform-specific guide.

## Supported Deployment Modes

Each mode serves a different operational profile. Pick the one that fits your institution's existing practices and the resources you are prepared to operate.

| Mode                                | Best fit                                                                 | You operate                                                                                     |
| ----------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| Google Cloud Run with Cloud SQL     | Institution that wants managed compute, ingress, PostgreSQL, and secrets | Google Cloud project, IAM, cost, Canvas setup, client certificates, monitoring, and recovery    |
| Docker Compose on a Linux host      | Institution with an established Linux/container operations practice      | Host, firewall, TLS, Docker, PostgreSQL volume, backups, scheduling, monitoring, and upgrades   |
| Existing container platform         | Institution with Kubernetes or another reviewed platform                 | All provider-specific manifests plus the application runtime contract                           |
| Maintained source-based Cloud Build | Contributors/operators of the existing `canvas-seb-*` services           | Repository checkout, Google Cloud resources, source build, fixed service names, and secret pins |

For any new public installation, prefer a published release bundle over a source checkout. The bundle ships the exact image digest, version-matched scripts, and a self-contained README that takes precedence over the generic documentation.

<Note>
  Hosting platform and artifact source are independent choices. A school may run the published image on Cloud Run, Compose, or another reviewed container platform. A source fork owns its own dependency review, image publication, provenance, and deployment tooling.
</Note>

## Release Trust and Image Selection

Stable images are published at:

```text theme={null}
ghcr.io/jsb2010/safe-online-exam
```

Every GitHub Release produces `linux/amd64` and `linux/arm64` images, an SBOM, provenance, a GitHub artifact attestation, a manifest digest, and checksum files for both deployment bundles. Stable tags include `X.Y.Z`, `X.Y`, `X`, and `latest`; prereleases publish only their exact prerelease tag.

Production must pin the immutable digest from the GitHub Release page:

```text theme={null}
ghcr.io/jsb2010/safe-online-exam@sha256:<digest>
```

<Warning>
  Never treat a mutable tag such as `latest`, `X`, or `X.Y` as a production pin. Mutable tags can silently change to a different image after deployment. Always use the immutable `sha256:` digest recorded in the release notes.
</Warning>

### Pre-Installation Verification Checklist

Before running any installer, complete these five steps in order:

1. Review the changelog and release notes for breaking changes and migration requirements.
2. Download the release archive and its adjacent `.sha256` checksum file.
3. Verify the checksum against the archive before extraction.
4. Verify the image attestation using the exact repository, signer workflow, source commit, and source tag printed in the release notes.
5. Preserve the release notes and digest in your change record.

Publishing a GitHub Release never deploys an institution's service automatically; deployment is always an explicit operator action.

## Operational Requirements

Every supported production installation requires all of the following, regardless of platform:

<AccordionGroup>
  <Accordion title="PostgreSQL 17 or newer">
    The application requires PostgreSQL 17 or newer with a dedicated database user and durable storage. The migration job (`node dist/server/server/data/migrate.js`) must complete successfully before the application receives traffic. Backups and a tested restore drill are required.
  </Accordion>

  <Accordion title="Stable public HTTPS origin">
    Canvas and SEB clients must reach the service at a stable public HTTPS URL (`TOOL_URL`). The application binds to `127.0.0.1:8080` internally; a trusted TLS terminator must present a valid certificate to the public internet. Do not use a production HTTP `TOOL_URL`.
  </Accordion>

  <Accordion title="Protected secrets">
    Session secret, state encryption key, OAuth token encryption keyring, LTI private key, Canvas API credentials, database password, SEB quit password, and the SEB config encryption certificate must be injected through environment variables, mounted secret files, or a secrets manager — never baked into an image or committed to source control.
  </Accordion>

  <Accordion title="Migration job">
    A one-shot `node dist/server/server/data/migrate.js` job must run to completion before any new application revision receives traffic. The Cloud Run and Compose bundles enforce this ordering automatically; custom platforms must replicate it.
  </Accordion>

  <Accordion title="Scheduled cleanup job">
    `node dist/server/server/data/cleanup.js --drain` must run on a regular schedule (at least daily) to remove expired sessions, one-time state, and stale records. Configure Cloud Scheduler, a systemd timer, or cron and alert when executions stop.
  </Accordion>

  <Accordion title="Backups and recovery drill">
    Back up PostgreSQL on a documented schedule and before high-risk changes. Test restoration into an isolated target at least annually. A backup that has never been restored is not verified.
  </Accordion>
</AccordionGroup>

## Platform-Specific Guides

<CardGroup cols={2}>
  <Card title="Docker Compose" icon="docker" href="/deployment/docker-compose">
    Self-hosted Linux deployment with Docker Compose, PostgreSQL, optional Caddy HTTPS, and the guided setup and upgrade helper.
  </Card>

  <Card title="Google Cloud Run" icon="cloud" href="/deployment/cloud-run">
    Managed Cloud Run with Cloud SQL, Secret Manager, Cloud Scheduler, and the versioned installer bundle.
  </Card>
</CardGroup>

After choosing a platform and completing the deployment, continue with [Canvas Setup](/deployment/canvas-setup) to register the LTI and OAuth Developer Keys, then follow the [SEB Certificate Management](/deployment/certificate-management) guide to provision the client encryption identity.
