How to set up a custom domain for Sandboxes hosted on E2B.
We will set up a GCP VM running Caddy server with Docker and Cloudflare DNS to proxy the requests to the Sandboxes.
Example: 8080-sandboxid.mydomain.com -> 8080-sandboxid.e2b.app
Prerequisites
- Domain name registered and configured with Cloudflare DNS.
- Cloudflare API Token that allows you to manage DNS records.
GCP VM Setup
-
Create a VM instance by running the following command:
Replace your-project-id with your actual project ID.
gcloud compute instances create e2b-custom-domain-proxy \
--project=your-project-id \
--zone=us-west1-a \
--machine-type=n2-standard-2 \
--can-ip-forward \
--tags=http-server,https-server \
--image-project=debian-cloud \
--image-family=debian-12 \
--boot-disk-size=20GB
-
After the VM is created, you can connect to it using the following command:
Replace your-project-id with your actual project ID.
# May take a few seconds until the instance is ready to accept SSH connections
gcloud compute ssh e2b-custom-domain-proxy \
--project=your-project-id \
--zone=us-west1-a
Server Setup
-
Install the latest stable version of Docker:
curl -fsSL https://get.docker.com | sudo sh
-
Create a Dockerfile that will be used to build the Caddy server image with Cloudflare DNS:
FROM caddy:builder AS builder
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare
FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
-
Create a Docker Compose file that will be used to start the Caddy server:
services:
caddy:
build:
context: .
dockerfile: Dockerfile
container_name: caddy-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp" # Optional: HTTP/3
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
environment:
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
networks:
- caddy_network
volumes:
caddy_data:
caddy_config:
networks:
caddy_network:
driver: bridge
-
Create a Caddyfile for proxying the requests to the Sandboxes:
Replace *.mydomain.com with your actual wildcard domain name.
*.mydomain.com {
# Use Cloudflare DNS for ACME challenge
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
# Capture sandboxId for reuse
# {labels.N} splits the host by "." and indexes from right to left:
# e.g., for "abc123.mydomain.com":
# {labels.0} = "com" (TLD)
# {labels.1} = "mydomain" (domain)
# {labels.2} = "abc123" (subdomain)
vars sandboxId {labels.2}
# Reverse proxy to corresponding e2b.app Sandbox
reverse_proxy {vars.sandboxId}.e2b.app:443 {
# Set the Host header to the e2b.app domain
header_up Host {vars.sandboxId}.e2b.app
# Forward real IP
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Host {host}
# Use HTTPS to upstream
transport http {
tls
tls_server_name {vars.sandboxId}.e2b.app
}
}
# Optional: Add logging
log {
output file /var/log/caddy/access.log
format json
}
}
-
Create a .env file that will be used to store the Cloudflare API Token:
CLOUDFLARE_API_TOKEN=your-cloudflare-api-token
-
Build and start the Caddy server:
docker compose build
docker compose up -d
Domain Setup
Log into the Cloudflare dashboard and create a new A wildcard DNS record pointing to the IP address of the GCP VM.
Replace GCP_VM_IP with the IP address of the GCP VM.
It may take a few minutes for the DNS record to propagate and for the certificate to be issued.
If you have existing AAAA (IPv6) records for this domain name, make sure they are either removed or updated to point to the GCP VM.
*.mydomain.com A GCP_VM_IP
Testing the Setup
We will create a new Sandbox on E2B and install a simple HTTP server in it.
-
Create a new Sandbox using E2B CLI:
-
Install and run a simple HTTP server in the sandbox:
sudo apt install nginx
sudo systemctl start nginx
-
Visit the sandbox URL in your browser:
https://80-sandboxid.mydomain.com. You should see the default nginx welcome page.