Skip to content

Arch VM Setup

If you are willing to do more setup, you should strongly consider using a virtual machine instead of jai for risky work. This is close to the workflow the author uses when asking AI agents to test jai itself, because developing jai requires privileges that are unacceptable for an AI agent on the host.

The idea is simple:

  • Bootstrap an Arch Linux guest into a normal directory with pacstrap
  • Boot that directory directly with QEMU/KVM and virtiofs
  • Keep the guest root in a place the host can still inspect and edit
  • Let the agent use sudo to jai as root inside the guest to test things

This is much heavier than jai codex, but it gives you a real VM with a separate kernel. If you are willing to jump through the extra hoops, you probably should.

What this guide assumes

  • An Arch Linux host, or another Linux host with arch-install-scripts available, especially pacstrap and arch-chroot
  • qemu-system-x86_64
  • virtiofsd
  • KVM support
  • Root access on the host
  • A local filesystem for the guest root directory

This is intentionally Arch-specific. The same overall approach works on other distros, but the bootstrap commands will differ.

Set image directory in a root shell

Open a root shell (run /bin/su or /bin/sudo -s), and set $VMROOT to the path of the directory you want to create to contain your VM image.

bash
VMROOT="$HOME/vm/jai-sb"

VMROOT can live anywhere on a local filesystem; this path is just an example.

Create the guest root directory

Create the directory you selected for $VMROOT and make it a mountpoint by bind-mounting it onto itself if it is not already a mountpoint:

bash
mkdir -p "$VMROOT"
mountpoint -q "$VMROOT" || mount -B "$VMROOT" "$VMROOT"

Making the directory a mountpoint gives pacstrap and arch-chroot a clear boundary, but isn't necessary to boot the VM once the image is fully constructed.

Bootstrap Arch

Install a minimal guest system into that directory:

bash
pacstrap -cG "$VMROOT" \
    base base-devel linux linux-headers sudo openssh \
    git ripgrep bash-completion less

Add any extra packages you want in the guest, but keep the first pass small until the VM boots cleanly.

Configure the guest

Set up pacman, timezone, locale, networking, SSH, and DNS to work in your guest image:

bash
arch-chroot "$VMROOT" pacman-key --init
arch-chroot "$VMROOT" pacman-key --populate

if zone=$(readlink /etc/localtime); then
    ln -sf "$zone" "$VMROOT/etc/localtime"
fi

sed -i -e '/^#en_US.UTF-8/s/^#//' "$VMROOT/etc/locale.gen"
echo 'LANG=en_US.UTF-8' > "$VMROOT/etc/locale.conf"
arch-chroot "$VMROOT" locale-gen

install -d -m 755 "$VMROOT/etc/systemd/network"
cat > "$VMROOT/etc/systemd/network/20-wired.network" <<'EOF'
[Match]
Name=en* eth*

[Network]
DHCP=yes
EOF

arch-chroot "$VMROOT" systemctl enable \
    systemd-networkd systemd-resolved sshd
ln -sf /run/systemd/resolve/resolv.conf "$VMROOT/etc/resolv.conf"

Install your SSH keys

If you already use ssh-agent, the quickest path is to copy the public keys it knows about into the guest:

bash
install -d -m 700 "$VMROOT/root/.ssh"
ssh-add -L > "$VMROOT/root/.ssh/authorized_keys"
chmod 600 "$VMROOT/root/.ssh/authorized_keys"

If you do not use ssh-agent, copy the public key you normally use into $VMROOT/root/.ssh/authorized_keys manually instead.

If you want to be able to log in from the console, you can set a root password by running passwd -R "$VMROOT" root. (Openssh does disallow empty passwords by default, so it's also not crazy to make the root account not require a password, which you can do with passwd -R "$VMROOT" -d root, but this isn't exactly best practice).

Add a matching user

Using the same login name and UID as the host makes host/guest file sharing much less awkward. Set $VMUSER to be the name of your local user account, which you can often get as $(logname) even within a su or sudo shell.

bash
VMUSER=$(logname)
VMUID=$(id -u "$VMUSER")

install -Dm 0600 /dev/null "$VMROOT/etc/skel/.ssh/authorized_keys"

arch-chroot "$VMROOT" useradd -m -G wheel -u "$VMUID" -U "$VMUSER"
ssh-add -L > "$VMROOT/home/$VMUSER/.ssh/authorized_keys"

echo '%wheel ALL=(ALL:ALL) NOPASSWD: ALL' \
    > "$VMROOT/etc/sudoers.d/30-nopass"

This configures /etc/skel to ensure useradd -m creates the guest user's .ssh/authorized_keys with the right ownership. After that, overwriting the file from the host as root preserves that ownership, so you do not have to chown anything under the guest home directory. Finally, it creates a file /etc/sudoers.d/30-nopass allowing anyone in the wheel group in the VM to run sudo without a password.

As with root, if you want to log in from the console, set a password with passwd -R "$VMROOT" "$VMUSER", or set an empty password with passwd -R "$VMROOT" -d "$VMUSER".

Create a launch script

The following script boots the guest directly from the directory you just created:

bash
#!/bin/sh

VMROOT="/home/alice/vm/jai-sb"
MEM=${MEM:-16G}
SOCK="$VMROOT.sock"

/usr/lib/virtiofsd --cache=auto --xattr --modcaps=+sys_admin \
    --socket-path="$SOCK" --shared-dir="$VMROOT" &

qemu-system-x86_64 -enable-kvm -cpu host -smp 8 -m "$MEM" \
    -kernel "$VMROOT/boot/vmlinuz-linux" \
    -append "root=myfs rootfstype=virtiofs rw console=ttyS0" \
    -chardev socket,id=char0,path="$SOCK" \
    -device vhost-user-fs-pci,chardev=char0,tag=myfs \
    -object "memory-backend-memfd,id=mem,size=$MEM,share=on" \
    -netdev "user,id=net0,hostfwd=tcp::2222-:22" \
    -device virtio-net-pci,netdev=net0 \
    -numa node,memdev=mem \
    -nographic

Put the script in a file run-vm and make the file executable with chmod +x run-vm.

Note the --modcaps=+sys_admin flag on virtiofsd matters if you want to test jai inside the guest, because overlayfs and union-mount workflows can require xattr operations that are otherwise blocked.

Boot the VM

As root, run:

bash
./run-vm

The current terminal becomes the guest's serial console. From another terminal on the host, you can SSH in through the forwarded port using either of the following two commands depending on whether you want to be root:

bash
ssh -p 2222 root@127.0.0.1
ssh -p 2222 127.0.0.1

Test jai inside the guest

Once inside the guest, building and testing jai is just normal guest work:

bash
git clone https://github.com/stanford-scs/jai.git
cd jai
./autogen.sh
./configure
make
sudo ./jai
# or can install in VM with:
# sudo make install

At that point you are testing jai inside a real VM rather than on your host.