Skip to main content
Are you a large language model? This page is available as raw markdown at /environments.md. The full docset is at /llms-full.md and the index is at /llms.md.

Environments

Every job runs your script as Bash on a fresh machine. The environment mode decides what C3 installs first.

Your projectUseC3 prepares
Python with a pyproject.tomlpython:A uv virtualenv from uv.lock, cached across jobs
Anything with system packages, other languages, custom CUDAdocker:A public Docker Hub or GitHub Container Registry image, your script runs inside it
Self-contained binaries or scripts with no setupneitherNothing. The script runs directly on the machine

python: and docker: cannot be combined. Setup done inside the script itself runs again on every job.

Python​

project: python-example
script: run.sh
hardware: l40
time: "02:00:00"

python:
project: ./

output:
- ./results
# run.sh
#!/bin/bash
set -euo pipefail
python3 train.py --output "$C3_ARTIFACTS_DIR"
# pyproject.toml
[project]
name = "python-example"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["jax[cuda12]", "numpy"]

C3 runs uv sync before your script and caches the environment by the lock file, so repeat jobs skip the install. Create or refresh the lock file locally:

uv lock

If you only have a requirements.txt, create a pyproject.toml with uv init and uv add -r requirements.txt, then uv lock. If the project is in a subdirectory, point python.project at it.

Docker​

project: docker-example
script: run.sh
hardware: l40
time: "02:00:00"

docker:
image: pytorch/pytorch:2.4.0-cuda12.4-cudnn9-runtime
requires_accelerator: cuda

output:
- ./results

C3 pulls the image on the machine and runs bash /workspace/run.sh inside it, with your workspace, datasets and $C3_ARTIFACTS_DIR mounted.

Images on the GitHub Container Registry work the same way:

docker:
image: ghcr.io/my-lab/trainer:1.4
requires_accelerator: cuda

Requirements:

  • A public image on Docker Hub or ghcr.io. ubuntu:24.04, user/image:tag, docker.io/... and ghcr.io/<owner>/<image>:<tag> are accepted, with a tag or a digest. Other registries are rejected before anything is uploaded.
  • The package must be public. C3 pulls anonymously and does not support private images on either registry. On GHCR, set the package visibility to public in GitHub package settings; GitHub reports a private or missing package as denied.
  • C3 reuses an image already present on the machine. Pin a digest if you need a specific build rather than a mutable tag such as latest.
  • The image must contain bash. Alpine and distroless images often do not.
  • Set requires_accelerator: cuda for GPU images and none for CPU images. C3 stops before running the script if the machine does not match.
  • The image keeps its own PATH, HOME and ENV. C3 adds only the job variables below.

For a CPU job, request a CPU profile and set requires_accelerator: none. See CPU jobs.

Bash​

project: bash-example
script: run.sh
hardware: l40
time: "00:30:00"

output:
- ./results
# run.sh
#!/bin/bash
set -euo pipefail
mkdir -p results
./bin/my-simulation --output results/output.dat

Whatever the script installs is installed again on every job. Move that setup into python: or docker: when startup time matters.

What is on the machine​

Jobs run on Ubuntu virtual machines managed by C3's agent. C3 stages your workspace and prepares the configured Python or Docker environment for each job. Machines may be reused between jobs; do not rely on setup from a previous job.

GPU machinesCPU machines
Ubuntu22.04 or 24.04, depending on the provider24.04
NVIDIA driver and CUDA toolkitYes. CUDA 12.2 or 13.0, depending on the providerNo
PythonThe Ubuntu system python3 (3.10 or 3.12). pip and venv are not guaranteed; use uvSame
uvYes, on the PATHYes
DockerYes, with the NVIDIA container runtimeYes
Also presentbash, curl, tar, gzip, zstdSame

Nothing else is guaranteed. Do not rely on git, a compiler or conda being present. In Python mode, put dependencies in pyproject.toml. In Docker mode, put them in the image. In Bash mode, install them in the script and accept the startup cost.

Variables available to your script​

VariableValue
C3_JOB_WORKDIRAbsolute path of your uploaded workspace, the working directory
C3_ARTIFACTS_DIRDirectory whose contents are collected as results. Always exists
C3_HARDWARE_PROFILEExact profile of the machine, such as l40s or cpu-d3-96vcpu-384gb
C3_HARDWARE_KINDgpu or cpu
C3_ACCELERATOR_KINDcuda or none
PYTHONUNBUFFERED1, so Python output streams to the logs promptly
VIRTUAL_ENVSet in Python mode
TMPDIRPer-job temporary directory, Python and Bash modes

The environment is sanitised: no C3 credentials or storage keys are visible to your script. .env files in your workspace are uploaded but not loaded; load them yourself if you need them.