> ## Documentation Index
> Fetch the complete documentation index at: https://docs.siftd.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SPIN Runtime

The SPIN Runtime executes notebook code within your infrastructure.
It is built on a Python-based Jupyter server with Docker containerization, featuring custom cell processors for each integration.
You can deploy it on Docker, Kubernetes, or cloud instances.

## Communication with the Runtime

Communication with the spin runtime is done via a websocket connection from the browser.
The runtime does not need to be reachable by the SPIN's cloud hosted control plane.
For more information see our [architecture docs](../architecture).

When adding a new runtime via the SPIN UI, you have to specify the URL of the runtime.
When sharing a runtime across your team, you will need to host the runtime in a way that is reachable by all those members.
Making it accessible from the internet via a public URL is an option.
Constraining access to the runtime via a VPN (such as [Tailscale](./tailscale-runtime)) or an SSH tunnel is another option that can enhance security.

<Note>
  Note that for runtimes not running on the users machine directly
  require a secure connection via **HTTPS** with a **valid certificate**.
  This is because the browser will not allow the runtime to connect to a non-secure origin unless the origin is `localhost`.
  See [Enabling HTTPS for the Runtime](#enabling-https-for-the-runtime) for detailed instructions on how to configure SSL certificates.
</Note>

## Deploy in Your Own Infrastructure

A Docker image is available for deployment in your own environment:

```
ghcr.io/siftd/spin-runtime:latest-prod
```

#### Docker

Run the runtime as a standalone container:

```bash theme={null}
docker run -d --name spin-runtime -p 8888:8888 \
           -v spin-runtime-data:/opt/spin/var \
           -e SPIN_TOKEN=your-secure-token \
           ghcr.io/siftd/spin-runtime:latest-prod
```

#### Docker Compose

Example configuration for Docker Compose:

```yaml compose.yml theme={null}
services:
  spin-runtime:
    image: ghcr.io/siftd/spin-runtime:latest-prod
    environment:
      - SPIN_TOKEN=your-secure-token
    ports:
      - "8888:8888"
    volumes:
      - spin-runtime-data:/opt/spin/var
    restart: unless-stopped

volumes:
  spin-runtime-data:
    driver: local
```

<Card title="Set up with Tailscale" icon="lock" href="/guide/tailscale-runtime">
  With Tailscale you can access the SPIN runtime without exposing it to the public internet.
  See how to configure SPIN runtime with Tailscale sidecar in Docker Compose.
</Card>

<Card title="Set up with Cloudflare Tunnels" icon="lock" href="/guide/cf-tunnels-runtime">
  With Cloudflare Tunnels you can access the SPIN runtime without exposing it to the public internet.
  See how to configure SPIN runtime with Cloudflare Tunnels in Docker Compose.
</Card>

### Kubernetes

TODO: Add instructions for deploying in Kubernetes.

## Upgrading the Runtime

When new versions of the SPIN runtime are released, you'll need to update your deployment to use the latest image.

### Docker

For standalone Docker containers:

```bash theme={null}
# Stop and remove the existing container
docker stop spin-runtime
docker rm spin-runtime

# Pull the latest image
docker pull ghcr.io/siftd/spin-runtime:latest-prod

# Start a new container with the same configuration
docker run -d --name spin-runtime -p 8888:8888 \
           -v spin-runtime-data:/opt/spin/var \
           -e SPIN_TOKEN=your-secure-token \
           ghcr.io/siftd/spin-runtime:latest-prod
```

### Docker Compose

For Docker Compose deployments, upgrading is simpler:

```bash theme={null}
# Pull the latest image and recreate the container
docker compose up -d --pull always
```

This command will:

* Pull the latest version of the image
* Recreate containers if the image has changed
* Preserve your volumes and configuration

## Cloud-Hosted Runtime

For testing, you can spin up a cloud-hosted runtime with a few clicks. This is great for experimentation, but for production use, we recommend self-hosting.

## Configuration

Configure the SPIN runtime using these environment variables:

| Variable              | Description                                                                                                                                                                                                          |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SPIN_TOKEN`          | Required. Secure token for authenticating connections to the runtime. Must match the token provided when adding the runtime to your workspace.                                                                       |
| `SPIN_HOME`           | Optional. Base directory for SPIN runtime files. Defaults to /opt/spin.                                                                                                                                              |
| `REQUESTS_CA_BUNDLE`  | Optional. Path to a CA certificate bundle file or directory for SSL verification. When not set, SSL certificate validation is disabled for outbound requests from the runtime. Set this to enforce SSL verification. |
| `<your-env-var-name>` | Optional. Any other environment variable can be passed to the runtime. Refer to them using the `{{runtime_env:<your-env-var-name>}}` syntax.                                                                         |

### Enabling HTTPS for the Runtime

By default, the SPIN runtime serves connections over HTTP. For production deployments where the runtime is accessed over the network (not localhost), you'll need to serve it over HTTPS.

There are several ways to achieve this:

* **Enable HTTPS directly on the runtime** (covered in this section)
* **Use a reverse proxy** (like nginx or Apache) that terminates SSL
* **Use a gateway or load balancer** that handles SSL termination
* **Use a tunnel solution** like [Cloudflare Tunnels](./cf-tunnels-runtime) or [Tailscale](./tailscale-runtime)

This section covers how to enable HTTPS directly on the runtime. If you prefer to handle SSL termination elsewhere in your infrastructure, you can continue running the runtime over HTTP and configure your proxy/gateway accordingly.

#### What You'll Need

To enable HTTPS, you need:

1. **SSL Certificate (`cert.pem`)**: This is your public certificate file that proves the identity of your server
2. **Private Key (`key.pem`)**: This is the private key that corresponds to your certificate

These files work together to encrypt the connection between browsers and your SPIN runtime. Without HTTPS, browsers will block connections to non-localhost addresses for security reasons.

#### Docker

To run the runtime with HTTPS enabled:

```bash theme={null}
docker run -d --name spin-runtime -p 8888:8888 \
           -v spin-runtime-data:/opt/spin/var \
           -v ./path/to/key.pem:/ssl/key.pem:ro \
           -v ./path/to/cert.pem:/ssl/cert.pem:ro \
           -e SPIN_TOKEN=<YOUR-GENERATED-TOKEN> \
           -e SSL_KEY_FILE=/ssl/key.pem \
           -e SSL_CERT_FILE=/ssl/cert.pem \
           ghcr.io/siftd/spin-runtime:latest-prod
```

Replace:

* `./path/to/key.pem` and `./path/to/cert.pem` with the actual paths to your SSL files
* `<YOUR-GENERATED-TOKEN>` with the actual SPIN\_TOKEN from UI Add Runtime flow

#### Docker Compose

For Docker Compose, add the SSL configuration to your service:

```yaml compose.yml theme={null}
services:
  spin-runtime:
    image: ghcr.io/siftd/spin-runtime:latest-prod
    environment:
      - SPIN_TOKEN=<YOUR-GENERATED-TOKEN>
      - SSL_KEY_FILE=/ssl/key.pem
      - SSL_CERT_FILE=/ssl/cert.pem
    ports:
      - "8888:8888"
    volumes:
      - spin-runtime-data:/opt/spin/var
      - ./path/to/key.pem:/ssl/key.pem:ro
      - ./path/to/cert.pem:/ssl/cert.pem:ro
    restart: unless-stopped

volumes:
  spin-runtime-data:
    driver: local
```

<Note>
  When HTTPS is enabled, the runtime will serve connections using TLS encryption. Make sure to update your runtime URL in the SPIN UI to use `https://` instead of `http://`.
</Note>

<Warning>
  * The `:ro` suffix on volume mounts makes the certificates read-only, which is a security best practice
  * Keep your private key (`key.pem`) secure and never commit it to version control
  * Never share or commit your SPIN\_TOKEN - treat it like a password
  * Ensure your certificate is valid for the domain/hostname you're using to access the runtime
</Warning>

### SSL Certificate Validation

By default, the SPIN runtime disables SSL certificate validation for outbound HTTPS requests to external services (e.g., APIs, data sources). This behavior helps avoid issues with self-signed certificates or internal certificate authorities in enterprise environments.

To enable SSL certificate validation, set the `REQUESTS_CA_BUNDLE` environment variable. This can point to either:

* **A single certificate bundle file** (e.g., `/etc/ssl/certs/ca-bundle.crt`)
* **A directory containing multiple certificates** (e.g., `/etc/ssl/certs/`)

<Note>
  When using a directory, it must be prepared using the `c_rehash` utility supplied with OpenSSL. This creates symbolic links with hashed filenames that allow efficient certificate lookup.

  Example of preparing a certificate directory:

  ```bash theme={null}
  # Copy your certificates to a directory
  mkdir ./certs
  cp /path/to/your/*.crt ./certs/

  # Process the directory with c_rehash
  c_rehash ./certs
  ```
</Note>

To enable SSL certificate validation:

1. **For Docker**: Mount your CA certificates and set the environment variable.

   Using a certificate bundle file:

   ```bash theme={null}
   docker run -d --name spin-runtime -p 8888:8888 \
              -v spin-runtime-data:/opt/spin/var \
              -v /path/to/ca-bundle.crt:/etc/ssl/certs/ca-bundle.crt:ro \
              -e SPIN_TOKEN=your-secure-token \
              -e REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt \
              ghcr.io/siftd/spin-runtime:latest-prod
   ```

   Using a certificate directory (must be processed with c\_rehash):

   ```bash theme={null}
   docker run -d --name spin-runtime -p 8888:8888 \
              -v spin-runtime-data:/opt/spin/var \
              -v /path/to/certs:/etc/ssl/certs:ro \
              -e SPIN_TOKEN=your-secure-token \
              -e REQUESTS_CA_BUNDLE=/etc/ssl/certs \
              ghcr.io/siftd/spin-runtime:latest-prod
   ```

2. **For Docker Compose**: Add the certificate volume and environment variable.

   Using a certificate bundle file:

   ```yaml compose.yml theme={null}
   services:
     spin-runtime:
       image: ghcr.io/siftd/spin-runtime:latest-prod
       environment:
         - SPIN_TOKEN=your-secure-token
         - REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-bundle.crt
       ports:
         - "8888:8888"
       volumes:
         - spin-runtime-data:/opt/spin/var
         - ./ca-bundle.crt:/etc/ssl/certs/ca-bundle.crt:ro
       restart: unless-stopped
   ```

   Using a certificate directory:

   ```yaml compose.yml theme={null}
   services:
     spin-runtime:
       image: ghcr.io/siftd/spin-runtime:latest-prod
       environment:
         - SPIN_TOKEN=your-secure-token
         - REQUESTS_CA_BUNDLE=/etc/ssl/certs
       ports:
         - "8888:8888"
       volumes:
         - spin-runtime-data:/opt/spin/var
         - ./certs:/etc/ssl/certs:ro  # Directory must be processed with c_rehash
       restart: unless-stopped
   ```

<Warning>
  When `REQUESTS_CA_BUNDLE` is not set, the runtime will accept any SSL certificate. This may pose security risks in production environments. Consider enabling SSL verification for production deployments.
</Warning>

## Host SSH Access

This feature allows the SPIN runtime container to SSH into its host machine, enabling you to run shell commands directly on the host system from your notebooks.

### Enabling Host SSH Access

1. When adding or editing a SPIN Runtime in the UI, enable the **Host SSH Access** option
2. Provide the SSH username for the host machine
3. Provide the SSH private key for authentication (if needed, instructions to generate ssh key pair below)

### Generating an SSH Key Pair

If you don't already have an SSH key pair for this purpose, generate one:

```bash theme={null}
ssh-keygen -t ed25519 -f ~/.ssh/spin_host_key -N ""
```

This creates:

* `~/.ssh/spin_host_key` — your private key (provide this to SPIN)
* `~/.ssh/spin_host_key.pub` — your public key (add this to `~/.ssh/authorized_keys`)

Add the public key to your authorized keys:

```bash theme={null}
cat ~/.ssh/spin_host_key.pub >> ~/.ssh/authorized_keys
```

For more information on SSH key generation, see [GitHub's SSH key guide](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) or your operating system's documentation.

### Configuring SSH on the Host Machine

The SPIN runtime runs inside a Docker container, which means it doesn't have direct access to the machine running Docker (the Docker host). Host SSH Access bridges this gap by allowing the runtime to SSH into the Docker host over localhost. This lets you run tools or scripts installed on the host, access files outside the container, or execute commands that require host-level access.

To use this feature, you'll need to enable SSH on the Docker host and optionally restrict it to localhost connections.

#### macOS

**1. Enable SSH**

Enable Remote Login in System Settings:

**System Settings > General > Sharing > Remote Login**

**2. Restrict SSH to localhost only (recommended)**

On macOS, SSH is managed by `launchd` which ignores `ListenAddress` settings in sshd\_config. Use the macOS firewall (pf) to block external SSH connections instead.

Create a firewall rule:

```bash theme={null}
echo "block in on ! lo0 proto tcp to any port 22" | sudo tee /etc/pf.anchors/ssh-local
```

Add the rule to the pf configuration by editing `/etc/pf.conf`:

```bash theme={null}
sudo nano /etc/pf.conf
```

Add these lines at the end of the file:

```text theme={null}
anchor "ssh-local"
load anchor "ssh-local" from "/etc/pf.anchors/ssh-local"
```

Enable the firewall:

```bash theme={null}
sudo pfctl -ef /etc/pf.conf
```

<Note>
  You may see warnings about "No ALTQ support" and "pf already enabled" — these are normal and can be ignored.
</Note>

**3. Verify SSH is local-only**

Verify the rule is loaded:

```bash theme={null}
sudo pfctl -a ssh-local -s rules
```

You should see:

```
block in on ! lo0 proto tcp from any to any port = 22
```

Test by running `ssh localhost` (should work) and attempting SSH from another machine (should be blocked).

#### Ubuntu Linux

**1. Install and enable SSH**

```bash theme={null}
sudo apt update
sudo apt install openssh-server
sudo systemctl enable ssh
sudo systemctl start ssh
```

**2. Restrict SSH to localhost only (recommended for personal laptops/computers)**

Edit the SSH daemon config:

```bash theme={null}
sudo nano /etc/ssh/sshd_config
```

Add or modify these lines:

```text theme={null}
ListenAddress 127.0.0.1
ListenAddress ::1
```

**3. Restart sshd**

```bash theme={null}
sudo systemctl restart ssh
```

**4. Verify SSH is local-only**

```bash theme={null}
ss -tlnp | grep :22
```

You should see SSH listening only on `127.0.0.1:22` and `[::1]:22`.

#### Other Linux Distributions

For other Linux distributions, the general steps are similar:

1. Install OpenSSH server (package name varies by distro)
2. Edit `/etc/ssh/sshd_config` to set `ListenAddress` to localhost
3. Restart the SSH service

Consult your distribution's documentation or the [OpenSSH documentation](https://www.openssh.com/manual.html) for specific instructions.

### Testing Host SSH Access

Once configured, test the connection from a SPIN notebook:

1. Add a **Shell** cell to your notebook
2. In the cell's type dropdown, select **SSH**
3. In the **SSH Connection** dropdown, select **Runtime Host**
4. Run a simple command like `ls` or `whoami` to verify the connection works

<Warning>
  * Keep your SSH private key secure and never share it
  * Restricting SSH to localhost is strongly recommended to prevent external access
  * Consider using a dedicated SSH key pair specifically for SPIN runtime access
</Warning>
