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

# Self-hosting

> Running the server yourself: the image, the database, the environment, health checks and restarts.

TrueCourse is one server that also serves the web app, with Postgres behind it. To run it for a team you need three things: the server, a database, and something that terminates HTTPS in front of it.

For running it on one machine without sign-in, see [Installation](/installation#run-it-locally).

## The image

The `Dockerfile` at the root of the repository builds the whole workspace and the web app into one image, and the server serves the web app from it. The image:

* runs on Node.js 22 and listens on `PORT`, which is 3001 inside the image;
* keeps its runtime directory at `/data`, which is scratch rather than state. See [Storage](/configuration/storage#the-runtime-directory);
* includes `git`, because runs clone repositories;
* starts the enterprise edition when the build included the `ee/` tree, and the open edition when it did not.

The image does not ship a browser. Flows with web steps need Playwright's Chromium on the machine that runs the server, and a run never downloads one.

## The database

The server applies its own migrations at boot, so the database needs no preparation beyond existing. `docker-compose.yml` in the repository runs Postgres 16 bound to localhost, which is meant for development. For a deployment, point `DATABASE_URL` at your own Postgres.

Everything durable lives there. The container holds nothing you need to back up.

## The environment

Required in every mode:

| Variable                | What it does                                                                                                          |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `DATABASE_URL`          | The Postgres connection string.                                                                                       |
| `TRUECOURSE_SECRET_KEY` | At least 32 characters. It encrypts each workspace's provider key and each repository's registered dependency values. |

A deployment for a team also needs the WorkOS variables, and the GitHub App variables to connect repositories. Both sets are in [Installation](/installation#deploy-for-a-team). Model and concurrency variables are in [Models & environment](/configuration/models).

## Health

The server answers `GET /api/health`. Use it as the liveness check for your container platform or your proxy.

## Restarts and releases

A restart stops the jobs and runs that were in flight. At boot the server marks them **Interrupted**, and they can be started again from a repository's Pipeline tab or from the run's conversation. Deploy when little is running, or expect interrupted runs.

During the restart the server is down, so whatever sits in front of it will answer an error for a moment.

## What the repository ships for Azure

`infra/azure` holds Bicep templates and a runbook for TrueCourse's own hosted deployment: a virtual machine with Docker and Caddy, a managed Postgres, a registry, a key vault and monitoring. It is written for that deployment rather than as a general installer, with resource names and regions baked in. Read it as a worked example, not as instructions to follow verbatim.

## Next steps

<CardGroup cols={2}>
  <Card title="Installation" icon="download" href="/installation">
    Every variable, for local mode and hosted mode.
  </Card>

  <Card title="Storage" icon="database" href="/configuration/storage">
    What Postgres holds and what stays on disk.
  </Card>
</CardGroup>
