Skip to content

Commit a53c172

Browse files
motatoesclaude
andcommitted
Fix Azure deploy scripts based on real deployment experience
Fixes 8 issues encountered during initial QEMU deployment: - Use host's generic Ubuntu kernel instead of dead S3 URL - Extract guest kernel modules (vsock, overlay) for rootfs - Fix rootfs build args and module patching in deploy script - Fix DB seed (correct table name, UUID IDs, key_prefix column) - Stop services before binary copy to avoid "text file busy" - Fix systemd LimitNPROC=unlimited to LimitNPROC=infinity - Use X-API-Key header instead of Authorization: Bearer for tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent bc63b50 commit a53c172

File tree

2 files changed

+94
-21
lines changed

2 files changed

+94
-21
lines changed

deploy/azure/deploy-azure-dev.sh

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# deploy-azure-dev.sh — Quick dev deployment on Azure D96as_v5 with QEMU backend.
2+
# deploy-azure-dev.sh — Quick dev deployment on Azure with QEMU backend.
33
# Usage: ./deploy-azure-dev.sh [create|deploy|ssh|status|destroy]
44
set -euo pipefail
55

@@ -8,7 +8,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
88

99
# --- Defaults ---
1010
AZURE_LOCATION="${AZURE_LOCATION:-eastus}"
11-
AZURE_VM_SIZE="${AZURE_VM_SIZE:-Standard_D96as_v5}"
11+
AZURE_VM_SIZE="${AZURE_VM_SIZE:-Standard_D48as_v6}"
1212
AZURE_RG="${AZURE_RG:-opensandbox-dev}"
1313
AZURE_VM_NAME="${AZURE_VM_NAME:-opensandbox-dev}"
1414
AZURE_IMAGE="${AZURE_IMAGE:-Canonical:ubuntu-24_04-lts:server:latest}"
@@ -170,6 +170,10 @@ CGO_ENABLED=0 go build -o bin/opensandbox-worker ./cmd/worker/
170170
echo "Building agent..."
171171
CGO_ENABLED=0 GOARCH=amd64 go build -o bin/osb-agent ./cmd/agent/
172172
173+
# Stop services before overwriting binaries (avoids "text file busy")
174+
sudo systemctl stop opensandbox-worker 2>/dev/null || true
175+
sudo systemctl stop opensandbox-server 2>/dev/null || true
176+
173177
sudo cp bin/opensandbox-server /usr/local/bin/
174178
sudo cp bin/opensandbox-worker /usr/local/bin/
175179
sudo cp bin/osb-agent /usr/local/bin/
@@ -179,14 +183,49 @@ BUILD
179183
# Build rootfs if needed
180184
ssh_cmd << 'ROOTFS'
181185
set -euo pipefail
186+
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
182187
if [ ! -f /data/firecracker/images/default.ext4 ]; then
183188
echo "Building rootfs image..."
184189
cd ~/opensandbox
185-
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
186-
sudo bash deploy/ec2/build-rootfs-docker.sh
190+
sudo -E bash deploy/ec2/build-rootfs-docker.sh /usr/local/bin/osb-agent /data/firecracker/images default
187191
else
188192
echo "Rootfs image already exists."
189193
fi
194+
195+
# Patch rootfs with guest kernel modules (vsock, overlay) and insmod symlink
196+
GUEST_MODDIR="/opt/opensandbox/guest-modules"
197+
if [ -d "$GUEST_MODDIR" ] && [ -f /data/firecracker/images/default.ext4 ]; then
198+
echo "Patching rootfs with guest kernel modules..."
199+
MNTDIR=$(mktemp -d)
200+
sudo mount -o loop /data/firecracker/images/default.ext4 "$MNTDIR"
201+
202+
# Copy modules
203+
sudo mkdir -p "$MNTDIR/lib/modules/vsock"
204+
sudo cp "$GUEST_MODDIR"/*.ko "$MNTDIR/lib/modules/vsock/" 2>/dev/null || true
205+
206+
# Create insmod symlink (busybox applet)
207+
if [ -f "$MNTDIR/bin/busybox" ] && [ ! -e "$MNTDIR/sbin/insmod" ]; then
208+
sudo ln -sf /bin/busybox "$MNTDIR/sbin/insmod"
209+
fi
210+
211+
# Update init script: load modules early (before overlay mount)
212+
if ! grep -q 'lib/modules/vsock' "$MNTDIR/sbin/init" 2>/dev/null; then
213+
# Insert module loading after the first "mount -t devtmpfs" line
214+
sudo sed -i '/^mount -t devtmpfs devtmpfs \/dev$/a\
215+
\
216+
# Load kernel modules (needed for QEMU with modular kernel)\
217+
if [ -d /lib/modules/vsock ]; then\
218+
for mod in /lib/modules/vsock/overlay.ko /lib/modules/vsock/vsock.ko /lib/modules/vsock/vmw_vsock_virtio_transport_common.ko /lib/modules/vsock/vmw_vsock_virtio_transport.ko; do\
219+
[ -f "$mod" ] \&\& insmod "$mod" 2>/dev/null || true\
220+
done\
221+
echo "init: kernel modules loaded"\
222+
fi' "$MNTDIR/sbin/init"
223+
fi
224+
225+
sudo umount "$MNTDIR"
226+
rmdir "$MNTDIR"
227+
echo "Rootfs patched."
228+
fi
190229
ROOTFS
191230

192231
# Setup env files
@@ -259,22 +298,30 @@ RESTART
259298
ssh_cmd << SEED
260299
set -euo pipefail
261300
export PGPASSWORD=opensandbox
262-
# Create org and API key if not exists
301+
KEY_HASH=\$(echo -n "${OPENSANDBOX_API_KEY}" | sha256sum | cut -d' ' -f1)
302+
303+
# Create org (UUID id, table is "orgs")
263304
psql -h localhost -U opensandbox -d opensandbox -c "
264-
INSERT INTO organizations (id, name, slug) VALUES ('org-dev', 'Dev Org', 'dev')
305+
INSERT INTO orgs (id, name, slug) VALUES ('00000000-0000-0000-0000-000000000001', 'Dev Org', 'dev')
265306
ON CONFLICT DO NOTHING;
266-
INSERT INTO api_keys (id, org_id, key_hash, name)
267-
VALUES ('key-dev', 'org-dev', '$(echo -n "${OPENSANDBOX_API_KEY}" | sha256sum | cut -d' ' -f1)', 'dev-key')
307+
" 2>/dev/null || echo "DB seed: orgs table not ready yet"
308+
309+
# Create API key (UUID id, requires key_prefix)
310+
psql -h localhost -U opensandbox -d opensandbox -c "
311+
INSERT INTO api_keys (id, org_id, key_hash, key_prefix, name)
312+
VALUES ('00000000-0000-0000-0000-000000000002', '00000000-0000-0000-0000-000000000001', '\${KEY_HASH}', '$(echo -n "${OPENSANDBOX_API_KEY}" | cut -c1-8)', 'dev-key')
268313
ON CONFLICT DO NOTHING;
269-
" 2>/dev/null || echo "DB seed skipped (tables may not exist yet)"
314+
" 2>/dev/null || echo "DB seed: api_keys table not ready yet"
315+
316+
echo "DB seeded (org + API key)"
270317
SEED
271318

272319
log "=== Deployment complete ==="
273320
log " Server: http://${VM_PUBLIC_IP}:8080"
274321
log " Worker: http://${VM_PUBLIC_IP}:8081"
275322
log " API key: ${OPENSANDBOX_API_KEY}"
276323
log ""
277-
log "Test: curl -X POST http://${VM_PUBLIC_IP}:8080/api/sandboxes -H 'Authorization: Bearer ${OPENSANDBOX_API_KEY}'"
324+
log "Test: curl -X POST http://${VM_PUBLIC_IP}:8080/api/sandboxes -H 'X-API-Key: ${OPENSANDBOX_API_KEY}'"
278325
}
279326

280327
# --- SSH ---
@@ -342,7 +389,7 @@ case "$CMD" in
342389
echo ""
343390
echo "Environment variables:"
344391
echo " AZURE_LOCATION Azure region (default: eastus)"
345-
echo " AZURE_VM_SIZE VM size (default: Standard_D96as_v5)"
392+
echo " AZURE_VM_SIZE VM size (default: Standard_D48as_v6)"
346393
echo " AZURE_DATA_DISK_GB Data disk size (default: 500)"
347394
;;
348395
esac

deploy/azure/setup-azure-host.sh

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,45 @@ EOF
4444
export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"
4545
echo "Go: $(/usr/local/go/bin/go version)"
4646

47-
# --- Kernel for QEMU ---
48-
# Use the same kernel as Firecracker — vmlinux-docker-5.10.bin from AWS S3 quickstart.
49-
# This kernel has CONFIG_VIRTIO_VSOCKETS, CONFIG_VIRTIO_BLK, CONFIG_VIRTIO_NET enabled.
50-
echo "Downloading guest kernel..."
47+
# --- Guest kernel for QEMU ---
48+
# Use the host's generic Ubuntu kernel (has VIRTIO_BLK=y, VIRTIO_NET=y, VIRTIO_PCI=y built-in).
49+
# We also need vsock and overlay as modules — those get baked into the rootfs image.
50+
echo "Setting up guest kernel..."
5151
KERNEL_DIR="/opt/opensandbox"
5252
mkdir -p "$KERNEL_DIR"
53-
KERNEL_URL="https://s3.amazonaws.com/spec.ccfc.min/img/quickstart_guide/${KERNEL_ARCH}/kernels/vmlinux-docker-5.10.bin"
54-
if [ ! -f "$KERNEL_DIR/vmlinux" ]; then
55-
curl -fsSL "$KERNEL_URL" -o "$KERNEL_DIR/vmlinux"
53+
54+
# Install generic kernel package (has virtio built-in, unlike the azure kernel)
55+
apt-get install -y -qq linux-image-generic
56+
57+
# Find the generic kernel and copy it
58+
GENERIC_VMLINUZ=$(ls -t /boot/vmlinuz-*-generic 2>/dev/null | head -1)
59+
if [ -n "$GENERIC_VMLINUZ" ]; then
60+
cp "$GENERIC_VMLINUZ" "$KERNEL_DIR/vmlinux"
5661
chmod 644 "$KERNEL_DIR/vmlinux"
57-
echo "Kernel downloaded: $KERNEL_DIR/vmlinux"
62+
GENERIC_KVER=$(basename "$GENERIC_VMLINUZ" | sed 's/vmlinuz-//')
63+
echo "Guest kernel: $GENERIC_VMLINUZ ($GENERIC_KVER)"
64+
65+
# Extract vsock and overlay modules for the guest rootfs (loaded via insmod at boot)
66+
MODDIR="/lib/modules/$GENERIC_KVER"
67+
GUEST_MODDIR="$KERNEL_DIR/guest-modules"
68+
mkdir -p "$GUEST_MODDIR"
69+
for mod in \
70+
"$MODDIR/kernel/fs/overlayfs/overlay.ko"* \
71+
"$MODDIR/kernel/net/vmw_vsock/vsock.ko"* \
72+
"$MODDIR/kernel/net/vmw_vsock/vmw_vsock_virtio_transport_common.ko"* \
73+
"$MODDIR/kernel/net/vmw_vsock/vmw_vsock_virtio_transport.ko"*; do
74+
[ -f "$mod" ] || continue
75+
base=$(basename "$mod")
76+
if [[ "$base" == *.zst ]]; then
77+
zstd -d "$mod" -o "$GUEST_MODDIR/${base%.zst}" 2>/dev/null
78+
else
79+
cp "$mod" "$GUEST_MODDIR/"
80+
fi
81+
done
82+
echo "Guest modules extracted to $GUEST_MODDIR:"
83+
ls "$GUEST_MODDIR/"
5884
else
59-
echo "Kernel already exists: $KERNEL_DIR/vmlinux"
85+
echo "WARNING: No generic kernel found. Guest VMs may not boot correctly."
6086
fi
6187

6288
# --- KVM + vhost-vsock ---
@@ -158,7 +184,7 @@ ExecStart=/usr/local/bin/opensandbox-worker
158184
Restart=on-failure
159185
RestartSec=5
160186
LimitNOFILE=1000000
161-
LimitNPROC=unlimited
187+
LimitNPROC=infinity
162188
KillMode=mixed
163189
TimeoutStopSec=180
164190

0 commit comments

Comments
 (0)