Sign in

Use a sandbox as your own template

Set up one sandbox with your packages, repo and system libraries, pause it, and start every job as a fork of it, set up and running in a second or two.

On this page6

Sandboxes start from two fixed templates, and there are no templates from your own image yet. A paused sandbox does the same job: set it up once, pause it, and fork it for each job. Each copy starts with its files, memory and running processes in a second or two, instead of repeating the install.

The steps use the prized CLI, signed in or with PRIZED_API_KEY set (CLI), on a workspace that has paid in: on the free tier a sandbox gets 60 minutes of running in all, and copies keep the parent's deletion time.

1. Set it up once

TPL=$(prized sandbox create --vcpu 2 --memory 4 --label role=template --env LD_LIBRARY_PATH=/home/prized/sysroot/usr/lib/x86_64-linux-gnu)
prized sandbox exec $TPL --timeout 10m -- 'python3 -m venv ~/.venv && ~/.venv/bin/pip install pandas playwright && ~/.venv/bin/playwright install chromium'
prized sandbox exec $TPL --timeout 10m -- 'git clone --depth 1 https://github.com/expressjs/express && cd express && npm install'

Everything goes in /home/prized, since there is no sudo: Python packages in a venv, and npm install -g after npm config set prefix ~/.local. The --env is for step 2. Copies keep the template's shape, and a small shape fits more of them (Fork).

2. Add system packages without root

apt-get install needs root, but apt can download packages as prized and unpack them in your home. Save this script:

apt-home.sh
set -e
shopt -s nullglob
mkdir -p ~/apt/lists/partial ~/apt/archives/partial ~/sysroot
cat > ~/apt/apt.conf <<EOF
Dir::State::Lists "$HOME/apt/lists";
Dir::Cache "$HOME/apt";
Dir::Cache::archives "$HOME/apt/archives";
Debug::NoLocking "true";
EOF
export APT_CONFIG=~/apt/apt.conf
apt-get update -qq
apt-get install --download-only -y -qq --no-install-recommends "$@"
for f in ~/apt/archives/*.deb; do case "$f" in */libc6_*|*/libc-bin_*) continue;; esac; dpkg -x "$f" ~/sysroot; done
LIB=~/sysroot/usr/lib/x86_64-linux-gnu
for f in $(find "$LIB" -mindepth 2 -name '*.so*'); do [ -e "$LIB/${f##*/}" ] || ln -s "$f" "$LIB/"; done
mkdir -p ~/.local/share && ln -sfn ~/sysroot/usr/share/fonts ~/.local/share/fonts

Run it with the packages you need, here the libraries Playwright's Chromium needs, and ffmpeg:

prized sandbox cp apt-home.sh $TPL:apt-home.sh
prized sandbox exec $TPL --timeout 10m -- 'bash apt-home.sh libnss3 libnspr4 libatk1.0-0t64 libatk-bridge2.0-0t64 libcups2t64 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2t64 ffmpeg'

Programs land in ~/sysroot/usr/bin (run ~/sysroot/usr/bin/ffmpeg), fonts where apps look for yours, and libraries where the create's LD_LIBRARY_PATH looks, for every command in the sandbox and its copies. Most libraries and command-line tools work this way; a tool that reads its data from a fixed path under /usr/share or /etc needs pointing at ~/sysroot, and a package that needs its install scripts to run, such as a system service, does not work.

3. Pause it

prized sandbox pause $TPL --wait

Paused, it keeps its memory, disk and processes and bills paused storage only: a 2 vCPU, 4 GB sandbox with the 10 GB disk holds 14 GB of it, and the first 20 GB are included (Billing: Sandboxes). It is kept until you delete it (Paused retention), and still counts against your workspace's CPU and memory quota.

4. Start each job as a fork

JOB=$(prized sandbox fork $TPL)
prized sandbox exec $JOB --cwd express -- npm test
prized sandbox rm $JOB

The copy has the venv, Chromium, ffmpeg and the installed repo, and any process the template had running; the template stays paused. The first fork of a template takes a few seconds longer, and --count makes several at once. Each copy is an ordinary sandbox, billed per second at the template's shape with its own run time.

When a fork does not fit

Copies start on the template's machine, so a busy machine can fit fewer than you ask for, or none (Fork). Fork as many as fit, try again later, or set up a second template: keep steps 1 to 3 in a script, so that is one command.

Change or replace it

Run jobs only in copies: whatever a command leaves on the template reaches every later fork. To change it, run commands on it (the first resumes it) and pause it again; to start over, set up a new one and delete the old with prized sandbox rm. Keep the setup script: a paused sandbox lives on one machine and is lost if that machine fails.