# Renest on RunPod.

> To restore a nest on RunPod, start a pod from the Renest base image, upgrade the renest tool, and paste the restore command from your drive into /workspace. Renest checks the machine first, brings back every file and dependency and checks each one against its recorded checksum, then starts the app and runs the packed workflow once. If the pod turns out broken, destroy it, rent another and paste the same command.

Canonical page: https://renest.ai/docs-guide-runpod.html

<h2 id="size">1 · The nest decides the GPU and disk, and the pre-flight check has the final say</h2>

<p><strong>GPU.</strong> The card doesn't have to match the one the nest was packed on. What
matters is whether this machine can run what the nest carries. Before downloading anything,
the pre-flight check compares the machine with the nest. It checks the GPU architecture
against the compiled code in the nest, the host driver against the CUDA line in the
dependency lock, the video memory the working run was seen using, and whether the GPU can
actually be used. If a card can't run the nest, the check refuses it up front, instead of
letting the restore die half an hour into a paid rental.</p>

<p>You can ask before you rent. On any computer with the tool installed, this checks whether
everything the nest does <em>not</em> carry can still be fetched, and needs no GPU:</p>

<pre>$ renest restore --grant grant.json --dir ./run --check-only</pre>

<p>On the pod, <code>--plan</code> runs the full machine check and lists everything the
restore would do, then stops before fetching anything.</p>

<p><strong>Disk.</strong> Start from the nest's size, shown on its page in your drive and in
the panel's <em>Estimated size</em>. Add room for the Python environment the restore installs
from the lock, which for image and training stacks is often several gigabytes on its own. The pre-flight check does this sum for the disk that holds the folder you restore into, and
checks any other disk the nest writes to (a model cache in your home folder, for example)
separately. If there isn't room, it stops with <code>Only … GiB free, and this nest needs
… GiB</code> before it starts downloading.</p>

<p><strong>The disk that needs the room is the one holding your <code>--dir</code>.</strong>
<code>--dir</code> has no default, and the command your drive gives you says
<code>--dir ./run</code>, which is relative to the folder you paste it in. On RunPod,
anything under <code>/workspace</code> lives on the pod's volume disk; other paths live on the
container disk, which is cleared when the pod stops. This guide pastes the command from
<code>/workspace</code>, so the restore lands in <code>/workspace/run</code>: size the
<strong>volume disk</strong> for the nest. Pasted from another folder, such as
<code>/</code>, the same command restores into <code>/run</code> on the container disk. That
works if the container disk is big enough, but what's there is gone when the pod stops.</p>

<p>For GPU generations and where your bucket sits relative to the machine, see the
<a href="docs-practical-guide.html">field notes on storage, GPUs and prices</a>.</p>

<h2 id="start">2 · Start from the Renest base image, or from any template you already use</h2>

<h3>The Renest base image is a clean starting point with the tool preinstalled</h3>

<p>The base image is a minimal Ubuntu 22.04 (linux/amd64) image for restoring nests. It
contains the <code>renest</code> tool, <code>uv</code>, <code>s5cmd</code>, <code>curl</code>,
<code>jq</code>, <code>tar</code>, <code>sha256sum</code>, <code>sshd</code>, and the system
libraries that image and fine-tuning workflows commonly load at runtime. By design it has
<strong>no torch, no ComfyUI, no models, no CUDA toolkit and no Python on PATH</strong>. Your
nest brings its own Python version and packages, and the restore puts them back.</p>

<p><strong>Template link.</strong> Open the Renest template on RunPod: https://console.runpod.io/hub/template/711pukq2zg?ref=nywbuitg This is the platform's referral link. Opening the link takes
you to RunPod's deploy page with the settings below already filled in. The hosted Renest
service is run by the same people who make this image.</p>

<p>To set it up by hand, create a pod template with:</p>

<ul>
  <li><strong>Container image:</strong> pinned by digest, so the pod boots exactly these bytes:
  <pre>ghcr.io/renest-ai/nest-base@sha256:e31d287a7244cd04f527b03693a7b623c514ec828ae8a5a98072b20264f928d8</pre>
  (This is the image tagged <code>20260913</code>. Date tags are never overwritten.)</li>
  <li><strong>Container start command:</strong> leave it empty. The image's own start script
  starts <code>sshd</code>, generates fresh host keys, installs your SSH key, creates
  <code>/workspace</code> and prints the host's driver version.</li>
  <li><strong>Expose TCP ports:</strong> <code>22</code>. Add HTTP port <code>8188</code> as
  well if you want to open ComfyUI through RunPod's web address after the restore (you can
  also use an SSH tunnel instead, see <a href="#after">step 7</a>).</li>
  <li><strong>SSH key:</strong> RunPod passes the public key from your account settings into
  the pod as <code>PUBLIC_KEY</code>, and the image writes it to
  <code>authorized_keys</code>. This guide connects over SSH.</li>
