macOS ejecutándose con QEMU en Docker
(github.com/sickcodes)- Docker-OSX ejecuta macOS basado en QEMU + KVM dentro de un contenedor Docker y ofrece salida X11, SSH, VNC, integración USB con iPhone y generación de seriales para investigación de seguridad de iMessage
- La forma de ejecución consiste en pasar a Docker el dispositivo
/dev/kvm, el socket de X11, el reenvío de puertos y la variable de entornoSHORTNAMEpara elegir la versión de macOS; incluye ejemplos desde Catalina 10.15 hasta Tahoe 16 - La composición de imágenes se divide por propósito, como
latest,auto,nakedynaked-auto; se puede adjuntar un.imgcreado por el usuario o ejecutar tareas de línea de comandos con una imagen Catalina preconfigurada - Los requisitos son un host x86_64 con soporte KVM, virtualización activada en BIOS y al menos 20 GB de espacio en disco; con Xcode se requieren 50 GB y con
:autotambién se necesitan al menos 50 GB - Además de Linux, también puede ejecutarse en virtualización anidada de WSL2 en Windows 11 build 22000+, pero la salida de pantalla requiere configurar una de estas opciones: WSLg, VNC o un entorno de escritorio
Ejecutar macOS dentro de un contenedor Docker
- Docker-OSX es un proyecto para ejecutar macOS dentro de un contenedor Docker
- Funciona sobre QEMU + KVM
- Soporta reenvío X11
- Ofrece una configuración donde funciona el USB de iPhone
- Indica que puede usarse para investigación de seguridad de macOS en Linux y Windows
- El proyecto está construido sobre OSX-KVM y también menciona KVM-OpenCore y OpenCorePkg
- También ofrece imagen en Docker Hub: sickcodes/docker-osx
Versiones de macOS soportadas y forma de inicio rápido
- El inicio rápido consiste en pasar los siguientes elementos en
docker run--device /dev/kvm-p 50922:10022para SSH- volumen
/tmp/.X11-unixpara X11 DISPLAYSHORTNAMEpara elegir la versión de macOS
- Los destinos de ejecución incluidos en el README son los siguientes
-
High Sierra 10.13
-
Mojave 10.14
-
Catalina 10.15
-
Big Sur 11
-
Monterey 12
-
Ventura 13
-
Sonoma 14
-
Sequoia 15
- Tahoe 16
- Algunos ejemplos posteriores a Monterey usan
GENERATE_UNIQUE=truejunto conMASTER_PLIST_URL - Los ejemplos de Sonoma, Sequoia y Tahoe también incluyen
CPU='Haswell-noTSX'yCPUID_FLAGS
-
Tipos de imágenes y propósito de uso
- Docker-OSX ofrece imágenes de contenedor según el objetivo
sickcodes/docker-osx:latest: para probar rápido o crear tu propia imagen de macOSsickcodes/docker-osx:auto: usa un sistema Catalina preconfigurado; el nombre de usuario esusery la contraseñaalpinesickcodes/docker-osx:naked: ejecuta adjuntando un archivo.imgdel usuariosickcodes/docker-osx:naked-auto: automatiza SSH y ejecución de comandos en una imagen del usuario pasandoUSERNAME,PASSWORDyOSX_COMMANDSsickcodes/docker-osx:big-sur,:monterey,:ventura,:sonoma,:high-sierra,:mojave: para ejecutar versiones específicas
- La imagen
nakedestá pensada para iniciar repetidamente una imagen de disco existente o restaurar el contenedor a un estado anterior autoynaked-autopueden usarse para tareas centradas en línea de comandos o trabajos sin interfaz, como builds basados en Homebrew
Funciones principales
- Las funciones indicadas por Docker-OSX son las siguientes
- Uso de iPhone en OSX KVM en Linux mediante usbfluxd
- Ejecución de VM de macOS Monterey
- Compartición de carpetas
- USB passthrough y hotplug
- SSH habilitado:
localhost:50922 - VNC habilitado: con la versión
./vnc,localhost:8888 - serial number generator para investigación de seguridad de iMessage
- Reenvío X11
- Soporte para Big Sur, imágenes personalizadas y modo headless con Xvfb
- Posibilidad de clonar el contenedor con
docker commit
- También soporta Kubernetes y señala que el Helm Chart y la documentación están en el directorio
helm
Requisitos y configuración inicial
- Los requisitos mínimos son los siguientes
- 20 GB o más de espacio en disco
- 50 GB si se usa Xcode
- 50 GB como mínimo si se usa
:auto - Virtualización habilitada en BIOS
- Host x86_64 con soporte KVM
- La configuración inicial consiste en instalar QEMU y dependencias relacionadas en el host, y luego habilitar
libvirtd,virtlogdy los módulos del kernel KVM - Proporciona comandos de instalación de paquetes para Arch, Ubuntu/Debian y CentOS/RHEL/Fedora
- En algunos casos, el usuario debe pertenecer a los grupos Docker, KVM y libvirt, y también verificar que el daemon de Docker esté en ejecución
Condiciones para ejecutarlo en Windows
- Ejecutar Docker-OSX en Windows es posible en un entorno de Windows 11 + WSL2
- Se requiere Windows 11 build 22000+, versión 21H2 o superior
- Tras instalar WSL, se agrega
nestedVirtualization=truea.wslconfig - En la distribución WSL, se verifica con
kvm-oksi/dev/kvmy la aceleración KVM están disponibles - En Docker for Windows deben activarse el motor basado en WSL2 y la integración con la distribución WSL predeterminada
- Los métodos de salida de pantalla se dividen en tres opciones
- WSLg: la opción más simple y recomendada, aunque puede tener problemas con la entrega del teclado o mostrar un segundo cursor
- VNC: usar la configuración de QEMU VNC o la sección de VNC
- Desktop Environment: consume más recursos, pero ofrece una experiencia completa de escritorio Linux
Compartición de archivos y manejo de discos
- Se propone
sshfscomo la forma más fácil y segura de compartir- En Linux/Windows se monta el rootfs de macOS en espacio de usuario con algo como
sshfs user@localhost: -p 50922 ~/mnt/osx
- En Linux/Windows se monta el rootfs de macOS en espacio de usuario con algo como
- También es posible compartir con QEMU 9p
- Se pasa la carpeta del host al contenedor como
/mnt/hostshare - Dentro de macOS se monta con
sudo -S mount_9p hostshare
- Se pasa la carpeta del host al contenedor como
- También se describe el uso de NFS
- Se registra el directorio compartido en
/etc/exportsdel host - El contenedor Docker-OSX se inicia con
--network host - En la terminal de macOS se usa
mount_nfs
- Se registra el directorio compartido en
- Si falta espacio en disco para Docker,
/var/lib/dockerpuede moverse a una unidad externa, almacenamiento en bloques o NFS, y luego crear un enlace simbólico- Se indica seguir ese tutorial solo si se acepta el riesgo de borrar las imágenes y capas actuales de Docker
USB de iPhone y USB passthrough
- Para PCs de escritorio se enlaza aparte un método de USB passthrough de iPhone basado en VFIO
- En laptops y PCs puede usarse USB passthrough por red mediante usbfluxd
- En Linux se conecta el iPhone o iPad por USB
- Se expone
usbmuxdpor el puerto TCP5000 - En el invitado macOS se conecta al host con algo como
usbfluxd -f -r 172.17.0.1:5000 - Se indica que, al cerrar y volver a abrir apps como Xcode, el dispositivo aparecerá
- Para USB passthrough general se indica que QEMU debe iniciarse como root
- Se identifica bus y puerto con
lsusb -t - Se usan
--privileged,/dev/kvm,EXTRA="-device ... usb-host ...", etc. - Mientras la VM está en ejecución, el sistema host no podrá acceder a ese dispositivo USB
- Se identifica bus y puerto con
Headless, VNC, SPICE y ejecución remota
- La ejecución headless se hace quitando dos líneas relacionadas con X11 en
docker run- Quitar el volumen
/tmp/.X11-unix - Quitar la variable de entorno
DISPLAY
- Quitar el volumen
- Se indica que un contenedor headless basado en imágenes personalizadas puede ser útil en pipelines de CI/CD
- VNC puede usarse solo en local, pero el README aclara que no tiene ningún cifrado TLS/HTTPS
- Se indica que usar un túnel SSH y cerrar los puertos externos mejora la seguridad
- También puede usarse SPICE
- Se accede con
remote-viewer spice://localhost:3001 - Se advierte que
-disable-ticketingen el ejemplo permite acceso a la VM sin autenticación, por lo que conviene revisar la configuración de autenticación del manual de SPICE
- Se accede con
Números de serie e investigación de iMessage/iCloud
- Para usar iMessage o iCloud se presentan los siguientes valores que deben cambiarse
SERIALBOARD_SERIALUUIDMAC_ADDRESS- Se explica que
ROMes la dirección MAC en minúsculas sin dos puntos
- Docker-OSX ofrece dos formas
GENERATE_UNIQUE=true: genera valores únicos en tiempo de ejecuciónGENERATE_SPECIFIC=true: usa valores especificados
./custom/generate-unique-machine-values.shpuede generar número de serie, dirección MAC, salida CSV/TSV e imagen de disco de arranque- Dentro de macOS se puede verificar el número de serie con
ioreg -l | grep IOPlatformSerialNumber
Rendimiento, resolución y configuración de red
- Se indica que osx-optimizer puede hacer que el contenedor sea más rápido
- Saltar la pantalla de inicio de sesión GUI
- Desactivar la indexación de Spotlight
- Desactivar el fondo pesado de la pantalla de inicio de sesión
- Desactivar actualizaciones
- La resolución puede cambiarse con las variables de entorno
WIDTHyHEIGHT- Deben usarse junto con
GENERATE_UNIQUE=trueoGENERATE_SPECIFIC=true - El arranque tarda unos 30 segundos más para crear una nueva partición de arranque
- Una resolución inválida vuelve al valor predeterminado
800x600
- Deben usarse junto con
- El adaptador de red puede cambiarse por variable de entorno
- Conexión rápida a internet:
NETWORKING=vmxnet3 - Conexión lenta a internet:
NETWORKING=e1000-82545em
- Conexión rápida a internet:
- Se indica que activar el reenvío IPv4 en instalaciones remotas puede mejorar el rendimiento, pero que la IP del host podría filtrarse aunque se use una VPN dentro del contenedor
Solución de problemas y limitaciones
- Si el daemon de Docker no está en ejecución, puede aparecer el error
docker: unknown server OS: .sudo dockerdsudo systemctl --start dockerdsudo systemctl --enable --now dockerd
- No es posible asignar más RAM de la que tiene la máquina física
- El valor predeterminado es
-e RAM=3 - Si se sobreasigna, puede aparecer el error
cannot set up guest memory 'pc.ram': Cannot allocate memory
- El valor predeterminado es
- Los errores relacionados con ALSA pueden aparecer durante la inicialización del contenedor o el arranque, y se indica que no hay de qué preocuparse si el inicio y las funciones operan normalmente
- En TODO todavía quedan estos puntos
- Documentación para investigadores de seguridad
- Aceleración por GPU
- Soporte para virt-manager
Licencia y avisos
- Docker-OSX está licenciado bajo GPL v3+
- Se especifica que está permitido usar Docker-OSX como herramienta para crear software propietario
- Incluye avisos relacionados con la investigación de seguridad de Apple y el Apple Bug Bounty Program, y enlaza un texto aparte sobre los temas legales de Hackintosh, OSX-KVM y Docker-OSX
- Se indica que los nombres de productos, logotipos, marcas y marcas registradas mencionados en el proyecto son propiedad de sus respectivos dueños, y que esos titulares no están afiliados, ni patrocinan ni avalan el repositorio
1 comentarios
Opiniones en Hacker News
Para quienes realmente quieren usar el proyecto, esto es importante, pero no entiendo por qué tantas recetas de build como Dockerfile están hechas para descargar material arbitrario de internet durante el proceso de compilación.
El Dockerfile de este proyecto también trae 2 repositorios Git y 1 script en tiempo de build.
Por supuesto que falla en servidores de build en sandbox sin acceso a internet, y cualquiera que se preocupe aunque sea un poco por la seguridad tiene que auditar toda la receta de build antes de usarla.
Ya no alcanza con revisar solo las dependencias indicadas en especificaciones de build como README, requirements.txt o package.json, y viendo las fallas recientes en infraestructura crítica y el aumento de ataques a la cadena de suministro, es una tendencia muy preocupante.
Aparecen sorpresas desagradables: problemas de versiones, falta de internet o, en el peor de los casos, que la dependencia ya no esté disponible. La distribución autocontenida debería ser lo predeterminado.
Fedora y openSUSE normalmente tienen políticas para que los paquetes del repositorio, incluidas las imágenes de contenedores y los paquetes de la distribución, se construyan solo con paquetes del repositorio o usen únicamente binarios agregados explícitamente durante el build.
Por eso, si puedes instalarlo con
dnf/zypper installo traerlo desde el registro de contenedores del proveedor, puedes confiar en los artefactos.Si necesitas lo último en bleeding edge, tienes que aceptar material arbitrario de internet.
Es difícil que un desarrollador open source cualquiera produzca artefactos de build confiables, listos para usarse offline, y no existe esa infraestructura. Por eso existen empresas como Red Hat o SUSE.
Las empresas de miles de millones de dólares están dispuestas a pagar para que alguien haga el trabajo de plomería y convierta artefactos arbitrarios de internet en artefactos confiables, reproducibles y firmados, además de hacer seguimiento de CVE y actualizaciones periódicas.
En los 80 se imaginaban componentes de software reutilizables y modulares que se encajaban como bloques de Lego, y entonces se llamaba CASE. Ahora eso se hizo realidad, pero por supuesto tiene un costo.
Si no se hace clone desde el Dockerfile, se necesitan instrucciones previas al build del tipo “usa
--recursiveal clonar o trae otros repositorios al directorio de trabajo actual congit submodule init”.La única posibilidad de aceleración por GPU es pasar una dGPU soportada mediante PCI passthrough. Las AMD RX 6xxx o superiores funcionan en macOS 14.x, pero con Nvidia moderna no hay posibilidad.
Las iGPU de Intel funcionan hasta Comet Lake y algunas Ice Lake, pero las más nuevas no.
macOS en builds para Apple Silicon parece difícil de emular por ahora, aunque hay algo de trabajo inicial sobre el arranque de ARM Darwin.
Además, como AMD no tiene Intel VT-x, la virtualización se rompe en hosts AMD, pero con un hack raro usando una versión antigua de VirtualBox se puede hacer que Docker funcione en cierta medida mediante emulación.
AMD tiene su propia alternativa a VT-x, AMD-V, así que debería funcionar sin problemas. Eso sí, arrancar macOS en una CPU AMD tiene otros obstáculos, que normalmente se resuelven cargando kexts o con otros trucos.
No entiendo bien el sentido de correr un sistema operativo completo con Docker. Bastaría con distribuirlo como OVA o en el formato de virtualización que prefieras. Probablemente un qcow2 y un script bash para iniciar la VM serían suficientes.
Artículos relacionados:
Docker-OSX: Run macOS VM in a Docker - https://news.ycombinator.com/item?id=34374710 - enero de 2023, 110 comentarios
macOS in QEMU in Docker - https://news.ycombinator.com/item?id=23419101 - junio de 2020, 186 comentarios
Lo configuré como experimento hace unos meses y funcionó bastante bien. Pero descubrí que, para que iMessage funcione, la aplicación envía a Apple el ID de hardware, y este proyecto usa valores falsos.
A partir de ese momento empecé a deslizarme por la pendiente del “esto no va a salir bien”, y descubrí que los valores falsos pueden ser marcados por Apple, con el resultado de que el ID de iCloud quede señalado como potencial spammer y se restrinja el acceso desde otros dispositivos.
La única opción es seguir probando valores con un script de generación de ID de hardware enlazado de forma algo ambigua hasta encontrar uno que “funcione”, pero no hay una señal clara de que realmente encaje bien y no dañe la reputación de iCloud.
Fuera de eso, funcionó realmente bien y es muy útil en un apuro.
Pronto me di cuenta de que era más fácil copiar el Serial de una Mac real aunque fuera vieja.
Dicho eso, esta herramienta parece más útil para cosas como scripts de build que dependen de frameworks propietarios de macOS, más que para usarla como una computadora personal.
Solo quiero probar si se puede compilar para iOS. Por ejemplo, cosas como Unity o React Native.
Aunque la compilación tarde 5 veces más, en términos de libertad podría ser bastante genial.
Así es también como Godot compila para iOS: https://github.com/godotengine/build-containers/blob/main/Do...
También hay una imagen de Docker con las herramientas preinstaladas, pero para apuntar a iOS requiere algunas modificaciones: https://github.com/shepherdjerred/macos-cross-compiler
Cuando estaba en RStudio, ahora Posit, trabajé en compilación cruzada de C/C++/Fortran/Rust desde hosts Linux apuntando a macOS x86_64/aarch64.
Si descargas desde Posit Package Manager(https://p3m.dev/client/) paquetes de R con código nativo, fueron compilados en forma cruzada de esta manera :)
Hace un tiempo entrevisté a Sick Codes sobre el enfoque de este producto: https://www.vice.com/en/article/akdmb8/open-source-app-lets-...
También está OSX-PROXMOX, que hace algo parecido en un homeserver con Proxmox: https://github.com/luchina-gabriel/OSX-PROXMOX
Personalmente uso este último en un HP Z420 Xeon y es muy estable, especialmente si se le agrega GPU passthrough.
Sería bueno poder correr sincronización de iCloud en un homeserver. Actualmente no hay una buena forma de hacer backup físico de iCloud en un homeserver/NAS, y solo funciona en Windows/Apple.
https://github.com/steilerDev/icloud-photos-sync
https://github.com/icloud-photos-downloader/icloud_photos_do...
Resulta que iCloud no actualiza las fotos originales. Se entiende, pero no ayuda a quien esperaba que esos cambios estuvieran incluidos al hacer el backup.
rsyncde la carpeta de iCloud desde una Mac/PC conectada hacia un NAS?Me pregunto si la redistribución de imágenes de macOS está permitida por la licencia. ¿O este proyecto está distribuyendo abiertamente copias pirata en Docker Hub?
Me pregunto si el avance se detendrá cuando salgan versiones más nuevas de macOS sin soporte para Intel.
¿Se puede ejecutar Docker dentro de este contenedor para correr macOS dentro de macOS? ;)
Realmente odio cuando la expresión “USB passthrough” se usa para situaciones que, en el mejor de los casos, son “proxy de USB sobre Ethernet”.
Eso no es passthrough. Tiene varias desventajas que no existen en el passthrough común y que quizá tampoco existan en el passthrough avanzado.
Pero ese enfoque trae otros problemas. Lo digo por experiencia operando grandes granjas de pruebas con VM y mucho hardware pasado directamente.
Dicho eso, “proxy de USB sobre Ethernet” también es passthrough real; solo es passthrough con más latencia que VirtIO.