After using NixOS for a year, I've found it to be a great operating system. When the software I need is on nixpkgs, things work out great. When I need to install software from outside of nixpkgs, though, it can become a pain. Trying to figure out the quirks of some closed source application can become pretty complicated. It would be great to package it and contribute it back to nixpkgs, but a lot of the time I just want to have the application working as soon as possible.
Since Ubuntu is a more standard linux distribution, I hope that it's better supported by some of these closed source applications. By dual booting, it's possible to get the best of both worlds.
While dual booting works great for me, it may not be the best solution for you.
One option is to run one of the operating systems in a virtual machine. I tried this, but it's just too slow on my old Thinkpad.
NixOS offers some escape hatches too - for example buildFHSUserEnv. This is worth trying out if a particular application is giving you problems. I couldn't figure out how to apply this to all of the applications that I want to run, though.
Another solution might just be to run nix (the package manager, not nixOS) on Ubuntu. I've never tried this. Personally, I'm generally happy with NixOS and want to stick with it as much as possible.
A lot of this post is taken from Chris Martin - Installing NixOS. It covers how to install NixOS with an encrypted disk partition, but doesn't cover dual booting. There is also the NixOS Manual and NixOS Bootloader Wiki.
We will use GRUB as a bootloader and use UEFI. For the NixOS filesystem, we will encrypt it with LUKS, but for the Ubuntu filesystem we won't bother.
First, back up all of the important data on your hard drive. We will be clearing the hard drive and starting from scratch, so everything will be lost. Basically all commands will need to run with sudo
. For convenience, you can run sudo -i
so that your whole terminal session will be run as root.
We will be installing NixOS first. Download the Graphical Live CD here. We will create a bootable USB drive from the downloaded .iso
file.
If you are on Windows, you will need to find another guide on creating a bootable USB drive and skip to the next section (Ubuntu has a tutorial here).
With the USB drive plugged in, run lsblk
to find how it is named:
# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
...
sda 8:0 0 298,1G 0 disk
├─sda1 8:1 0 100M 0 part
├─sda2 8:2 0 500M 0 part /boot/efi
├─sda3 8:3 0 97,7G 0 part
└─sda4 8:4 0 97,7G 0 part /
sdb 8:16 1 2,8G 0 disk
├─sdb1 8:17 1 2G 0 part /media/chris/Ubuntu 18.04.4 LTS amd64
└─sdb2 8:18 1 2,4M 0 part
On my machine, this USB drive corresponds to /dev/sdb
(I can tell since my USB has 3G, and not 298G).
Next, we format the drive. You may need to replace /dev/sdb
with the path to your USB. This will overwrite whatever is in the USB drive, so be careful and make sure nothing important is on the drive.
# dd bs=4M if=/<path to your downloads>/nixos.iso of=/dev/sdb status=progress
Now it is necessary to update the BIOS settings on your computer to make sure that UEFI is used for booting. This step will depend completely on your particular computer, so unfortunately I can't help much with this.
On my Thinkpad, I've set "UEFI/Legacy Boot" to "UEFI Only":
At this point, we are ready to install NixOS. Restart your computer and interrupt the normal boot process to boot from the USB drive. The way to do this will depend on your specific computer model.
Even though we downloaded the graphical installer, we will be greeted by a command prompt. To open the graphical desktop, run sudo systemctl start display-manager
. If you don't already have an ethernet connection, connect to wifi. Open a terminal for the following steps (you can use the "Konsole" program).
We should check that we've booted into UEFI, rather than Legacy mode by running [ -d /sys/firmware/efi/efivars ] && echo "UEFI" || echo "Legacy"
. If you see UEFI, then all is good. If you see Legacy, check the BIOS settings again. I'm not sure why it matters how we boot, since we are just booting the installer. Still, my installed NixOS failed to boot when installed from "Legacy" but worked fine when installed from UEFI, so I think it makes a difference.
We can now begin partitioning the disk. You can ignore any errors about /etc/fstab
when running the following commands.
# parted /dev/sda -- mklabel gpt
First, we create a partition that will be used by GRUB:
# parted /dev/sda -- mkpart primary 1MiB 100MiB
We again create another partition that will be used by GRUB:
# parted /dev/sda -- mkpart ESP fat32 101MiB 600MiB
We can now create a partition for NixOS. Depending on the size of your disk, you will probably want to change the end position. I set it to 100000MiB
giving me a size of 100GB.
# parted /dev/sda -- mkpart primary 601MiB 100000MiB
We now create a partition for Ubuntu. Again, you may want to change the start and end position. Just make sure that the start position is just after the end of the previous partition.
# parted /dev/sda -- mkpart primary 100001MiB 200000MiB
We now set some flags for the two GRUB partitions:
# parted /dev/sda -- set 1 bios_grub on
# parted /dev/sda -- set 2 boot on
Checking the result, we should obtain something like:
# parted -l
Number Start End Size File system Name Flags
1 1049kB 105MB 104MB primary bios_grub
2 106MB 629MB 523MB fat16 ESP boot, esp
3 630MB 105GB 104GB primary
4 105GB 210GB 105GB primary
We now encrypt the disk partition for NixOS. You will need to set a password:
# cryptsetup luksFormat /dev/sda3
From the physical partition for NixOS, we create virtual partitions:
# cryptsetup luksOpen /dev/sda3 enc-pv
# pvcreate /dev/mapper/enc-pv
# vgcreate vg /dev/mapper/enc-pv
# lvcreate -n swap vg -L 10G
# lvcreate -n root vg -l 100%FREE
We also format the partitions:
# mkfs.vfat -n BOOT /dev/sda2
# mkfs.ext4 -L root /dev/vg/root
# mkfs.ext4 /dev/sda4
# mkswap -L swap /dev/vg/swap
Now we mount the partitions needed to install NixOS:
# mount /dev/vg/root /mnt
# mkdir /mnt/boot
# mount /dev/sda2 /mnt/boot
# swapon /dev/vg/swap
Now we generate the NixOS configuration files:
# nixos-generate-config --root /mnt
We now edit the configuration file we just created in /mnt/etc/nixos/configuration.nix
. Personally, I used the editor nano
by running nano /mnt/etc/nixos/configuration.nix
In the configuration file, delete boot.loader.systemd-boot.enable
and add:
boot = {
initrd.luks.devices = [{
name = "root";
device = "/dev/sda3";
preLVM = true;
}];
loader.grub = {
device = "/dev/sda";
enable = true;
version = 2;
useOSProber = true;
efiSupport = true;
};
loader.efi.canTouchEfiVariables = true;
};
To make sure we boot into a usable environment, set:
networking.networkmanager.enable = true;
services.xserver.enable = true;
services.xserver.layout = "us"; # Update if you have some other layout
services.xserver.desktopManager.plasma5.enable = true;
and uncomment services.xserver.layout
.
We will also install Firefox so that we can browse the internet. If you need any other software, you can add it here as well. You can search for avaialable packages here. It will still be possible to add more applications later, this is just to have some important initial ones:
environment.systemPackages = with pkgs; [
firefox
];
Finally, add a new user:
users.users.chris = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
and add a password for the user: passwd --root /mnt chris
With the NixOS configuration saved, we can install NixOS by running: # nixos-install
. There are some errors, but these can be ignored for now:
mktemp: failed to create directory via template ‘/tmp/os-prober.XXXXXX’: No such file or directory
grub-probe: error: cannot find a GRUB drive for /dev/sdb1. Check your device.map.
installing the GRUB 2 boot loader on /dev/sda...
Installing for i386-pc platform.
Installation finished. No error reported.
installing the GRUB 2 EFI boot loader into /boot...
Installing for x86_64-efi platform.
modprobe: can't change directory to '/lib/modules': No such file or directory
NixOS is now installed installed, and you can reboot the system. During the boot process, you will be prompted for a password to the encrypted disk partition and also need to log in using the user added in configuration.nix
.
With NixOS installed, we can setup Ubuntu. If you're tired and want a break, this is a good stopping point - NixOS is running fine.
Let's again prepare a bootable USB drive, but this time with Ubuntu. Don't forget to change /dev/sdb
based on the path to your USB drive.
sudo dd bs=4M if=~/Downloads/ubuntu.iso of=/dev/sdb status=progress
Now reboot the computer and again interrupt the normal boot process to boot from USB. After booting from the USB, you should see a GRUB menu . At this point, select "try Ubuntu" since the default installer won't work for us.
With Ubuntu open, open the terminal and run ubiquity --no-bootloader
.This will start a graphical interface for installation. We add --no-bootloader
since we don't want to overwrite the GRUB bootloader we already installed. When you reach the page "Installation Type", select "Something Else" .
On the menu of disk partitions, select /dev/sda4
, which we setup earlier and press "change". Select "Ext4 Journaling file system" and set the mount point to /
. You can now continue the installation process and reboot when it's finished installing.
After rebooting, you'll notice that Ubuntu still doesn't show up in the GRUB boot menu. We still have one step left.
Boot into NixOS again and run nixos-rebuild --install-bootloader switch
. This will update GRUB and it should automatically detect Ubuntu. It should now be possible to select Ubuntu or NixOS from the boot menu.
Thanks for the writeup!