</ul>

<p>Two limits to know before you rent:</p>

<ul>
  <li><strong>There is no C compiler.</strong> A workflow that compiles GPU kernels while it
  runs (some triton paths) won't run on this image. Runtime-level base images generally don't
  include one either.</li>
  <li><strong>It has no single licence.</strong> The image mixes Ubuntu packages (many
  GPL/LGPL), permissively licensed binaries, and the source-available <code>renest</code>
  tool, so its licence metadata says NOASSERTION. Notices, the written offer for source code
  and licence texts are in <code>/usr/share/doc/renest-floor/</code>. See the
  <a href="docs-source-offer.html">source code offer</a>.</li>
</ul>

<h3>Any other template works too</h3>

<p>Renest doesn't need our image. A RunPod PyTorch template, or any Linux image with an NVIDIA
driver visible, is fine: install the tool in step 3 and the pre-flight check tells you whether
the machine is suitable. The nest installs its own Python, so the template's Python version
doesn't matter.</p>

<h2 id="install">3 · Install the tool, or upgrade it on the base image</h2>

<pre># no uv yet?
$ curl -LsSf https://astral.sh/uv/install.sh | sh
$ source &#126;/.bashrc
# then install renest (or upgrade an older copy)
$ uv tool install --upgrade renest
$ export PATH="$HOME/.local/bin:$PATH"</pre>

<p>The <code>export</code> line matters on a fresh pod. Without it, <code>renest</code> answers
<code>command not found</code>. <code>--upgrade</code> moves an older install to the latest
version and does nothing on a clean machine. If you'd rather not use <code>uv</code>, running
<code>pip install renest</code> in an environment with Python 3.11 or newer works too, but it
installs into whatever environment is active.</p>

<p>On the base image, <code>renest</code> is already on PATH, but <strong>the copy baked into
the image (tag <code>20260913</code>) is older than the latest release</strong>. It has no
<code>renest start</code> and doesn't print the <em>What's next</em> lines described in step 7.
Upgrade it the moment you're connected. If you skip this, the <code>renest start</code> command
in step 7 doesn't exist:</p>

<pre>$ uv tool install --upgrade renest
$ renest --version</pre>

<h2 id="key">4 · An access key is needed to pack to your drive, not to restore</h2>

<p><strong>Restoring doesn't need a key.</strong> The restore code from your drive is itself
the credential. Packing with <code>--dest hosted</code> does need one, and so do
<code>renest list</code> and <code>renest export</code>. There is no <code>renest login</code>
command.</p>

<p>Create a key in the web console under <strong>Settings → Access</strong>: in the
<em>Access keys</em> section, choose <strong>New key</strong> and give it a label such as
"my RunPod box". It is shown once. On the pod, write it into the tool's
config file, which only you can read:</p>

