Setting Up Vim (for Haskell)

This entry is part 4 of 6 in the series Setting Up Haskell Development on NixOS Linux from Scratch

In this installment, we are going to set up vim for Haskell development.  If you don’t want to use vim, you can skip this post entirely.  On the other hand, if you do want to use vim or are at least curious about trying it out (like me), then keep reading.

Chances are, if you do any kind of programming in a unix-like environment, you already know that vim is a text editor.  Its proponents claim that proficiency in vim enables you to code faster than in any other editor.  As for myself, my programming experience is mostly in IDEs, so I’m a veritable vim newbie.  When I first started experimenting in vim not too long ago, I found the number of configuration options and plugins to be overwhelming.  In fact, I’ve had to scrap several earlier version of this post as I found new combinations to try!  So, this post will explore just one possible vim configuration for Haskell development, and to be honest it’s one with which I have limited experience so far.  Still, I expect the baseline discussed here to be a good starting point for pretty much anybody.

As time goes on, I will likely change my vim configuration to better suit my needs as I discover them.  I plan to keep my vim configuration version controlled, so if you are curious about the latest version you can check it out. Also, this post is not a tutorial about how to use vim, but rather how to configure it for Haskell.  If you want practice with basic vim controls, you might want to try out the free levels of vim-adventures.

General Vim Options

Vim configuration is controlled through a the ~/.vimrc file.  This file is processed when vim first starts up and allows the user to configure vim in a huge number of ways.  Just wrapping your head around all the various options can be overwhelming.  Configuring vim means building this vimrc file to our liking.

Installing Vundle for Managing Plugins

One of the things that makes vim a popular editor choice is huge number of plugins available to customize your text editing experience.  Downloading plugins is easy, but to get vim to recognize your plugins, you have to mess with vim’s runtimepath variable.  This can get pretty tedious, but thankfully there are plugin managers that will do the work for us.  Vundle is one such declarative plugin manager, which fits with our NixOS theme.

Installing Vundle is a breeze.  First, execute the following command:

git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim

This will make a bundle directory under which we will install our various plugins.  We’re not done yet, though.  We also need to add the following to the top of our .vimrc file to run Vundle at startup.  The comments are mine and optional

" ========= VUNDLE CONFIG ===========
set nocompatible
filetype off
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
Plugin 'gmarik/Vundle.vim'

" LIST PLUGINS HERE

" VUNDLE CLEANUP    
call vundle#end()
filetype plugin indent on

Essentially, this code is declaring that the Vundle plugin will manage itself. One downside of Vundle, however, is that the plugins must have a github repository to be managed.  If this is a problem for you, check out the alternative pathogen.

Installing General Utility Plugins

Next, we’ll install some utility plugins for vim, which will also demonstrate how to install plugins using Vundle generally.  The plugins I’m choosing are vim-sensible, vim-unimpaired, and syntastic.  Vim-sensible touts itself as being a standard set of defaults on which pretty much everyone can agree.  Vim-unimpaired adds lots of key bindings to make tasks like navigating through compiler errors, for example, a lot easier.  Syntastic runs syntax checkers and displays the errors in plain view. Simply add the following lines to the .vimrc file in the section I labeled LIST PLUGINS HERE.

" LIST PLUGINS HERE
Plugin 'tpope/vim-unimpaired'
Plugin 'tpope/vim-sensible'
Plugin 'scrooloose/syntastic'
let g:syntastic_always_populate_loc_list=1
" A Haskell plugin we'll install later is 'dag/vim2hs',
" but installing it now is fine, too.

Save the file, (re)load vim, and enter :PluginInstall.  Vundle will set up the path to only use the plugins you’ve declared in .vimrc, kind of like NixOS does!  Cool.  A split screen should show up indicating the status of the selected plugins. If you ever want to add or remove plugins, just change the listed plugins in the .vimrc file and run :PluginInstall again.

The line let g:syntastic_always_populate_loc_list=1 configures syntastic to put the errors in the vim locations list, which allows us to jump through the errors using the vim-unimpaired bindings of [L, ]L, [l, and ]l.

Adding Custom Options Directly

