Running GUI Linux in a virtual machine on a Mac

Overview

Running GUI Linux in a virtual machine on a Mac

Install and run GUI Linux in a virtual machine using the Virtualization framework.

การ build และใช้งาน

** ให้เรากำหนด Developer Profile และ Signing package

Support Intel & Apple Silicon

ตั้งแต่ Version 1.1 เป็นต้นไป App จะเป็น Universal สามารถใช้ได้ทั้ง Intel และ M1, M2

การใช้งานครั้งแรกหลังจากติดตั้ง App

เนื่องจาก App ไม่ได้อยู่ใน App Store ให้ท่านเปิด option การรันจาก App Store และ นักพัฒนาที่เชื่อถือได้

System Setting --> Privacy Security --> Security --> App Store amd identified developer

หลังจากนั้นให้เปิด App ด้วยการ Click ขวา และเลือก Open

ถ้าหากท่านสามารถใช้งานได้จะมี Dialog ขึ้นมาหากต้องการติดตั้ง Linux ตัวแรกใน default path ก็ให้ Click OK ได้เลย แต่ถ้าหากต้องการใช้ command line ให้ Cancel แล้วสั่งคำสั่งจากตั้วอย่างด้านล่าง

Options ที่เพิ่มเข้าไป

$ /Applications/RunLinuxVM.app/Contents/MacOS/RunLinuxVM --help
Options available:
 --cpu, -c: number of cpus [1..9]
 --disk, -d: disk image size in GB
 --mem, -m: memory size in GB
 --iso, -i: Linux installer ISO path
 --live, -l: Boot ISO in live mode only
 --path, -p: bundle path with tailing slash eg. /path/to/Debian.bundle/
 --raw-imgs, -I: additional disk image files seperate by comma
 --resolution, -r: screen resolution preset [hd, fhd, 2k, 4k]
 --share-paths, -s: share paths to guest seperate by comma
 --help, -h: show this help
 --version: show app version

การ run VM

ถ้า click run app โดยตรงจะใช้ path ที่กำหนดไว้ใน code คือ $HOME/LinuxVM.bundle ถ้าเราปิด dialog ทิ้งหรือติดตั้งไม่สำเร็จต้องลบ path นั้นทิ้งก่อน ถึงจะ run ครั้งต่อไปได้

ตัวอย่างการ run แบบระบุ options

การ run ครั้งแรกจะเป็นการติดตั้งเราต้องเตรียม ISO ไว้ให้เรียบร้อย และ ระบุ option -d หรือ --disk เป็นขนาดของ image หน่วยเป็น GB ถ้า run ครั้งต่อไปก็ไม่จำเป็นต้องระบุขนาด disk

/Applications/RunLinuxVM.app/Contents/MacOS/RunLinuxVM  \
 --path $HOME/LinuxVM/Ubuntu.bundle/ \
 --resolution hd  \
 --cpu 4 \
 --mem 4 \
 --disk 10

การ run หลังจากติดตั้งเสร็จเราสามารถเปลี่ยนค่าต่าง ๆ ได้ตามใจชอบหรือตามความสามารถของเครื่องนะครับ

/Applications/RunLinuxVM.app/Contents/MacOS/RunLinuxVM  \
 --path $HOME/LinuxVM/Ubuntu.bundle/ \
 --resolution 4k \
 -cpu 4 \
 -mem 4 

Live Mode

ในกรณีที่ท่านไม่อยากติดตั้งแค่อยากจะเล่นจาก ISO อย่างเดียวสามารถระบุ iso และ live ดังนี้

/Applications/RunLinuxVM.app/Contents/MacOS/RunLinuxVM  \
--live \
--iso Ubuntu-22.10.iso

แต่ปัจจุบัน Distro ที่มี iso arm64 ยังน้อย แต่ถ้าท่านใช้ CPU Intel สามารถ run ได้หลาย Distro

Share directory from macOS

ท่านสามารถ Share directory จาก macOS ไปยัง Linux Guest ได้ โดยการระบุ option ถ้าหากมีมากกว่าหนึ่ง directory ให้ใช้ comma คั่นเช่น

/Applications/RunLinuxVM.app/Contents/MacOS/RunLinuxVM  \
--path $HOME/LinuxVM/Debian.bundle/ \
--share-paths "$HOME,/Volums/SSD/"

