Compare commits
16 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb83ada34 | ||
|
|
ca12925111 | ||
|
|
65790ee3e2 | ||
|
|
cc1277cd98 | ||
|
|
77093a0ce6 | ||
|
|
70c2559d40 | ||
|
|
2861664a03 | ||
|
|
63bcc0aea3 | ||
|
|
26501daa4e | ||
|
|
cbc379c0cc | ||
|
|
b3ed5e66a5 | ||
|
|
9ee89df424 | ||
|
|
20fa7fa3c5 | ||
|
|
8c6fb6c3bc | ||
|
|
d7788a5212 | ||
|
|
bdf8b97dbc |
8 changed files with 3524 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
config.env
|
||||
169
CHANGELOG.md
Normal file
169
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.14.1] - 2025-01-25
|
||||
|
||||
### Changed
|
||||
- Updated README.md with Windows skip parameters and VNC password info
|
||||
- Updated CLAUDE.md with Windows script documentation and security patterns
|
||||
- Fixed VNC password minimum documentation (6 → 8 chars)
|
||||
|
||||
## [0.14.0] - 2025-01-25
|
||||
|
||||
### Security
|
||||
- Add SHA256 checksum verification for Ubuntu cloud image downloads (prevents MITM attacks)
|
||||
- Add strict input validation for git name, email, VM password, and VNC password
|
||||
- Validate loaded config.env values to detect tampering
|
||||
- VNC password minimum increased from 6 to 8 characters
|
||||
- Block shell metacharacters in all user inputs to prevent injection
|
||||
- Config file created with restricted ACL from the start (no race condition window)
|
||||
- Add security reminder to remove cloud-init ISO after first boot (contains passwords)
|
||||
|
||||
### Added
|
||||
- ARM64 architecture detection for Windows on ARM devices
|
||||
- Log file creation at `$env:TEMP\setup_env_windows_<timestamp>.log`
|
||||
- Cleanup on failure: automatically removes partial VM, disk, and ISO on error
|
||||
- Hosts file backup before modification (removed on success, kept on failure)
|
||||
- Input validation functions: `Test-GitName`, `Test-GitEmail`, `Test-VMPassword`, `Test-VNCPassword`
|
||||
- Checksum caching to avoid re-downloading verification data
|
||||
|
||||
### Changed
|
||||
- Ubuntu image URL now uses detected architecture instead of hardcoded amd64
|
||||
- All major operations now log to file for troubleshooting
|
||||
- VM creation wrapped in try/catch with automatic cleanup on failure
|
||||
|
||||
## [0.13.0] - 2025-01-25
|
||||
|
||||
### Changed
|
||||
- Rewrote `setup_env_windows.ps1` to fully implement WINDOWS_PLAN.md
|
||||
- Password handling uses cloud-init `chpasswd` with plaintext (type: text) instead of broken hash generation
|
||||
- Multiple ISO creation methods with fallback chain: oscdimg → WSL genisoimage → IMAPI2 COM
|
||||
- Downloads use BITS transfer for reliability with progress reporting
|
||||
- SSH readiness checking with timeout before displaying connection info
|
||||
|
||||
### Added
|
||||
- Component skip parameters: `-SkipVNC`, `-SkipPostgreSQL`, `-SkipOllama`, `-SkipPlaywright`
|
||||
- VNC password support via base64 encoding in cloud-init
|
||||
- Automatic hosts file cleanup when VM is deleted with `-Force`
|
||||
- Proper prerequisite checking for Hyper-V, Windows edition, and admin privileges
|
||||
|
||||
### Fixed
|
||||
- Cloud-init password configuration (was using bash syntax in PowerShell)
|
||||
- ISO creation now works without Windows ADK by using WSL or IMAPI2 fallbacks
|
||||
- Hosts file handling with proper admin privilege elevation
|
||||
|
||||
## [0.12.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- Python runtime management via mise (alongside Node.js, Erlang, Elixir)
|
||||
- `WINDOWS_PLAN.md` documenting Hyper-V implementation strategy and security rationale
|
||||
|
||||
### Fixed
|
||||
- Tidewave CLI download URL (now uses correct `tidewave_app` repo with musl binaries)
|
||||
|
||||
### Changed
|
||||
- Python is now a selectable component managed by mise instead of system apt
|
||||
|
||||
## [0.11.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- Windows support via Hyper-V for maximum security isolation
|
||||
- `setup_env_windows.ps1` PowerShell script with full VM provisioning
|
||||
- Ubuntu cloud image support with cloud-init automation
|
||||
- SSH key generation for passwordless VM access on Windows
|
||||
- Hosts file integration for easy `<vmname>.local` access
|
||||
|
||||
### Security
|
||||
- Hyper-V provides stronger isolation than WSL2 (separate kernel, network, filesystem)
|
||||
- No host integration services enabled by default
|
||||
|
||||
## [0.10.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- OpenCode: Open-source AI coding assistant with multi-provider support
|
||||
- Tidewave CLI: Elixir/Phoenix MCP server for AI-powered development
|
||||
- New component selection options for OpenCode and Tidewave
|
||||
|
||||
## [0.9.1] - 2025-01-25
|
||||
|
||||
### Fixed
|
||||
- Add error checking for base64 decode operations in VM provisioning
|
||||
- Add `set -e` to VM bootstrap script for early failure detection
|
||||
|
||||
## [0.9.0] - 2025-01-25
|
||||
|
||||
### Security
|
||||
- Fix rustup pipe-to-shell vulnerability: now downloads to temp file with validation before execution
|
||||
- Fix SKIP_EXPORTS command injection risk: refactored to use base64-encoded list instead of shell command string
|
||||
- Fix Playwright symlink path validation: validates executable and path prefix before creating symlinks
|
||||
|
||||
## [0.8.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- Project memory system using CLAUDE.md, CHANGELOG.md, and README.md
|
||||
- Versioning rules and documentation update guidelines in CLAUDE.md
|
||||
|
||||
## [0.7.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- CHANGELOG.md with version history following Keep a Changelog format
|
||||
|
||||
## [0.6.0] - 2025-01-25
|
||||
|
||||
### Changed
|
||||
- All tools now use latest versions by default instead of pinning specific versions
|
||||
- PostgreSQL authentication uses scram-sha-256 for all TCP connections
|
||||
- Simplified tool installation by removing version pinning constraints
|
||||
|
||||
### Security
|
||||
- VNC passwords are never stored and must be entered each time
|
||||
- Added documentation for input validation patterns and safe config loading
|
||||
|
||||
## [0.5.0] - 2025-01-25
|
||||
|
||||
### Security
|
||||
- Prevents shell injection through input validation and safe parameter passing
|
||||
- Replaces direct sourcing with manual config parsing to avoid code execution
|
||||
- Downloads and validates install scripts before execution instead of piping
|
||||
- Uses base64 encoding for secure VM parameter transmission
|
||||
- Adds checksum verification for binary downloads
|
||||
- Creates secure temporary directories and files with proper permissions
|
||||
|
||||
## [0.4.0] - 2025-01-25
|
||||
|
||||
### Changed
|
||||
- Replaces sequential installation with parallel step execution
|
||||
- Introduces real-time progress dashboard with spinner and status
|
||||
- Removes color variables to improve terminal compatibility
|
||||
- Restructures logging with per-step files for better debugging
|
||||
|
||||
### Performance
|
||||
- Significantly reduces total setup time by running independent steps concurrently
|
||||
|
||||
## [0.3.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- Dual-mode operation: orchestration on macOS, provisioning on Linux
|
||||
- Interactive component selection with visual menu interface
|
||||
- VNC desktop access for OAuth workflows and browser-based tasks
|
||||
|
||||
### Security
|
||||
- Secure VM creation with disabled host filesystem access
|
||||
|
||||
## [0.2.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- OrbStack development sandbox setup script
|
||||
- mise version manager with Node.js, Erlang, and Elixir support
|
||||
- PostgreSQL 16 with remote access configuration
|
||||
- Claude Code integration with multiple plugin marketplaces
|
||||
- Chromium browser and Playwright for automation tasks
|
||||
|
||||
## [0.1.0] - 2025-01-25
|
||||
|
||||
### Added
|
||||
- Initial project structure
|
||||
147
CLAUDE.md
Normal file
147
CLAUDE.md
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
# CLAUDE.md
|
||||
|
||||
## Project Memory
|
||||
|
||||
This project uses three documentation files as persistent memory. **You must keep these files up to date when making changes:**
|
||||
|
||||
| File | Purpose | Update When |
|
||||
|------|---------|-------------|
|
||||
| `CLAUDE.md` | Technical context for Claude Code sessions | Adding new patterns, conventions, or implementation details |
|
||||
| `CHANGELOG.md` | Version history following Keep a Changelog format | Every commit (add entry, bump version) |
|
||||
| `README.md` | User-facing documentation | Changing user-visible behavior, adding features, or modifying usage |
|
||||
|
||||
### Versioning Rules
|
||||
|
||||
- Use semantic versioning (MAJOR.MINOR.PATCH)
|
||||
- Increment PATCH for bug fixes and minor updates
|
||||
- Increment MINOR for new features and enhancements
|
||||
- Increment MAJOR for breaking changes
|
||||
- Tag every commit with its version: `git tag -a vX.Y.Z -m "Description"`
|
||||
|
||||
## Project Overview
|
||||
|
||||
This repository provides scripts for creating isolated development sandboxes for Claude Code on macOS (OrbStack) and Windows (Hyper-V). Both platforms offer full VM isolation for safely running AI coding assistants with elevated permissions.
|
||||
|
||||
**Supported platforms:**
|
||||
- **macOS**: OrbStack VMs (ARM64 Apple Silicon)
|
||||
- **Windows**: Hyper-V VMs (maximum security, stronger than WSL2)
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
setup_env.sh - macOS script (OrbStack host mode + Linux VM provisioning)
|
||||
setup_env_windows.ps1 - Windows script (Hyper-V with cloud-init)
|
||||
WINDOWS_PLAN.md - Windows implementation plan and security rationale
|
||||
config.env.example - Example credentials file
|
||||
config.env - User credentials (gitignored, created on first run)
|
||||
.gitignore - Ignores config.env
|
||||
README.md - User-facing documentation
|
||||
CHANGELOG.md - Version history (Keep a Changelog format)
|
||||
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)
|
||||
- **Versions**: All tools use latest by default. Erlang/Elixir versions can be configured at the top of `setup_env.sh` (`ERLANG_VERSION`, `ELIXIR_VERSION`) - set to "latest" or pin to specific versions
|
||||
- **PostgreSQL auth**: Peer for local socket, scram-sha-256 for all TCP connections (localhost and network)
|
||||
- **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` stores git name/email only; VNC password is prompted each time (never stored)
|
||||
|
||||
## 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
|
||||
|
||||
### Security Patterns (macOS/Linux)
|
||||
|
||||
- **Input validation**: Use `validate_vm_name()`, `validate_vnc_password()`, `validate_safe_input()` for all user inputs
|
||||
- **Safe config loading**: Use `load_config_safely()` which parses key=value pairs without shell execution (never `source`)
|
||||
- **Credential passing**: Base64-encode values before passing to VM via `orb run` to prevent shell injection
|
||||
- **Download helper**: Use `download_verified_binary()` for binary downloads (supports optional checksum verification)
|
||||
- **Temp files**: Always use `mktemp` with restrictive permissions (`chmod 600`/`700`)
|
||||
- **Symlinks**: Check with `[ ! -e path ]` (not `[ ! -L path ]`) to avoid overwriting existing files
|
||||
- **Architecture detection**: Use `detect_architecture()` for portable binary downloads
|
||||
|
||||
### Editing setup_env_windows.ps1
|
||||
|
||||
- PowerShell script for Windows Hyper-V VM creation
|
||||
- Uses Ubuntu cloud images with cloud-init for automated provisioning
|
||||
- Supports ARM64 architecture detection for Windows on ARM
|
||||
- Skip parameters: `-SkipVNC`, `-SkipPostgreSQL`, `-SkipOllama`, `-SkipPlaywright`
|
||||
- ISO creation fallback chain: oscdimg → WSL genisoimage → IMAPI2 COM
|
||||
- Log file created at `$env:TEMP\setup_env_windows_<timestamp>.log`
|
||||
|
||||
### Security Patterns (Windows)
|
||||
|
||||
- **Input validation**: Use `Test-GitName`, `Test-GitEmail`, `Test-VMPassword`, `Test-VNCPassword` for all user inputs
|
||||
- **Config file security**: ACL set to owner-only before writing content (no race condition)
|
||||
- **Config validation**: Loaded config.env values are re-validated to detect tampering
|
||||
- **Checksum verification**: Ubuntu image verified against SHA256 checksums from Canonical
|
||||
- **Cleanup on failure**: `Invoke-Cleanup` removes partial VM, disk, and ISO on errors
|
||||
- **Hosts file backup**: Created before modification, removed on success, kept on failure
|
||||
- **Cloud-init ISO**: Contains passwords in plaintext; user reminded to remove after first boot
|
||||
|
||||
### Testing
|
||||
|
||||
There are no automated tests. To test changes:
|
||||
|
||||
**macOS:**
|
||||
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`
|
||||
|
||||
**Windows:**
|
||||
1. Remove existing test VM: `Stop-VM -Name test-sandbox -Force; Remove-VM -Name test-sandbox -Force`
|
||||
2. Run: `.\setup_env_windows.ps1 -VMName test-sandbox`
|
||||
3. Verify provisioning completes (check `/var/log/provision.log` in VM)
|
||||
4. Test SSH: `ssh -i $env:USERPROFILE\.ssh\id_ed25519_test-sandbox dev@test-sandbox.local`
|
||||
5. Clean up: `Stop-VM -Name test-sandbox -Force; Remove-VM -Name test-sandbox -Force`
|
||||
|
||||
### Security Considerations
|
||||
|
||||
- `config.env` is chmod 600 / owner-only ACL and gitignored (stores git name/email only, never passwords)
|
||||
- PostgreSQL uses scram-sha-256 for all TCP connections (peer auth for local socket)
|
||||
- The script refuses to run as root inside the VM
|
||||
- VNC password is required (min 8 chars), validated to block shell metacharacters, never stored
|
||||
- VNC binds to all interfaces (`-localhost no`) to allow connections from the host — this is intentional and documented
|
||||
- All user inputs are validated before use to prevent command injection
|
||||
- External scripts (mise, ollama) are downloaded to temp files and validated before execution
|
||||
- Host filesystem access is disabled inside the VM for isolation
|
||||
- Windows: Ubuntu image downloads are verified against SHA256 checksums
|
||||
376
README.md
376
README.md
|
|
@ -0,0 +1,376 @@
|
|||
# Secure AI Coding Sandboxes
|
||||
|
||||
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 — complete isolation from your host with easy access for development.
|
||||
|
||||
| Platform | Script | Isolation Level |
|
||||
|----------|--------|-----------------|
|
||||
| **macOS** | `setup_env.sh` (OrbStack) | Full VM isolation |
|
||||
| **Windows** | `setup_env_windows.ps1` (Hyper-V) | Full VM isolation |
|
||||
|
||||
## 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.
|
||||
|
||||
These scripts create throwaway VMs where Claude can run unrestricted:
|
||||
|
||||
- **Isolated filesystem** — Claude can't touch your host files, keys, or configs
|
||||
- **Isolated network** — services run on their own IP, no port conflicts with your host
|
||||
- **Disposable** — delete and recreate in one command
|
||||
- **Multiple VMs** — run separate sandboxes per project with shared git credentials
|
||||
- **Full access from host** — edit files in your editor, browse databases, view running apps
|
||||
|
||||
## Quick Start (macOS)
|
||||
|
||||
```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`
|
||||
|
||||
### macOS Setup
|
||||
|
||||
```bash
|
||||
# Create and provision a VM (one command from macOS)
|
||||
./setup_env.sh my-sandbox
|
||||
```
|
||||
|
||||
On first run, you'll be prompted for git commit author name and email. 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. If you select VNC, you'll be prompted for a VNC password (this is never stored and must be entered each time).
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
### macOS Requirements
|
||||
|
||||
- macOS with Apple Silicon (ARM64)
|
||||
- [OrbStack](https://orbstack.dev) installed (`brew install orbstack`)
|
||||
|
||||
## Quick Start (Windows)
|
||||
|
||||
```powershell
|
||||
# Run as Administrator
|
||||
.\setup_env_windows.ps1 -VMName my-project
|
||||
|
||||
# Connect via SSH (after provisioning)
|
||||
ssh -i $env:USERPROFILE\.ssh\id_ed25519_my-project dev@my-project.local
|
||||
|
||||
# Run Claude unrestricted
|
||||
claude --dangerously-skip-permissions
|
||||
```
|
||||
|
||||
If anything goes wrong: `Remove-VM -Name my-project -Force` then run the script again.
|
||||
|
||||
### Windows Setup
|
||||
|
||||
```powershell
|
||||
# Create and provision a VM (run as Administrator)
|
||||
.\setup_env_windows.ps1 -VMName my-sandbox
|
||||
|
||||
# Customize resources
|
||||
.\setup_env_windows.ps1 -VMName my-sandbox -MemoryGB 16 -DiskGB 100 -CPUs 8
|
||||
|
||||
# Skip optional components
|
||||
.\setup_env_windows.ps1 -VMName my-sandbox -SkipVNC -SkipOllama
|
||||
```
|
||||
|
||||
On first run, you'll be prompted for:
|
||||
- Git commit author name and email (saved to `config.env`)
|
||||
- VM user password (min 8 chars, not stored)
|
||||
- VNC password if VNC is enabled (min 8 chars, not stored)
|
||||
|
||||
### Windows Requirements
|
||||
|
||||
- Windows 10/11 Pro, Enterprise, or Education (Hyper-V not available on Home)
|
||||
- Hyper-V enabled: `Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All`
|
||||
- Administrator privileges
|
||||
- One of: Windows ADK, WSL with genisoimage, or Windows 10+ (IMAPI2 fallback)
|
||||
|
||||
### Why Hyper-V (not WSL2)?
|
||||
|
||||
WSL2 is convenient but provides weaker isolation:
|
||||
- Shares kernel with all WSL2 instances
|
||||
- Host filesystem mounted by default
|
||||
- Can launch Windows executables from Linux
|
||||
- Network traffic bypasses Windows firewall
|
||||
|
||||
Hyper-V provides **maximum security**:
|
||||
- Separate kernel per VM
|
||||
- Complete filesystem isolation
|
||||
- Own network stack
|
||||
- No Windows integration by default
|
||||
|
||||
## 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 | latest | BEAM VM |
|
||||
| Elixir | latest | 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 (Anthropic) |
|
||||
| OpenCode | latest | Open-source AI coding assistant (multi-provider) |
|
||||
| Tidewave | latest | Elixir/Phoenix MCP server for AI tools |
|
||||
| yq | latest | YAML processor |
|
||||
| watchexec | latest | File watcher (via cargo) |
|
||||
| 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): scram-sha-256 (password required)
|
||||
- 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
|
||||
|
||||
All tools are configured to use the latest versions by default. Erlang and Elixir versions can be customized in `setup_env.sh`:
|
||||
|
||||
```bash
|
||||
ERLANG_VERSION="latest" # or pin to specific version like "28.3.1"
|
||||
ELIXIR_VERSION="latest" # or pin to specific version like "1.19.5-otp-28"
|
||||
```
|
||||
|
||||
### Shared credentials
|
||||
|
||||
Git credentials (name, email) are stored in `config.env` (gitignored). VNC passwords are never stored and must be entered each time you create a VM with VNC enabled.
|
||||
|
||||
To reset git credentials:
|
||||
|
||||
```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. Log files are created with mode 600 (owner-only access).
|
||||
|
||||
## Security
|
||||
|
||||
The script includes several security hardening measures:
|
||||
|
||||
- **Input validation**: VM names, VNC passwords, and git credentials are validated against strict patterns
|
||||
- **No credential storage**: VNC passwords are prompted each time and never written to disk
|
||||
- **Safe credential passing**: Values are base64-encoded when passed to the VM to prevent shell injection
|
||||
- **Config file security**: `config.env` is created with mode 600 and parsed safely (not sourced)
|
||||
- **Secure temp files**: Uses `mktemp` with restrictive permissions for all temporary files
|
||||
- **Host filesystem isolation**: macOS home directory access is disabled inside the VM
|
||||
- **PostgreSQL hardening**: Uses peer auth for local sockets, scram-sha-256 for network connections
|
||||
257
WINDOWS_PLAN.md
Normal file
257
WINDOWS_PLAN.md
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
# Windows Hyper-V Implementation Plan
|
||||
|
||||
This document describes the plan for implementing secure, isolated development sandboxes on Windows using Hyper-V instead of WSL2.
|
||||
|
||||
## Why Hyper-V Over WSL2
|
||||
|
||||
### WSL2 Security Limitations
|
||||
|
||||
| Issue | Impact |
|
||||
|-------|--------|
|
||||
| **Shared kernel** | All WSL2 instances share Microsoft's Linux kernel |
|
||||
| **Host filesystem access** | `/mnt/c` mounted by default, can access Windows files |
|
||||
| **Bidirectional execution** | Linux can launch Windows executables |
|
||||
| **Firewall bypass** | WSL2 outbound traffic bypasses Windows firewall rules |
|
||||
| **Process visibility** | Windows has limited visibility into WSL2 processes |
|
||||
| **Credential exposure** | Linux processes can potentially access Windows credentials |
|
||||
|
||||
### CVE History
|
||||
|
||||
- **CVE-2024-20681**: Local privilege escalation to SYSTEM via WSL
|
||||
- **CVE-2025-9074**: Container escape via WSL2 filesystem sharing
|
||||
- **CVE-2025-53788**: Undisclosed flaw in WSL/host communication
|
||||
|
||||
### Hyper-V Isolation Model
|
||||
|
||||
| Feature | Benefit |
|
||||
|---------|---------|
|
||||
| **Separate kernel** | Each VM runs its own Linux kernel |
|
||||
| **Complete filesystem isolation** | No access to Windows files by default |
|
||||
| **Own network stack** | Separate IP, no firewall bypass |
|
||||
| **No Windows integration** | Cannot launch Windows programs |
|
||||
| **Snapshot support** | Can checkpoint and restore VM state |
|
||||
| **Hardware isolation** | Uses VT-x/AMD-V virtualization |
|
||||
|
||||
## Implementation Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Windows Host │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ ┌─────────────────────────────────┐ │
|
||||
│ │ setup_env_windows.ps1│ │ Hyper-V Manager │ │
|
||||
│ │ │ │ │ │
|
||||
│ │ • Check prereqs │───▶│ ┌──────────────────────────┐ │ │
|
||||
│ │ • Download image │ │ │ Ubuntu VM │ │ │
|
||||
│ │ • Create cloud-init │ │ │ │ │ │
|
||||
│ │ • Provision VM │ │ │ • Isolated filesystem │ │ │
|
||||
│ │ • Configure network │ │ │ • Own network (NAT) │ │ │
|
||||
│ └─────────────────────┘ │ │ • Claude Code + tools │ │ │
|
||||
│ │ │ • No Windows access │ │ │
|
||||
│ │ └──────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Script Workflow
|
||||
|
||||
### Phase 1: Prerequisites Check
|
||||
|
||||
```powershell
|
||||
# Verify environment
|
||||
1. Check Administrator privileges
|
||||
2. Check Windows edition (Pro/Enterprise/Education required)
|
||||
3. Check Hyper-V enabled
|
||||
4. Check for existing VM (handle -Force flag)
|
||||
5. Find suitable network switch
|
||||
```
|
||||
|
||||
### Phase 2: Configuration
|
||||
|
||||
```powershell
|
||||
# Collect credentials
|
||||
1. Load config.env if exists (git name/email)
|
||||
2. Prompt for missing values
|
||||
3. Prompt for VM password (not stored)
|
||||
4. Generate SSH key pair for VM access
|
||||
```
|
||||
|
||||
### Phase 3: Image Preparation
|
||||
|
||||
```powershell
|
||||
# Prepare Ubuntu cloud image
|
||||
1. Download Ubuntu cloud image (VHDX format)
|
||||
2. Cache in $env:ProgramData\HyperV-DevSandbox\Images
|
||||
3. Copy and resize for new VM
|
||||
4. Generate cloud-init ISO with:
|
||||
- User account configuration
|
||||
- SSH key injection
|
||||
- Package installation
|
||||
- Setup script embedding
|
||||
```
|
||||
|
||||
### Phase 4: VM Creation
|
||||
|
||||
```powershell
|
||||
# Create Hyper-V VM
|
||||
1. Create Generation 2 VM (UEFI)
|
||||
2. Configure resources (CPU, RAM, disk)
|
||||
3. Disable Secure Boot (for Ubuntu)
|
||||
4. Attach cloud-init ISO
|
||||
5. Disable integration services for isolation
|
||||
6. Enable nested virtualization (for Docker)
|
||||
```
|
||||
|
||||
### Phase 5: Provisioning
|
||||
|
||||
```powershell
|
||||
# Start and provision
|
||||
1. Start VM
|
||||
2. Wait for IP assignment
|
||||
3. Add to hosts file (<vmname>.local)
|
||||
4. Cloud-init runs setup_env.sh internally
|
||||
5. Display connection instructions
|
||||
```
|
||||
|
||||
## Cloud-Init Configuration
|
||||
|
||||
```yaml
|
||||
#cloud-config
|
||||
hostname: <vmname>
|
||||
users:
|
||||
- name: dev
|
||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||
ssh_authorized_keys:
|
||||
- <generated-public-key>
|
||||
packages:
|
||||
- openssh-server
|
||||
- curl
|
||||
- git
|
||||
write_files:
|
||||
- path: /tmp/setup_env.sh
|
||||
content: <base64-encoded-script>
|
||||
runcmd:
|
||||
- bash /tmp/setup_env.sh --non-interactive --yes
|
||||
```
|
||||
|
||||
## Security Hardening
|
||||
|
||||
### VM Configuration
|
||||
|
||||
```powershell
|
||||
# Disable integration services for maximum isolation
|
||||
Disable-VMIntegrationService -Name "Guest Service Interface"
|
||||
Disable-VMIntegrationService -Name "Heartbeat"
|
||||
# Keep Time Synchronization and Shutdown for usability
|
||||
```
|
||||
|
||||
### Network Isolation Options
|
||||
|
||||
1. **NAT (Default)**: VM can access internet, isolated from LAN
|
||||
2. **Internal Only**: VM can only communicate with host
|
||||
3. **Private**: Completely isolated network
|
||||
|
||||
### Firewall Rules (Optional)
|
||||
|
||||
```powershell
|
||||
# Allow SSH access only
|
||||
New-NetFirewallRule -Name "HyperV-SSH-$VMName" `
|
||||
-Direction Inbound -LocalPort 22 -Protocol TCP `
|
||||
-RemoteAddress <VM-IP> -Action Allow
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
### Windows Edition
|
||||
|
||||
- Windows 10/11 Pro
|
||||
- Windows 10/11 Enterprise
|
||||
- Windows 10/11 Education
|
||||
- Windows Server 2016+
|
||||
|
||||
**Not supported**: Windows 10/11 Home (no Hyper-V)
|
||||
|
||||
### Hardware
|
||||
|
||||
- 64-bit processor with SLAT (Second Level Address Translation)
|
||||
- VM Monitor Mode extensions (VT-x on Intel, AMD-V on AMD)
|
||||
- Minimum 4 GB RAM (8+ GB recommended)
|
||||
- BIOS/UEFI virtualization enabled
|
||||
|
||||
### Software
|
||||
|
||||
- Hyper-V enabled: `Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All`
|
||||
- Windows ADK (for cloud-init ISO creation): [Download](https://docs.microsoft.com/en-us/windows-hardware/get-started/adk-install)
|
||||
|
||||
## Usage
|
||||
|
||||
### Create Sandbox
|
||||
|
||||
```powershell
|
||||
# Basic usage (run as Administrator)
|
||||
.\setup_env_windows.ps1 -VMName my-project
|
||||
|
||||
# With custom resources
|
||||
.\setup_env_windows.ps1 -VMName my-project -MemoryGB 16 -DiskGB 100 -CPUs 8
|
||||
|
||||
# Replace existing VM
|
||||
.\setup_env_windows.ps1 -VMName my-project -Force
|
||||
```
|
||||
|
||||
### Connect to Sandbox
|
||||
|
||||
```powershell
|
||||
# Via SSH (recommended)
|
||||
ssh -i $env:USERPROFILE\.ssh\id_ed25519_<vmname> dev@<vmname>.local
|
||||
|
||||
# Via Hyper-V console
|
||||
vmconnect localhost <vmname>
|
||||
```
|
||||
|
||||
### Manage Sandbox
|
||||
|
||||
```powershell
|
||||
# Stop VM
|
||||
Stop-VM -Name <vmname>
|
||||
|
||||
# Start VM
|
||||
Start-VM -Name <vmname>
|
||||
|
||||
# Get VM IP
|
||||
(Get-VM -Name <vmname> | Get-VMNetworkAdapter).IPAddresses
|
||||
|
||||
# Delete VM completely
|
||||
Stop-VM -Name <vmname> -Force
|
||||
Remove-VM -Name <vmname> -Force
|
||||
Remove-Item -Path "$env:ProgramData\HyperV-DevSandbox\VMs\<vmname>" -Recurse -Force
|
||||
```
|
||||
|
||||
## Comparison: OrbStack vs Hyper-V
|
||||
|
||||
| Feature | OrbStack (macOS) | Hyper-V (Windows) |
|
||||
|---------|------------------|-------------------|
|
||||
| Host OS | macOS only | Windows only |
|
||||
| Setup complexity | Low | Medium |
|
||||
| Isolation | Full VM | Full VM |
|
||||
| DNS | `*.orb.local` auto | Manual hosts file |
|
||||
| SSH | Automatic | Key-based |
|
||||
| Filesystem sharing | Configurable | Disabled by default |
|
||||
| Performance | Near-native | Near-native |
|
||||
| Nested virtualization | Yes | Yes |
|
||||
|
||||
## Known Limitations
|
||||
|
||||
1. **Windows ADK Required**: Cloud-init ISO creation requires `oscdimg` from Windows ADK
|
||||
2. **Manual DNS**: No automatic DNS like OrbStack's `*.orb.local`
|
||||
3. **Key Management**: SSH keys generated per-VM, stored in user's .ssh folder
|
||||
4. **No Clipboard Sharing**: Disabled for security (can be enabled if needed)
|
||||
5. **Generation 2 Only**: Uses UEFI, no legacy BIOS support
|
||||
|
||||
## Future Improvements
|
||||
|
||||
- [ ] Add option for WSL2 (for users who prefer convenience over security)
|
||||
- [ ] Implement automatic DNS via Windows hosts file or local DNS server
|
||||
- [ ] Add PowerShell ISO creation without Windows ADK dependency
|
||||
- [ ] Support for VM templates/checkpoints
|
||||
- [ ] Integration with Windows Terminal for easy access
|
||||
- [ ] Optional WinRM configuration for PowerShell remoting
|
||||
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"
|
||||
1492
setup_env.sh
Executable file
1492
setup_env.sh
Executable file
File diff suppressed because it is too large
Load diff
1076
setup_env_windows.ps1
Normal file
1076
setup_env_windows.ps1
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue