Friday, January 2, 2026

NUC6i3 Skylake Hackintosh with Intel GPU Passthrough on Proxmox



I recently purchased a NUC6i3 and was wondering if it was possible to install Mac OS on it. After a bit of fiddling I can say that Mac OS Catalina runs on it just fine with one caveat: there are no drivers for the built in wifi card (Intel Dual Band Wireless-AC 8260). That means you have to use the ethernet port or buy a USB wifi adapter.


One of my others goals though was to be able to remotely manage a box like this and have Mac OS run in a virtual machine. This makes maintenance much easier as you have snapshotting and backup capability.

For this build I wanted the following:


  • Proxmox Virtual Environment 6.2-6 (as of this writing the latest version in the pvetest repository)
  • Mac OS X Catalina
  • OpenCore bootloader
  • Intel HD Integrated Graphics Passthrough

The issue with the Intel passthrough is that all the guides seem to state you have to use a legacy bios. I wanted to get it to work with the latest OpenCore using an EFI partition.


A huge shoutout to Nick and his guide to get things started:
https://www.nicksherlock.com/2020/04/installing-macos-catalina-on-proxmox-with-opencore/


Do a base install of Proxmox. I use the USB method.

After installing edit /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=on nomodeset nofb rd.driver.pre=vfio-pci video=efifb:off,vesafb:off simplefb=off modprobe.blacklist=i915 pcie_acs_override=downstream iommu=pt vfio-pci.ids=8086:1916"

Some of these probably aren't required but they worked for me. The intel_iommu is used to allow PCI passthrough.

After modification I ran update-grub

Next I edited /etc/modprobe.d/vfio.conf and added:

options vfio-pci ids=8086:1916

This loads the vfio-pci module and indicates that you want to passthrough the Intel integrated GPU.

A lspci command should show:
00:02.0 VGA compatible controller: Intel Corporation HD Graphics 520 (rev 07)


The ids corresponds to this device on the NUC6.


I also blacklisted the following:

blacklist snd_hda_intel
blacklist snd_hda_codec_hdmi
blacklist i915

I added these to /etc/modprobe.d/blacklist.conf 


Afterwards I ran update-initramfs -u to make sure the changes took and rebooted. After rebooting you should have no display. This is because vfio-pci should now claim the device. After booting lspci -v shows:

00:02.0 VGA compatible controller: Intel Corporation HD Graphics 520 (rev 07) (prog-if 00 [VGA controller])
        Subsystem: Intel Corporation Skylake GT2 [HD Graphics 520]
        Flags: bus master, fast devsel, latency 0, IRQ 134
        Memory at de000000 (64-bit, non-prefetchable) [size=16M]
        Memory at c0000000 (64-bit, prefetchable) [size=256M]
        I/O ports at f000 [size=64]
        [virtual] Expansion ROM at 000c0000 [disabled] [size=128K]
        Capabilities: [40] Vendor Specific Information: Len=0c <?>
        Capabilities: [70] Express Root Complex Integrated Endpoint, MSI 00
        Capabilities: [ac] MSI: Enable+ Count=1/1 Maskable- 64bit-
        Capabilities: [d0] Power Management version 2
        Capabilities: [100] Process Address Space ID (PASID)
        Capabilities: [200] Address Translation Service (ATS)
        Capabilities: [300] Page Request Interface (PRI)
        Kernel driver in use: vfio-pci
        Kernel modules: i915


One thing I had to do was make sure I installed Mac OS X first without doing the passthrough. I then added the passthrough and things worked.

I was also able to keep the monitor defined in Proxmox and was able to see some bootloader images.







Tuesday, May 9, 2017

Mautic Nginx Configuration and Setup


Just a quick example of how to setup Mautic using Nginx.