ถ้า directory มีอยู่จริง app จะทำการ share ให้เมื่อท่าน boot เข้าไปยัง Linux ให้ mount โดยใช้คำสั่ง

$ sudo mount -t virtiofs /User/mrchoke/ /mnt/mac_home
$ sudo mount -t virtiofs /Volums/SSD/ /mnt/mac_ssd

โดย Tag ที่ระบุจะเป็น path เต็มของ macOS

การ add disk image เพิ่มเติม

ในกรณีที่ท่านต้องการเพิ่ม disk image หรือ raw disk image ที่มีนามสกุล .img เช่น linux image จากค่ายต่าง ๆ image ของ VM ที่ถูกสร้างจาก App นี้สามารถเพิ่มเข้าไปได้ทั้งหมดถ้ามากกว่าหนึ่ง image ให้ใช้ comma คั่น เช่น

/Applications/RunLinuxVM.app/Contents/MacOS/RunLinuxVM  \
--path $HOME/LinuxVM/Debian.bundle/ \
--raw-imgs "$HOME/LinuxVM/Ubuntu.bundle/Disk.img,$HOME/Downloads/Manjaro-ARM.img"

ถ้า image เหล่านั้นมีอยู่จริง เมื่อ boot เข้าไปยัง Linux เสร็จแล้วสามารถ mount ใช้งาน หรือ format เพื่อทำการติดตั้งแบบ chroot ได้ โดยสามารถตรวจสอบด้วยคำสั่ง

$ lsblk 
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
vda    254:0    0   64G  0 disk 
- vda1 254:1    0  512M  0 part /boot/efi
- vda2 254:2    0 62.5G  0 part /
- vda3 254:3    0  976M  0 part [SWAP]
vdb    254:16   0   10G  0 disk 
- vdb1 254:17   0  300M  0 part 
- vdb2 254:18   0  9.7G  0 part 
vdc    254:32   0   15G  0 disk 
- vdc1 254:33   0  128M  0 part 
- vdc2 254:34   0 14.9G  0 part

หรือจะ fdisk -l ก็ได้ ซึ่งจะเห็น disk เพิ่มเติมเข้ามาจากเดิมจะมีแค่ /dev/vda ก็จะมี /dev/vdb /dev/vdc ...

Running Intel Binaries in Linux VMs with Rosetta

Feature นี้จะใช้ได้เฉพาะ เครื่อง M1 หรือ M2 เท่านั้นบน Intel ไม่จำเป็นเพราะเป็น x86_64 อยู่แล้ว ผมได้เพิ่ม code จากตัวอย่างของ apple ไว้แล้วสามารถทดลองใช้ได้เลยโดยมีวิธีการดังนี้

Tag ผมใช้คำว่่า ROSETTA

% mkdir /tmp/mountpoint
% sudo mount -t virtiofs ROSETTA /tmp/mountpoint
% ls /tmp/mountpoint rosetta
% sudo /usr/sbin/update-binfmts --install rosetta /tmp/mountpoint/rosetta \
    --magic "\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00" \
    --mask "\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff" \
    --credentials yes --preserve no --fix-binary yes

Linux ที่มีคำสั่ง update-binfmts เช่น Ubuntu และ Debian ให้ลงเพิ่มเติมก่อน

% apt install binfmt-support

Features อื่น ๆ

  • Copy / Paste ระหว่าง Host กับ Guest ได้ และ สามารถข้ามไปมาระหว่าง Guest กับ Guest ก็ได้ หรือระหว่า อุปกรณ์อื่น ๆ ของท่านที่ login ด้วย Apple ID เดียวกัน

สิ่งที่อาจจะเกิดขึ้นได้

  • บาง Distro จะไม่มีเสียงเพราะ kernel ไม่ support virtio_snd แต่สามารถ compile kernel ใหม่ได้เช่น Debian 11 เป็นต้น
  • Copy / Paste Distro ส่วนใหญ่จะมี spice-vdagent มาให้แต่ก็มีบาง Distro ท่านอาจจะต้องติดตั้งเองถึงจะได้ใช้งานได้

Overview

This sample code project demonstrates how to install and run GUI Linux virtual machines (VMs) on a Mac.

