Creates dual-mode development sandbox setup
Implements orchestration on macOS and provisioning on Linux for isolated Claude Code environments Adds interactive component selection with visual menu interface Enables secure VM creation with disabled host filesystem access Provides comprehensive toolchain including PostgreSQL, Erlang/Elixir, and browser automation Configures VNC desktop access for OAuth workflows and browser-based tasks
This commit is contained in:
parent
bdf8b97dbc
commit
d7788a5212
5 changed files with 1178 additions and 190 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
config.env
|
||||
80
CLAUDE.md
Normal file
80
CLAUDE.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# CLAUDE.md
|
||||
|
||||
## Project Overview
|
||||
|
||||
This repository contains a dual-mode setup script for creating OrbStack-based development sandboxes tailored for Claude Code with Elixir/Erlang, browser automation, and PostgreSQL.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
setup_env.sh - Main script (macOS host mode + Linux VM provisioning mode)
|
||||
config.env.example - Example credentials file
|
||||
config.env - User credentials (gitignored, created on first run)
|
||||
.gitignore - Ignores config.env
|
||||
README.md - User-facing documentation
|
||||
CLAUDE.md - This file (context for Claude Code sessions)
|
||||
```
|
||||
|
||||
## How the Script Works
|
||||
|
||||
The script has two modes, detected via `uname -s`:
|
||||
|
||||
- **Darwin (macOS)**: Orchestrator mode. Checks for OrbStack, reads/creates `config.env`, creates a VM, copies itself in, runs itself inside the VM with `--non-interactive`.
|
||||
- **Linux (VM)**: Provisioning mode. Installs all tools, configures PostgreSQL, sets up VNC, installs Claude Code plugins.
|
||||
|
||||
This means `./setup_env.sh my-vm` on macOS does everything end-to-end.
|
||||
|
||||
## Key Technical Details
|
||||
|
||||
- **Target environment**: OrbStack Ubuntu VM on macOS Apple Silicon (ARM64)
|
||||
- **Version manager**: mise (manages Node.js, Erlang, Elixir)
|
||||
- **Language versions**: Configured at the top of `setup_env.sh` as variables (`ERLANG_VERSION`, `ELIXIR_VERSION`)
|
||||
- **PostgreSQL auth**: Peer for local socket, trust for localhost TCP (127.0.0.1), scram-sha-256 for host network (192.168.0.0/16)
|
||||
- **Browser**: Chromium (no Chrome ARM64 Linux builds exist), symlinked to `google-chrome`
|
||||
- **VNC**: TigerVNC + XFCE on display :1 (port 5901), controlled via `vnc-start`/`vnc-stop` helpers in `~/bin`
|
||||
- **Shared credentials**: `config.env` is created once and reused for all VMs
|
||||
|
||||
## Working on This Project
|
||||
|
||||
### Editing setup_env.sh
|
||||
|
||||
- The macOS host-mode block is at the top (inside the `if [[ "$(uname -s)" == "Darwin" ]]` block)
|
||||
- The Linux VM-mode block is everything after that conditional
|
||||
- Version numbers are defined as variables at the top (`ERLANG_VERSION`, `ELIXIR_VERSION`)
|
||||
- All installation steps must be idempotent (safe to run multiple times)
|
||||
- Use `log_info`, `log_warn`, `log_error` helpers for output
|
||||
- New apt packages go in the base dependencies section
|
||||
- New Claude plugins go in the appropriate array (`ANTHROPIC_PLUGINS` or `SUPERPOWERS_PLUGINS`)
|
||||
- Redirect verbose output to `$LOG_FILE`, show only meaningful progress to the user
|
||||
- The `LOG_FILE` variable is only set in VM mode (not available in macOS host mode)
|
||||
- Each optional component is wrapped in `prompt_install "Name" "Description"` — this handles both interactive prompts and `--yes`/`--non-interactive` auto-accept
|
||||
- Track dependency flags (`INSTALLED_NODE`, `INSTALLED_CHROMIUM`) to skip dependent components gracefully
|
||||
|
||||
### Script Conventions
|
||||
|
||||
- `set -euo pipefail` is enforced - handle potential failures with `|| true` or explicit checks
|
||||
- Use `command_exists` to check for already-installed tools
|
||||
- Use `apt-get` (not `apt`) for scripting reliability
|
||||
- Quote all variable expansions
|
||||
- Use `find` for PostgreSQL config paths (version-agnostic)
|
||||
- The `--non-interactive` flag is for VM mode (implies `--yes`); macOS mode always uses config.env
|
||||
- `--yes`/`-y` accepts all components without prompting but still allows interactive credential entry
|
||||
- `MISE_GLOBAL_CONFIG_FILE` and `MISE_CONFIG_DIR` are set to prevent OrbStack host-mount config pollution
|
||||
|
||||
### Testing
|
||||
|
||||
There are no automated tests. To test changes:
|
||||
1. Remove an existing test VM: `orb delete test-sandbox`
|
||||
2. Run: `./setup_env.sh test-sandbox`
|
||||
3. Verify provisioning completes
|
||||
4. Run again to verify idempotency: `ssh test-sandbox@orb -- bash /tmp/setup_env.sh --non-interactive` (will need env vars)
|
||||
5. Test VNC: `ssh test-sandbox@orb -- vnc-start`, then `open vnc://test-sandbox.orb.local:5901`
|
||||
6. Clean up: `orb delete test-sandbox`
|
||||
|
||||
### Security Considerations
|
||||
|
||||
- `config.env` is chmod 600 and gitignored
|
||||
- PostgreSQL remote access uses scram-sha-256 (not trust)
|
||||
- The script refuses to run as root inside the VM
|
||||
- VNC password is required (min 6 chars)
|
||||
- VNC binds to all interfaces (`-localhost no`) to allow connections from the macOS host — this is intentional for the OrbStack use case
|
||||
297
README.md
297
README.md
|
|
@ -0,0 +1,297 @@
|
|||
# OrbStack Development Sandbox
|
||||
|
||||
Disposable, isolated Linux VMs for running Claude Code with `--dangerously-skip-permissions`. One command creates a fully provisioned environment. Blow it away and recreate it in minutes.
|
||||
|
||||
The VM is a real Linux machine with its own filesystem, network, and process space — but you edit files from your Mac, access services on `*.orb.local`, and SSH in without any key setup. All the isolation of a container with none of the friction.
|
||||
|
||||
## Why This Exists
|
||||
|
||||
Running `claude --dangerously-skip-permissions` on your host machine means Claude can execute arbitrary commands, install packages, modify system files, and access everything on your disk. That's powerful for autonomous coding but risky on a machine with your SSH keys, credentials, and personal files.
|
||||
|
||||
This script creates throwaway VMs where Claude can run unrestricted:
|
||||
|
||||
- **Isolated filesystem** — Claude can't touch your macOS files, keys, or configs
|
||||
- **Isolated network** — services run on their own IP, no port conflicts with your host
|
||||
- **Disposable** — `orb delete my-sandbox` wipes everything; recreate in one command
|
||||
- **Multiple VMs** — run separate sandboxes per project with shared git credentials
|
||||
- **Full access from Mac** — edit files in your editor, browse databases, view running apps
|
||||
|
||||
```bash
|
||||
# Create a sandbox, SSH in, run Claude unrestricted
|
||||
./setup_env.sh my-project
|
||||
ssh my-project@orb
|
||||
claude --dangerously-skip-permissions
|
||||
```
|
||||
|
||||
If anything goes wrong: `orb delete my-project && ./setup_env.sh my-project`
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Create and provision a VM (one command from macOS)
|
||||
./setup_env.sh my-sandbox
|
||||
```
|
||||
|
||||
On first run, you'll be prompted for git name, email, and a VNC password. These are saved to `config.env` and reused for all future VMs. You'll also get an interactive checklist to select which components to install.
|
||||
|
||||
```bash
|
||||
# Create additional VMs — reuses config.env, shows component picker
|
||||
./setup_env.sh my-other-project
|
||||
./setup_env.sh elixir-playground
|
||||
```
|
||||
|
||||
When run manually inside a VM, you're prompted for each component individually:
|
||||
|
||||
```bash
|
||||
# Inside a VM — interactive, prompts per component
|
||||
./setup_env.sh
|
||||
|
||||
# Inside a VM — accept all without prompting
|
||||
./setup_env.sh -y
|
||||
./setup_env.sh --yes
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- macOS with Apple Silicon (ARM64)
|
||||
- [OrbStack](https://orbstack.dev) installed (`brew install orbstack`)
|
||||
|
||||
## What Gets Installed
|
||||
|
||||
All components are optional — deselect what you don't need in the interactive picker.
|
||||
|
||||
| Tool | Version | Purpose |
|
||||
|------|---------|---------|
|
||||
| mise | latest | Version manager for runtimes |
|
||||
| Node.js | LTS | JavaScript runtime |
|
||||
| Erlang | 28.3.1 | BEAM VM |
|
||||
| Elixir | 1.19.5-otp-28 | Elixir language |
|
||||
| Chromium | system | Browser automation target |
|
||||
| Playwright | latest | Browser testing framework |
|
||||
| PostgreSQL | system default | Database |
|
||||
| Ollama | latest | Local LLM inference |
|
||||
| Claude Code | latest | AI coding assistant |
|
||||
| TigerVNC + XFCE | system | VNC access for browser login flows |
|
||||
|
||||
## Connecting from macOS
|
||||
|
||||
### SSH
|
||||
|
||||
```bash
|
||||
# Shell into the VM (no key setup required)
|
||||
ssh my-sandbox@orb
|
||||
|
||||
# Run a command directly
|
||||
ssh my-sandbox@orb -- ls ~/projects
|
||||
|
||||
# Run Claude unrestricted
|
||||
ssh my-sandbox@orb -- claude --dangerously-skip-permissions
|
||||
```
|
||||
|
||||
OrbStack handles SSH key configuration automatically.
|
||||
|
||||
### Editing Files
|
||||
|
||||
Your editor connects to the VM over SSH. You edit files as if they were local — full LSP support, syntax highlighting, file tree, integrated terminal.
|
||||
|
||||
**Zed:**
|
||||
1. `Cmd+Shift+P` -> "Open Remote Folder"
|
||||
2. Enter: `my-sandbox@orb:~/projects`
|
||||
|
||||
**VS Code / Cursor:**
|
||||
1. Install the "Remote - SSH" extension
|
||||
2. `Cmd+Shift+P` -> "Remote-SSH: Connect to Host"
|
||||
3. Enter: `my-sandbox@orb`
|
||||
4. Open folder: `~/projects`
|
||||
|
||||
**Finder (direct filesystem access):**
|
||||
```
|
||||
/Volumes/OrbStack/my-sandbox/home/<user>/
|
||||
```
|
||||
|
||||
### Viewing Running Apps
|
||||
|
||||
Services running in the VM are accessible from your Mac via `<vm-name>.orb.local`:
|
||||
|
||||
```bash
|
||||
# Phoenix/Rails/Next.js dev server running on port 4000 inside the VM
|
||||
open http://my-sandbox.orb.local:4000
|
||||
|
||||
# Or use port forwarding if the app only binds to localhost
|
||||
ssh -L 4000:localhost:4000 my-sandbox@orb
|
||||
```
|
||||
|
||||
PostgreSQL, Redis, or any service listening on the VM's interfaces is reachable at `my-sandbox.orb.local:<port>` from your Mac — no extra configuration.
|
||||
|
||||
## VNC (Browser Access)
|
||||
|
||||
For tasks requiring a visible browser (e.g., Claude Code OAuth login):
|
||||
|
||||
```bash
|
||||
# Start VNC server inside the VM
|
||||
ssh my-sandbox@orb -- vnc-start
|
||||
|
||||
# Connect from macOS (opens Screen Sharing.app)
|
||||
open vnc://my-sandbox.orb.local:5901
|
||||
|
||||
# Stop when done (saves resources)
|
||||
ssh my-sandbox@orb -- vnc-stop
|
||||
```
|
||||
|
||||
### macOS Screen Sharing (built-in)
|
||||
|
||||
```bash
|
||||
open vnc://my-sandbox.orb.local:5901
|
||||
```
|
||||
|
||||
Enter your VNC password when prompted.
|
||||
|
||||
### RealVNC Viewer
|
||||
|
||||
1. Download from https://www.realvnc.com/en/connect/download/viewer/
|
||||
2. Enter address: `my-sandbox.orb.local:5901`
|
||||
3. When prompted for credentials, enter your VNC password (username can be left blank)
|
||||
|
||||
### TigerVNC Viewer
|
||||
|
||||
```bash
|
||||
# Install via Homebrew
|
||||
brew install tiger-vnc
|
||||
|
||||
# Connect
|
||||
vncviewer my-sandbox.orb.local:5901
|
||||
```
|
||||
|
||||
Enter your VNC password when prompted.
|
||||
|
||||
### Connection details for any VNC client
|
||||
|
||||
- **Host**: `my-sandbox.orb.local`
|
||||
- **Port**: `5901` (display `:1`)
|
||||
- **Password**: the VNC password from `config.env`
|
||||
- **Resolution**: 1280x800 (configurable in `~/bin/vnc-start`)
|
||||
|
||||
## PostgreSQL
|
||||
|
||||
A superuser matching your Linux username and a `dev` database are created automatically.
|
||||
|
||||
**Auth model:**
|
||||
- Local socket (`psql dev`): peer auth (OS username must match PG role)
|
||||
- Localhost TCP (127.0.0.1): trust (passwordless)
|
||||
- Host network (192.168.0.0/16, i.e., from macOS): scram-sha-256
|
||||
|
||||
### From inside the VM
|
||||
|
||||
```bash
|
||||
psql dev # Connect to dev database
|
||||
psql -l # List databases
|
||||
createdb myapp_dev # Create a new database
|
||||
```
|
||||
|
||||
### From macOS
|
||||
|
||||
```bash
|
||||
# Direct (requires: brew install libpq)
|
||||
psql -h my-sandbox.orb.local -U <user> -d dev
|
||||
```
|
||||
|
||||
### Connection strings
|
||||
|
||||
```
|
||||
# Elixir/Phoenix
|
||||
postgres://<user>@my-sandbox.orb.local/myapp_dev
|
||||
|
||||
# Generic
|
||||
host=my-sandbox.orb.local port=5432 dbname=dev user=<user>
|
||||
```
|
||||
|
||||
### DataGrip
|
||||
|
||||
1. New Data Source -> PostgreSQL
|
||||
2. **SSH/SSL** tab: Check "Use SSH tunnel", Host: `my-sandbox@orb`, Auth: Key pair
|
||||
3. **General** tab: Host: `localhost`, Port: `5432`, User: your VM username, Database: `dev`, No password
|
||||
4. Test Connection -> Apply
|
||||
|
||||
### DBeaver
|
||||
|
||||
1. New Database Connection -> PostgreSQL
|
||||
2. **SSH** tab: Check "Use SSH Tunnel", Host: `my-sandbox.orb.local`, Port: `22`, Auth: Public Key
|
||||
3. **Main** tab: Host: `localhost`, Port: `5432`, Database: `dev`, Username: your VM username, no password
|
||||
4. Test Connection -> Finish
|
||||
|
||||
### Creating additional databases
|
||||
|
||||
```bash
|
||||
# From inside the VM
|
||||
createdb myapp_dev
|
||||
createdb myapp_test
|
||||
|
||||
# From macOS
|
||||
ssh my-sandbox@orb -- createdb myapp_dev
|
||||
```
|
||||
|
||||
## Claude Code Plugins
|
||||
|
||||
The script installs these plugins at user scope:
|
||||
|
||||
**Anthropic marketplace** (`anthropics/claude-code`):
|
||||
- code-review, code-simplifier, feature-dev, pr-review-toolkit, security-guidance, frontend-design
|
||||
|
||||
**Superpowers marketplace** (`obra/superpowers`):
|
||||
- double-shot-latte, elements-of-style, superpowers, superpowers-chrome, superpowers-lab
|
||||
|
||||
**MCP Servers**:
|
||||
- `playwright` - Browser automation and screenshots
|
||||
- `superpowers-chrome` - Direct Chrome/Chromium control (headless)
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit the version variables at the top of `setup_env.sh`:
|
||||
|
||||
```bash
|
||||
ERLANG_VERSION="28.3.1"
|
||||
ELIXIR_VERSION="1.19.5-otp-28"
|
||||
```
|
||||
|
||||
### Shared credentials
|
||||
|
||||
Credentials are stored in `config.env` (gitignored). To reset:
|
||||
|
||||
```bash
|
||||
rm config.env
|
||||
./setup_env.sh my-sandbox # will prompt again
|
||||
```
|
||||
|
||||
Or copy the example and edit:
|
||||
|
||||
```bash
|
||||
cp config.env.example config.env
|
||||
# Edit config.env with your values
|
||||
```
|
||||
|
||||
## Managing VMs
|
||||
|
||||
```bash
|
||||
# List all VMs
|
||||
orb list
|
||||
|
||||
# Delete a VM (instant cleanup)
|
||||
orb delete my-sandbox
|
||||
|
||||
# Stop a VM (preserves state, frees resources)
|
||||
orb stop my-sandbox
|
||||
|
||||
# Start a stopped VM
|
||||
orb start my-sandbox
|
||||
|
||||
# Nuclear option — delete and recreate
|
||||
orb delete my-sandbox && ./setup_env.sh my-sandbox
|
||||
```
|
||||
|
||||
## Idempotency
|
||||
|
||||
The VM provisioning script is safe to run multiple times. It checks for existing installations before re-installing and avoids appending duplicate configuration lines.
|
||||
|
||||
## Logs
|
||||
|
||||
Each provisioning run creates a log file at `/tmp/setup_env_<timestamp>.log` inside the VM with detailed output from package installations and any errors.
|
||||
6
config.env.example
Normal file
6
config.env.example
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Copy this file to config.env and fill in your values.
|
||||
# config.env is gitignored and shared across all VMs you create.
|
||||
|
||||
GIT_NAME="guessthepw"
|
||||
GIT_EMAIL="admin@guessthe.pw"
|
||||
VNC_PASSWORD="changeme123"
|
||||
944
setup_env.sh
Normal file → Executable file
944
setup_env.sh
Normal file → Executable file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue