Docs/Getting started
Getting started

The tenant environment

By Samuel Seidel · Updated September 19, 2026 · 6 min read

A GPUwerk instance is a Docker container on a dedicated DGX Spark, not a virtual machine and not bare metal. That distinction decides what you can install, what a restart keeps, and which commands don't exist here at all. This page is the reference for what's actually underneath the shell you land in.

On this page
  1. What you get
  2. What the container is not
  3. What persists across a restart
  4. The startup hook
  5. Storage: the shared 1 TB NVMe
  6. Networking

What you get

Each instance is one dedicated DGX Spark: a GB10 chip with 128 GB of unified memory shared between CPU and GPU, not split across the two. Your workload runs as a Docker container with that GPU passed straight through, and inside the container you are root.

The NVIDIA driver and the CUDA userspace come from the host and the image, not from you. You never install or upgrade a driver yourself, and there would be no point trying: the kernel module lives on the host, outside the container entirely, and a rebuild would hand you back whatever the image ships anyway.

What the container is not

It is not a full Linux host. There's no systemd and nothing running as PID 1 except the entrypoint script, which execs into sshd. systemctl has nothing to talk to and fails outright. Run your own services from an interactive shell, from tmux so they survive a disconnect, or from the startup hook below so they come back after a restart on their own.

The container also runs with a deliberately short capability list, not the full root capability set a VM would give you: changing file ownership and permissions, binding to ports below 1024, sending signals to other processes, and chrooting. It does not get NET_ADMIN, so there's no /dev/net/tun, no VPN client or Tailscale running in kernel mode, and no custom iptables rules. There's no Docker socket and no privileged mode, so Docker-in-Docker doesn't run either. The cgroup and mount namespaces belong to the container, not the host, so you can't mount a block device or change your own cgroup limits from inside it.

What persists across a restart

/workspace is a named Docker volume, separate from the container's own filesystem. It survives a restart and a rebuild. A rebuild reinstalls the image fresh and reattaches the same /workspace, so anything you installed outside it, an apt package under /usr, a pip install into the system Python, is gone; anything under /workspace is not.

Stopping an instance takes one of two paths depending on your plan. A held node stays reserved for you, quiesced, so starting again is seconds. Otherwise, stopping archives /workspace to GPUwerk's storage and frees the node for someone else; starting again pulls that archive back down, slower the bigger it is. Either way /workspace survives the stop. There's a 30 GB cap on what archives automatically: go over it and the node isn't released, because releasing hardware we couldn't finish copying off would mean losing the data. Free up space, keep the instance running or held instead, or contact support if you need more room on a regular basis. Terminate is the one action that deletes /workspace for good, which is why it asks you to type the instance name first.

SSH host keys are the other thing kept in /workspace, under .hostkeys, so your instance's identity doesn't change across a restart and you don't get a fresh host-key warning every time.

The startup hook

If you keep long-running services under /workspace, you no longer have to SSH in and start them by hand after every restart. Make /workspace/.gpuwerk-init executable and it runs automatically on every container start, first boot, restart or rebuild alike, as root. It's launched detached, so a hook that hangs or exits with an error can never delay or block SSH coming up; its output goes to /workspace/.gpuwerk-init.log, not your terminal. Available on images built after September 19, 2026. If your instance was deployed earlier, a rebuild picks up the new image.

#!/bin/sh
# /workspace/.gpuwerk-init: must not block, it runs detached anyway
cd /workspace
nohup llama-server -m my-model.gguf --host 0.0.0.0 --port 8899 \
    >> llama-server.log 2>&1 &
nohup python3 my-service.py >> my-service.log 2>&1 &

Check /workspace/.gpuwerk-init.log after a restart to confirm it ran; each run writes a timestamp line before launching, so you can tell one restart's output from the next.

Storage: the shared 1 TB NVMe

Every Spark has 1 TB of NVMe, and it's one filesystem, not a slice cut out for you. The host, GPUwerk's own container images, staged model weights for on-demand serving, and your container plus /workspace all sit on the same disk. df run inside your container reports the node-wide numbers, not a per-tenant quota, so "Used" includes provider-side files you can't see or list, and the inode count works the same way. What df reports as free is genuinely what you can use; how much of the rest is provider-side data varies by node, so we won't promise a specific free amount here. Contact support if you need more headroom on a reserved node.

Networking

Every instance gets SSH on the port the console shows on the instance page, and one application port forwarded from the outside to a port inside the container, 8888 by default. Outbound internet access is allowed, so pip install, git clone and a model download all work normally. For the forwarded app port to actually answer, your service has to bind 0.0.0.0 inside the container, not 127.0.0.1: Docker's port publishing reaches the container's network namespace from outside, and a service listening only on loopback is invisible to it.

NextCreate an SSH key and connect Back toAll docs

Nothing to unbox.

A dedicated DGX Spark in EU-Central, available through the console, with $20 in credit for your first $10 top-up.

Deploy a Spark