The Xcode project includes a single target, GUILinuxVirtualMachineSampleApp, which is a macOS app that installs a Linux distribution from an ISO image into a VM, and subsequently runs the installed Linux VM.

Download a Linux installation image

Before you run the sample program, you need to download an ISO installation image from a Linux distribution website. Some common Linux distributions include:

  • Debian

  • Fedora

  • Ubuntu

  • Important: The Virtualization framework can run Linux VMs on a Mac with Apple silicon, and on an Intel-based Mac. The Linux ISO image you download must support the CPU architecture of your Mac. For a Mac with Apple silicon, download a Linux ISO image for ARM, which is usually indicated by aarch64 or arm64 in the image filename. For an Intel-based Mac, download a Linux ISO image for Intel-compatible CPUs, which is usually indicated by x86_64 or amd64 in the image filename.

  • Note: If you need to run Intel Linux binaries in ARM Linux on a Mac with Apple silicon, the Virtualization framework supports this capability using the Rosetta translation environment. For more information, see Running Intel Binaries in Linux VMs with Rosetta.

Configure the sample code project

  1. Launch Xcode and open GUILinuxVirtualMachineSampleApp.xcodeproj.

  2. Navigate to the Signing & Capabilities panel and select your team ID.

  3. Build and run GUILinuxVirtualMachineSampleApp. The sample app starts the VM and configures a graphical view that you interact with. The Linux VM continues running until you shut it down from the guest OS, or when you quit the app.

    When you run the app for the first time, it displays a file picker so you can choose the Linux installation ISO image to use for installing your Linux VM. Navigate to the ISO image that you downloaded, select the file, and click Open. The VM boots into the OS installer, and the installer's user interface appears in the app's window. Follow the installation instructions. When the installation finishes, the Linux VM is ready to use.

    As part of the installation process, the Virtualization framework creates a GUI Linux VM.bundle package in your home directory. The sample app only supports running one VM at a time, however, the Virtualization framework supports running multiple VMs simultaneously. Running multiple VMs requires an app to manage the execution and artifacts of each individual VM.

    The contents of the bundle represent the state of the Linux guest, and contain the following:

    • Disk.img — The main disk image of the installed Linux OS.
    • MachineIdentifier — The data representation of the VZGenericMachineIdentifier object.
    • NVRAM — The EFI variable store.

    Subsequent launches of GUILinuxVirtualMachineSampleApp run the installed Linux VM. To reinstall the VM, delete the GUI Linux VM.bundle package and run the app again.

Install GUI Linux from an ISO image

The sample app configures a VZDiskImageStorageDeviceAttachment object with the downloaded ISO image attached, and creates a VZUSBMassStorageDeviceConfiguration with it to emulate a USB thumb drive that's plugged in to the VM.

private func createUSBMassStorageDeviceConfiguration() -> VZUSBMassStorageDeviceConfiguration {
    guard let intallerDiskAttachment = try? VZDiskImageStorageDeviceAttachment(url: installerISOPath!, readOnly: true) else {
        fatalError("Failed to create installer's disk attachment.")
    }

    return VZUSBMassStorageDeviceConfiguration(attachment: intallerDiskAttachment)
}

Set up the VM

The sample app uses a VZVirtualMachineConfiguration object to configure the basic characteristics of the VM, such as the CPU count, memory size, various device configurations, and a VZEFIBootloader to load the Linux operating system into the VM.

let virtualMachineConfiguration = VZVirtualMachineConfiguration()

virtualMachineConfiguration.cpuCount = computeCPUCount()
virtualMachineConfiguration.memorySize = computeMemorySize()

let platform = VZGenericPlatformConfiguration()
let bootloader = VZEFIBootLoader()
let disksArray = NSMutableArray()

if needsInstall {
    // This is a fresh install: Create a new machine identifier and EFI variable store,
    // and configure a USB mass storage device to boot the ISO image.
    platform.machineIdentifier = createAndSaveMachineIdentifier()
    bootloader.variableStore = createEFIVariableStore()
    disksArray.add(createUSBMassStorageDeviceConfiguration())
} else {
    // The VM is booting from a disk image that already has the OS installed.
    // Retrieve the machine identifier and EFI variable store that were saved to
    // disk during installation.
    platform.machineIdentifier = retrieveMachineIdentifier()
    bootloader.variableStore = retrieveEFIVariableStore()
}

