Skip to main content
A Celesto custom template is a reusable setup for cloud computers (on-demand Linux machines your agent runs on), with your tools already installed. You write the setup commands once, such as installing Go, Django, or PyTorch, and Celesto runs them for you. Every computer you create from the template then starts with those tools ready, so your agent can get to work right away instead of installing the same packages on every run.

How Celesto custom templates work

You give Celesto two things:
  • A base template. One of the built-in templates, such as coding-agent. Your template starts with the tools the base already includes.
  • A build script. Shell commands that install what you need. Celesto runs the script each time it builds the template, not each time a computer starts.
Building takes a few minutes. When the build finishes, Celesto saves the result as an image (a saved copy of the computer’s disk). New computers start from that image, so they skip the setup and are ready as quickly as computers from a built-in template.

Create a custom template and use it

1

Create the template

Pass a name, a base template to start from, and your setup commands. Write the commands as a shell script, one command per line.
create_template.py
The template is created right away with status queued, and Celesto starts building it.
2

Wait for the build

Add this to the end of create_template.py. wait() follows the build and returns when the template is ready. The on_log callback prints the build log as it runs.
The log ends with ==> Done, and wait() returns. template.status is now ready.
3

Create a computer from the template

Add this to the end of create_template.py too. create_computer() returns a cloud computer that starts from your template. Celesto creates the computer when the with block starts and deletes it when the block ends.
You see a line such as go version go1.22.2 linux/amd64. Go came with the template, so nothing was installed when the computer started.
Every template gets an ID that starts with tpl_, saved in template.id. To create a computer from the template in another script, pass that ID as template_id:

Choose a base template

The base template is your starting point. Your template starts with its tools, and your build script adds to them. Pick one of these built-in templates: You can’t use a custom template as a base.

Choose the computer size for a custom template

Computers from a template get the base template’s size unless you choose one. When your packages need more room, pass all three size settings together: vcpus (virtual CPU cores), ram_mb (memory in MB), and disk_size_mb (disk space in MB). Use the values from one of the named computer sizes. This example uses Large: 4 vCPUs, 16 GB of memory, and a 60 GB disk.
The size must be at least as big as the base template. For browser-agent, that means Standard or larger. The finished image must fit in disk_size_mb, so give large installs such as torch or CUDA a bigger disk. An image can be at most about 29 GB, whatever size you choose. New computers from the template start with this size. Celesto always builds custom templates on a Large machine.

Write the custom template build script

The build script runs as root (the administrator account, so you can install system packages directly), inside a fresh copy of the base template. Keep these rules in mind:
  • The first failing command stops the build. The script runs in strict mode (set -euxo pipefail), so any command that fails ends the build and the error shows its line.
  • List packages in the script. The build receives only the script text, so name each package directly, such as pip install django pytest. Commands that read local files, such as pip install -r requirements.txt or ./setup.sh, fail.
  • Answer prompts in advance. Use apt-get install -y so apt doesn’t stop to ask yes or no. Celesto runs apt-get update for you before your script starts.
  • Install services, start them later. The image keeps installed files, not running programs. Install a service such as PostgreSQL in the script, then start it on the computer when you need it.
  • Stay within the limits. A script can be at most 64 KB, and a build can run for at most 30 minutes.
Check a script before you create a template. lint() reviews it in seconds against the coding-agent base (pass base_template_id to check another base) and returns warnings, so you catch mistakes before you spend a build on them:
The output names each problem and how to fix it:

Install code from your repositories

The build script can download code from the internet, so it can clone a public repository and install it. The template then includes the code, ready on every new computer:
Clone private repositories on the computer after it starts, using a token you pass at that point. Keep tokens and other secrets out of the build script: everyone in your organization can read the script, and the build log prints every command it runs.

Fix a failed custom template build