The above plugins do a good job of setting up some standard options, but everyone prefers their own twist on things.  Mine is given below, which I put in my .vimrc file after the Vundle settings.  Each setting is commented to explain what’s going on.

" ========== GENERAL VIM SETTINGS ==========
" Enable search highlighting
set hlsearch
" Enable line numbers
set number
" Use F11 to toggle between paste and nopaste
set pastetoggle=

" vim-sensible enables smarttab. Here, we configure the rest:
" Set the display size of t characters
set tabstop=2
" When hitting , insert combination of t and spaces for this width.
" This combination is deleted as if it were 1 t when using backspace.
set softtabstop=2
" Set code-shifting width. Since smarttab is enabled, this is also the tab
" insert size for the beginning of a line.
set shiftwidth=2
" When inserting tab characters, use spaces instead
set expandtab

" Instead of failing command, present dialog if unsaved changes
set confirm

" Enable mouse in all modes
set mouse=a

" Map jk and kj to  to exit insert mode. We need to use F11 to toggle to
" paste mode before pasting any string with jk or kj, then switch back. When
" inserting jk or kj manually, we will need to type the keys slowly so that
" the key mapping times out. Using jk or kj to escape is easier than many
" other alternatives.
ino jk 
ino kj 

" Set a vertical line for long line width. This will give us a visual
" indicator for cases in which line length is approaching 80 chars
set colorcolumn=80
" Set the command section height to 2 lines.  Useful if notices (like syntastic) are shown on command lines
set cmdheight=2

Customizations for Haskell

Now we’ll add some new features for our vim installation specifically to work with Haskell.

ghcmod

Installing the syntastic plugin for syntax checking was only part of the story as syntastic only runs external syntax checkers and displays their results. So now we need a syntax checker. Enter ghcmod.

nix-install haskellPackages.ghcMod

That’s it. Syntastic will recognize that ghcmod is installed and run it whenever a Haskell file is saved. To verify that it’s being recognized, open a Haskell file, type some Haskell code, then run :SyntasticInfo, which will show what checkers syntastic plans to use for the file. You can also run the checkers explicitly with :SyntasticCheck.

vim2hs

vim2hs is a vim plugin for Haskell syntax highlighting and linting, among other things.  It seems more lightweight than the haskellmode-vim alternative plugin and was highly recommended in a reddit discussion about vim and Haskell.  Let’s give it shot.

Plugin 'dag/vim2hs'

Remember to re-run :PluginInstall within vim after updating .vimrc.


That’s it for the basic vim setup. Changing the color scheme, customizing the display, and other items related more toward personal taste are left for you to explore!

Installing Essential Software In NixOS

This entry is part 3 of 6 in the series Setting Up Haskell Development on NixOS Linux from Scratch

Welcome to part 3 of my series on setting up NixOS for Haskell development!  In this part, we’ll learn how to discover and install essential software for NixOS.  We won’t cover the particulars of installing Haskell-related components (I’m saving that for a post on its own), but some of our decisions here will be motivated by the foresight that Haskell development is what we eventually want to do.  As always, if you see an error, please let me know.  I’m figuring this stuff out as I go.

In the last post, we learned a bit about the Nix package manager.  Let’s recap the essential points:

  • All software components in NixOS are installed using the Nix package manager.
  • Packages in Nix are defined using the nix language to create nix expressions.
  • Nix expressions define all inputs to a build process, including dependencies, which can themselves be nix expressions.
  • Nix will build all required dependencies if they do not already exist on your system.
  • Packages installed for all users are defined in the nix expression /etc/nixos/configuration.nix

The rest of this post will focus on how to install packages into your user environment.  These are the packages that are active on a per-user basis, so other users won’t necessarily have the same active packages as you do.

Finding and Installing Packages

Packages are installed by running Nix expressions, so how do we find Nix expressions?  There are actually a few different ways to get them.

  • Use the nix expressions that are included with your installation of NixOS, which are part of a nix channel.  A nix channel allows you to easily download updated expressions as well as pre-compiled binaries.
  • Download a set of nix expressions from the internet.
  • Subscribe to a new nix channel to download more up-to-date software packages than are available in the default channel.

