User Input
CODEBLOCK0
You MUST consider the user input before proceeding (if not empty).
Execution Instructions
This skill provides a disposable VM sandbox for safe development and testing. All privileged operations (sudo, iptables, Docker, systemd, KVM) happen inside the VM — the host is never modified.
You (the agent) should NEVER need host-level sudo. Instead, use this Vagrant workflow to get a fully provisioned, disposable VM where you have unrestricted root access.
Prerequisites
Before using this workflow, verify a provider is available:
CODEBLOCK1
See references/platform-setup.md for detailed provider installation.
Core Workflow
Step 1: Create a Vagrantfile in the User's Project
If the user's project does not already have a Vagrantfile, you MUST create a real, working one in their project directory. This is not a template or example — it must work end-to-end with vagrant up.
Requirements for the Vagrantfile you create:
- - Base box: INLINECODE2
- Sync the project root into the VM: INLINECODE3
- Include all three providers (Parallels, libvirt, VirtualBox) so it works on any platform
- Provision with the actual tools the project needs (inspect the project first — look for
go.mod, package.json, requirements.txt, Makefile, Dockerfile, etc.) - Use
set -euo pipefail in provisioning scripts - Make provisioning idempotent
Here is the base Vagrantfile — you MUST customize the provisioning section based on what the project actually uses:
CODEBLOCK2
You MUST customize the provisioning section. Read the project to determine what it needs:
- -
go.mod → install Go - INLINECODE11 → install Node.js
- INLINECODE12 /
pyproject.toml → install Python - INLINECODE14 → Docker is already included above
- Network testing → add INLINECODE15
- KVM/microVM testing → add INLINECODE16
Uncomment the relevant blocks and add any other tooling. Do NOT leave placeholder comments in the final Vagrantfile — produce a clean, working file.
Then add .vagrant/ to the user's .gitignore if not already present:
CODEBLOCK3
The Vagrantfile itself should be committed — it's reusable project infrastructure.
If the user already has a Vagrantfile, use it as-is unless they ask to modify it.
Step 2: Start the VM
CODEBLOCK4
This boots the VM with the user's project synced at /project inside the VM.
Step 3: Run Commands Inside the VM
All commands use vagrant ssh -c from the host. No interactive SSH needed.
CODEBLOCK5
Step 4: Iterate on Code Changes
When you modify source on the host:
CODEBLOCK6
Step 5: Tear Down
CODEBLOCK7
Testing Patterns
Pattern: Build-Test-Fix Loop
CODEBLOCK8
Pattern: Docker-in-VM
CODEBLOCK9
Pattern: Network/Firewall Testing
CODEBLOCK10
Pattern: bats End-to-End Tests
Run a bats-core test suite against a live VM as proof that the system under test works. The VM must be up before running bats.
CODEBLOCK11
Capture output to show the user:
CODEBLOCK12
bats exits non-zero on any failure — treat that as a test run failure.
Pattern: Full Reprovision (Nuclear Option)
CODEBLOCK13
Configuration
Environment variables to customize the VM (set before vagrant up):
| Variable | Default | Purpose |
|---|
| INLINECODE23 | 4 | Number of vCPUs |
| INLINECODE24 |
4096 | RAM in MB |
Example:
CODEBLOCK14
See references/vm-contents.md for full details on VM filesystem layout and installed software.
Safety Guarantees
- - No host sudo required — all privileged operations are inside the VM
- Fully disposable —
vagrant destroy -f removes everything - Idempotent provisioning —
vagrant provision is safe to re-run - Isolated networking — VM has its own network stack
- Source is rsynced — VM gets a copy; your host repo is never modified by the VM
- No persistent state — destroying the VM removes all data
- Vagrantfile is committed — reusable across sessions;
.vagrant/ is gitignored
Examples
Example 1: Test iptables firewall rules without touching host network
User says: "I need to test some firewall rules before deploying to production"
Actions:
- 1. Create Vagrantfile with
iptables dnsmasq dnsutils iproute2 net-tools provisioned - INLINECODE29
- INLINECODE30
- INLINECODE31
- INLINECODE32 — verify rules look right
- INLINECODE33 — export if good
- INLINECODE34 to get rules file back, or
vagrant destroy -f to scrap
Result: Firewall rules iterated safely. Host network never touched. Rules exportable.
Example 2: Test systemd service configuration
User says: "I need to test this systemd unit file before deploying"
Actions:
- 1. Create Vagrantfile with the project synced
- INLINECODE36
- INLINECODE37
- INLINECODE38
- INLINECODE39 — check it works
- INLINECODE40 — check logs
- INLINECODE41 — clean slate
Result: Service tested with real systemd, real journald. No risk to host init system.
Example 3: Docker daemon configuration and privileged port binding
User says: "I need to test a Docker compose setup that binds port 80"
Actions:
- 1. Create Vagrantfile with Docker CE provisioned
- INLINECODE42
- INLINECODE43
- INLINECODE44 — test from inside VM
- INLINECODE45 — check output
- INLINECODE46 — cleanup
- INLINECODE47
Result: Full Docker compose stack running with privileged ports — impossible without sudo on the host.
Example 4: Run the built-in e2e examples
Three working examples live under examples/ in this skill's directory. All follow the same pattern — boot, test, tear down:
CODEBLOCK15
examples/nginx-hardened/ — Linux / libvirt (16 tests)
Deploys nginx + hardened iptables (INPUT DROP, allow SSH + HTTP only).
Why VM: iptables -F INPUT; iptables -P INPUT DROP on the host locks you out.
CODEBLOCK16
examples/mac-docker-compose/ — Mac Apple Silicon / Parallels (14 tests)
Runs a Docker Compose stack: nginx on port 80 proxying a Python JSON API.
Why VM: Docker Desktop requires a commercial license; Docker CE in a VM has none of its restrictions.
CODEBLOCK17
examples/windows-systemd-service/ — Windows WSL2 / VirtualBox (20 tests)
Deploys a Python HTTP server as a real systemd unit, running as a dedicated system user.
Why VM: WSL2 does not run real systemd — unit files cannot be tested without a real Linux init.
WSL2 pre-flight:
CODEBLOCK18
CODEBLOCK19
Troubleshooting
VM Won't Boot
Error: vagrant up hangs or times out
Cause: Provider not installed or configured correctly
Solution:
- 1. Check provider is installed: INLINECODE54
- Debug boot: INLINECODE55
- Try explicit provider: INLINECODE56
Source Not Synced
Error: /project directory is empty or missing inside VM
Cause: rsync failed or synced_folder misconfigured
Solution:
- 1. Re-sync: INLINECODE58
- Check Vagrantfile has INLINECODE59
Provider Mismatch
Error: vagrant up uses wrong provider
Cause: Multiple providers installed, Vagrant auto-selects
Solution:
- 1. Check what's running: INLINECODE61
- Force provider: INLINECODE62
KVM Not Available Inside VM
Error: /dev/kvm missing inside the VM
Cause: Host doesn't support nested virtualization or provider not configured
Solution:
- 1. Ensure host has KVM:
test -e /dev/kvm on host - Use libvirt provider with INLINECODE65
- Mac: nested KVM is not available — use a Linux host for KVM workloads
用户输入
text
$ARGUMENTS
在继续之前,你必须考虑用户输入(如果不为空)。
执行说明
本技能提供一个一次性虚拟机沙箱,用于安全的开发和测试。所有特权操作(sudo、iptables、Docker、systemd、KVM)都在虚拟机内部进行——宿主机不会被修改。
你(代理)永远不需要宿主机级别的 sudo。 相反,使用此 Vagrant 工作流程来获取一个完全配置好的、一次性虚拟机,在其中你拥有不受限制的 root 访问权限。
前置条件
在使用此工作流程之前,请确认有一个可用的提供者:
bash
检查 Vagrant 是否已安装
command -v vagrant
检查是否有可用的提供者(任意一个即可)
command -v prlctl # Parallels(Mac Apple Silicon — 推荐)
vagrant plugin list | grep libvirt # libvirt(Linux — 嵌套 KVM)
command -v VBoxManage # VirtualBox(备选)
详细的提供者安装说明请参见 references/platform-setup.md。
核心工作流程
步骤 1:在用户项目中创建 Vagrantfile
如果用户项目尚未包含 Vagrantfile,你必须在其项目目录中创建一个真实可用的文件。这不是模板或示例——它必须能够与 vagrant up 端到端配合使用。
你创建的 Vagrantfile 要求:
- - 基础镜像:bento/ubuntu-24.04
- 将项目根目录同步到虚拟机中:config.vm.synced_folder ., /project, type: rsync
- 包含所有三个提供者(Parallels、libvirt、VirtualBox),以便在任何平台上都能工作
- 使用项目实际需要的工具进行配置(先检查项目——查找 go.mod、package.json、requirements.txt、Makefile、Dockerfile 等)
- 在配置脚本中使用 set -euo pipefail
- 使配置具有幂等性
以下是基础 Vagrantfile——你必须根据项目实际使用的内容自定义配置部分:
ruby
-- mode: ruby --
Vagrantfile — 一次性开发/测试虚拟机
VMCPUS = Integer(ENV[VMCPUS] || 4)
VMMEMORY = Integer(ENV[VMMEMORY] || 4096)
Vagrant.configure(2) do |config|
config.vm.box = bento/ubuntu-24.04
config.vm.boxcheckupdate = false
config.vm.hostname = dev
config.vm.boot_timeout = 300
config.ssh.forward_agent = true
# ─── 将项目同步到虚拟机中的 /project ─────────────────────────────────────
config.vm.synced_folder ., /project, type: rsync,
rsyncexclude: [
.git/, node_modules/, vendor/, .vagrant/,
bin/, dist/, build/, .next/,
]
# ─── 提供者:Parallels(Mac Apple Silicon — 推荐)────────────────────────
config.vm.provider parallels do |prl|
prl.cpus = VM_CPUS
prl.memory = VM_MEMORY
prl.updateguesttools = true
end
# ─── 提供者:libvirt(Linux — 首选,嵌套 KVM)────────────────────────────
config.vm.provider libvirt do |lv|
lv.cpus = VM_CPUS
lv.memory = VM_MEMORY
lv.cpu_mode = host-passthrough
lv.nested = true
end
# ─── 提供者:VirtualBox(跨平台备选)─────────────────────────────────────
config.vm.provider virtualbox do |vb|
vb.cpus = VM_CPUS
vb.memory = VM_MEMORY
vb.customize [modifyvm, :id, --nested-hw-virt, on]
end
# ─── 配置:安装项目依赖 ──────────────────────────────────────────────
# 根据项目自定义此项。检查 go.mod、package.json、
# requirements.txt、Dockerfile、Makefile 等,并安装所需内容。
config.vm.provision shell, privileged: true, inline: <<-SHELL
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq build-essential curl git jq ca-certificates gnupg
# ── Docker ────────────────────────────────────────────────────────────
if ! command -v docker &>/dev/null; then
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
-o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo $VERSION_CODENAME) stable \
| tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update -qq
apt-get install -y -qq docker-ce docker-ce-cli containerd.io
fi
systemctl enable --now docker
usermod -aG docker vagrant
# ── 在下方添加项目特定的工具 ────────────────────────────────
# 示例(取消注释/添加项目所需的内容):
#
# Go:
# GO_VERSION=1.24.3
# curl -fsSL https://go.dev/dl/go${GO_VERSION}.linux-$(dpkg --print-architecture).tar.gz \
# | tar -C /usr/local -xz
# echo export PATH=/usr/local/go/bin:$HOME/go/bin:$PATH > /etc/profile.d/go.sh
#
# Node.js:
# curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
# apt-get install -y -qq nodejs
#
# Python:
# apt-get install -y -qq python3 python3-pip python3-venv
echo 虚拟机已就绪 — 项目已同步到 /project
SHELL
end
你必须自定义配置部分。 阅读项目以确定其需要什么:
- - go.mod → 安装 Go
- package.json → 安装 Node.js
- requirements.txt / pyproject.toml → 安装 Python
- Dockerfile → 上面已包含 Docker
- 网络测试 → 添加 iptables dnsmasq dnsutils iproute2 net-tools
- KVM/微型VM 测试 → 添加 qemu-kvm libvirt-daemon-system
取消注释相关代码块并添加任何其他工具。不要在最终的 Vagrantfile 中留下占位符注释——生成一个干净、可工作的文件。
然后,如果尚未存在,将 .vagrant/ 添加到用户的 .gitignore 中:
bash
grep -qxF .vagrant/ .gitignore 2>/dev/null || echo .vagrant/ >> .gitignore
Vagrantfile 本身应该被提交——它是可重用的项目基础设施。
如果用户已有 Vagrantfile,除非他们要求修改,否则按原样使用。
步骤 2:启动虚拟机
bash
vagrant up
这将启动虚拟机,并将用户项目同步到虚拟机内的 /project。
步骤 3:在虚拟机内运行命令
所有命令都从宿主机使用 vagrant ssh -c。 无需交互式 SSH。
bash
使用 sudo 运行任何命令
vagrant ssh -c sudo apt-get install -y some-package
构建项目
vagrant ssh -c cd /project && make build
vagrant ssh -c cd /project && go test ./...
Docker 操作
vagrant ssh -c docker build -t myimage .
vagrant ssh -c docker run --rm myimage
网络/防火墙测试
vagrant ssh -c sudo iptables -L -n
步骤 4:迭代代码更改
当你在宿主机上修改源代码时:
bash
vagrant rsync # 将更改同步到虚拟机
vagrant ssh -c cd /project && make build # 重新构建
vagrant ssh -c cd /project && make test # 测试
步骤