virtualMachineConfiguration.platform = platform
virtualMachineConfiguration.bootLoader = bootloader

disksArray.add(createBlockDeviceConfiguration())
guard let disks = disksArray as? [VZStorageDeviceConfiguration] else {
    fatalError("Invalid disksArray.")
}
virtualMachineConfiguration.storageDevices = disks

virtualMachineConfiguration.networkDevices = [createNetworkDeviceConfiguration()]
virtualMachineConfiguration.graphicsDevices = [createGraphicsDeviceConfiguration()]
virtualMachineConfiguration.audioDevices = [createInputAudioDeviceConfiguration(), createOutputAudioDeviceConfiguration()]

virtualMachineConfiguration.keyboards = [VZUSBKeyboardConfiguration()]
virtualMachineConfiguration.pointingDevices = [VZUSBScreenCoordinatePointingDeviceConfiguration()]
virtualMachineConfiguration.consoleDevices = [createSpiceAgentConsoleDeviceConfiguration()]

try! virtualMachineConfiguration.validate()
virtualMachine = VZVirtualMachine(configuration: virtualMachineConfiguration)

Enable copy-and-paste support between the host and the guest

In macOS 13 and later, the Virtualization framework supports copy-and-paste of text and images between the Mac host and Linux guests through the SPICE agent clipboard-sharing capability. The example below shows the steps for configuring VZVirtioConsoleDeviceConfiguration and VZSpiceAgentPortAttachment to enable this capability:

private func createSpiceAgentConsoleDeviceConfiguration() -> VZVirtioConsoleDeviceConfiguration {
    let consoleDevice = VZVirtioConsoleDeviceConfiguration()

    let spiceAgentPort = VZVirtioConsolePortConfiguration()
    spiceAgentPort.name = VZSpiceAgentPortAttachment.spiceAgentPortName
    spiceAgentPort.attachment = VZSpiceAgentPortAttachment()
    consoleDevice.ports[0] = spiceAgentPort

    return consoleDevice
}
  • Important: To use the copy-and-paste capability in Linux, the user needs to install the spice-vdagent package, which is available through most Linux package managers. Developers need to communicate this requirement to users of their apps.

Start the VM

After building the configuration data for the VM, the sample app uses the VZVirtualMachine object to start the execution of the Linux guest operating system.

Before calling the VM's start method, the sample app configures a delegate object to receive messages about the state of the virtual machine. When the Linux operating system shuts down, the VM calls the delegate's guestDidStop method. In response, the delegate method prints a message and exits the sample.

self.virtualMachineView.virtualMachine = self.virtualMachine
self.virtualMachine.delegate = self
self.virtualMachine.start(completionHandler: { (result) in
    switch result {
    case let .failure(error):
        fatalError("Virtual machine failed to start with error: \(error)")

    default:
        print("Virtual machine successfully started.")
    }
})
You might also like...
Identify Intel-Only Apps on your Mac with ease:
Identify Intel-Only Apps on your Mac with ease:

Silicon About Identify Intel-Only Apps on your Mac with ease: License Project is released under the terms of the MIT License. Repository Infos Owner:

Manager the window of the mac.
Manager the window of the mac.

WindowManager For developping WindowManager please clone the repostority. For cloing

 An ultra-lightweight native Discord client for vintage and modern Mac OS
An ultra-lightweight native Discord client for vintage and modern Mac OS

Discord Lite An ultra-lightweight native Discord client for vintage and modern Mac OS Minimum System Requirements Mac OS X version 10.4 (Tiger) PowerP

A command line tool for managing Swift Playground projects on your Mac.

swift-playground-tools A command line tool for managing Swift Playground projects on your Mac. Generate Xcode Project $ playground-tools generate-xcod

MacLookup - Lookup for all Mac names, colors, model identifiers and part numbers

MacLookup Lookup for all Mac names, colors, model identifiers and part numbers.

Billboard - Add a text to your Mac menu bar
Billboard - Add a text to your Mac menu bar

📰 Billboard Put text on your Mac status bar This is a little app that allows to

DevToys For mac
DevToys For mac