When a build fails, wait() raises TemplateBuildError. Its message gives the script line number, the exit code, and, for common mistakes, a hint:
Fix the script, then build again:
If the template built successfully before, new computers keep using that build while it rebuilds, and also if the rebuild fails.
Common failures and fixes:
The base template doesn’t include that command. Pick a base that has it, or install it earlier in the script, for example apt-get install -y golang-go.
The system Python blocks pip install. Build from coding-agent, whose pip installs into its own Python setup, or create a virtual environment (a private Python setup) first: python3 -m venv /opt/venv, then /opt/venv/bin/pip install ....
apt can’t find a package with that name. Check the spelling, and look up the Ubuntu 24.04 name at packages.ubuntu.com.
The script took longer than 30 minutes. Remove downloads you don’t need, or move slow, optional steps out of the template and run them on the computer.

Rebuild a custom template on a schedule

rebuild() runs your build script again on the latest version of the base template. Rebuild every day to pick up new package versions and changes in your repositories. New computers keep using the previous build until the new one is ready. Any scheduler can run the rebuild. This script rebuilds one template and waits for the result:
rebuild_template.py
To run it every day with GitHub Actions, add this workflow to your repository. Save an organization admin’s API key as the CELESTO_API_KEY repository secret, since rebuilding needs admin access:
.github/workflows/rebuild-template.yml
The run log ends with tpl_0123456789ab is ready. A failed build fails the run, so GitHub notifies you.
Each organization can run 2 builds at a time. To rebuild many templates, such as one per customer workspace, rebuild them one after another instead of all at once.

Custom templates vs snapshots

A custom template saves installed files: packages, tools, and code on the disk. Every computer created from it starts fresh from those files, like a newly booted machine. Programs that were running during the build don’t carry over, so start services such as databases on each computer. A snapshot, as some other sandbox providers use the word, freezes a whole running machine, including its memory and running programs. To keep one computer’s work between sessions instead, stop and start the computer. Stopping keeps its disk, and starting brings back the same files.

Manage custom templates

Use these Python methods to create, check, build, use, and delete custom templates. Organization members can create templates and start computers from them. Viewers can list templates and read their build logs. Only admins and owners can edit, rebuild, or delete a template.

Custom template limits and errors

  • 2 builds at a time. Each organization can have 2 builds queued or running. Creating or rebuilding a third raises CloudAPIError with status 429 (too many requests). Wait for one to finish, then try again.
  • One build per template. Rebuilding while a build is queued or running raises CloudAPIError with status 409 (conflict). Call wait(), then rebuild().
  • Unique names. Each name can be used once per organization, and a deleted template’s name is free again. A name already in use raises CloudAPIError with status 409.
  • A finished build first. create_computer() needs at least one successful build. While the first build runs, it raises an error that tells you to call wait(). If the first build failed, the error tells you to fix the script and call rebuild().
Every CloudAPIError message says what to do next, and error.status_code holds the HTTP status. wait() keeps checking for up to 40 minutes. Your build keeps running on Celesto even if a check fails, so wait() retries through rate limits (caps on how many requests you can send), server errors, and network errors. If time runs out, it raises OperationTimeoutError. Call wait() again to keep waiting.

Custom template fields

Each Template object has these attributes. Call template.refresh() to load the latest values.
string
Template ID, starting with tpl_. Pass it as template_id to create computers.
string
The template name, unique in your organization.
string
Build state: queued, building, ready, failed, or needs_rebuild. needs_rebuild means Celesto updated the base template and your old build can no longer start computers. Call rebuild().
string
The built-in template the build started from.
string
The setup commands Celesto runs during a build.
TemplateBuildFailure | None
Where the last build failed, when its script exited with an error: line, line_number, exit_code, and hint.
string | None
Why the last build failed, when the cause was outside your script, such as the 30 minute limit.
list[TemplateLintWarning]
Script warnings from the last create or edit. Empty otherwise.
integer
Virtual CPU cores for each computer made from this template.
integer
Memory in MB for each computer made from this template.
integer
Disk space in MB for each computer made from this template.
datetime
When the template was created. updated_at holds the time of the last change.
Last modified on October 22, 2026