# Workspace Configuration

> Cordium documentation. Canonical page: <https://octelium.com/docs/cordium/latest/use/config>.

A Workspace's behavior is determined by its spec, the spec of its parent Template, the runtime configuration of its Space, and user-level configuration from UserConfig. These four levels are merged at initialization time in a defined precedence order.

This page covers every configuration option available in the Workspace and Template spec, with real-world examples demonstrating common development and automation patterns.

For exact fields, types, and enum values, see the [Workspace JSON Schema](https://octelium.com/schemas/cordium/latest/cordium.v1.Workspace.schema.json) and [Template JSON Schema](https://octelium.com/schemas/cordium/latest/cordium.v1.Template.schema.json).

## Configuration Sources and Merging

### Precedence Order

Workspace configuration is resolved from the most specific resource to the least specific resource:

```text
Workspace spec
      ↓
Template spec
      ↓
Space runtime spec
      ↓
Cluster defaults and caps
```

### YAML File Format

All Workspace and Template configurations share the same top-level structure:

```yaml
spec:
  image: ...
  repository: ...
  additionalRepositories: ...
  runtime: ...
  applications: ...
  limit: ...
  vars: ...                    
  gitProvider: ...              # Template only
```

## Image Configuration

The `spec.image` field defines the container image used as the Workspace filesystem. If omitted, Cordium uses a default base image with common development tools.

### Registry Image

```yaml
spec:
  image:
    registry:
      url: ubuntu:24.04
```

For images requiring authentication:

```yaml
spec:
  image:
    registry:
      url: registry.mycompany.com/dev/base:latest
      authentication:
        username: robot-user
        password:
          fromSecret: registry-password
```

The `fromSecret` value is the name of a Secret in the same Space. The value is resolved server-side and never stored in the Workspace spec or visible in API responses.

### Inline Dockerfile

```yaml
spec:
  image:
    dockerfile:
      inline: |
        FROM debian:bookworm-slim
        RUN apt-get update && apt-get install -y \
            build-essential git curl wget \
            python3 python3-pip python3-venv \
            && rm -rf /var/lib/apt/lists/*
        RUN pip3 install --break-system-packages poetry
```

### Dockerfile from URL

```yaml
spec:
  image:
    dockerfile:
      url: https://raw.githubusercontent.com/myorg/dockerfiles/main/dev/Dockerfile
```

### Git Repository

Clone a git repository and build from a Dockerfile or devcontainer spec found within it:

```yaml
spec:
  image:
    git:
      url: https://github.com/myorg/dev-images
      cloneOptions:
        checkout: main
      dockerfile: images/backend/Dockerfile
      context: images/backend
```

If `dockerfile` is omitted, Cordium looks for `.devcontainer/devcontainer.json` in the repository root.

### Repository Devcontainer

Build from the devcontainer spec found in the Workspace's primary repository:

```yaml
spec:
  image:
    repository:
      devcontainer:
        dirPath: .devcontainer
```

Or build from a specific Dockerfile within the repository:

```yaml
spec:
  image:
    repository:
      dockerfile:
        path: docker/Dockerfile.dev
        context: .
```

## Repository Cloning

### Primary Repository

The `spec.repository` field defines the primary repository cloned into `/workspace/repo`:

```yaml
spec:
  repository:
    url: https://github.com/myorg/my-project
    cloneOptions:
      branch: main
      depth: 1                   # shallow clone depth (0 = full history)
      singleBranch: true         # only fetch the specified branch
      checkout: abc1234          # specific commit or tag to checkout
      shallowSubmodules: true
      disableLazyUnshallow: false # if true, skips async full-history fetch
```

By default, Cordium performs a shallow clone at Workspace initialization for fast startup, then fetches full history asynchronously in the background. Set `disableLazyUnshallow: true` to skip the background fetch if full history is not needed (e.g. for CI/CD runs).

### Repository Authentication

For private repositories using HTTP basic auth with a Secret:

```yaml
spec:
  repository:
    url: https://github.com/myorg/private-repo
    authentication:
      http:
        username: oauth2
        password:
          fromSecret: github-pat
```

For repositories where a GitProvider OAuth2 token should be used, configure a GitProvider on the Template instead of inline authentication. The token is injected automatically without any spec changes.

### Additional Repositories

Clone one or more repositories alongside the primary. Additional repositories are cloned in parallel and land at their configured `clonePath`:

```yaml
spec:
  additionalRepositories:
    - name: shared-libs
      clonePath: /workspace/additional-repos/shared-libs
      repository:
        url: https://github.com/myorg/shared-libs
        cloneOptions:
          branch: main
    - name: config-repo
      clonePath: /workspace/additional-repos/config
      repository:
        url: https://github.com/myorg/k8s-config
        authentication:
          http:
            username: deploy-token
            password:
              fromSecret: config-repo-token
```

## Runtime Configuration

The `spec.runtime` field controls environment variables, lifecycle tasks, and container behavior.

### Environment Variables

Environment variables are injected into the Workspace container and all lifecycle tasks. Values can be static strings or resolved from Secrets:

```yaml
spec:
  runtime:
    envVars:
      - key: NODE_ENV
        value: development
      - key: LOG_LEVEL
        value: debug
      - key: DATABASE_URL
        fromSecret: staging-database-url
      - key: STRIPE_SECRET_KEY
        fromSecret: stripe-secret-key
```

Environment variables are merged across all configuration levels. If the same key appears at multiple levels, the more specific level wins (Workspace > Template > Space > UserConfig).

### Lifecycle Tasks

Tasks run at defined points in the Workspace lifecycle. Every task supports the following fields:

| Field          | Type   | Description                                                                                                       |
| -------------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
| `name`         | string | A unique name for the task, used in logs and failure reporting.                                                   |
| `run`          | string | Shell command to execute.                                                                                         |
| `type`         | enum   | `ON_CREATE`, `POST_START`, or `PRE_STOP`.                                                                         |
| `workingDir`   | string | Working directory for the task. Defaults to the user's home directory.                                            |
| `isBackground` | bool   | If true, the task starts and Workspace initialization proceeds without waiting for it to complete.                |
| `runAsRoot`    | bool   | If true, the task runs as root inside the Workspace. Default is the Workspace user.                               |
| `onFailure`    | enum   | `ON_FAILURE_ABORT` stops Workspace initialization on failure. `ON_FAILURE_CONTINUE` logs the error and continues. |
| `envVars`      | list   | Per-task environment variable overrides, merged with the Workspace-level env vars.                                |

#### Task Types

**`ON_CREATE`** runs on the first start of a Workspace (fresh run) only. It does not run on subsequent starts of a persistent Workspace. Use it for one-time setup: installing dependencies, running database migrations, compiling assets, seeding initial data.

**`POST_START`** runs on every Workspace start, including subsequent starts of a persistent Workspace. Use it for starting background services, running dev servers, establishing tunnels, or any service that must be running for the Workspace to be usable.

**`PRE_STOP`** runs before the Workspace container stops. Use it for graceful shutdown of services, flushing write buffers, or cleanup before the filesystem is snapshotted.

```yaml
spec:
  runtime:
    tasks:
      - name: install-deps
        run: npm ci
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_ABORT

      - name: run-migrations
        run: npm run db:migrate
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_ABORT
        envVars:
          - key: NODE_ENV
            value: development

      - name: seed-data
        run: npm run db:seed
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_CONTINUE

      - name: start-redis
        run: redis-server --daemonize yes
        type: POST_START
        runAsRoot: true

      - name: dev-server
        run: npm run dev
        type: POST_START
        workingDir: /workspace/repo
        isBackground: true

      - name: graceful-shutdown
        run: npm run shutdown
        type: PRE_STOP
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_CONTINUE
```

### Container Command and Entrypoint

Override the container's default command and entrypoint:

```yaml
spec:
  runtime:
    cmd: "sleep infinity"
    entrypoint: "/usr/bin/tini --"
    disableInit: false
```

`disableInit: false` (the default) adds a minimal init process as PID 1 for zombie process reaping. Set to `true` only if the container image already includes its own init system.

## Applications and Port Sharing

Named applications expose Workspace ports through the portal's reverse proxy:

```yaml
spec:
  applications:
    - name: web
      port: 3000
      isDefault: true    # accessible at <workspace>.cordium.<domain>
    - name: api
      port: 8080         # accessible at api_<workspace>.cordium.<domain>
    - name: storybook
      port: 6006
    - name: docs
      port: 4000
```

Only one application can be marked `isDefault`. Specific ports not defined in the spec are accessible via `port_<number>_<workspace>.cordium.<domain>`.

## Resource Limits

```yaml
spec:
  limit:
    cpu:
      millicores: 4000     # 4 CPU cores (1 core = 1000 millicores)
    memory:
      megabytes: 8192      # 8 GB RAM
    storage:
      megabytes: 30000     # 30 GB disk
```

If omitted, limits are resolved from the Template, Space default, or Cluster default, in that order, and then capped by the Space maximum and Cluster maximum.

## Variables

Variables are referenced using `${{ vars.NAME }}` syntax in string fields:

```yaml
spec:
  vars:
    - name: BRANCH
      value: main
    - name: SERVICE
      value: svc
    - name: RUN_TESTS
      value: "true"
  repository:
    url: https://github.com/myorg/monorepo
    cloneOptions:
      branch: ${{ vars.BRANCH }}
  runtime:
    tasks:
      - name: build
        run: |
          cd ${{ vars.SERVICE }}
          go build ./cmd/...
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_ABORT
      - name: test
        run: |
          if [ "${{ vars.RUN_TESTS }}" = "true" ]; then
            cd ${{ vars.SERVICE }} && go test ./... -race
          fi
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_ABORT
```

Variable substitution is applied after all configuration levels are merged, against the final spec. Substitution is supported in task `run` scripts, repository URLs, image URLs, working directories, and environment variable values. It is not applied to Secret names or structural fields like task types and failure modes.

## Auto-Stop

Setting `autoStop: true` causes the Workspace to stop automatically once all non-background lifecycle tasks complete. Background tasks (those with `isBackground: true`) are not counted. This is most useful for CI/CD runs and automated workloads where no human interaction is expected after initialization completes.

```yaml
spec:
  runtime:
    autoStop: true
    tasks:
      - name: build
        run: make build
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_ABORT
      - name: test
        run: make test
        type: ON_CREATE
        workingDir: /workspace/repo
        onFailure: ON_FAILURE_ABORT
```

## Capabilities

Linux capabilities can be added and dropped as follows:

```yaml
spec:
  runtime:
    capabilities:
      add:
        - NET_ADMIN
        - NET_RAW
      drop:
        - SYS_PTRACE
        - AUDIT_WRITE
```

Such capabilities are merged with the Space-level and ClusterConfig-level configurations.

## Template-Only Fields

The following fields are available in Template specs but not in Workspace specs.

### GitProvider

Associate a GitProvider with a Template to enable automatic OAuth2 token injection for authenticated git operations:

```yaml
spec:
  gitProvider: github   # name of a GitProvider in the same Space
  repository:
    url: https://github.com/myorg/backend-service
```

## Inline Repository Configuration

A `.cordium.yaml` or `.cordium/workspace.yaml` file placed at the root of a cloned repository is automatically detected and merged with the Template spec at initialization time. This lets repository-specific configuration live in version control alongside the code:

```bash
my-project/
├── .cordium/
│   └── workspace.yaml    ← merged with Template spec at Workspace init
├── src/
└── ...
```

The repository config file is treated as more specific than the Template spec but still subject to Space and Cluster resource limit caps.

## Devcontainer Support

Cordium implements the [Development Container specification](https://containers.dev/). If a Workspace's repository contains `.devcontainer/devcontainer.json` or `.devcontainer.json`, Cordium automatically builds or pulls the image defined in the devcontainer spec, it applies `containerEnv` values as Workspace environment variables, it downloads and installs devcontainer features from OCI registries, it appends `onCreateCommand`, `updateContentCommand`, `postCreateCommand`, and `postStartCommand` hooks to the appropriate task types and it installs VS Code extensions listed in `customizations.vscode.extensions`.

No Cordium-specific configuration is needed to activate devcontainer support. Set the image source to `repository` or `git` and ensure the repository contains a valid devcontainer spec.

## API Reference

[Workspace JSON Schema (Cordium cordium/v1, latest documentation)](https://octelium.com/schemas/cordium/latest/cordium.v1.Workspace.schema.json)

[Template JSON Schema (Cordium cordium/v1, latest documentation)](https://octelium.com/schemas/cordium/latest/cordium.v1.Template.schema.json)
