Каждую неделю появляется новая песочница для агентов. Большинство таких решений опирается на встроенные механизмы Linux: namespaces, seccomp, cgroups и Landlock. Эти инструменты полезны, но они делят одно ядро с хостом и оставляют оператора внутри модели политик хоста. Полная microVM дает более четкую границу: ядро, которое вы сами выбрали, корневой диск, который можно проверить, сетевой линк, который можно записать, и отказ, который не становится состоянием хоста.
https://github.com/ingresslabs/firecracker-sandbox.git
Firecracker полезен именно тогда, когда граница видна. В этой сборке граница состоит из собственного ядра Linux, ext4 диска, процесса Firecracker и tap интерфейса tap0 на хосте. Виртуальная машина не прячется за большой облачной панелью. У хоста адрес 192.168.1.1. У гостя адрес 192.168.1.2. Каждый пакет проходит через этот короткий маршрут.
Я проверил весь путь на root@121.115.45.227. Это Ubuntu 22.04 с /dev/kvm, 16 CPU, Firecracker 1.15.1, make, gcc, screen и iptables. Собранное ядро было Linux 7.0.9. Итоговый vmlinux занял 49 MB. ВМ загрузила Debian 11 до multi user режима и вошла как root через ttyS0.
Это минимальное полезное доказательство: ядро загружается, корневой диск монтируется, serial console работает, сеть можно наблюдать с хоста.
Сборка ядра
В репозитории песочницы уже есть цель Makefile:
make build-kernel
Скрипт сборки скачивает текущий stable исходный код Linux, начинает с make defconfig и включает драйверы, которые нужны Firecracker: virtio block, virtio net, virtio PCI, virtio MMIO, ext4, devtmpfs и serial console. Serial console здесь не украшение. Если гость падает до готовой сети, ttyS0 и firecracker-console.log остаются самым простым способом увидеть причину.
Базовый config широкий, поэтому сборка не маленькая. На тестовом хосте скрипт собрал полный x86 kernel и только потом скопировал vmlinux в каталог песочницы. Для строгой production сборки лучше держать небольшой проверенный kernel config и запускать make olddefconfig перед компиляцией. Для лабораторного доказательства скрипта репозитория достаточно.
Сборка корневого диска
Обычный путь такой:
make build-simple-rootfs
Эта цель создает firecracker-rootfs.ext4, ставит Debian с systemd, включает автоматический вход root через serial console и пишет статическую сетевую конфигурацию для eth0. Тестовый запуск показал две практические правки. Цель пыталась записать mnt/etc/network/interfaces до создания mnt/etc/network. Еще в rootfs был обязательный mount virtiofs, хотя в ядре не было соответствующей поддержки гостя. Нужно создать каталог до записи interface file. Общий mount стоит сделать необязательным или убрать, пока не включен CONFIG_VIRTIO_FS.
Аргументы загрузки в vm-config.json простые:
"kernel_image_path": "./vmlinux","boot_args": "console=ttyS0 reboot=k panic=1 pci=off root=/dev/vda rw rootfstype=ext4 init=/lib/systemd/systemd"
Это контракт между ядром и диском. Firecracker загружает vmlinux, подключает root image как /dev/vda и отправляет вывод консоли в screen log.
Подъем сети
Makefile создает tap0, назначает 192.168.1.1/24, включает forwarding и добавляет NAT. На хостах с несколькими default route наивная команда iptables может сломаться, потому что выражение interface разворачивается в несколько имен. Интерфейс лучше выбрать явно:
WAN=$(ip route | awk '/^default/ {print $5; exit}')ip tuntap add tap0 mode tapip addr add 192.168.1.1/24 dev tap0ip link set tap0 upsysctl -w net.ipv4.ip_forward=1iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o "$WAN" -j MASQUERADEiptables -A FORWARD -i tap0 -j ACCEPTiptables -A FORWARD -o tap0 -j ACCEPT
Внутри гостя нужна такая же сеть с другой стороны:
ip link set eth0 upip addr replace 192.168.1.2/24 dev eth0ip route replace default via 192.168.1.1printf 'nameserver 8.8.8.8\n' > /etc/resolv.conf
Перевод строки в resolv.conf важен. В одном запуске я получил сломанное значение nameserver 8.8.8.8n, и curl не мог разрешить opencode.ai.
Загрузка ВМ
Запуск в отдельной screen сессии:
make up-detachedmake login
На удаленном хосте после исправления NAT я запускал напрямую:
screen -L -Logfile firecracker-console.log -dmS firecracker-vm \ firecracker --api-sock /tmp/firecracker.socket --config-file vm-config.json
Консоль показала, что Debian 11 дошел до multi user режима. Prompt сообщил Linux 7.0.9 на x86_64 и вход root через ttyS0. Это сделало ВМ реальной целью для теста, а не JSON файлом, который просто парсится без ошибки.
Запуск opencode с DeepSeek внутри ВМ
Запрос агента должен идти из гостя, а не с хоста. Я использовал /Users/antonvkrylov/work/blade/.AI как локальный источник provider credentials и скопировал только строку DEEPSEEK_API_KEY во временный файл на удаленном хосте. Этот файл был смонтирован в root disk как /root/.deepseek.env. Guest service прочитал его, записал auth для opencode в /root/.local/share/opencode/auth.json, выполнил запрос и затем удалил оба secret файла.
Гостю нужны curl и ca-certificates:
apt-get updateapt-get install -y curl ca-certificates
Запрос внутри ВМ использовал opencode 1.15.5:
export OPENCODE_MODEL=deepseek/deepseek-v4-flashcurl -fsSL https://opencode.ai/install -o /tmp/opencode-install.shVERSION=1.15.5 bash /tmp/opencode-install.sh --no-modify-pathopencode run \ --model "$OPENCODE_MODEL" \ --agent build \ --format json \ --dir /root/opencode-proof \ "Reply with exactly BLADE_FIRECRACKER_OPENCODE_DEEPSEEK_OK"
Тестовый запуск завершился со статусом 0. В логе opencode были строки llm.provider=deepseek и llm.model=deepseek-v4-flash. Secret file и auth.json исчезли после завершения сервиса. Это правильная форма: credential material живет коротко, provider log конкретный, ключ не остается в guest image.
Наблюдение за трафиком opencode
Простая сеть нужна не только для загрузки. Она делает агентный вызов наблюдаемым. Перед загрузкой ВМ запустите capture на хосте:
tcpdump -n -i tap0 'host 192.168.1.2 or arp'
Первый smoke test поймал ARP и ICMP между 192.168.1.2 и 192.168.1.1, что доказало сетевой путь гостя. Повторный запуск opencode показал путь модели: DNS запрос от 192.168.1.2 к 8.8.8.8 для api.deepseek.com, ответ CloudFront, затем TLS сессии от 192.168.1.2 к 3.173.21.63:443. В той же трассе был служебный трафик к models.dev и registry.npmjs.org.
Через tcpdump нельзя прочитать prompt или ответ, потому что HTTPS скрывает payload. Зато можно доказать время, направление, объем байтов и source address. Для проверки песочницы этого часто достаточно: вызов вышел из ВМ, прошел через tap0 и использовал ожидаемый provider модели.
Запуск в других средах
На bare metal Linux Firecracker можно запускать напрямую с KVM. На удаленном лабораторном сервере лучше копировать репозиторий по SSH и собирать там, потому что KVM находится на самом хосте. В CI имеет смысл кешировать vmlinux и ext4 rootfs, а в job выполнять только network setup, VM boot, opencode и packet capture. На macOS или Windows нужен Linux VM с nested virtualization, либо Firecracker стоит считать удаленной целью и управлять им через SSH.
Полезный инвариант небольшой: собрать именно то ядро, которое вы будете загружать, загрузить именно тот диск, который вы будете проверять, отправить agent request изнутри гостя и смотреть на tap interface, пока песочница говорит с внешним миром.
ссылка на оригинал статьи https://habr.com/ru/articles/1038218/