<pre>$ mkdir -p &#126;/.config/renest
$ ( umask 077; read -rsp "Access key: " k; echo
    printf '[auth]\ntoken = "%s"\n' "$k" &gt; &#126;/.config/renest/config.toml )</pre>

<p>Pasting at the prompt keeps the key out of your shell history, and <code>umask 077</code>
creates the file as 0600. If <code>config.toml</code> already has other settings, add the
<code>[auth]</code> section to it instead of overwriting it.</p>

<p>For a single session, you can use the <code>RENEST_TOKEN</code> environment variable instead
(<code>read -rsp "Access key: " RENEST_TOKEN; export RENEST_TOKEN</code>). It lasts only as
long as the shell. If both are set, the environment variable wins.</p>

<p>Be clear about where the key now lives. A file on a rented pod stays on that pod's disk
after you log out. Don't bake it into a template or an image, don't commit it, and
<strong>revoke it in Settings → Access when you're done with the pod</strong>. Your
account key is the only credential this path puts on the pod. Bucket keys never go there.</p>

<h2 id="pack">5 · Pack the run once it has worked</h2>

<p>Get the workflow rendering, or the training run finished, first. Renest captures only
setups that have already produced a result. Then, from the pod's terminal:</p>

<pre>$ renest pack --dir /workspace --workflow workflow-api.json &#92;
    --out /workspace/nests --dest hosted</pre>

<ul>
  <li><code>--dir</code> (required): the folder that holds <code>ComfyUI/</code>.</li>
  <li><code>--out</code> (required for a real pack): where the nest is written on this
  machine. <code>--dry-run</code> prints the plan without it.</li>
  <li><code>--dest hosted</code>: also upload it to your drive. Without this flag, the nest
  exists only in <code>--out</code>. The access key is checked <em>before</em> packing starts,
  so a missing key costs you nothing.</li>
  <li><code>--workflow</code>: must be exported in API format (<em>Export (API)</em> in
  ComfyUI). For fine-tuning, use <code>--framework kohya|llamafactory --run-record
  run.json</code> instead.</li>
</ul>

<p>Pack again from the same folder and Renest adds a new version to the same nest. Use
<code>--new-nest</code> to start a separate one. Prefer a button? The
<a href="docs-plugin-nest-this-run.html">ComfyUI panel</a> packs to the pod's disk, but it
doesn't upload, and on a pod it needs an SSH tunnel.</p>

<h2 id="restore">6 · Restore with the command your drive gives you</h2>

<p>In your drive, open the nest and choose <strong>Restore</strong>. Pick how long the restore
code should last: <em>1 day</em>, <em>3 days</em> or <em>7 days</em>. Copy the pod
command. It writes the code to <code>grant.json</code> and runs the restore. Paste it from
<code>/workspace</code>, so that <code>./run</code> lands on the volume disk (step 1):</p>

<pre>$ cd /workspace
$ cat &gt; grant.json &lt;&lt;'RENEST_GRANT'
&#123; …your restore code… &#125;
RENEST_GRANT
$ renest restore --grant grant.json --dir ./run</pre>

<p>Treat the code as a password. Anyone holding it can restore that version until it expires,
and you can revoke it from the drive at any time. It is <strong>not tied to a machine</strong>,
so the same code works on a replacement pod.</p>

<p>The restore checks the machine first, downloads every file and checks it against its
recorded checksum, installs dependencies from the lock, then starts the app and runs the
packed workflow once. <strong>A restore has succeeded when that run produces output</strong>
(an image, or a non-empty training artifact), not merely when the command exits cleanly. If
the connection drops, run the same command again. Files already on disk that match their
checksums are kept.</p>

<h2 id="after">7 · After the restore, your image is in the output folder and ComfyUI starts with renest start</h2>

<p><strong>Where is my image, and how do I open ComfyUI?</strong> Those are the first two
questions after a restore. Short answers: the test image is in
<code>/workspace/run/ComfyUI/output</code>; start ComfyUI with
<code>renest start --dir /workspace/run --listen 0.0.0.0</code>, expose HTTP port
<code>8188</code> on the pod (or tunnel over SSH), and open it in your browser. The full
walk-through, for any machine, is <a href="docs-after-restore.html">After the restore</a>.</p>

<p>The restore starts the app only for its own check, then stops it. Its closing lines are the
last thing it prints, below the JSON report: a <code>✅ Done</code> line followed by a
<strong>What's next:</strong> block. That block is built from this nest's own manifest, so its
commands and paths are the ones to use. For an image nest restored into
<code>/workspace/run</code> whose recorded start command listens on <code>127.0.0.1</code>, it
contains lines like these:</p>

<pre>[restore] What's next:
[restore]   · Start it yourself: cd /workspace/run/ComfyUI &amp;&amp; /workspace/run/.venv/bin/python main.py --listen 127.0.0.1.
[restore]   · That command listens on 127.0.0.1, which answers this machine only — right for the
            check that just ran, not for your browser. To reach it from outside, change that one
            value to 0.0.0.0 (or run `renest start --dir /workspace/run --listen 0.0.0.0`, which
            does it for you).
[restore]   · Started that way it listens on port 8188. On a rented GPU box, reaching it from your
            own browser also means exposing that port in your provider's panel — the check never
            did that for you.
[restore]   · Images render into /workspace/run/ComfyUI/output — that is where yours is.
[restore]   · The workflow that produced the test render: /workspace/run/.renest/staging/workflow.json.
            Drop it into the app to start from what worked.
[restore]   · Moving to another machine? The same restore command works there too — it reuses what is
            already fetched and carries on.
[restore]   · Or let the tool do it for you: renest start --dir /workspace/run</pre>

<p>If the recorded command names no address at all, the second and third lines are replaced
by one: <code>Started that way it listens on port 8188. On a rented GPU box, reaching it
from your own browser means it has to be listening on 0.0.0.0 and that port exposed in your
provider's panel — the check never did either for you.</code></p>

<p>In practice, for ComfyUI:</p>

<ul>
  <li><strong>Start it</strong> with <code>renest start --dir /workspace/run --listen
  0.0.0.0</code>. It runs exactly the command the block printed, from the same folder, with the
  restored Python environment, and <code>--listen</code> changes only the address that command
  already names. <code>--dry-run</code> prints the command and stops. If the recorded command
  names no address, <code>--listen</code> refuses rather than invent a flag; then run the
  printed command yourself with <code>--listen 0.0.0.0</code> added:
  <pre>$ cd /workspace/run/ComfyUI
$ /workspace/run/.venv/bin/python main.py --listen 0.0.0.0 --port 8188</pre></li>
  <li><strong>Open it.</strong> Either expose HTTP port <code>8188</code> on the pod and open
  RunPod's web address for that port, or skip the port and tunnel over SSH:
  <code>ssh -N -L 8188:127.0.0.1:8188 root@&lt;pod-address&gt; -p &lt;ssh-port&gt;</code>, then
  browse to <code>http://127.0.0.1:8188</code>. Over the tunnel, plain
  <code>renest start --dir /workspace/run</code> is enough.</li>
  <li><strong>Find your images</strong> in the <code>output</code> folder the block names.</li>
  <li><strong>Drag the workflow file it names into ComfyUI</strong> to start from what
  worked.</li>
  <li><strong>For a fine-tuning nest,</strong> the block instead names the output file the nest
  was packed to produce, and the command to run the training again.</li>
</ul>

<p>If the block has no start command, that's because the nest doesn't record one. It
doesn't guess.</p>

<h2 id="broken">If the machine turns out broken, destroy it and paste the same command on another</h2>

<p>The restore code is not tied to a machine. If a pod misbehaves (the GPU disappears, the
app can't see CUDA, the disk is slower or smaller than advertised), don't spend time repairing
it: copy off anything you want to keep, terminate it, start another pod from the same
template, and paste the same restore command from <code>/workspace</code>. Nothing is wrong
with your nest, and the code works until it expires or you revoke it. If it has expired, issue
a new one from the nest's <strong>Restore</strong> page.</p>

<h2 id="fail">When it stops, the message names the problem, and a replacement machine fixes most machine problems</h2>

<ul>
  <li><strong>The pre-flight check refuses.</strong> You'll see a plain reason: not enough
  disk, a driver too old for the lock's CUDA line, a GPU architecture the nest's compiled code
  doesn't support. This is the check doing its job before you pay for a download. Rent a
  machine that fits. <code>--force</code> goes ahead anyway, but only use it if you know
  better than the check.</li>
  <li><strong>A passed check doesn't guarantee the GPU is usable when the app starts.</strong>
  The check runs a full <code>nvidia-smi</code>. On a faulty host it warns with a line that
  begins <code>Full nvidia-smi failed here</code> and ends <code>replace the machine rather
  than re-downloading</code>. It warns rather than refuses, because the fault sometimes clears.
  A host can also pass that check and still fail when the app starts, with <code>No CUDA GPUs
  are available</code>. Either way, nothing is wrong with your nest. Stop that pod, start
  another, and paste the same restore command.</li>
  <li><strong>Anything else.</strong> If the tool prints an instruction, do that one thing and
  run the same command again. To turn a failed run into something you can read and paste into
  a ticket, run <code>renest support --dir ./run</code>. It never goes online and never
  uploads. Do this <em>before</em> you stop the pod.</li>
</ul>

<h2 id="stop">Copy what you need, then stop or terminate the pod</h2>

<p>A running pod is billed whether or not you're using it. Before you stop it:</p>

<ol>
  <li>Copy off your outputs, and anything from <code>renest support</code> you want to keep.</li>
  <li>If you put an access key on the pod, revoke it in <strong>Settings →
  Access</strong>.</li>
  <li><strong>Stop</strong> keeps the volume disk, which RunPod still charges for.
  <strong>Terminate</strong> deletes the pod and all data that isn't on a network volume. Your nest is safe either way: it's
  on your drive, and a new restore code, or the unexpired old one, brings it back on the next
  pod.</li>
</ol>
