QEMU user-mode emulation for running foreign-architecture binaries, plus macOS VM bridging for raw-socket Linux tools. Use when: running x86 binaries on ARM hosts, setting up qemu-user-static, using binfmt_misc, building containers with QEMU emulation, running Linux network tools (like MikroTik netinstall-cli) on macOS via QEMU system VM, or when the user mentions qemu-i386, qemu-user, binfmt, cross-architecture emulation, or vmnet-bridged.
Installs into .claude/skills of the current project.
Are you the author of Tikoci Qemu User Emulation?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tikoci-tikoci-qemu-user-emulation)
---
name: tikoci-qemu-user-emulation
description: "QEMU user-mode emulation for running foreign-architecture binaries, plus macOS VM bridging for raw-socket Linux tools. Use when: running x86 binaries on ARM hosts, setting up qemu-user-static, using binfmt_misc, building containers with QEMU emulation, running Linux network tools (like MikroTik netinstall-cli) on macOS via QEMU system VM, or when the user mentions qemu-i386, qemu-user, binfmt, cross-architecture emulation, or vmnet-bridged."
---
# QEMU User-Mode Emulation & macOS VM Bridging
## QEMU User-Mode Emulation
QEMU user-mode lets you run a binary compiled for one architecture on a host with a different architecture. The binary runs as a regular process — no VM, no kernel emulation. System calls are translated to the host kernel.
### Use Case
Run x86/i386 Linux binaries (like `netinstall-cli`) on ARM/ARM64 Linux hosts. On x86_64 Linux, the kernel natively supports running i386 binaries, so no QEMU is needed.
### Installation
| Platform | Package | Binary name |
|---|---|---|
| Debian/Ubuntu | `qemu-user-static` | `qemu-i386-static` |
| Alpine | `qemu-i386` | `qemu-i386` |
| Fedora/RHEL | `qemu-user-static` | `qemu-i386-static` |
| Container (tonistiigi/binfmt) | N/A | `qemu-i386` |
**Note:** Debian/Ubuntu use `qemu-i386-static` (statically linked — can be copied into containers). Alpine uses `qemu-i386` (dynamically linked — must stay on the host or in a matching rootfs).
### Direct Usage
```sh
# Prefix the command with the QEMU binary
qemu-i386-static ./netinstall-cli -r -b -i eth0 routeros-7.22-arm64.npk
# Or with explicit path
/usr/bin/qemu-i386 ./my-x86-binary arg1 arg2
```
### Auto-Detection Pattern
When you need to find the right QEMU binary across platforms:
```sh
# Priority: local binary, static (Debian), dynamic (Alpine)
for q in ./i386 qemu-i386-static qemu-i386; do
if [ -x "$q" ] || command -v "$q" >/dev/null 2>&1; then
QEMU="$q"
break
fi
done
# On x86_64, skip QEMU entirely
if [ "$(uname -m)" = "x86_64" ]; then
QEMU=""
fi
# Usage
${QEMU:+$QEMU} ./netinstall-cli [args...]
```
### binfmt_misc (Automatic Transparent Emulation)
Linux's `binfmt_misc` can automatically invoke QEMU for foreign binaries:
```sh
# Register QEMU handlers (usually done by package install or docker setup)
# The tonistiigi/binfmt image does this for Docker:
docker run --privileged --rm tonistiigi/binfmt --install all
# After registration, foreign binaries run transparently:
./my-i386-binary # kernel automatically invokes qemu-i386
```
**In containers:** The QEMU binary must be accessible inside the container's filesystem. With static QEMU (`qemu-i386-static`), copy it into the container image. With binfmt and the `F` flag, the kernel pre-loads the interpreter.
### Container Embedding
For containers that need to run x86 binaries on ARM hosts, embed QEMU in the image:
```sh
# Extract from the binfmt support image
crane export --platform linux/arm64 tonistiigi/binfmt:latest - | \
tar xf - usr/bin/qemu-i386
mv usr/bin/qemu-i386 rootfs/app/i386
chmod +x rootfs/app/i386
```
In the container, invoke the binary as: `./i386 ./netinstall-cli [args...]`
## macOS: When User-Mode Isn't Enough
QEMU user-mode is a **Linux-only feature**. On macOS, you cannot use `qemu-i386` user-mode. For Linux ELF binaries that need raw network access (BOOTP/TFTP on privileged ports), a full QEMU system VM is required.
### vmnet-bridged + 9p Pattern
Boot a minimal Alpine Linux VM that bridges to a macOS network interface (L2 access) and shares the host working directory via 9p virtfs. The Linux binary runs natively inside x86_64 Linux — no user-mode QEMU.
**Key components:**
- `qemu-system-x86_64` (`brew install qemu`) + `sudo` (for vmnet-bridged)
- Alpine `linux-virt` kernel + custom initramfs (Alpine rootfs + kernel modules + init script)
- Kernel modules loaded via `insmod` in explicit dependency order (busybox has no `modprobe`)
- `virtio_net` depends on `net_failover` → `failover` (not obvious)
- `9p` depends on `9pnet_virtio` → `9pnet` → `netfs`
**Critical lessons:**
- Get kernel and modules from the **same** `linux-virt` APK — version mismatch breaks module loading
- Busybox `insmod` cannot load compressed `.ko.gz` — decompress at build time
- `netinstall-cli` requires an IPv4 address on the interface (use link-local `169.254.1.1/16`)
See [macOS VM bridging reference](./references/macos-vm-bridging.md) for the full QEMU launch command, initramfs build process, init script, and module load order.
## Additional Resources
**Reference files:**
- For full macOS VM launch command, initramfs build, init script, and module load order: see [macOS VM bridging reference](./references/macos-vm-bridging.md)
**Related skills:**
- For RouterOS CHR system-level QEMU (full RouterOS in VM): see the `routeros-qemu-chr` skill
- For building OCI images with embedded QEMU: see the `tikoci-oci-image-building` skill
- For netinstall-cli specifics: see the `routeros-netinstall` skill