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

# Run the console from source

> The console process, its database, object storage and reverse proxy, plus the settings every backend needs.

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
git clone https://github.com/tuneplane/tuneplane && cd tuneplane
uv sync
uv run tuneplane-server serve --port 8080 --serve    # --serve binds 0.0.0.0
```

For a packaged deployment use [Docker Compose](/en/ops/install-compose),
[Kubernetes](/en/ops/install-kubernetes) or [Helm](/en/ops/install-helm) instead. This page is the
source install, and the settings below apply to all four.

Configuration is environment variables prefixed `TUNEPLANE_`, or a `.env` at the repository root.
`.env.example` there is the annotated template.

## The settings every deployment needs

| Environment variable                                                        | Description                                                                                                                                                      |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TUNEPLANE_DEFAULT_FLEET_KIND`                                              | `local` \| `node` \| `kuberay` \| `slurm`                                                                                                                        |
| `TUNEPLANE_WEB_JWT_SECRET`                                                  | **Must be set** to a fixed strong random string; the default random generation logs everyone out on restart and makes tokens non-interchangeable across replicas |
| `TUNEPLANE_PUBLIC_URL`                                                      | Externally reachable address (for OIDC callbacks / CLI authorization)                                                                                            |
| `TUNEPLANE_INGEST_URL`                                                      | Address training containers report metrics to; **must be a console URL reachable from inside the cluster network**, never 127.0.0.1                              |
| `TUNEPLANE_ALLOWED_IMAGE_REGISTRIES`                                        | Comma-separated registry hosts for user `--image`. Empty: first-class framework overrides unrestricted, **custom images rejected**                               |
| `TUNEPLANE_IMAGE_VERL` / `TUNEPLANE_IMAGE_TRL` / `TUNEPLANE_IMAGE_OPENRLHF` | Default OCI images for those frameworks (deployment artifacts; catalog does not embed the reference)                                                             |
| `TUNEPLANE_DB_PATH` / `TUNEPLANE_DB_URL`                                    | Defaults to SQLite (`.tuneplane-data/web.db`); production can switch to PostgreSQL                                                                               |
| `TUNEPLANE_REDIS_URL`                                                       | Strongly recommended for multi-replica deployments: instant token revocation, distributed rate limiting, consistency                                             |
| `TUNEPLANE_TIMEZONE`                                                        | Service-level timezone (schedule windows and daily-report boundaries)                                                                                            |

## Object storage (MinIO / S3)

Datasets, job package distribution (required for kuberay), and artifact archiving share one setup:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
TUNEPLANE_S3_ENDPOINT=https://minio.internal
TUNEPLANE_S3_ACCESS_KEY=…
TUNEPLANE_S3_SECRET_KEY=…
TUNEPLANE_S3_BUCKET=tuneplane
```

The job side only ever receives **presigned URLs** and never holds storage credentials.

The console uploads datasets and volume files the same way — the browser PUTs straight to the
endpoint above — so the bucket needs **CORS** allowing `PUT` and `GET` from the console's origin,
with `ETag` exposed. Without it those uploads fail in the browser while `tp dataset push`, which
does not run in one, keeps working:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
mc admin config set myminio api cors_allow_origin=https://console.internal
```

## Reverse proxy

`deploy/nginx.conf.example` is the template. Three things it has to get right:

| Setting                              | Why                                                                                            |
| ------------------------------------ | ---------------------------------------------------------------------------------------------- |
| `proxy_buffering off` for `/api`     | Live logs are Server-Sent Events. Buffered, they arrive in bursts or not at all                |
| Long read timeouts                   | A follow connection stays open for hours                                                       |
| `/docs` proxied to the Mintlify site | Optional. It serves this documentation under your own console domain; see `mintlify/README.md` |

## Migrations

Alembic migrations run automatically at service startup; to run them manually:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
uv run alembic upgrade head
```

## The first administrator

On a fresh deployment the first user is created through the console's first-visit onboarding at
`/api/auth/setup`, or with `tp admin user-add`. For single sign-on, see
[setting up sign-in](/en/ops/auth).

## Check it worked

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
curl https://tuneplane.your-company.com/api/version
```

Answers with the console version and the JobSpec dialect it speaks. Then run the
[smoke test](/en/ops/smoke-test) once before going live: one command verifies the whole submit,
schedule, container and ingest chain is configured, without needing a GPU.

## Next

[Choose a backend](/en/ops/overview) · [Fleets](/en/ops/fleets) ·
[Configuration reference](/en/ops/configuration)