Let’s explore each one of these in turn.  Spoiler alert: we’ll use 1) early on but most of our time will be spent with 2).  I’ll touch on 3), but honestly it’s not something I recommend if you’re doing Haskell development because I don’t think it offers much, if anything, over option 2).

Expressions Available through NixOS Installation

Your NixOS installation comes with a set of packages that are included by default.  These are installed in /nix/var/nix/profiles/per-user/root/channels/nixos, but NixOS is kind enough to give you a shortcut via ~/.nix-defexpr/channels_root/nixos.  This is the default location from which nix expressions are run.  It also happens to be a nix channel, but I’ll discuss nix channels later.  The key point is that NixOS comes with oodles of expressions built-in and ready to be run.  In fact, let’s run one right now in preparation for later steps.  We’ll install git. All of the manipulations of the user environment are invoked using the nix-env command. For example, if we want to see a list of all available packages from the built-in expressions

nix-env -qaP --description *

Here, q means query, a means available packages, and P means show the attribute path, which is essentially a way to specify a particular expression instead of using the software package name.  The description option includes the description of the packages, as well.  In the case of git, we’ll see this among the long list of available packages:

nixos.pkgs.gitAndTools.gitFull  git-1.9.4  Git, a popular distributed version control system

The software is named git-1.9.4, but the attribute path specifying the nix expression used to build it is nixos.pkgs.gitAndTools.gitFull.  We can use either the package name or the attribute path to install git, but the attribute path is the recommended strategy since it removes all ambiguity about which package should be installed and how. 

So let’s install git using the following command:

nix-env -iA nixos.pkgs.gitAndTools.gitFull

Nix will then download all dependencies that you don’t already have (which, since this is our first installation, is all of them) and install git.  Here the flag i means install and A means by attribute path (yes, it bothers me that query commands use -P and install commands use -A).  We can verify the installation worked successfully by querying the list of installed packages in the user environment.

nix-env -q --installed

The command above should list git as being an installed package.

Installing from Downloaded Expressions

Another approach to getting expressions is to download a collection of them from the internet.  The most popular collection is the nixpkgs repository on github.  In fact, the nix expressions that are bundled with NixOS (and which we explored above) are simply a stable version of this nixpkgs repository.

While the nixpkgs repository has a lot of available Haskell packages already, I quickly ran into ones that I needed but weren’t included.  Properly installing these packages requires adding new nix expressions to the available set.  This is why I recommend running downloaded nix expressions as the default method of installation for Haskell developers; most likely, you’ll be adding and running your own expressions anyway, and you can pull in updates with git just as easily as you can using nix channels.

Since Nix is declarative, our expressions will be useful for everyone else, too, so why not contribute them back to nixpkgs?  For this, we’ll need to fork the nixpkgs repository and then clone our fork to our local machine.  Any updates made locally can be made on a branch, pushed back to github, and then pulled into the main nixpkgs repository. FYI: when I cloned the repository, it was about 125 MB in size.

After you fork and clone the repo locally, cd to its root.  We’re going to run pretty much the same nix-env command we did before, except now we use the -f flag to read the nix expressions from the directory.  Personally, I’m trying to get good at vim, so I’ll be querying for it with the following:

nix-env -f . -qaP --description vim
vim  vim-7.4.316  The most popular clone of the VI editor

Pretty easy.  In this case, I got lucky and was able to guess the package name “vim” correctly, but in general there are better ways to search, as we’ll find later. Installation is also an analogous command.

nix-env -f . -iA vim

We’ll investigate how to update this local nixpkgs repository with our own additions in a future post.

Subscribing to a New Channel

The third option for getting expressions is to subscribe to a new channel.  I say new channel because all NixOS installations are automatically subscribed to the channel associated with the released OS version.  For instance, I can inspect the default channel’s manifest and see that it’s for NixOS version 14.04.

