Developer Tools

    Self-Host the Sandpack Bundler

    Run CodeSandbox's in-browser code execution engine on your own RamNode VPS. Your users' code never leaves your infrastructure, CORS is fully under your control, and you can pin bundler versions indefinitely.

    Docker
    Nginx + TLS
    ~20 Minutes
    1GB RAM

    What You Will Build

    A production-ready Sandpack bundler service running in Docker behind an Nginx reverse proxy with a TLS certificate. Once deployed, any Sandpack-powered application can point its bundlerURL at your domain instead of CodeSandbox's servers.

    Prerequisites

    • A RamNode VPS running Ubuntu 22.04 LTS with at least 1 GB RAM and 10 GB disk
    • A domain name or subdomain pointed at your VPS IP (e.g., sandbox.yourdomain.com)
    • Root or sudo access
    • SSH access to the server

    Need help with initial setup? See our Initial Server Setup for Ubuntu guide.

    1

    Update the System and Install Docker

    Start by logging into your VPS and bringing the package list up to date.

    Update system packages
    sudo apt update && sudo apt upgrade -y

    Install Docker using the official convenience script:

    Install Docker
    curl -fsSL https://get.docker.com | sh
    sudo usermod -aG docker $USER
    newgrp docker

    Verify Docker is running:

    Verify installation
    docker --version
    docker run hello-world

    You should see Hello from Docker! confirming the daemon is active.

    2

    Pull and Run the Sandpack Bundler Container

    The LibreChat team maintains a pre-built Docker image of the CodeSandbox bundler that packages an optimized Nginx configuration alongside the compiled bundler static files.

    Pull the bundler image
    docker pull ghcr.io/librechat-ai/codesandbox-client/bundler:latest

    Run the container on port 8080:

    Start the bundler container
    docker run -d \
      --name sandpack-bundler \
      --restart unless-stopped \
      -p 8080:80 \
      ghcr.io/librechat-ai/codesandbox-client/bundler:latest

    Confirm the container is running:

    Verify the container
    docker ps

    Test it locally:

    Test local response
    curl -I http://localhost:8080

    A 200 OK response confirms the bundler is serving files correctly.

    3

    Install Nginx and Certbot

    The bundler needs to be accessible over HTTPS on a public domain. Install Nginx and Certbot:

    Install Nginx and Certbot
    sudo apt install -y nginx certbot python3-certbot-nginx
    4

    Configure the Nginx Reverse Proxy

    Create a new Nginx server block for your sandpack subdomain:

    Create Nginx config
    sudo nano /etc/nginx/sites-available/sandpack

    Paste the following configuration, replacing sandbox.yourdomain.com with your actual subdomain:

    /etc/nginx/sites-available/sandpack
    server {
        listen 80;
        server_name sandbox.yourdomain.com;
    
        location / {
            proxy_pass         http://127.0.0.1:8080;
            proxy_http_version 1.1;
    
            proxy_set_header   Host              $host;
            proxy_set_header   X-Real-IP         $remote_addr;
            proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Proto $scheme;
    
            # CORS headers — tighten the origin in production
            add_header Access-Control-Allow-Origin  "*" always;
            add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
            add_header Access-Control-Allow-Headers "Content-Type" always;
    
            # Cache static bundler assets aggressively
            proxy_cache_bypass $http_upgrade;
            expires 7d;
            add_header Cache-Control "public, immutable";
        }
    }

    Enable the site and test the configuration:

    Enable and test Nginx config
    sudo ln -s /etc/nginx/sites-available/sandpack /etc/nginx/sites-enabled/
    sudo nginx -t
    sudo systemctl reload nginx
    5

    Obtain a TLS Certificate

    Browsers require HTTPS for Service Workers, which Sandpack relies on for caching transpilers. Run Certbot to obtain a free Let's Encrypt certificate:

    Obtain TLS certificate
    sudo certbot --nginx -d sandbox.yourdomain.com

    Choose option 2 when asked whether to redirect HTTP to HTTPS — this ensures all traffic is encrypted.

    Verify auto-renewal is set up:

    Check renewal timer
    sudo systemctl status certbot.timer
    6

    Verify the Deployment

    Open a browser and navigate to https://sandbox.yourdomain.com. You should see an Nginx response or blank page — this is expected. The bundler serves JavaScript assets, not a visual UI.

    Confirm it is working by requesting a known asset path:

    Test bundler endpoint
    curl -I https://sandbox.yourdomain.com/static/js/sandbox.js

    A 200 OK with Content-Type: application/javascript confirms the bundler is live and reachable.

    7

    Connect Your Application to the Self-Hosted Bundler

    Any application using sandpack-react or sandpack-client can now point to your VPS. Update the bundlerURL option:

    React (sandpack-react)

    React integration
    import { Sandpack } from "@codesandbox/sandpack-react";
    
    export default function CodePlayground() {
      return (
        <Sandpack
          template="react"
          options={{
            bundlerURL: "https://sandbox.yourdomain.com",
          }}
        />
      );
    }

    Vanilla JS (sandpack-client)

    Vanilla JS integration
    import { SandpackClient } from "@codesandbox/sandpack-client";
    
    const client = new SandpackClient(
      iframeElement,
      sandboxInfo,
      { bundlerURL: "https://sandbox.yourdomain.com" }
    );

    LibreChat integration

    If you are running a self-hosted LibreChat instance, add the following to your .env file:

    .env
    SANDPACK_BUNDLER_URL=https://sandbox.yourdomain.com
    8

    Keep the Container Updated

    The bundler image is updated periodically. To pull the latest version and restart:

    Update the bundler
    docker pull ghcr.io/librechat-ai/codesandbox-client/bundler:latest
    docker stop sandpack-bundler
    docker rm sandpack-bundler
    docker run -d \
      --name sandpack-bundler \
      --restart unless-stopped \
      -p 8080:80 \
      ghcr.io/librechat-ai/codesandbox-client/bundler:latest

    You can automate this with a cron job or a simple shell script scheduled via crontab -e.

    Hardening CORS for Production

    The configuration above uses Access-Control-Allow-Origin: *, which is fine for testing but overly permissive in production. Replace the wildcard with your application's origin:

    Single origin
    add_header Access-Control-Allow-Origin "https://yourapp.com" always;

    If you need to allow multiple origins, use a conditional in Nginx:

    Multiple origins
    set $cors_origin "";
    if ($http_origin ~* "^https://(yourapp\.com|staging\.yourapp\.com)quot;) {
        set $cors_origin $http_origin;
    }
    add_header Access-Control-Allow-Origin $cors_origin always;

    Troubleshooting

    Container exits immediately

    Run docker logs sandpack-bundler to inspect the output. Missing port bindings are the most common cause.

    CORS errors in the browser

    Confirm the Access-Control-Allow-Origin header is present using curl -I -H "Origin: https://yourapp.com" https://sandbox.yourdomain.com. If the header is missing, check that Nginx has been reloaded after your config change.

    Service Worker fails to register

    This almost always means the bundler is being served over HTTP rather than HTTPS. Double-check that Certbot completed successfully and that the HTTPS redirect is active.

    Bundler loads but code does not execute

    The bundler fetches npm package tarballs from the public npm CDN at runtime. If your VPS is behind a restrictive firewall, ensure outbound traffic to registry.npmjs.org is permitted.

    Resource Usage

    On a RamNode 1GB VPS, the bundler container uses approximately 30–50 MB of RAM at idle and peaks around 80 MB under moderate concurrent load. The Docker image is roughly 45 MB compressed. This makes it viable to run alongside other services on even the smallest RamNode plan, though a 2GB instance gives comfortable headroom for co-hosting an application and its bundler on the same node.

    What's Next

    • Pin a specific image tag instead of latest to lock bundler behavior across deployments
    • Add rate limiting in Nginx using limit_req_zone to prevent abuse on public-facing instances
    • Monitor with Uptime Kuma — see the RamNode Uptime Kuma deployment guide for a lightweight self-hosted monitoring setup
    • Deploy LibreChat alongside this bundler to get a full self-hosted AI assistant with live code execution capabilities