DevToysMac This is the mac app version of DevToys! How to install Download and extract the latest Releases. Extract DevToys.app from DevToys.zip Scree

A nano-sized weather station based on a Raspberry Pi with an API, iOS & Mac Catalyst app, and sensor-based automations.
A nano-sized weather station based on a Raspberry Pi with an API, iOS & Mac Catalyst app, and sensor-based automations.

Nanotool A nano-sized weather station based on a Raspberry Pi with an API, iOS & Mac Catalyst app, and sensor-based automations. Descriere Vremea este

A macOS menubar app to temporarily prevent the Mac from sleeping.

Caffeinate A macOS menubar app to temporarily prevent the Mac from sleeping. How does it work Left-clicking the cup will toggle Caffeinate. If the cup

Comments
  • Can't run on Ventura 13 Developer Beta 3

    Can't run on Ventura 13 Developer Beta 3

    dyld[18186]: Symbol not found: _$sSl17_StringProcessingSQ7ElementRpzrlE5split2bySay11SubSequenceQzGqd___tSTRd__ABQyd__ACRSlF
      Referenced from: <C80A0776-D55E-338C-AF33-E672214D0906> /Users/mrchoke/Library/Developer/Xcode/DerivedData/RunLinuxVM-gntzfvuibsgfnnbqmhfhwmdzbjui/Build/Products/Release/RunLinuxVM.app/Contents/MacOS/RunLinuxVM
      Expected in:     <F6C12222-2607-3DD3-8BE3-A79513D980CF> /usr/lib/swift/libswift_StringProcessing.dylib
    
    opened by mrchoke 1
Releases(v1.1.17)
Owner
MrChoke
Just For FuN!
MrChoke
A ARM macOS Virtual Machine, using macOS 12's new Virtualization framework.

macOS Virtual Machine A ARM macOS Virtual Machine, using macOS 12's new Virtualization framework. I copied KhaosT's code from here, all I did is chang

Ming Chang 127 Nov 30, 2022
macOS Virtual Machine using Virtualization.framework

virtualOS Run a virtual macOS machine on your Apple Silicon computer. On first start, the latest macOS restore image is automatically downloaded from

null 102 Dec 24, 2022
Swift sample app for running privileged operations on macOS using a helper tool

SwiftAuthorizationSample demonstrates how to run privileged operations on macOS using a helper tool managed by launchd. This sample was created with t

null 31 Dec 20, 2022
A Swift SPM framework for running and managing Lua code from Swift

LuaKit A Swift Package for running and managing Lua code from Swift. Documentation For documentation, add this package as Swift Package Dependency, an

GGorAA 5 Nov 24, 2022
A very simplistic state machine system for Swift while mainly used with Raylib on Swift

A very simplistic state machine system for Swift while mainly used with Raylib on Swift

Conifer Coniferoslav 2 Dec 12, 2022
Multiple Arcade Machine Emulator for iOS, iPadOS, tvOS, macOS (Catalyst)

MAME4iOS Original Author: David Valdeita (Seleuco) This is a port of MAME for iOS, iPadOS, tvOS and macOS. MAME4iOS is designed to run for modern iOS

null 438 Jan 4, 2023
Joplin - an open source note taking and to-do application with synchronization capabilities for Windows, macOS, Linux, Android and iOS. Forum: https://discourse.joplinapp.org/

Joplin® is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are sea

Laurent 33.7k Dec 30, 2022
A Swift library for hardware projects on Linux/ARM boards with support for GPIOs/SPI/I2C/PWM/UART/1Wire.

A Swift library for hardware projects on Linux/ARM boards with support for GPIOs/SPI/I2C/PWM/UART/1Wire. Summary This library provides an easy way to

uraimo 1.3k Dec 26, 2022
A Swift cross-platform (Apple and Linux) networking library.

KippleNetworking A Swift library that offers cross-platform (Apple and Linux) networking support, intended for the creation of cross-platform SDKs to

Kipple 11 Sep 20, 2022
BioViewer - Protein (.pdb, .cif and .fasta) viewer for iPhone, iPad and Mac, using SwiftUI + SceneKit

BioViewer - Protein (.pdb, .cif and .fasta) viewer for iPhone, iPad and Mac, using SwiftUI + SceneKit

Raúl Montón 16 Dec 21, 2022