Getting Started
Everything you need to go from zero to a running sandbox.
1. Install the CLI
Download the latest release from GitHub Releases, then extract it:
tar xzf sandcastle_*.tar.gz
sudo mv sandcastle /usr/local/bin/
2. Log in
Point the CLI at this server and authenticate via your browser:
sandcastle login https://demo.sandcastle.rocks
3. Enable Tailscale (recommended)
Each sandbox gets its own Tailscale IP so you can reach services directly — no port forwarding needed.
# Interactive login — opens a browser URL to authenticate
sandcastle tailscale enable
# Or use an auth key for headless setups
sandcastle tailscale enable --auth-key tskey-auth-...
After authenticating, approve the advertised subnet routes in the Tailscale admin console.
4. Create a sandbox
Web UI — click the "Create Sandcastle" button on your dashboard to create a sandbox with all available options:
- Name — unique identifier for your sandbox
- Container Image — custom image or default
- Snapshot — restore from an existing snapshot
- Mount Home — persistent home directory across all sandboxes
- Data Path — mount user data (or subpath) to /persisted
- Tailscale — connect to your Tailscale network
- Docker daemon — enable/disable Docker-in-Docker
- Temporary — auto-remove when you disconnect
Or use the CLI for quick creation:
Quick throwaway sandbox — deleted when you disconnect:
sandcastle create scratch --rm
Persistent sandbox — keeps your home directory and data across restarts:
sandcastle create my-dev --home --data
Lightweight sandbox — no Docker daemon or VNC (faster startup):
sandcastle create lean --no-docker --no-vnc
sandcastle config set mount_home truesandcastle config set data_path .sandcastle config set vnc falsesandcastle config set docker falseOr via env:
export SANDCASTLE_HOME=1 SANDCASTLE_DATA=. SANDCASTLE_VNC=false
5. Connect
Two ways to get a shell:
# tmux session (reconnectable, auto-starts stopped sandboxes)
sandcastle connect my-dev
# Plain SSH (no tmux)
sandcastle ssh my-dev
# Pass extra SSH options after --
sandcastle connect my-dev -- -L 8080:localhost:8080
sandcastle ssh my-dev -- -D 1080
SSH agent forwarding
The CLI automatically forwards your local SSH agent (-A)
so you can use your SSH keys (e.g. for Git) inside the sandbox without copying them.
This works with the default SSH protocol.
Mosh (persistent, roaming sessions)
Use mosh for a connection that survives network changes and high-latency links. Mosh is pre-installed in every sandbox.
sandcastle connect --mosh my-dev
ssh-add -l keys will not be available inside the sandbox.
If you need agent forwarding (e.g. for Git over SSH), use the default SSH protocol instead.
mosh must be installed on your local machine
(brew install mosh on macOS,
apt install mosh on Debian/Ubuntu).
Mosh uses UDP ports 60000–61000 — if your sandbox is reachable only via SSH tunneling, use
Tailscale instead (it handles UDP natively).
6. Web terminal
Click tmux or shell on any running sandbox to open a browser-based terminal. No SSH client needed — just a web browser.
7. VNC
Click the VNC button on any running sandbox to access Google Chrome with a graphical desktop environment. Perfect for browser automation, visual testing, or running GUI applications.
~/.config/google-chrome alongside all your other home directory files.
Without Mount Home, profiles are stored separately in a dedicated directory.
8. SMB file sharing
Mount your sandbox home directory or /persisted
as a network drive from macOS, Windows, or Linux using SMB3.
This is useful for editing files with your local IDE or dragging and dropping in Finder/Explorer.
Setup
# Set your SMB password (stored encrypted on the server)
sandcastle smb set-password
# Create a sandbox with SMB enabled
sandcastle create my-dev --smb --tailscale
Connect
# macOS (Finder → Go → Connect to Server, or in Terminal):
open smb://<tailscale-ip>/home
open smb://<tailscale-ip>/persisted # if --data was used
# Windows (File Explorer → Map Network Drive):
\\<tailscale-ip>\home
# Linux:
sudo mount -t cifs //<tailscale-ip>/home /mnt/sandbox \
-o username=<your-sandcastle-username>,vers=3.0
The Tailscale IP is shown on the sandbox detail page. Username is your Sandcastle username. Password is what you set with sandcastle smb set-password.
9. Manage sandboxes
sandcastle list # Show all your sandboxes
sandcastle stop my-dev # Stop a running sandbox
sandcastle start my-dev # Start a stopped sandbox
sandcastle rebuild my-dev # Recreate with latest image
sandcastle rename my-dev new # Rename a sandbox
sandcastle delete my-dev # Archive sandbox (soft-delete, data kept)
# Copy files to/from a sandbox
sandcastle cp file.txt my-dev:~/ # local → sandbox
sandcastle cp my-dev:~/data.csv . # sandbox → local
sandcastle cp -r my-dev:~/project ./ # recursive
Archive & restore
When you delete a sandbox it is archived rather than immediately purged. Archived sandboxes have no running container but their data is preserved on disk. After the retention period (default: 30 days) a background job permanently deletes them. Admins can adjust the system-wide retention on the Settings page, and each user can override it in their profile settings.
# List archived sandboxes
sandcastle list --archived
# Restore an archived sandbox (recreates and starts the container)
sandcastle unarchive my-dev
# Permanently delete an archived sandbox immediately, bypassing the retention period
sandcastle purge my-dev
Archived sandboxes also appear as a collapsible section on your dashboard with a Restore button. The sandbox name is freed immediately on archive, so you can create a new sandbox with the same name.
10. Routes
Expose services running inside your sandbox to the outside world. Two modes are supported:
HTTP routes (layer 7, custom domain + TLS)
Route a custom domain to a port inside the sandbox. Traefik terminates TLS automatically.
# Add an HTTP route — app.example.com → container port 8080 (default)
sandcastle route add myapp app.example.com
# Add an HTTP route on a custom container port
sandcastle route add myapp api.example.com 3000
Point a DNS A/CNAME record at demo.sandcastle.rocks before adding the route. TLS certificates are provisioned automatically.
TCP routes (layer 4, raw port forward)
Forward a public TCP port (3000–3099) directly to a container port. Useful for databases, message brokers, or any non-HTTP service.
# Forward a public port to container port 5432 (e.g. Postgres)
sandcastle route add myapp --tcp 5432
# Output: TCP port 3042 → container port 5432
A public port from the pool is assigned automatically. Connect with demo.sandcastle.rocks:<public-port>.
Managing routes
# List all routes for a sandbox (shows ID, mode, domain/port, container port)
sandcastle route list myapp
# Remove an HTTP route by domain
sandcastle route delete myapp app.example.com
# Remove any route by ID (use the ID from route list)
sandcastle route delete myapp --id 42
Routes can also be managed from the sandbox detail page in the web UI.
11. Snapshots
Save and restore the full state of a sandbox. Snapshots are composite — they capture
the container filesystem (via docker commit)
and, when on a BTRFS filesystem, also the home directory and data directory.
# Create a snapshot (all available layers)
sandcastle snapshot create my-dev before-migration
# Create with a description and specific layers
sandcastle snapshot create my-dev checkpoint --label "before big refactor" --layers container,home
# List all snapshots
sandcastle snapshot list
# Show details of a specific snapshot
sandcastle snapshot show before-migration
# Restore a snapshot into an existing sandbox (all layers)
sandcastle snapshot restore my-dev before-migration
# Restore only the container layer
sandcastle snapshot restore my-dev before-migration --layers container
# Create a new sandbox from a snapshot (all layers)
sandcastle create my-dev-v2 --from-snapshot before-migration
# Clone only the container layer into a new sandbox
sandcastle create my-dev-v2 --from-snapshot before-migration --restore-layers container
# Delete a snapshot
sandcastle snapshot delete before-migration
Web UI: Each sandbox has a detail page (click the sandbox name) with a Snapshots tab for creating, viewing, and deleting snapshots. The global Snapshots page shows all snapshots across all your sandboxes with clone-to-new-sandbox support.
12. User settings
Click Settings in the navbar to manage your account preferences:
- Profile — Update your email address and change your password
- Tailscale — View connection status and toggle auto-connect for new sandboxes
- Sandbox Archive — Set your personal archive retention period (overrides the system default)
- VNC — Toggle Chrome profile persistence across sandbox recreations
- API Tokens — Create, list, and revoke multiple named API tokens for different devices or applications
Via Web UI: Go to Settings → click "New Token" → give it a name → copy the token
Via CLI: Run
sandcastle token create laptop to create a named tokensandcastle token list to view all your tokenssandcastle token revoke <id> to revoke a specific token
13. Inviting users (admin)
Admins can invite new users via email. Each invite generates a unique, one-time registration link. New users click the link to choose a username and set a password — no pre-created account required.
To send an invite:
- Go to Admin → Invites
- Click Invite User
- Enter the invitee's email address and an optional personal message
- Click Send Invite — the invitee will receive an email with a registration link
Invite lifecycle:
- Pending — sent but not yet accepted; link is still valid
- Accepted — user has registered; link is invalidated
- Expired — link expired (default: 7 days) before being accepted
Pending invites can be revoked from the Invites admin panel at any time. Once revoked, the registration link immediately becomes invalid.
14. Custom SSL certificates (advanced)
For internal networks, you can configure alternative hostnames with custom SSL certificates to avoid browser warnings.
Generate certificates with mkcert:
# Install mkcert (macOS example)
brew install mkcert
mkcert -install
# Generate certificate for your domains
mkcert sandcastle.internal sc.local
Configure Sandcastle:
Add these variables to your sandcastle.env before installation:
SANDCASTLE_ALT_HOSTNAMES=sandcastle.internal,sc.local
SANDCASTLE_CUSTOM_CERT_PATH=/path/to/sandcastle.internal+1.pem
SANDCASTLE_CUSTOM_KEY_PATH=/path/to/sandcastle.internal+1-key.pem
SANDCASTLE_TLS_MODE=selfsigned
The installer will copy the certificates to $SANDCASTLE_HOME/data/traefik/certs/ and configure Traefik to serve them for the specified hostnames.
/etc/hosts) to point your alternative hostnames to the Sandcastle server IP.
15. CLI preferences
Persist connection preferences in ~/.sandcastle/config.yaml.
Environment variables override the file (useful with
mise or direnv).
# Use mosh instead of SSH by default
sandcastle config set connect_protocol mosh
# Disable automatic tmux session attachment
sandcastle config set use_tmux false
# Always mount persistent home directory on create
sandcastle config set mount_home true
# Always mount user data directory on create
sandcastle config set data_path .
# Disable VNC by default
sandcastle config set vnc false
# Disable Docker (DinD) by default
sandcastle config set docker false
# Show effective settings (merged from config file + env vars)
sandcastle config show
Environment variable overrides (highest priority):
SANDCASTLE_CONNECT_PROTOCOL=mosh # "ssh" (default) | "mosh"
SANDCASTLE_USE_TMUX=false # "true" (default) | "false"
SANDCASTLE_SSH_EXTRA_ARGS="-v" # extra flags appended to ssh/mosh
SANDCASTLE_HOME=1 # mount persistent home on create
SANDCASTLE_DATA=. # mount user data dir on create
SANDCASTLE_VNC=false # disable VNC on create
SANDCASTLE_DOCKER=false # disable Docker (DinD) on create
Example: per-project override with mise:
# .mise.toml
[env]
SANDCASTLE_CONNECT_PROTOCOL = "mosh"
SANDCASTLE_USE_TMUX = "false"
16. Short aliases
Common commands have 1-2 letter shortcuts:
sandcastle cr # create (temp sandbox)
sandcastle cr dev # create dev
sandcastle c dev # connect dev
sandcastle s dev # ssh dev
sandcastle x dev -- cmd # exec
sandcastle ls # list
sandcastle rm dev # delete dev
sandcastle mv dev new # rename dev → new
sandcastle up dev # start dev
sandcastle dn dev # stop dev
sandcastle cp f dev:~/ # scp file to sandbox
sandcastle i # info
sandcastle st # status
sandcastle snap # snapshot
sandcastle ts # tailscale
Run sandcastle --help for the full command reference.