cat ~/.nix-defexpr/channels_root/manifest.nix 
[ { meta = { }; name = "nixos-14.04.312.b84584f"; .......

Ok, but what is a channel?  A channel is a set of nix expressions combined with a manifest file.  The manifest file describes what binaries are available for downloading instead of building from scratch, so they can save you a lot of time if you are doing many installations. 

You can pull in new updates from a channel using the nix-channel --update command. The default channel is not really sufficient for development purposes because we want to add and run our own nix expressions.  As such, I’m glossing over channels in favor of pulling updates in from the git repository directly.  I admit I’m not the most knowledgeable about channels, so if there some best practices out there to make working with them easier, please let me know.

Enhancing the Nix Experience

We have seen how to query and install packages using Nix, but there are some small customizations we can make to make our development lives a bit easier.  Instead of using nix-env and specifying our standard set of flags again and again, we can write some custom bash commands to do most of the typing for us. One problem: how can we search for packages by keyword?  The nix-env command takes a package name as an input, not a general keyword. Thankfully, we have grep, which can search through the large list of available packages and find keywords and regular expressions for us. The code below defines a new bash command nix-search that will search through all the expressions in our git repository looking for matches of a particular keyword or regular expression.  Searching for the right expression to install will be much easier.

nix-search(){ echo "Searching..."; nix-env -f ~/Code/nixpkgs -qaP --description * | grep -i "$1"; }

All this hard-coding of -f ~/Code/nixpkgs is a problem waiting to happen, though. A better way is to use the .nix-defexpr folder to simply change the default location that Nix searches for expressions. In doing so, we won’t even need the -f flag anymore.

One thing I’d like is to have .nix-defexpr be a link itself to my ~/Code/nixpkgs directory. Otherwise, my attribute paths will need some kind of prefix, and since I only want to use expressions under ~/Code/nixpkgs, using this unnecessary prefix will get a little annoying. Normally, we could simply make .nix-defexpr a link to the right directory, but it turns out that if .nix-defexpr is a link, it is deleted when you log in and replaced with the Nix default. So, as a work around, I’m adding code to my .bashrc file to set up .nix-defexpr the way I want when I open the terminal.

We also should change the NIX_PATH environment variable similarly to what I have done below.

# In ~/.bashrc
rm -r ~/.nix-defexpr
ln -s /home/dan/Code/nixpkgs ~/.nix-defexpr

# Then export the right env variables:
export NIX_PATH=/home/dan/Code:nixos-config=/etc/nixos/configuration.nix;
nix-search(){ echo "Searching..."; nix-env -qaP --description * | grep -i "$1"; }

We can make installing easier too by writing a new command to run expressions from our git repo, specified by attribute path.

nix-install(){ nix-env -iA $1; }

The first version of this post used the -f flag exclusively because I didn’t yet know about NIX_PATH and .nix-defexpr. Having a nix-install helper function makes more sense when the -f flag was being used, but in its current form it doesn’t save any keystrokes. The user may use her discretion when deciding whether or not to use nix-install.

Put both functions into the .bashrc file in your home directory, then use source ~/.bashrc to reload the .bashrc file for the updates to take effect.  We can use the new commands like this (might need to scroll right!):

[dan@nixos:~]$ nix-search vim
Searching...
bvi                                                                 bvi-1.3.2                                                                     Hex editor with vim style keybindings
qvim                                                                qvim-7.4                                                                      The most popular clone of the VI editor (Qt GUI fork)
vim                                                                 vim-7.4.316                                                                   The most popular clone of the VI editor
vimWrapper                                                          vim-with-vimrc-7.4.316                                                        The most popular clone of the VI editor
vimb                                                                vimb-2.4                                                                      A Vim-like browser
vimbWrapper                                                         vimb-with-plugins-2.4                                                         A Vim-like browser (with plugins: )
vimprobable2                                                        vimprobable2-1.4.2                                                            Vimprobable is a web browser that behaves like the Vimperator plugin available for Mozilla Firefox 
vimprobable2Wrapper                                                 vimprobable2-with-plugins-1.4.2                                               Vimprobable is a web browser that behaves like the Vimperator plugin available for Mozilla Firefox  (with plugins: )
vimNox                                                              vim_configurable-7.4.316                                                      The most popular clone of the VI editor
vimHugeX                                                            vim_configurable-7.4.316                                                      The most popular clone of the VI editor
vimHugeXWrapper                                                     vim_configurable-with-vimrc-7.4.316                                           The most popular clone of the VI editor

[dan@nixos:~]$ nix-install vim
replacing old `vim-7.4.316'
installing `vim-7.4.316'

An Aside About Nix Search Paths

I have had to update this post a few times as I learn more about how Nix search paths work. I have tried to keep everything mentioned here correct and consistent, but having everything clearly spelled out is valuable. Here’s my most up-to-date knowledge:

  • By default, the nix-env command searches the expressions contained in the ~/.nix-defexpr directory. This directory can have subfolders or symbolic links to any other directories, and Nix will prepend any attributes with the symbolic link name. For instance, if .nix-defexpr contained a link dans_nixpkgs -> ~/Code/nixpkgs, then searches using nix-env will show attributes as dans_nixpkgs.haskellPackages.snap, for instance.
  • By making .nix-defexpr a symbolic link itself, you can eliminate the prefixes, but .nix-defexpr will be reset back to the default the next time you boot the machine. As a work around, I have placed code in my .bashrc file to set it up the way I want each time a terminal is opened.
  • The .nix-defexpr default location is what is overridden when using the -f flag.
  • The NIX_PATH environment variable is used when resolving <brackets> in nix expressions. For example, NIX_PATH=/home/dan/Code will lead to <nixpkgs> resolving to /home/dan/Code/nixpkgs. It has no effect on the nix-env command itself.
  • nixos-config must point to the configuration.nix file or else nixos-rebuild calls will fail.

Installing Haskell Platform and GHC

We can use our new bash commands to start installing our required Haskell packages.  In the past, I have tried to avoid Haskell Platform because, invariably, I would need a different version of one of the packages it offers or I would need a package that isn’t included.  Unfortunately, following either of these scenarios has sometimes required that I re-install all my packages from scratch to resolve odd dependency conflicts. But, this is NixOS, and the claim is that NixOS is designed to prevent that kind of baloney from happening.  Only time and experience will tell if that’s true, but in the meantime we’ll barge right ahead and get Haskell Platform since it is often suggested as the best way to get started with Haskell.

[dan@nixos:~]$ nix-search "haskell platform"
Searching...
<omitted>
haskellPlatform                                                     haskell-platform-2013.2.0.0                                                   Haskell Platform meta package
[dan@nixos:~]$ nix-install haskellPlatform

After installation is complete, we will have Haskell Platform 2013.2.0.0 installed, which used ghc 7.6.3 to build.   However, we did not yet install ghc because NixOS only puts packages we install on the path, not their dependencies. Installing ghc is now a fast operation because all NixOS is doing is adding the existing executable to the path. At the same time, let’s install cabal.

nix-install haskellPackages.ghc
nix-install haskellPackages.cabalInstall

I have received reports from some users that haskellPackages.ghc doesn’t work for them, but haskellPlatform.ghc does, so give that a try if the above doesn’t work for you.


That’s it for this installment.  Check back soon for the next *exciting *post in this series, although I’m not yet sure what it will be.

Installing NixOS

This entry is part 2 of 6 in the series Setting Up Haskell Development on NixOS Linux from Scratch

In the last post of this series, we set up a VM to run NixOS using VirtualBox.  Now we actually need to go ahead and install NixOS.  We’ll be installing it into our VM, but if you are installing it into an actual machine, most of the instructions here will work for you.

This post is based on this article on the NixOS wiki, but there are some differences because I chose to configure NixOS differently.

Installing NixOS

  1. Go to the NixOS download page and download a release of NixOS.  At the time of this writing, the newest release is 14.04, and I chose the Graphical Live CD, 64-bit Intel/AMD version, which is recommended for most users.
  2. Open up the VirtualBox VM Manager and select your NixOS VM.  Then choose Settings > Storage.  Click the CD icon in the storage tree.  Then, on the right side under Attributes, click the CD icon to choose a virtual CD/DVD file.  Select the nixos ISO file you downloaded in step 1.NixOS Boot
  3. Click OK, then start.  You should see the following menu.  Choose the first option, NixOS installer.  It is chosen for you automatically after about 10 seconds.GRUB Installer
  4. After the NixOS installer boots up, you’ll be at a terminal login prompt that tells you to login as root.  Enter root for your login name and hit enter.
  5. So far, we haven’t actually installed anything.  Before we can do that, we need to initialize the file system on our virtual machine so it can read and write files to our virtual disk we set up in the previous post.  The first thing to do is create a partition on our virtual disk.  Type
    fdisk /dev/sda

    to run the disk partitioning program, which has a simple but completely non-intuitive interface.  The commands I entered, in order, are n (for new partition), p (for primary partition), 1 (assign partition number 1), no selection (defaults to 2048 for start of partition), and no selection (again, default).  Finally, I enter w to write the partition to disk.  See below.Parition Disk

  6. Next, we need to make a file system onto our new partition.  Enter
    mkfs.ext4 -j -L nixos /dev/sda1

    This command will make a new file system with the ext4 format into partition 1 of sda, enable journaling, and give our new filesystem the label nixos.

  7. Now that we created the filesystem, we need to mount it.  Mounting it is like connecting different filesystems together, but in this case we need to connect our filesystem to the OS.  Mount the filesystem with
    mount LABEL=nixos /mnt

That’s the last step in setting up the disk and file system.  Next, we’ll configure NixOS itself.

Configuring NixOS

If you just want to get NixOS set up as fast as possible, skip to the instructions below.  Before I get to that, however, I’ll briefly describe the Nix philosophy and implementation from a few different levels.  These are just my impressions and understanding from using NixOS for a few days, but I have found this information to be crucial in order to do anything useful.

NixOS is a Linux distribution built around the Nix package manager, which is available for installation on other OSes if you want, but is the only package manager for NixOS.  Every piece of software installed on the entire system is installed through Nix.

So what makes Nix useful?  In most other package managers, new versions of software replace older versions.  If some component of the system depends on that software but is incompatible with the new version, then it will break after the upgrade.  Extend this problem to the huge graph of intermingling dependencies among all the software on a user’s computer and you get what’s called dependency hell.  Other Linux distributions try to prevent dependency hell by keeping official lists of software packages that are expected to be compatible, installing packages from this list, and occasionally updating the list with new versions.

Nix, on the other hand, installs new version of software side-by-side with their older versions, and older versions are deleted only when they are no longer required.  Nix achieves this through a combination of two mechanisms: a sophisticated system of sym links that keeps track of which version of packages are “active” at any time and a build system that exhaustively describes every input into each individual package.

The second part is the part we need to understand for our next steps.  Installing new software requires writing a Nix expression that completely describes all the prerequisites and dependencies for the software to be installed.  These dependencies can themselves be Nix expressions defined elsewhere.  When we install new packages, what we are doing is running a Nix expression for that package.  Nix first recursively ensures all build dependencies are available, either by checking that they are already built or by running Nix expressions to build them.  Then, it builds and installs our new package.

This is exactly the process we’ll use to install NixOS itself.

  1. First, we need an expression that will define the components we want to build and install.  We can make one and configure it using
    nixos-generate-config --root /mnt 
    nano /mnt/etc/nixos/configuration.nix

    This will open the configuration.nix expression in the nano editor.

  2. The configuration looks something like the one below.  Use the arrow keys to navigate through the file.  Lines marked with a # are comments, and several important configuration lines are commented out by default.  Use nano to move the cursor around and delete the # to enable the features you want.  In the picture, I have deleted the #s for boot.loader.grub, networking.hostName, and networking.wireless.enable.  I also uncommented all the lines that begin with services.xserver to enable a GUI.  I also uncommented the lines at the bottom of the file that add a new user and modified them as shown.  When you are done, use Ctrl-O to save the changes and Ctrl-X to exit.Nix configNix User Config
  3. With the configuration.nix nix expression defined, we are ready to install NixOS! Run
    nixos-install

    to start the installation.  If there is a problem with the filesystem and the installation refuses to start, you can redo the steps starting with the fdisk step, but use d (for delete) as the first command to delete the primary partition and start fresh.

  4. After installation completes, shut down the virtual machine, and in the VirtualBox Manager go to Settings > Storage, click on the CD on the right hand side and choose “Remove disc from virtual drive.”  This removes the NixOS installer from the boot menu so we don’t boot into it by default.  Then start the VM again.
  5. When the VM boots up, you should see a graphical login window.  We can’t log in yet because we need to change some passwords first.  To do this, we need to use the command line again.  Access the console login using the Power drop down menu.Console Login
  6. Log in as root, which still has no password.  We will change that right now with
    passwd

    Enter a new root password for your system.  If you created any users, you can set their passwords also with, for example,

    passwd dan
  7. reboot one final time and verify you can log in successfully.

That’s it! whew Next in the series, we’ll tackle how to install essential software.

Installing VirtualBox (for NixOS)

This entry is part 1 of 6 in the series Setting Up Haskell Development on NixOS Linux from Scratch

Welcome to the first installment of my series about setting up Haskell development on NixOS Linux from scratch!

I consider myself somewhere in the beginning-intermediate stages of Haskell skill, having created a useful application for Windows as learning exercise.  However, to really take my Haskell skill to the next level, I needed to migrate to the de facto standard Haskell environment – Linux.  Ollie Charles, a Haskell reddit member who writes the wonderful 24 Days of Hackage tutorial series on his site, has adopted NixOS as his Linux distro of choice and wrote a blog post describing how to get started.  I decided to trust his choice and try it out for myself.

As I dove deeper into the rabbit hole of getting my environment set up properly, I found myself getting frustrated with having to search all over the net for tutorials, walkthroughs, and installation help just to get everything set up.  Indeed, Ollie’s post does a good job giving the flavor of Haskell development on NixOS, but it’s not comprehensive enough to provide the whole story.  The goal of this series is to provide that whole story as I discover it myself.  If something in these posts is unclear or flat out wrong, please let me know!

Ok, with the introduction out of the way, let’s jump right in.

Installing VirtualBox

VirtualBox is a free program from Oracle that allows you to run a virtual machine on a host computer.  In this case, we’ll use a virtual machine to run NixOS and host the VM on Windows.

  1. Download VirtualBox installer from here.  At the time of this writing, the latest version is 4.3.12.  Since we are hosting the VM on a Windows computer, we want VirtualBox 4.3.12 for Windows hosts.
  2. Run the installer.  You’ll see something like the screen below.  I accepted all the defaults except I don’t like shortcuts on my desktop, so I disabled that (on the next screen).  Also, I got a warning that I would be temporarily disconnected from my network as part of the installation process.Virtual Box Installer
  3. Wait for installation to complete.  If you are prompted to install devices, go ahead and install them.  Installation took 10-20 seconds for me.

Create a virtual machine to run NixOS

Now that we have VirtualBox installed, we need to create a virtual machine that will run our NixOS distribution.

  1. Start your newly installed VirtualBox software.  When you start it up, you’ll be at the VirtualBox Manager window.  From this window, you can create and manage multiple virtual machines that all run inside the host computer.  We only need to create one, though.  Click the blue New button.
  2. Now we’re at the Create Virtual Machine Wizard, which looks something like the window below.  Your selections will be similar to mine but might need to be different based on your computer architecture.  I have a 64 bit machine, so I chose Other Linux (64-bit).  You can also use whatever Name you like.  I happen to know I will be using NixOS 14.04.Create VM
  3. Next you will choose the amount of RAM for the VM.  This is the amount of RAM your VM reserves for its own use while you are running it.  My machine has 8 GB total, so I allocated 4 GB (4096 MB) to my VM because I never plan to run it at the same time as another RAM-hungry process.VM Ram Size
  4. At the next screen, you are prompted to create a virtual hard drive.  Choose to create a new drive now and choose the VDI format on the next screen.  After that, choose “Dynamically Allocated,” which allows your VM to take up hard drive space as it needs it instead of reserving it all up front.  Lastly, choose the size of your new virtual drive.  The default setting for me is 8 GB, which sounds sufficient for small development box.  Besides, if we run low on space, we can increase the size later.VM Hard Drive Size
  5. After that, your VM is created!  You can now click on the orange Settings gear to explore different ways to configure your VM.  I plan to run with the defaults until I decide I need more processing power or otherwise need to change the settings. The only thing I changed was under General ? Advanced where I changed Shared Clipboard and Drag’n’Drop to both be bidirectional.

And that’s it! Don’t bother starting the VM yet, though.  There’s no point until we install the NixOS operating system onto it.  We’ll cover that in Part 2.