server {
listen 443;
    server_name mautic.example.com;

ssl on;
    ssl_certificate /etc/letsencrypt/live/mautic.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mautic.example.com/privkey.pem; # managed by Certbot

    access_log /var/log/nginx/mautic_access.log;
    error_log /var/log/nginx/mautic_error.log;

    client_max_body_size 50m;

    gzip on;
    gzip_proxied any;
    gzip_types       text/css text/plain text/xml application/xml application/javascript application/x-javascript text/javascript application/json text/x-json;
    gzip_vary        on;
    gzip_disable     "MSIE [1-6]\.";

    root /home/example/mautic;
    index index.php index.html index.htm;

    # redirect index.php to root
    #rewrite ^/index.php/(.*) /$1  permanent;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

Tuesday, January 24, 2017

Interview Question: How would you architect Uber?

There was recently a thread on hacker news about what questions you would ask a software architect. One of the questions was how you would architect Uber:

I would probably divide up the architecture into the following pieces:

  • Driver App
  • Passenger App
  • Backend Server


Let’s architect out the driver experience first. Drivers need to be onboarded so figure a whole system just for onboarding a driver. Once drivers are in the system we need to be able to track their location whenever they are ready to accept rides. So the app at a bare minimum needs to be able to constantly relay the driver’s current location to the backend server.

This needs to be updated in real time. I may look toward a messaging bus/queue for these types of updates so I can throw location updates out if get too behind. I would look at how multiplayer games like Quake implemented reporting real time location to the server as fast as possible and with as little delay as possible.

Once the backend server has the location we can look to the passenger app to do almost the same thing. The passenger app at a minimum needs to report trips that people want to take. Basically source and destination location.

Once we have both in the system we can now creating a matching algorithm or module. I would base this on how stock markets match and route orders. There are a number of different techniques for this. I would model the drivers as ask orders and the passenger requests as buy orders. Once a driver has been matched to a passenger we can send them both notifications and provide updates along the way.

Keep in mind that this is really only for traditional Ubers with one passenger. With pools the matching algorithm becomes more complex as well as the infrastructure to support it.

Monday, January 23, 2017

Developing for the NRF51822 on Mac OS X

Over the weekend I worked on trying to get a development environment up and running for the Nordic nRF51822 system on a chip.

This outlines how I did it:

Need to Download Segger JLink. This is used to flash the board.

J-Link Software and Documentation pack for MacOSX
https://www.segger.com/downloads/jlink?step=1&file=JLinkLinuxDEB64_4.94.3

For Mac I installed: JLink_MacOSX_V612f.pkg


After it was installed I was able to run JLinkExe (it put it in my path)

$ JLinkExe 
SEGGER J-Link Commander V6.12f (Compiled Jan 13 2017 16:41:09)
DLL version V6.12f, compiled Jan 13 2017 16:40:56

Connecting to J-Link via USB...Updating firmware:  J-Link OB-SAM3U128-V2-NordicSemi compiled Nov 14 2016 16:58:29
Replacing firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled May  4 2015 13:48:48
Waiting for new firmware to boot
New firmware booted successfully
O.K.
Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Nov 14 2016 16:58:29
Hardware version: V1.00
S/N: 681696138
VTref = 3.300V


Type "connect" to establish a target connection, '?' for help

J-Link>


I had to use SWD:


JLinkExe -device nrf51822 -if swd -speed 2000



J-Link>loadfile nrf51422_xxac.hex
Downloading file [nrf51422_xxac.hex]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Flash programming performed for 1 range (4096 bytes)
J-Link: Flash download: Total time needed: 0.132s (Prepare: 0.043s, Compare: 0.004s, Erase: 0.000s, Program: 0.075s, Verify: 0.001s, Restore: 0.008s)
O.K.

J-Link>

Tuesday, September 27, 2016

Google for Work Referral Codes


I occasionally get some promotion codes for Google Apps. These promotion codes give you $10 off per user for a year.

Here are the instructions for redeeming:

1. Use my referral link (http://goo.gl/2SJHuh)
3. Promotion codes expire in six months.
4. Promotion codes will only work in the US. If you need some for Canada let me know.

Promotion codes: 

  • KANEA9NQUM47XLA
  • KCV4Y7NGHRUECTM
  • L3QY9WXKMCVUGQL
  • L4XHXUQLGKALJ3A
  • L7FJJDC7JAMNW9X
  • L9UKK3YQ7HMLFKA
  • LC7GVN6AAR4QANC
  • M33TR9MJJA9P66J
  • M4CAWERL67WWTEX
  • M6LMATUHUEC9VR4
  • M7U4Y4JCFY3HJDT
  • MA6QDM9M37D7Q4T
  • MCLWVCAF99XP3FJ
  • N3F7KTFDRQWAKCR
  • N4PDUWWCQTV4FCH
  • N6YWFU43N9JYMNY
  • N9EPVWLQ9GNGXXQ
  • NAQNTMQFUYFLXMY
  • NCWQ37Y774JFV74
  • P3YJQF3FAVFRRY6
  • P6FWA7MPU6ML97L
  • P7RPFRY9P6RRWWM
  • PA7FUTD7D7PL9DW
  • PCJ6RNFG6MR3MCJ
  • Q3FW6PXGGXTC476
Have fun!

Saturday, November 28, 2015

Troubleshooting rtorrent: Storage error: [File chunk write error: Invalid argument.]


So I decided to try and improve the performance of one of my VMs that was running torrents.

Instead of using samba to mount the filesystem from inside the guest I went with QEMU / KVM's v9fs.

The filesystem is actually called 9p or Plan 9 File System:

https://www.kernel.org/doc/Documentation/filesystems/9p.txt

After mounting and figuring out permission issues I started rtorrent and got the error

[File chunk write error: Invalid argument.]

Apparently rtorrent uses mmap and the Plan9 file system kernel module did not support memory mapping. However it was added in a later kernel release. So all I had to do was upgrade my kernel (I was on the default 14.04 LTS kernel):


sudo apt-get install linux-image-generic-lts-vivid linux-headers-generic-lts-vivid

Restarted and used the following mount command it all worked:

mount -t 9p -o trans=virtio,version=9p2000.L,cache=mmap,rw /mount/external /data

Before the cache=mmap did not work (only cache=loose or cache=none)

Monday, April 13, 2015

Making your Windows KVM guest boxes fly with VirtIO



In order to extract the maximum performance out of a Windows guest OS on KVM / qemu you should install VirtIO.

What is virtio?

There are quite a few articles about it but basically it is like the VMWare Tools for KVM. It is a bunch of libraries that basically speed up your guest OS by making it more efficient to communicate with the host.

What speed ups are we talking about? Mainly disk I/O and network. Without Virtio drivers installed your Windows guest will feel like molasses. Or more like the difference between traditional hard drives and SSDs. It will still work but you won't like it.

What tripped me up about install the drivers was that everywhere I looked it said to download them from the Fedora project here: http://alt.fedoraproject.org/pub/alt/virtio-win/stable/.

The problem is I was using Ubuntu so while you can install the drivers it just blue screens on you with a giant STOP error. Basically I was using the wrong drivers.

I am on Ubuntu 14.04 LTS so what I really wanted was this: https://launchpad.net/kvm-guest-drivers-windows/+download


The overall technique is setup a device that uses virtio in the libvirt configuration file for your guest. This is an xml configuration file you access by typing virsh and then "edit <name>".

After you do this you will want to specify a specific network card or disk that has type="virtio". This will cause Windows to detect a new type of device in Device Manager. You then update the driver by using the downloads found on launchpad.

If you are lucky you will see the following:


Both should say "packaged by Canonical". These are the major drivers you will want. The other is a serial driver and then a balloon driver. The balloon driver is for dynamic memory management.

If you are wondering why you don't need to install these drivers on Linux guests it is because linux guests have it compiled into the kernel by default.