├── README.adoc ├── bin ├── install-nix ├── install-nixpkgs-yosemite └── prepare-boot-drive-from-iso └── etc └── nixos └── configuration.nix /README.adoc: -------------------------------------------------------------------------------- 1 | == NixOS on MBP 2 | 3 | This is a repo that will house notes and scripts related to getting 4 | NixOS running on a newer generation (late 2013+) MacBook Pro laptop 5 | (Retina). 6 | 7 | === Preparing Installation Media 8 | 9 | Contrary to other reports on the internet (in the wild) you do not need 10 | to prerpare your bootable USB installer on another Linux distro. 11 | 12 | *You should be using 16.03 or 16.09 images at this point!* 13 | 14 | As of 2016-10-15 here are the latest `nixos` image download locations: 15 | 16 | * link:https://nixos.org/releases/nixos/16.09[NixOS 16.09] 17 | 18 | Download the minimal ISO from the link above. 19 | 20 | The command I used on my NixOS box was the following, though on OSX you should 21 | be able to use `/dev/disk2` or similar after unmounting the USB drive in OSX. 22 | 23 | When preparing your USB install drive on Linux run: 24 | 25 | [source,bash] 26 | ---- 27 | sudo dd bs=4M if=path/to/nixos-minimal-16.09-x86_64-linux.iso of=/dev/sdc 28 | ---- 29 | 30 | When preparing your USB install drive on OS X or BSD-based distributions run: 31 | 32 | [source,bash] 33 | ---- 34 | sudo dd bs=4m if=path/to/nixos-minimal-16.09-x86_64-linux.iso of=/dev/disk2 35 | ---- 36 | 37 | 38 | === Before Installing 39 | 40 | You will need to resize your OSX partition. I did this by booting into the 41 | OSX Recovery partition and using the Disk Utility from there. 42 | 43 | To boot into the Recovery partition you hold down the Cmd+R keys on boot 44 | startup until you see it enter Recovery mode. 45 | 46 | === Boot USB Drive 47 | 48 | Boot from the USB drive by holding down the Option key during the boot 49 | startup tone until you see options of devices to boot from. 50 | 51 | You will likely need to choose the second option called 'EFI Boot'. 52 | 53 | === Preparing Partitions in Stage2 54 | 55 | If you are unsure on how to configure your partitions consult the `man gdisk`. 56 | I suggest the following basic setup (this is what I did): 57 | 58 | [source] 59 | ---- 60 | $ sudo gdisk -l /dev/sda 61 | 62 | GPT fdisk (gdisk) version 0.8.8 63 | 64 | Partition table scan: 65 | MBR: protective 66 | BSD: not present 67 | APM: not present 68 | GPT: present 69 | 70 | Found valid GPT with protective MBR; using GPT. 71 | Disk /dev/sda: 490234752 sectors, 233.8 GiB 72 | Logical sector size: 512 bytes 73 | Disk identifier (GUID): XXXXXXXXXXXXXXXXXXXXXXXX 74 | Partition table holds up to 128 entries 75 | First usable sector is 34, last usable sector is 490234718 76 | Partitions will be aligned on 8-sector boundaries 77 | Total free space is 6 sectors (3.0 KiB) 78 | 79 | Number Start (sector) End (sector) Size Code Name 80 | 1 40 409639 200.0 MiB EF00 EFI System Partition 81 | 2 409640 98957655 47.0 GiB AF05 Customer 82 | 3 XXXXXXXX XXXXXXXXX 620.0 MiB AB00 Recovery HD 83 | 4 XXXXXXXXX XXXXXXXXX 170.0 GiB 8300 nixosroot 84 | 5 XXXXXXXXX XXXXXXXXX 16.0 GiB 8200 nixosswap 85 | ---- 86 | 87 | I did this with the following commands after stage2 loaded in the NixOS 88 | installer: 89 | 90 | [source,shell] 91 | ---- 92 | # cryptsetup luksFormat /dev/sda4 93 | # cryptsetup luksOpen /dev/sda4 nixosroot 94 | # mkfs.ext4 /dev/mapper/nixosroot 95 | # mkswap -L nixosswap /dev/sda5 96 | ---- 97 | 98 | If you do not already have a `vfat` filesystem for boot images you will need 99 | to run the following command (I didn't need to do this): 100 | 101 | [source,shell] 102 | ---- 103 | # mkfs.vfat /dev/sda1 104 | ---- 105 | 106 | Now we need to mount the new or existing filesystems: 107 | 108 | ---- 109 | # mount /dev/mapper/nixosroot /mnt 110 | # mkdir /mnt/boot 111 | # mount /dev/sda1 /mnt/boot 112 | # swapon /dev/disk/by-label/nixosswap 113 | ---- 114 | 115 | *Make sure you mount `/dev/sda1` under `/mnt/boot`.* 116 | 117 | After that run: `nixos-generate-config --root /mnt` 118 | 119 | After this you may want to modify the `configuration.nix` to include gummiboot. 120 | 121 | Then run: `nixos-install` 122 | 123 | === Configuration Post-Install 124 | 125 | My `/etc/nixos/configuration.nix` for the MBP can be found at 126 | link:etc/nixos/configuration.nix[]. 127 | 128 | Some parts of note that are required for the MBP are: 129 | 130 | ==== Boot Options 131 | 132 | Use gummiboot. I got gummiboot working straight away. 133 | 134 | [source,nix] 135 | ---- 136 | { 137 | # Other stuff up here.... 138 | 139 | boot.loader.grub.enable = false; 140 | boot.loader.systemd-boot.enable = true; 141 | # Whether or not the installation process should modify EFI boot variables 142 | boot.loader.efi.canTouchEfiVariables = true; 143 | # If you rely on a dirty /tmp dir you are doing it wrong. Your laptop will 144 | # never be cattle. 145 | boot.cleanTmpDir = true; 146 | # This gets your audio output and input (mic) working 147 | boot.extraModprobeConfig = '' 148 | options libata.force=noncq 149 | options resume=/dev/sda5 150 | options snd_hda_intel index=0 model=intel-mac-auto id=PCH 151 | options snd_hda_intel index=1 model=intel-mac-auto id=HDMI 152 | options snd_hda_intel model=mbp101 153 | options hid_apple fnmode=2 154 | ''; 155 | 156 | # some other stuff below here 157 | } 158 | ---- 159 | 160 | See the full base configuration at link:etc/nixos/configuration.nix[configuration.nix]. 161 | 162 | ==== Tidbit: Audio 163 | 164 | If you use xmonad and you want to attach your Fn keys to the appropriate audio 165 | behaviors you are accustomed to on OSX/Darwin then you can 166 | link:https://github.com/mbbx6spp/.home/blob/lookie/dotfiles/xmonad/xmonad.hs#L110-131[take a look at my `xmonad.hs` file]. 167 | 168 | For those just interested in the raw commands here they are below: 169 | 170 | [source,shell] 171 | ---- 172 | $ amixer -q set Master toggle # mute/unmute 173 | $ amixer -q set Master 5%- # decrease volume by 5% 174 | $ amixer -q set Master 5%+ # increase volume by 5% 175 | ---- 176 | 177 | ==== Tidbit: Brightness / Visual Tempurature 178 | 179 | Some of you may be familiar with OSX apps that changes your brightness and 180 | screen tone based on the time of day. 181 | 182 | On Linux the best one I could find was redshift which is configurable in 183 | NixOS via the link:https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/services/x11/redshift.nix[builtin module]. 184 | 185 | Here is an excerpt from my latest `/etc/nixos/configuration.nix` file for 186 | redshift configs: 187 | 188 | [source,javascript] 189 | ---- 190 | services.redshift.enable = true; 191 | services.redshift.brightness.day = "0.8"; 192 | services.redshift.brightness.night = "0.4"; 193 | services.redshift.latitude = "0.0000"; 194 | services.redshift.longitude = "0.0000"; 195 | ---- 196 | 197 | For the raw commands to use to increase or decrease brightness see below: 198 | 199 | [source,shell] 200 | ---- 201 | $ cat /sys/class/backlight/acpi_video0/brightness # echos current brightness level 202 | 10 203 | $ cat /sys/class/backlight/acpi_video0/max_brightness # echos max brightness level 204 | 100 205 | $ echo 25 | sudo tee /sys/class/backlight/acpi_video0/brightness # sets brightness to 25/100 206 | $ cat /sys/class/backlight/acpi_video0/brightness 207 | 25 208 | ---- 209 | 210 | HTH! 211 | -------------------------------------------------------------------------------- /bin/install-nix: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Purpose: Install Nix package manager 3 | 4 | set -eu 5 | curl https://nixos.org/nix/install | sh 6 | -------------------------------------------------------------------------------- /bin/install-nixpkgs-yosemite: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Purpose: Setup nixpkgs for Yosemite because Apple sucks and broke everything 3 | 4 | declare -r _nixpgks_yosemite_fork="https://github.com/joelteon/nixpkgs.git" 5 | declare -r _nixpkgs_binary_caches="http://zalora-public-nix-cache.s3-website-ap-southeast-1.amazonaws.com/ http://cache.nixos.org/" 6 | declare -r _nixpkgs_nix_conf="/etc/nix/nix.conf" 7 | 8 | function _usage() { 9 | echo "Usage: $0 NIXPKGDIR" 10 | } 11 | 12 | function _main() { 13 | local -r dir="${1:-${PWD}}" 14 | local -r platform="$(uname -o)" 15 | 16 | if [ "${platform}" != "Darwin" ]; then 17 | >&2 echo "Error: Can only run on Darwin" 18 | return 1 19 | fi 20 | 21 | set -eu 22 | 23 | mkdir -p "${dir}" 24 | pushd "${dir}" 25 | git clone "${_nixpgks_yosemite_fork}" 26 | popd 27 | nix-channel --remove nixkpkgs 28 | rm -rf "${HOME}/.nix-defexpr/nixpkgs" 29 | ln -s "${dir}/nixpkgs" "${HOME}/.nix-defexpr/nixpkgs" 30 | sudo mkdir -p /etc/nix 31 | echo "binary-caches = ${_nixpkgs_binary_caches}" | \ 32 | sudo tee "${_nixpkgs_nix_conf}" 33 | echo "Add this to your shell rc file:" 34 | echo "export NIX_PATH=\"${dir}:nixpkgs=${dir}\"" 35 | nix-env -i hello 36 | } 37 | 38 | if [ "${BASH_SOURCE[0]}" != "${0}" ]; then 39 | >&2 echo "Error: Sourced executable script ${0}, nothing to do." 40 | else 41 | if [ "$#" -ne 1 ]; then 42 | _usage 43 | exit 1 44 | else 45 | case "${1}" in 46 | -h|--help) _usage; exit 0;; 47 | *) set -e; _main "${1}";; 48 | esac 49 | fi 50 | fi 51 | 52 | -------------------------------------------------------------------------------- /bin/prepare-boot-drive-from-iso: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Purpose: To create a bootable (USB) drive on OSX 3 | # Note: For a NixOS 14.12 ISO (~330MB) to a 512MB USB drive, the last step (rsync) took over 3 minutes. 4 | 5 | declare -r platform="$(uname -s)" 6 | 7 | if [ "${platform}" != "Darwin" ]; then 8 | >&2 echo "Error: This will not run on ${platform} (anything other than Darwin)." 9 | exit 1 10 | fi 11 | 12 | if [ "$#" -ne 2 ]; then 13 | >&2 echo "Error: Expected two arguments, received $#." 14 | >&2 echo "Usage: $0 SOURCEISO DESKDRIVE" 15 | >&2 echo "Example: $0 ~/Downloads/nixos-14.12.iso /dev/disk2" 16 | exit 1 17 | fi 18 | 19 | set -eu 20 | declare -r source_iso="${1}" 21 | declare -r dest_drive="${2}" 22 | declare -r tmp_dir="$(mktemp -d -t nixos.XXXXX)" 23 | declare -r source_dmg="${tmp_dir}/nixos.dmg" 24 | declare -r vol_root="/Volumes" 25 | declare -r vol_name="NIXOS_BOOT" 26 | declare -r vol_dir="${vol_root}/${vol_name}" 27 | 28 | if [ ! -f "${source_iso}" ]; then 29 | >&2 echo "Error: Given source ISO file does exist or is not a file." 30 | exit 1 31 | fi 32 | 33 | if [ -f "${source_dmg}" ]; then 34 | >&2 echo "Error: There already exists a DMG file at ${source_dmg}." 35 | >&2 echo " Please remove and rereun to proceed." 36 | exit 1 37 | fi 38 | 39 | if [ ! -b "${dest_drive}" ]; then 40 | >&2 echo "Error: No block device exists at ${dest_drive}." 41 | >&2 echo " Please confirm drive path and rerun to proceed." 42 | exit 1 43 | fi 44 | 45 | # The "magic" of hdiutil and diskutil I gained from many hours using these for bitcoin storage 46 | # purposes. Don't ask, but I knew there had to be a way to not have to load Ubuntu first and 47 | # then make the USB bootable for NixOS directly on OSX for users that don't have a physical 48 | # linux box laying around (for USB purposes). 49 | # This did take a couple of hours of getting this right though despite my existing knowledge of 50 | # hdiutil and diskutil ridiculousness. Thanks Apple. :) 51 | function main { 52 | hdiutil convert -format UDRW -o "${source_dmg}" "${source_iso}" 53 | diskutil partitionDisk "${dest_drive}" GPTFormat "MS-DOS FAT32" "${vol_name}" "100%" 54 | hdiutil attach -readOnly "${source_dmg}" -mountpoint "${tmp_dir}/nixos" 55 | rsync -rv --progress "${tmp_dir}/nixos/" "${vol_dir}/" 56 | diskutil unmountDisk "${dest_drive}" 57 | diskutil eject "${dest_drive}" 58 | hdiutil unmount "${tmp_dir}/nixos" 59 | rm -rf "${tmp_dir}" 60 | } 61 | 62 | read -p "This will replace all your data on $2. Are you sure you want to proceed? (yes|no) " yn 63 | case "${yn}" in 64 | y|yes) 65 | main ;; 66 | *) 67 | exit 0 ;; 68 | esac 69 | 70 | echo "Now reboot and hold down the Alt/Option then choose this USB drive to boot from." 71 | -------------------------------------------------------------------------------- /etc/nixos/configuration.nix: -------------------------------------------------------------------------------- 1 | # Edit this configuration file to define what should be installed on 2 | # your system. Help is available in the configuration.nix(5) man page 3 | # and in the NixOS manual (accessible by running ‘nixos-help’). 4 | 5 | { config, pkgs, ... }: 6 | 7 | let 8 | 9 | in 10 | { 11 | imports = 12 | [ # Include the results of the hardware scan. 13 | ./hardware-configuration.nix 14 | ]; 15 | 16 | #boot.kernelPackages = pkgs.linuxPackages_3_18; 17 | boot.loader.grub.enable = false; 18 | boot.loader.systemd-boot.enable = true; 19 | #boot.loader.systemd-boot.timeout = 2; 20 | boot.loader.efi.canTouchEfiVariables = true; 21 | boot.cleanTmpDir = true; 22 | boot.extraModprobeConfig = '' 23 | options libata.force=noncq 24 | options resume=/dev/sda3 25 | options snd_hda_intel index=0 model=intel-mac-auto id=PCH 26 | options snd_hda_intel index=1 model=intel-mac-auto id=HDMI 27 | options snd-hda-intel model=mbp101 28 | options hid_apple fnmode=2 29 | ''; 30 | 31 | # TODO: update timezone for your needs 32 | time.timeZone = "America/Chicago"; 33 | 34 | fonts.enableFontDir = true; 35 | fonts.enableCoreFonts = true; 36 | fonts.enableGhostscriptFonts = true; 37 | # I like fonts. Sue me. 38 | fonts.fonts = with pkgs; [ 39 | corefonts 40 | inconsolata 41 | liberation_ttf 42 | dejavu_fonts 43 | bakoma_ttf 44 | gentium 45 | ubuntu_font_family 46 | terminus_font 47 | ]; 48 | 49 | nix.useSandbox = true; 50 | nix.binaryCaches = 51 | [ 52 | https://cache.nixos.org 53 | ]; 54 | 55 | # TODO: Update hostname to your liking 56 | networking.hostName = "dkmbp0"; 57 | # Manage your /etc/hosts file below 58 | networking.extraHosts = '' 59 | 127.0.0.1 myawesome.devbox 60 | ''; 61 | networking.firewall.enable = true; 62 | networking.wireless.enable = true; 63 | 64 | # TODO: enable bluetooth if you use it on your MBP, otherwise I 65 | # just disable to save on battery. 66 | hardware.bluetooth.enable = true; 67 | # This enables the facetime HD webcam on newer Macbook Pros (mid-2014+). 68 | hardware.facetimehd.enable = true; 69 | # Enable pulseaudio for audio 70 | hardware.pulseaudio.enable = true; 71 | hardware.opengl.extraPackages = [ pkgs.vaapiIntel ]; 72 | 73 | environment.variables = { 74 | #MY_ENV_VAR = "\${HOME}/bla/bla"; 75 | }; 76 | # minimize the number of systemPackages to essentials because 77 | # you should keep most of your apps in your user profile. 78 | environment.systemPackages = with pkgs; [ 79 | # CLI tools 80 | screen 81 | tcpdump 82 | acpi 83 | vim 84 | git 85 | ]; 86 | 87 | nixpkgs.config.allowUnfree = true; 88 | nixpkgs.config.packageOverrides = pkgs: { 89 | # TODO: If you need Thunderbolt module you can uncomment the 90 | # block below: 91 | #linux = pkgs.linuxPackages.override { 92 | # extraConfig = '' 93 | # THUNDERBOLT m 94 | # ''; 95 | #}; 96 | }; 97 | 98 | powerManagement.enable = true; 99 | 100 | programs.light.enable = true; 101 | programs.bash.enableCompletion = true; 102 | 103 | services.dnsmasq.enable = true; 104 | # TODO: Update your DNSmasq configuration below to your needs 105 | services.dnsmasq.extraConfig = '' 106 | address=/dev/127.0.0.1 107 | server=/bla.cool/IPHERE 108 | ''; 109 | # TODO: Update your DNS servers below 110 | services.dnsmasq.servers = [ 111 | "8.8.4.4" 112 | "8.8.8.8" 113 | ]; 114 | 115 | services.locate.enable = true; 116 | 117 | # TODO: uncomment and setup your openvpn config below (expects config info 118 | # in /etc/nixos/mycorp/ dir). 119 | #services.openvpn.servers.mycorp = { 120 | # autoStart = false; # requires you `sudo systemctl start openvpn-mycorp` manually 121 | # config = builtins.readFile ./mycorp/openvpn.conf; 122 | # up = "${pkgs.update-resolve-conf}/libexec/openvpn/update-resolve-conf"; 123 | # down = "${pkgs.update-resolve-conf}/libexec/openvpn/update-resolve-conf"; 124 | #}; 125 | 126 | services.tlp.enable = true; 127 | 128 | services.xserver.enable = true; 129 | services.xserver.enableTCP = false; 130 | services.xserver.layout = "us"; 131 | services.xserver.xkbVariant = "mac"; 132 | #services.xserver.videoDrivers = [ "intel" ]; 133 | services.xserver.xkbOptions = "terminate:ctrl_alt_bksp, ctrl:nocaps"; 134 | # TODO: uncomment if you use an external HTMI monitor 135 | #services.xserver.xrandrHeads = [ "HDMI-0" "eDP" ]; 136 | #services.xserver.resolutions = [ 137 | # { x = "3840"; y = "2160"; } 138 | # { x = "2880"; y = "1800"; } 139 | #]; 140 | 141 | services.xserver.desktopManager.kde5.enable = true; 142 | services.xserver.displayManager.kdm.enable = true; 143 | 144 | services.xserver.multitouch.enable = true; 145 | services.xserver.multitouch.invertScroll = true; 146 | 147 | services.xserver.synaptics.additionalOptions = '' 148 | Option "VertScrollDelta" "-100" 149 | Option "HorizScrollDelta" "-100" 150 | ''; 151 | services.xserver.synaptics.enable = true; 152 | services.xserver.synaptics.tapButtons = true; 153 | services.xserver.synaptics.fingersMap = [ 0 0 0 ]; 154 | services.xserver.synaptics.buttonsMap = [ 1 3 2 ]; 155 | services.xserver.synaptics.twoFingerScroll = true; 156 | 157 | security.sudo.enable = true; 158 | security.sudo.wheelNeedsPassword = true; 159 | 160 | users.mutableUsers = true; 161 | users.ldap.daemon.enable = false; 162 | # TODO: update username and description, etc. 163 | users.extraUsers.spotter = { 164 | isNormalUser = true; 165 | uid = 1000; 166 | group = "users"; 167 | description = "Susan Potter"; 168 | extraGroups = [ 169 | "wheel" 170 | "docker" 171 | "networkmanager" 172 | "messagebus" 173 | "systemd-journal" 174 | "disk" 175 | "audio" 176 | "video" 177 | ]; 178 | createHome = true; 179 | home = "/home/spotter"; 180 | }; 181 | 182 | virtualisation.docker.enable = true; 183 | } 184 | --------------------------------------------------------------------------------