Skip to main content

Init scripts

An init script is a bash script stored with a GPU instance. It runs to completion before the startup command, every time the pod starts.

A template records the image and the command; it cannot record what you did inside the container — and that is where most of the work happens. A pip package the image lacks, a model checkout, a config file: none of it survives the pod. Committing a new image would carry it, but that needs a registry you can push to and a build step. A script needs neither.

Where it runs​

sshSetup  →  sshd  →  ssh tunnel  →  INIT SCRIPT  →  startup command

It runs after sshd is up, on purpose. These scripts install packages and download weights — minutes, not seconds — and being able to SSH in and watch is the difference between "still working" and "stuck".

Writing one​

There are two places to write an init script:

  • Save as template on a GPU instance's detail page — this is the normal one. By then you have found out the hard way what the image was missing, and you are writing it down. See Compute templates.
  • Edit config on a running instance's detail page — adds or changes the script and rebuilds the pod. See Editing a running instance.

The script is then carried by every launch from that template, and by every restart of that instance.

Make it repeatable​

The pod re-runs the script every time it starts — after an OOM kill, a node drain, or a redeploy — and the container filesystem is fresh each time, so a marker file written last time is gone too.

The pattern that works is: install into a mounted volume, and guard on the path.

pip install -r /mnt/models/requirements.txt
[ -d /mnt/models/flux ] || huggingface-cli download acme/flux --local-dir /mnt/models/flux

This is also what makes init scripts and persistent storage worth combining: the volume survives the pod, so the expensive half of the script only runs once.

A failing script does not kill the instance​

If the script exits non-zero, the instance:

  1. prints the failure loudly in the pod log,
  2. skips the startup command, and
  3. stays up, idle, with SSH still working.

The script's whole job is to run things that break the first few times. A pod that exits goes into CrashLoopBackOff, where it restarts too fast to SSH into — and the one state you cannot debug is the one you cannot get into. Staying up means the instance is still billable, but it is reachable, which is where a broken script needs to be looked at.

The startup command is skipped because running your service without its dependencies produces a second, more confusing failure that buries the first.

To debug: open the terminal or SSH in, read the log above the failure, fix the script with Edit config, and redeploy.

Jupyter images are refused​

A Jupyter image keeps its own entrypoint, so an init script attached to one would never run. Rather than store something silently inert, EcoLink refuses it:

HTTP 400 Bad Request
{ "error": "a Jupyter image keeps its own entrypoint, so the init script would never run — put these steps in the startup command instead" }

The console hides the init-script field entirely for images whose name contains jupyter.

What it does not carry​

System-level changes: edits under /etc, anything compiled into /usr/local. Those need a custom image — see Container images.

For the common cases — pip packages, model weights, config files — a script is enough.

Limits​

LimitDetail
Size64 KB
Resource kindsGPU instances only. Model instances and GPU clusters have no equivalent yet
ImagesNot available on Jupyter images
RunsEvery pod start, not once

From the API​

init_script is an ordinary field on the launch body:

curl https://api.ecohash.com/gpu-instances \
-X POST \
-H "Authorization: Bearer eco_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "flux-dev-box",
"region_id": "<region-id>",
"gpu_type": "<gpu-type-for-region>",
"gpu_count": 1,
"container_image": "nvidia/cuda:12.3.2-cudnn9-devel-ubuntu22.04",
"estimated_duration_hours": 8,
"init_script": "pip install -r /mnt/models/requirements.txt\n[ -d /mnt/models/flux ] || huggingface-cli download acme/flux --local-dir /mnt/models/flux"
}'

It can also be changed on a running instance with PATCH /gpu-instances/{id} — see Editing a running instance.

What to do next​

Your privacy choices

Essential cookies are always on. You can change these choices at any time.