[ docs ]
Everything you need to run a sandbox
Boot a clean machine, reach it over SSH or HTTP, deploy anything on it, and let it destroy itself.
Quickstart
Create an account, open the dashboard, pick a base image and a time to live, then press Create sandbox. It boots in about half a second.
Every sandbox gets a URL immediately. Your machine is running a web server on port 8080 serving /srv/app:
http://<sandbox-id>.rishiii.me
Nothing persists. When the TTL runs out the machine is destroyed and its disk is wiped.
SSH keys
SSH uses public keys — there is no password. If you do not already have a key, generate one:
ssh-keygen -t ed25519 -C "you@example.com" # press enter to accept the default path (~/.ssh/id_ed25519) # a passphrase is optional but recommended
Then copy the public half — the file ending in .pub:
pbcopy < ~/.ssh/id_ed25519.pub
cat ~/.ssh/id_ed25519.pub
Paste it into the dashboard under [ ssh access ] → Add SSH key. It takes effect immediately.
.pub file. The file without an extension is your private key — it never leaves your machine.Connecting
List the sandboxes your key can reach:
ssh sandbox@rishiii.me
Open an interactive shell inside one:
ssh -t sandbox@rishiii.me <sandbox-id>
Or run a single command and exit:
ssh sandbox@rishiii.me <sandbox-id> "uname -a"
-t flag asks for a terminal. Without it you get no prompt, colours, or line editing.You connect as sandbox@ regardless of your account — your key decides which machines you can open, and you can only ever reach your own.
Deploying an app
Anything you serve on port 8080 is published at your sandbox URL. The simplest version is to drop files into /srv/app, which is already being served:
ssh -t sandbox@rishiii.me <id> echo "<h1>hello world</h1>" > /srv/app/index.html # refresh your sandbox URL
To run your own server instead, stop the default one and bind port 8080. On the node-22 image:
ssh -t sandbox@rishiii.me <id>
pkill busybox # free port 8080
mkdir -p /app && cd /app
npm init -y && npm install express
cat > server.js <<'EOF'
const express = require('express')
const app = express()
app.get('/', (_, res) => res.send('deployed on HyperNode'))
app.listen(8080, '0.0.0.0')
EOF
node server.jsCopy files up from your machine with scp or rsync:
# scp/rsync go through the same gateway tar czf - ./dist | ssh sandbox@rishiii.me <id> "tar xzf - -C /srv/app"
0.0.0.0, not 127.0.0.1. A server listening only on loopback is not reachable from outside the sandbox.Limits & lifecycle
| Resource | Limit |
|---|---|
| Sandboxes per account | 1 at a time |
| Memory | 512 MB (hard cap, no swap) |
| CPU | 0.5 cores |
| Processes | 256 |
| Disk | 2 GB writable |
| Time to live | 30 minutes, 1 hour, or 4 hours |
Base images: ubuntu-24.04, alpine-3.20, node-22, python-3.12. All are arm64.
A reaper runs every 30 seconds and destroys machines that are past their TTL, over their disk limit, or have crashed. Destroying is permanent: the writable layer is wiped, so copy anything you want to keep back out first.
Isolation & security
Sandboxes are not plain containers. Each one runs on gVisor, a user-space kernel that intercepts syscalls, so guest code never talks to the host kernel directly. Inside, uname -r reports 4.19.0-gvisorrather than the host's kernel.
| Control | State |
|---|---|
| Kernel | gVisor (runsc), not the host kernel |
| Linux capabilities | all dropped |
| Privilege escalation | blocked (no-new-privileges) |
| Docker socket | never mounted |
| Host filesystem | not visible |
| Cloud metadata endpoint | blocked |
| Outbound SMTP | blocked (anti-abuse) |
You are root inside your own sandbox and can install whatever you like. Outbound internet works normally, so apt, apk, npm and pip all behave as expected.
Troubleshooting
| Symptom | Cause & fix |
|---|---|
Permission denied (publickey) | No key added yet, or the wrong one. Add your .pub in the dashboard and confirm with ssh -i <key> sandbox@host. |
sandbox <id> not found | It expired, or it is not yours. Run ssh sandbox@host with no arguments to list what you can reach. |
| URL shows the placeholder page | Your server is not on port 8080 yet, or it is bound to 127.0.0.1 instead of 0.0.0.0. |
| Sandbox vanished early | It hit its TTL, exceeded 2 GB of disk, or was OOM-killed at 512 MB. |
| You can run one sandbox at a time | Destroy the running one from the dashboard first. |
Self-hosting this platform? See docs/DEPLOY.md in the repository for the host setup, firewall rules, and TLS.