# Templates and Pre-builds

> Cordium documentation. Canonical page: <https://octelium.com/docs/cordium/latest/workspaces/templates>.

A *Template* is a reusable *Workspace* blueprint that belongs to a *Space*. *Templates* let *Space* admins standardize the development environments, CI runners and AI agent sandboxes of a team or a project in one place, while every *User* simply creates *Workspaces* from them. A *Template*'s spec has the same structure as a *Workspace*'s spec (read more [here](https://octelium.com/docs/cordium/latest/workspaces/overview.md)), except for the following differences:

- *Templates* cannot define applications nor ephemerality, since these are specific to each *Workspace*.
- *Templates* can define a `gitProvider`, which is the name of a *GitProvider* of the same *Space* that is used to authenticate git operations of the *Workspaces* on behalf of their owners (read more [here](https://octelium.com/docs/cordium/latest/workspaces/secrets.md#gitproviders)).
- *Templates* can be pre-built (see below).

## Creating Templates

*Templates* are created by the admins of their *Space*. The simplest way is via a YAML file:

```yaml
spec:
  image:
    registry:
      url: golang:1.26-bookworm
  repository:
    url: https://github.com/acme-corp/payments-api
    authentication:
      http:
        username: x-access-token
        password:
          fromSecret: github-read-token.payments.cordium
  vars:
    - name: LOG_LEVEL
      value: info
  runtime:
    envVars:
      - key: GOFLAGS
        value: -mod=mod
      - key: LOG_LEVEL
        value: ${{ vars.LOG_LEVEL }}
    tasks:
      - name: deps
        type: ON_CREATE
        workingDir: /workspace/repo
        run: go mod download && go build ./...
        onFailure: ON_FAILURE_ABORT
    volumeMounts:
      - volumeRef:
          name: go-cache
        mountPath: /cache
  limit:
    cpu:
      millicores: 4000
    memory:
      megabytes: 8192
    storage:
      megabytes: 30000
```

```bash
cordium create template api-dev.payments.cordium --file template.yaml
```

You can also create *Templates* via flags, or combine a file with flags that override it:

```bash
cordium create template node-app.payments.cordium \
  --image node:24-bookworm \
  --repository https://github.com/acme-corp/storefront \
  -e NODE_ENV=development \
  --env-from-secret NPM_TOKEN=npm-token.payments.cordium \
  --cpu 4000 --memory 8192
```

You can list the *Templates* of a *Space* as follows:

```bash
cordium get template --space payments.cordium
```

> **Note:**
>
> *Templates* can be updated from the web portal and via the API. Since the specs are merged at initialization time, changes to a *Template* apply to the subsequent runs of all its *Workspaces* (except for the parts that only apply on fresh runs, such as the image and the `ON_CREATE` tasks).

## Using Templates

*Workspaces* are created from a *Template* by its full name. A *Workspace* can extend and override its *Template*'s configuration (read more about merging [here](https://octelium.com/docs/cordium/latest/workspaces/overview.md#configuration-levels)):

```bash
# Create and start a Workspace from a Template
cordium run --template api-dev.payments.cordium

# Override a variable
cordium run --template api-dev.payments.cordium --var LOG_LEVEL=debug

# Extend the Template with a Workspace-specific spec
cordium run --template api-dev.payments.cordium --file workspace.yaml --port api:8080
```

## Pre-builds

Some environments take a long time to initialize: large repositories to clone, Docker images to build, dependencies to install, or projects to compile. Pre-builds move this work out of the startup path. A pre-build runs a special *Workspace* from the *Template* that performs all the fresh-run work (i.e. pulling or building the image, cloning the repositories, installing the devcontainer features and running the `ON_CREATE` and foreground `POST_START` tasks), and then takes a CSI volume snapshot of its storage once it completes successfully. From then on, the new *Workspaces* of the *Template* are restored from that snapshot and are ready within seconds instead of minutes.

You can trigger a pre-build from the web portal, via the `BuildTemplate` API, or via the CLI:

```bash
cordium build api-dev.payments.cordium
```

You can cancel a running pre-build as follows:

```bash
cordium build api-dev.payments.cordium --cancel
```

Triggering a new pre-build while another one is running cancels the running one. The state of the pre-builds is available in the *Template*'s `status.buildInfo` field, which lists the recent pre-builds with their state (i.e. `STATE_RUNNING`, `STATE_READY` or `STATE_FAILED`), timestamps and failure reasons, as well as the ID of the pre-build that new *Workspaces* are currently restored from (i.e. `currentReadyBuildID`).

Pre-builds differ from regular runs as follows:

- They run with the `ClusterConfig`'s build limits (read more [here](https://octelium.com/docs/cordium/latest/management/clusterconfig.md#limits)).
- They do not connect to the *Cluster* via `octelium connect`, which means that they have no secretless access to Octelium *Services*. They also skip the background tasks, the `PRE_STOP` tasks, the dotfiles and the git credentials of *GitProviders*. As a result, a pre-build can only clone repositories that are public or authenticated via a *Secret* (read more [here](https://octelium.com/docs/cordium/latest/workspaces/repositories.md#private-repositories)).
- They stop automatically once their tasks complete, and they are never stopped by the inactivity timeout.

A *Workspace* that is restored from a pre-build is not a fresh run: its `ON_CREATE` tasks do not run again, while its `POST_START` tasks, dotfiles and the *Workspace*-specific configuration are applied normally.

> **Note:**
>
> A pre-build is a snapshot of a point in time. The repositories of restored *Workspaces* are at the commit that was cloned by the pre-build, and the pre-build keeps being used after the *Template* is updated. Therefore:
>
> - Trigger a new pre-build whenever you update the *Template*.
> - Trigger pre-builds periodically or on every push to the main branch (e.g. from your CI via `cordium build`), so that restored *Workspaces* stay close to the latest commit.
> - Run `git pull` or `git fetch` in a `POST_START` task when the latest commit is required.

Pre-builds require a CSI driver that supports volume snapshots (read more [here](https://octelium.com/docs/cordium/latest/management/storage.md)). *Workspaces* can also be forked from any running or stopped *Workspace* via *WorkspaceSnapshots*, which is the per-*User* counterpart of pre-builds (read more [here](https://octelium.com/docs/cordium/latest/workspaces/snapshots.md)).
