在 NixOS 上使用 microvm.nix 的编码代理虚拟机
摘要
一篇技术指南,介绍如何在 NixOS 上使用 microvm.nix 创建临时虚拟机,以便在无法访问个人文件的情况下安全运行编码代理。
<p>我已经认识到,编码代理在处理计算机程序代码方面是有价值的工具,无论用途如何,例如了解程序架构、诊断错误或开发概念验证。根据使用场景,审查代理想要运行的每个命令会很快变得繁琐且耗时。为了在不审查的情况下安全运行编码代理,我想要一个虚拟机解决方案,使代理无法访问我的个人文件,并且如果代理被恶意软件入侵也无大碍:我只需丢弃虚拟机并重新开始。</p>
<p>我不喜欢设置一个有状态虚拟机并在需要时重新安装(哎呀!),而是更喜欢临时虚拟机的模式,即除了显式与主机共享的内容外,磁盘上不保留任何东西。</p>
<p><a href="https://github.com/microvm-nix/microvm.nix"><code>microvm.nix</code> 项目</a>使得在 NixOS 上创建此类虚拟机变得容易,本文展示了我是如何设置我的虚拟机的。</p>
<h2 id="see-also">另请参阅</h2>
<p>如果你以前没有听说过 NixOS,请查看 <a href="https://en.wikipedia.org/wiki/NixOS">NixOS 维基百科页面</a>和 <a href="https://nixos.org/">nixos.org</a>。我曾在 <a href="/talks/#2025">2025 年谈论过我为何转向 Nix</a>,并发布了一些<a href="/posts/tags/nix/">关于 Nix 的博客文章</a>。</p>
<p>要了解 AI 代理的威胁模型,请阅读 <a href="https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/">Simon Willison 的《AI 代理的致命三重奏:私有数据、不可信内容和外部通信》(2025 年 6 月)</a>。本文处理威胁模型的方法是删除等式中的“私有数据”部分。</p>
<p>如果你想了解沙盒的整个领域,请查看 <a href="https://www.luiscardoso.dev/blog/sandboxes-for-ai">Luis Cardoso 的《AI 沙盒现场指南》(2026 年 1 月)</a>。我不会在本文中比较不同的解决方案,只会向你展示一条可能路径。</p>
<p>最后,也许你不想自己构建/运行沙盒基础设施。好消息是:沙盒是一个热门话题,许多商业产品不断涌现以满足这一需求。例如,David Crawshaw 和 Josh Bleecher Snyder(我都从 Go 社区了解他们)最近推出了 <a href="https://blog.exe.dev/meet-exe.dev">exe.dev</a>,一个对代理友好的虚拟机托管服务。另一个例子是 <a href="https://fly.io/blog/code-and-let-live/">Fly.io,他们推出了 Sprites</a>。</p>
<h2 id="setting-up-microvmnix">设置 microvm.nix</h2>
<p>让我们直接开始吧!接下来的部分将引导你了解我是如何配置的。</p>
<h3 id="step-1-network-prep">步骤 1:网络准备</h3>
<p>首先,我创建了一个新的 <code>microbr</code> 桥接,它使用 <code>192.168.33.1/24</code> 作为 IP 地址范围,并通过 <code>eno1</code> 网络接口进行 NAT。所有 <code>microvm*</code> 接口都将添加到该桥接中:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>systemd<span style="color:#666">.</span>network<span style="color:#666">.</span>netdevs<span style="color:#666">.</span><span style="color:#4070a0">"20-microbr"</span><span style="color:#666">.</span>netdevConfig <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> Kind <span style="color:#666">=</span> <span style="color:#4070a0">"bridge"</span>;
</span></span><span style="display:flex;"><span> Name <span style="color:#666">=</span> <span style="color:#4070a0">"microbr"</span>;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>systemd<span style="color:#666">.</span>network<span style="color:#666">.</span>networks<span style="color:#666">.</span><span style="color:#4070a0">"20-microbr"</span> <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> matchConfig<span style="color:#666">.</span>Name <span style="color:#666">=</span> <span style="color:#4070a0">"microbr"</span>;
</span></span><span style="display:flex;"><span> addresses <span style="color:#666">=</span> [ { Address <span style="color:#666">=</span> <span style="color:#4070a0">"192.168.83.1/24"</span>; } ];
</span></span><span style="display:flex;"><span> networkConfig <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> ConfigureWithoutCarrier <span style="color:#666">=</span> <span style="color:#60add5">true</span>;
</span></span><span style="display:flex;"><span> };
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>systemd<span style="color:#666">.</span>network<span style="color:#666">.</span>networks<span style="color:#666">.</span><span style="color:#4070a0">"21-microvm-tap"</span> <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> matchConfig<span style="color:#666">.</span>Name <span style="color:#666">=</span> <span style="color:#4070a0">"microvm*"</span>;
</span></span><span style="display:flex;"><span> networkConfig<span style="color:#666">.</span>Bridge <span style="color:#666">=</span> <span style="color:#4070a0">"microbr"</span>;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>networking<span style="color:#666">.</span>nat <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> enable <span style="color:#666">=</span> <span style="color:#60add5">true</span>;
</span></span><span style="display:flex;"><span> internalInterfaces <span style="color:#666">=</span> [ <span style="color:#4070a0">"microbr"</span> ];
</span></span><span style="display:flex;"><span> externalInterface <span style="color:#666">=</span> <span style="color:#4070a0">"eno1"</span>;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><h3 id="step-2-flakenix">步骤 2:<code>flake.nix</code></h3>
<p>然后,我将 <code>microvm</code> 模块作为新输入添加到我的 <code>flake.nix</code>(有关详细信息,请查看 <a href="https://microvm-nix.github.io/microvm.nix/">microvm.nix 文档</a>),并在我的 PC(midna)的 NixOS 配置上启用了 <code>microvm.nixosModules.host</code> 模块。我还创建了一个新的 <code>microvm.nix</code> 文件,在其中声明了我所有的虚拟机。这是我的 <code>flake.nix</code> 的样子:</p>
<div class="highlight"><pre tabindex="0" style="background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;display:grid;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span> inputs <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> nixpkgs <span style="color:#666">=</span> {
</span></span><span style="display:flex;"><span> url <span style="color:#666">=</span> <span style="color:#4070a0">"github:nixos/nixpkgs/nixos-25.11"</span>;
</span></span><span style="display:flex;"><span> };
</span></span><span style="display:flex; background-color:#d8d8d8"><span> <span style="color:#60a0b0;font-style:italic"># For more recent claude-code</span>
</span></span><span style="display:flex; background-color:#d8d8d8"><span> nixpkgs-unstable <span style="color:#666">=</span> {
</span></span><span style="display:flex; background-color:#d8d8d8"><span> url <span style="color:#666">=</span> <span style="color:#4070a0">"github:nixos/nixpkgs/nixos-unstable"</span>;
</span></span>
查看缓存全文
缓存时间: 2026/05/16 03:32
# 在 NixOS 上使用 microvm.nix 搭建编码代理虚拟机
来源:https://michael.stapelberg.ch/posts/2026-02-01-coding-agent-microvm-nix/
## 目录
- [参见](#参见)
- [配置 microvm.nix](#配置-microvmnix)
- [第 1 步:网络准备](#第-1-步网络准备)
- [第 2 步:`flake.nix`](#第-2-步-flakenix)
- [第 3 步:`microvm.nix`](#第-3-步-microvmnix)
- [第 4 步:`microvm-base.nix`](#第-4-步-microvm-basenix)
- [第 5 步:`microvm-home.nix`](#第-5-步-microvm-homenix)
- [第 6 步:`goprotobuf.nix`](#第-6-步-goprotobufnix)
- [运行虚拟机](#运行虚拟机)
- [使用 Claude 创建虚拟机](#使用-claude-创建虚拟机)
- [使用 Claude Code 复制此配置](#使用-claude-code-复制此配置)
- [结论](#结论)
我已经开始欣赏[编码代理](https://en.wikipedia.org/wiki/AI-assisted_software_development)作为处理计算机程序代码的有用工具——无论是学习程序架构、诊断 Bug 还是开发概念验证。根据使用场景,审查代理想要运行的每条命令很快就会变得繁琐且耗时。为了安全地运行编码代理而无需审查,我希望有一个虚拟机(VM)解决方案:代理无法访问我的个人文件,即使代理被恶意软件攻陷也无大碍——我可以直接丢弃虚拟机并重新开始。比起设置一个有状态的虚拟机并在需要时重新安装(哎呀!),我更喜欢临时虚拟机的模式:磁盘上不持久保留任何内容,除了显式与宿主机共享的部分。
[microvm.nix](https://github.com/microvm-nix/microvm.nix) 项目使得在 NixOS 上创建这样的虚拟机变得很容易,本文展示了我如何设置我的虚拟机。
## 参见
如果你还没听说过 NixOS,可以看看 [NixOS Wikipedia 页面](https://en.wikipedia.org/wiki/NixOS) 和 [nixos.org](https://nixos.org/)。我[在 2025 年谈论过为何切换到 Nix](https://michael.stapelberg.ch/talks/#2025),并发表过 [几篇关于 Nix 的博客文章](https://michael.stapelberg.ch/posts/tags/nix/)。
要理解 AI 代理的威胁模型,请阅读 Simon Willison 的《AI 代理的致命三重威胁:私有数据、不可信内容和外部通信》(2025 年 6 月)(https://simonwillison.net/2025/Jun/16/the-lethal-trifecta/)。本文处理威胁模型的方法是将“私有数据”这一部分从方程中移除。
如果你想了解沙盒的整个领域,请查看 Luis Cardoso 的《AI 沙盒实用指南》(2026 年 1 月)(https://www.luiscardoso.dev/blog/sandboxes-for-ai)。本文不会比较不同解决方案,只展示一条可行的路径。
最后,也许你不想自己构建/运行沙盒基础设施。好消息是:沙盒是热门话题,许多商业服务正在涌现以解决这一需求。例如,David Crawshaw 和 Josh Bleecher Snyder(我都是通过 Go 社区认识的)最近推出了 [exe.dev](https://blog.exe.dev/meet-exe.dev),一个面向代理的虚拟机托管服务。另一个例子是 Fly.io,他们推出了 [Sprites](https://fly.io/blog/code-and-let-live/)。
## 配置 microvm.nix
让我们直接进入正题!接下来的几个小节将带你了解我如何配置我的设置。
### 第 1 步:网络准备
首先,我创建了一个新的 `microbr` 桥接,使用 `192.168.33.1/24` 作为 IP 地址范围,并通过 `eno1` 网络接口执行 NAT。所有 `microvm*` 接口都将添加到该桥接:
```nix
systemd.network.netdevs."20-microbr".netdevConfig = {
Kind = "bridge";
Name = "microbr";
};
systemd.network.networks."20-microbr" = {
matchConfig.Name = "microbr";
addresses = [ { Address = "192.168.83.1/24"; } ];
networkConfig = { ConfigureWithoutCarrier = true; };
};
systemd.network.networks."21-microvm-tap" = {
matchConfig.Name = "microvm*";
networkConfig.Bridge = "microbr";
};
networking.nat = {
enable = true;
internalInterfaces = [ "microbr" ];
externalInterface = "eno1";
};
```
### 第 2 步:`flake.nix`
然后,我将 `microvm` 模块作为新输入添加到我的 `flake.nix`(详情请查看 [microvm.nix 文档](https://microvm-nix.github.io/microvm.nix/)),并在我的 PC(midna)的 NixOS 配置上启用了 `microvm.nixosModules.host` 模块。我还创建了一个新的 `microvm.nix` 文件,其中声明了我所有的虚拟机。以下是我的 `flake.nix` 内容:
```nix
{
inputs = {
nixpkgs = {
url = "github:nixos/nixpkgs/nixos-25.11";
};
# 为了更新版本的 claude-code
nixpkgs-unstable = {
url = "github:nixos/nixpkgs/nixos-unstable";
};
stapelbergnix = {
url = "github:stapelberg/nix";
inputs.nixpkgs.follows = "nixpkgs";
};
zkjnastools = {
url = "github:stapelberg/zkj-nas-tools";
inputs.nixpkgs.follows = "nixpkgs";
};
microvm = {
url = "github:microvm-nix/microvm.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
home-manager = {
url = "github:nix-community/home-manager/release-25.11";
inputs.nixpkgs.follows = "nixpkgs";
};
configfiles = {
url = "github:stapelberg/configfiles";
flake = false; # 仓库不是 flake
};
};
outputs = { self, stapelbergnix, zkjnastools, nixpkgs, nixpkgs-unstable, microvm, home-manager, configfiles, }@inputs:
let
system = "x86_64-linux";
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = false;
};
pkgs-unstable = import nixpkgs-unstable {
inherit system;
config.allowUnfree = true;
};
in {
nixosConfigurations = {
midna = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = { inherit inputs; };
modules = [
(import ./configuration.nix)
stapelbergnix.lib.userSettings
# 使用 systemd 进行网络配置
stapelbergnix.lib.systemdNetwork
# 使用 systemd-boot 作为引导加载程序
stapelbergnix.lib.systemdBoot
# 在 tailnet 中运行 prometheus node exporter
stapelbergnix.lib.prometheusNode
zkjnastools.nixosModules.zkjbackup
microvm.nixosModules.host
./microvm.nix
];
};
};
};
}
```
### 第 3 步:`microvm.nix`
下面的 `microvm.nix` 声明了两个 microvm:一个用于 Emacs(我想了解更多),另一个用于 Go Protobuf(一个我熟悉的代码库,可用于理解 Claude 的能力):
```nix
{ config, lib, pkgs, inputs, ... }:
let
inherit (inputs) nixpkgs-unstable stapelbergnix microvm configfiles home-manager;
microvmBase = import ./microvm-base.nix;
in {
microvm.vms.emacsvm = {
autostart = false;
config = {
imports = [
stapelbergnix.lib.userSettings
microvm.nixosModules.microvm
(microvmBase {
hostName = "emacsvm";
ipAddress = "192.168.83.6";
tapId = "microvm4";
mac = "02:00:00:00:00:05";
workspace = "/home/michael/microvm/emacs";
inherit nixpkgs-unstable configfiles home-manager stapelbergnix;
})
./microvms/emacs.nix
];
};
};
microvm.vms.goprotobufvm = {
autostart = false;
config = {
imports = [
stapelbergnix.lib.userSettings
microvm.nixosModules.microvm
(microvmBase {
hostName = "goprotobufvm";
ipAddress = "192.168.83.7";
tapId = "microvm5";
mac = "02:00:00:00:00:06";
workspace = "/home/michael/microvm/goprotobuf";
inherit nixpkgs-unstable configfiles home-manager stapelbergnix;
extraZshInit = ''
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH
'';
})
./microvms/goprotobuf.nix
];
};
};
}
```
### 第 4 步:`microvm-base.nix`
`microvm-base.nix` 模块接受这些参数并声明:
- 网络设置:我喜欢使用 `systemd-networkd(8)`(https://manpages.debian.org/systemd-networkd.8) 和 `systemd-resolved(8)`(https://manpages.debian.org/systemd-resolved.8)。
- 共享目录:
- 工作空间目录,例如 `~/microvm/emacs`
- 宿主机的 Nix store,以便虚拟机可以从缓存中访问软件(通常如此)
- 该虚拟机的 SSH 主机密钥
- `~/claude-microvm`,这是一个单独的状态目录,仅用于 microvm 中。
- 一个 8 GB 的磁盘覆盖层(var.img),存储在 `/var/lib/microvms/` 中
- `cloud-hypervisor`(QEMU 也效果很好!)作为虚拟机监控程序,配备 8 个 vCPU 和 4 GB RAM。
- 解决 systemd 尝试卸载 `/nix/store` 的问题(会导致死锁)。
展开完整的 `microvm-base.nix` 代码
```nix
{ hostName, ipAddress, tapId, mac, workspace, nixpkgs-unstable, configfiles, home-manager, stapelbergnix, extraZshInit ? "", }:
{ config, lib, pkgs, ... }:
let
system = pkgs.stdenv.hostPlatform.system;
pkgsUnstable = import nixpkgs-unstable {
inherit system;
config.allowUnfree = true;
};
in {
imports = [
home-manager.nixosModules.home-manager
];
# home-manager configuration
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit configfiles stapelbergnix; };
home-manager.users.michael = {
imports = [ ./microvm-home.nix ];
microvm.extraZshInit = extraZshInit;
};
# Claude Code CLI (来自 nixpkgs-unstable, unfree)
environment.systemPackages = [ pkgsUnstable.claude-code ];
networking.hostName = hostName;
system.stateVersion = "25.11";
services.openssh.enable = true;
# 为了匹配 midna(宿主机)
users.groups.michael = { gid = 1000; };
users.users.michael = { group = "michael"; };
services.resolved.enable = true;
networking.useDHCP = false;
networking.useNetworkd = true;
networking.tempAddresses = "disabled";
systemd.network.enable = true;
systemd.network.networks."10-e" = {
matchConfig.Name = "e*";
addresses = [ { Address = "${ipAddress}/24"; } ];
routes = [ { Gateway = "192.168.83.1"; } ];
};
networking.nameservers = [ "8.8.8.8" "1.1.1.1" ];
# 禁用防火墙以实现更快的启动和更少的麻烦;
# 反正我们处于 NAT 层后面。
networking.firewall.enable = false;
systemd.settings.Manager = {
# 快速关机/重启! https://mas.to/@zekjur/113109742103219075
DefaultTimeoutStopSec = "5s";
};
# 修复 microvm 关机挂起问题 (issue #170):
# 如果没有这个,systemd 在关机时会尝试卸载 /nix/store,
# 但 umount 位于 /nix/store 中,导致死锁。
systemd.mounts = [
{
what = "store";
where = "/nix/store";
overrideStrategy = "asDropin";
unitConfig.DefaultDependencies = false;
}
];
# 使用从虚拟机外部挂载的 SSH 主机密钥(保持不变)。
services.openssh.hostKeys = [
{ path = "/etc/ssh/host-keys/ssh_host_ed25519_key"; type = "ed25519"; }
];
microvm = {
# 启用可写的 nix store 覆盖层,以便 nix-daemon 工作。
# 这是 home-manager 激活所必需的。
# 默认使用 tmpfs(临时),这没问题,因为我们
# 不会在虚拟机中构建任何东西。
writableStoreOverlay = "/nix/.rw-store";
volumes = [
{
mountPoint = "/var";
image = "var.img";
size = 8192; # MB
}
];
shares = [
{
# 对于由 systemd 启动的 MicroVM,使用 proto = "virtiofs"
proto = "virtiofs";
tag = "ro-store";
# 宿主机上的 /nix/store 将被获取,这样就不需要为它构建
# squashfs/erofs 了。
source = "/nix/store";
mountPoint = "/nix/.ro-store";
}
{
proto = "virtiofs";
tag = "ssh-keys";
source = "${workspace}/ssh-host-keys";
mountPoint = "/etc/ssh/host-keys";
}
{
proto = "virtiofs";
tag = "claude-credentials";
source = "/home/michael/claude-microvm";
mountPoint = "/home/michael/claude-microvm";
}
{
proto = "virtiofs";
tag = "workspace";
source = workspace;
mountPoint = workspace;
}
];
interfaces = [
{
type = "tap";
id = tapId;
mac = mac;
}
];
hypervisor = "cloud-hypervisor";
vcpu = 8;
mem = 4096;
socket = "control.socket";
};
}
```
### 第 5 步:`microvm-home.nix`
`microvm-base.nix` 进而引入了 `microvm-home.nix`,它配置 home-manager 以:
- 使用我的配置设置 Zsh
- 使用我的配置设置 Emacs
- 在共享目录 `~/claude-microvm` 中设置 Claude Code。
展开完整的 `microvm-home.nix` 代码
```nix
{ config, pkgs, lib, configfiles, stapelbergnix, ... }:
{
options.microvm = {
extraZshInit = lib.mkOption {
type = lib.types.lines;
default = "";
description = "要添加到 zsh initContent 的额外行";
};
};
config = {
home.username = "michael";
home.homeDirectory = "/home/michael";
programs.zsh = {
enable = true;
history = {
size = 4000;
save = 10000000;
ignoreDups = true;
share = false;
append = true;
};
initContent = ''
${builtins.readFile "${configfiles}/zshrc"}
export CLAUDE_CONFIG_DIR=/home/michael/claude-microvm
${config.microvm.extraZshInit}
'';
};
programs.emacs = {
enable = true;
package = stapelbergnix.lib.emacsWithPackages { inherit pkgs; };
};
home.file.".config/emacs" = {
source = "${configfiles}/config/emacs";
};
home.stateVersion = "25.11";
programs.home-manager.enable = true;
};
}
```
### 第 6 步:`goprotobuf.nix`
`goprotobuf.nix` 提供了一系列必需和便捷的包:
```nix
# Project-specific configuration for goprotobufvm
{ pkgs, ... }: {
# Development environment for Go Protobuf
environment.systemPackages = with pkgs; [
# Go toolchain
go
gopls
delve
protobuf
gnumake
gcc
git
ripgrep
];
}
```
### 运行虚拟机
让我们创建工作空间目录并创建 SSH 主机密钥:
```bash
mkdir -p ~/microvm/emacs/ssh-host-keys
ssh-keygen -t ed25519 -N "" \
-f ~/microvm/emacs/ssh-host-keys/ssh_host_ed25519_key
```
现在我们可以启动虚拟机:
```bash
sudo systemctl start microvm@emacsvm
```
它在几秒钟内启动并响应 ping。然后,SSH 进入虚拟机(也许在 `tmux(1)`(https://manpages.debian.org/tmux.1) 会话中),在共享的工作空间目录中运行 Claude(或你选择的编码代理),无需权限提示:
```bash
% ssh 192.168.83.2
emacsvm% cd microvm/emacs
emacsvm% claude --dangerously-skip-permissions
```
这是在此类设置中运行 Claude 的样子:
Claude Code 处于“绕过权限”模式 (https://michael.stapelberg.ch/posts/2026-02-01-coding-agent-microvm-nix/2026-01-28-neofetch-featured.png)
## 使用 Claude 创建虚拟机
在完成一次设置 MicroVM 的过程后,它就变得乏味了。我很好奇 [Claude Skills](https://code.claude.com/docs/en/skills) 是否能帮助完成这样的任务。Skills 是 markdown 文件,指示 Claude 在特定情况下执行某些步骤。我创建了 `~/.claude/skills/create-microvm/SKILL.md`,内容如下:
```markdown
---
name: create-microvm
description: 在 midna 上创建一个新的 microvm 虚拟机,用于在其中运行 Claude,
包括源代码仓库和构建依赖项。当用户要求创建新的 microvm 时使用。
---
检查 ~/machines/midna 中现有的结构(使用 Flakes 的 NixOS 配置),其中包括
~/machines/midna/microvms/ 目录中的多个 MicroVM。
然后,为用户要求创建的 microvm 创建类似的结构。请确保考虑:
1. 创建一个以 NAME(microvm 名称)命名的新子目录。
2. 在 microvm.nix 中创建一个条目,类似于现有 microvm,但要:
3. 将 hostname 改为 NAME
4. 更改 IP 地址(例如 192.168.83.3):查找已使用的,并选择下一个空闲的
5. 将 workspace share 改为 /home/michael/microvm/NAME
6. 根据用户请求包含新 microvm 的构建依赖项
7. 创建 ssh-host-keys 目录
8. 生成 SSH 主机密钥
9. 根据用户请求将源代码仓库克隆/下载到此 microvm
定义好 microvm 后,更新 ~/machines/midna 以包含它。
要验证,构建配置(但不要部署)。
你需要先将更改提交到 microvm,然后 ~/machines/midna 才能看到它们。
```
当使用此技能与 Claude Code(测试版本:v2.0.76 和 v2.1.15)配合使用时,采用 Opus 4.5 模型 (https://www.ant
相似文章
使用Nix的开发环境:四个快速示例
本教程演示了使用Nix设置开发环境的四种方法,包括交互式一次性使用、配置文件以及密封的Nix Flakes,并以GoCV和OpenCV为例。
我喜欢的 NixOS 声明式安装方式
一份关于使用 nixos-anywhere 等工具通过网络声明式安装 NixOS 的指南,重点强调在版本控制下管理配置文件。
开源适用于 Docker 和 gVisor 沙箱的 MicroVM 运行时
Aerol AI 开源了一个与 Docker 和 gVisor 沙箱兼容的 MicroVM 运行时,其设置和启动速度比现有方案更快。
使用sops-nix在NixOS上管理机密
使用sops-nix在NixOS配置中管理机密的指南,涵盖设置、加密以及与Samba等服务的集成。
在 VPS 上运行我的智能体
作者概述了一种在隔离 VPS 上运行 AI 编码智能体的方法,旨在实现自主、异步工作,同时不危及本地机器的安全性。