Setting Up Wireless Networking with NixOS

Posted by Craige McWhirter on

NixOS Gears by Craige McWhirter

The current NixOS Manual is a little sparse on details for different options to configure wireless networking. The version in master is a little better but still ambiguous. I've made a pull request to resolve this but in the interim, this documents how to configure a number of wireless scenarios with NixOS.

If you're going to use NetworkManager, this is not for you. This is for those of us who want reproducible configurations.

To enable a wireless connection with no spaces or special characters in the name that uses a pre-shared key, you first need to generate the raw PSK:

$ wpa_passphrase exampleSSID abcd1234
network={
        ssid="exampleSSID"
        #psk="abcd1234"
        psk=46c25aa68ccb90945621c1f1adbe93683f884f5f31c6e2d524eb6b446642762d
}

Now you can add the following stanza to your configuration.nix to enable wireless networking and this specific wireless connection:

networking.wireless = {
  enable = true;
  userControlled.enable = true;
  networks = {
    exampleSSID = {
      pskRaw = "46c25aa68ccb90945621c1f1adbe93683f884f5f31c6e2d524eb6b446642762d";
    };
  };
};

If you had another WiFi connection that had spaces and/or special characters in the name, you would configure it like this:

networking.wireless = {
  enable = true;
  userControlled.enable = true;
  networks = {
    "example's SSID" = {
      pskRaw = "46c25aa68ccb90945621c1f1adbe93683f884f5f31c6e2d524eb6b446642762d";
    };
  };
};

The final scenario that I have, is connecting to open SSIDs that have some kind of secondary method (like a login in web page) for authentication of connections:

networking.wireless = {
  enable = true;
  userControlled.enable = true;
  networks = {
    FreeWiFi = {};
  };
};

This is all fairly straight forward but was non-trivial to find the answers too.

Generating an sha256 Hash for Nix Packages

Posted by Craige McWhirter on

NixOS Gears by Craige McWhirter

Let's say that you're working to replicate the PureOS environment for the Librem 5 phone so that you can run NixOS on it instead and need to package calls. Perhaps you just want to use Nix to package something else that isn't packaged yet.

When you start digging into Nix packaging, you'll start to see stanzas like this one:

src = fetchFromGitLab {
  domain = "source.puri.sm";
  owner = "Librem5";
  repo = pname;
  rev = "v${version}";
  sha256 = "1702hbdqhfpgw0c4vj2ag08vgl83byiryrbngbq11b9azmj3jhzs";
};

It's fairly self explanatory and merely a breakdown of a URL into it's component parts so that they can be reused elsewhere in the packaging system. It was the generation of the sha256 hash that stumped me the most.

I'd not been able to guess how it was generated. I was not able to find clear instructions in the otherwise pretty thorough Nix documentation.

Putting clues together from a variety of other blog posts, this is how I eventually came to generate the correct sha256 hash for Nix packages:

Using the above hash for libhandy, I was able to test the method I'd come up with, using nix-prefetch-url to download the tagged version and provide an sha256 hash which I could compare to one in the existing libhandy default.nix file:

$ nix-prefetch-url --unpack https://source.puri.sm/Librem5/libhandy/-/archive/v0.0.10/libhandy-v0.0.10.tar.gz
unpacking...
[0.3 MiB DL]
path is
'/nix/store/58i61w34hx06gcdaf1x0gwi081qk54km-libhandy-v0.0.10.tar.gz'
1702hbdqhfpgw0c4vj2ag08vgl83byiryrbngbq11b9azmj3jhzs

Low and behold, I have matching sha256 hashes. As I'm wanting to create a package for "calls", I now safely do the same against it's repository on the way to crafting a Nix file for that:

$ nix-prefetch-url --unpack https://source.puri.sm/Librem5/calls/-/archive/v0.0.1/calls-v0.0.1.tar.gz
unpacking...
[0.1 MiB DL]
path is '/nix/store/3c7aifgmf90d7s60ph5lla2qp4kzarb8-calls-v0.0.1.tar.gz'
0qjgajrq3kbml3zrwwzl23jbj6y62ccjakp667jq57jbs8af77pq

That sha256 hash is what I'll drop into my nix file for "calls":

src = fetchFromGitLab {
  domain = "source.puri.sm";
  owner = "Librem5";
  repo = pname;
  rev = "v${version}";
  sha256 =
  0qjgajrq3kbml3zrwwzl23jbj6y62ccjakp667jq57jbs8af77pq";
};

Now we have an sha256 hash that can be used by Nix to verify source downloads before building.

Installing NixOS on a Headless Raspberry Pi 3

Posted by Craige McWhirter on

NixOS Raspberry Pi Gears by Craige McWhirter

This represents the first step in being able to build ready-to-run NixOS images for headless Raspberry Pi 3 devices. Aarch64 images for NixOS need to be built natively on aarch64 hardware so the first Pi 3, the subject of this post, will need a keyboard and mouse attached for two commands.

A fair chunk of this post is collated from NixOS on ARM and NixOS on ARM/Raspberry Pi into a coherent, flowing process with additional steps related to the goal of this being a headless Raspberry Pi 3.

Head to Hydra job nixos:release-19.03:nixos.sd_image.aarch64-linux and download the latest successful build. ie:

 $ wget https://hydra.nixos.org/build/95346103/download/1/nixos-sd-image-19.03.172980.d5a3e5f476b-aarch64-linux.img

You will then need to write this to your SD Card:

# dd if=nixos-sd-image-19.03.172980.d5a3e5f476b-aarch64-linux.img of=/dev/sdX status=progress

Make sure you replace "/dev/sdX" with the correct location of your SD card.

Once the SD card has been written, attach the keyboard and screen, insert the SD card into the Pi and boot it up.

When the boot process has been completed, you will be thrown to a root prompt where you need to set a password for root and start the ssh service:

[root@pi-tri:~]#
[root@pi-tri:~]# passwd
New password:
Retype new password:
passwd: password updated successfully

[root@pi-tri:~]# systemctl start sshd

You can now complete the rest of this process from the comfort of whereever you normally work.

After successfully ssh-ing in and examining your disk layout with lsblk, the first step is to remove the undersized, FAT32 /boot partition:

# fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2178694e

Device         Boot  Start      End  Sectors  Size Id Type
/dev/mmcblk0p1 *     16384   262143   245760  120M  b W95 FAT32
/dev/mmcblk0p2      262144 15522439 15260296  7.3G 83 Linux


# echo -e 'a\n1\na\n2\nw' | fdisk /dev/mmcblk0

Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): Partition number (1,2, default 2):
The bootable flag on partition 1 is disabled now.

Command (m for help): Partition number (1,2, default 2):
The bootable flag on partition 2 is enabled now.

Command (m for help): The partition table has been altered.
Syncing disks.

# fdisk -l /dev/mmcblk0
Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x2178694e

Device         Boot  Start      End  Sectors  Size Id Type
/dev/mmcblk0p1       16384   262143   245760  120M  b W95 FAT32
/dev/mmcblk0p2 *    262144 15522439 15260296  7.3G 83 Linux

Next we need to configure NixOS to boot the basic system we need with ssh enabled, root and a single user and disks configured correctly. I have this example file which at the time of writing looked like this:

# This is an example of a basic NixOS configuration file for a Raspberry Pi 3.
# It's best used as your first configuration.nix file and provides ssh, root
# and user accounts as well as Pi 3 specific tweaks.

{ config, pkgs, lib, ... }:

{
  # NixOS wants to enable GRUB by default
  boot.loader.grub.enable = false;
  # Enables the generation of /boot/extlinux/extlinux.conf
  boot.loader.generic-extlinux-compatible.enable = true;

  # For a Raspberry Pi 2 or 3):
  boot.kernelPackages = pkgs.linuxPackages_latest;

  # !!! Needed for the virtual console to work on the RPi 3, as the default of 16M doesn't seem to be enough.
  # If X.org behaves weirdly (I only saw the cursor) then try increasing this to 256M.
  boot.kernelParams = ["cma=32M"];

  # File systems configuration for using the installer's partition layout
  fileSystems = {
    "/" = {
      device = "/dev/disk/by-label/NIXOS_SD";
      fsType = "ext4";
    };
  };

  # !!! Adding a swap file is optional, but strongly recommended!
  swapDevices = [ { device = "/swapfile"; size = 1024; } ];

  hardware.enableRedistributableFirmware = true; # Enable support for Pi firmware blobs

  networking.hostName = "nixosPi";     # Define your hostname.
  networking.wireless.enable = false;  # Toggles wireless support via wpa_supplicant.

  # Select internationalisation properties.
  i18n = {
    consoleFont = "Lat2-Terminus16";
    consoleKeyMap = "us";
    defaultLocale = "en_AU.UTF-8";
  };

  time.timeZone = "Australia/Brisbane"; # Set your preferred timezone:

  # List services that you want to enable:
  services.openssh.enable = true;  # Enable the OpenSSH daemon.

  # Configure users for your Pi:
   users.mutableUsers = false;     # Remove any users not defined in here

  users.users.root = {
    hashedPassword = "$6$eeqJLxwQzMP4l$GTUALgbCfaqR8ut9kQOOG8uXOuqhtIsIUSP.4ncVaIs5PNlxdvAvV.krfutHafrxNN7KzaM7uksr6bXP5X0Sx1";
    openssh.authorizedKeys.keys = [
      "ssh-ed25519 Voohu4vei4dayohm3eeHeecheifahxeetauR4geigh9eTheey3eedae4ais7pei4ruv4 me@myhost"
    ];
  };

  # Groups to add
  users.groups.myusername.gid = 1000;

  # Define a user account.
  users.users.myusername = {
    isNormalUser = true;
    uid = 1000;
    group = "myusername";
    extraGroups = ["wheel" ];
    hashedPassword = "$6$l2I7i6YqMpeviVy$u84FSHGvZlDCfR8qfrgaP.n7/hkfGpuiSaOY3ziamwXXHkccrOr8Md4V5G2M1KcMJQmX5qP7KOryGAxAtc5T60";
    openssh.authorizedKeys.keys = [
      "ssh-ed25519 Voohu4vei4dayohm3eeHeecheifahxeetauR4geigh9eTheey3eedae4ais7pei4ruv4 me@myhost"
    ];
  };

  # This value determines the NixOS release with which your system is to be
  # compatible, in order to avoid breaking some software such as database
  # servers. You should change this only after NixOS release notes say you
  # should.
  system.stateVersion = "19.03"; # Did you read the comment?
  system.autoUpgrade.enable = true;
  system.autoUpgrade.channel = https://nixos.org/channels/nixos-19.03;
}

Once this is copied into place, you only need to rebuild NixOS using it by running:

# nixos-rebuild switch

Now you should have headless Pi 3 which you can use to build CD card images for other Pi 3's that are fully configured and ready to run.

Booting a NixOS aarch64 Image in Qemu

Posted by Craige McWhirter on

NixOS Gears by Craige McWhirter

To boot a NixOS aarch64 image in qemu, in this example, a Raspberry Pi3 (B), you can use the following command:

 qemu-system-aarch64 -M raspi3 -drive format=raw,file=NIXOS.IMG \
 -kernel ./u-boot-rpi3.bin -serial stdio -d in_asm -m 1024

You will need to replace NIXOS.IMG with the name of the image file you downloaded ie: nixos-sd-image-18.09.2568.1e9e709953e-aarch64-linux.img

You will also need to mount the image file and copy out u-boot-rpi3.bin for the -kernel option.

Installing an xmonad Environment on NixOS

Posted by Craige McWhirter on

NixOS Coin by Craige McWhirter

Xmonad is a very fast, reliable and flexible window manager for Linux and other related operating systems. As I recently shifted from Debian + Propellor to NixOS + NixOps, I now needed to redefine my Xmonad requirements for the new platform.

TL;DR

  • Grab my xmonad.nix file and import it in your /etc/nixos/configuration.nix
  • You can also grab my related xmonad.hs, xmobarrc and session files to use the complete setup.

An Example

At the time of writing, I used the below xmonad.nix to install my requirements. My current version can be found here.

# Configuration for my xmonad desktop requirements

{ config, pkgs, ... }:

{

  services.xserver.enable = true;                        # Enable the X11 windowing system.
  services.xserver.layout = "us";                        # Set your preferred keyboard layout.
  services.xserver.desktopManager.default = "none";      # Unset the default desktop manager.
  services.xserver.windowManager = {                     # Open configuration for the window manager.
    xmonad.enable = true;                                # Enable xmonad.
    xmonad.enableContribAndExtras = true;                # Enable xmonad contrib and extras.
    xmonad.extraPackages = hpkgs: [                      # Open configuration for additional Haskell packages.
      hpkgs.xmonad-contrib                               # Install xmonad-contrib.
      hpkgs.xmonad-extras                                # Install xmonad-extras.
      hpkgs.xmonad                                       # Install xmonad itself.
    ];
    default = "xmonad";                                  # Set xmonad as the default window manager.
  };

  services.xserver.desktopManager.xterm.enable = false;  # Disable NixOS default desktop manager.

  services.xserver.libinput.enable = true;               # Enable touchpad support.

  services.udisks2.enable = true;                        # Enable udisks2.
  services.devmon.enable = true;                         # Enable external device automounting.

  services.xserver.displayManager.sddm.enable = true;    # Enable the default NixOS display manager.
  services.xserver.desktopManager.plasma5.enable = true; # Enable KDE, the default NixOS desktop environment.

  # Install any additional fonts that I require to be used with xmonad
  fonts.fonts = with pkgs; [
    opensans-ttf             # Used in in my xmobar configuration
  ];

  # Install other packages that I require to be used with xmonad.
  environment.systemPackages = with pkgs; [
    dmenu                    # A menu for use with xmonad
    feh                      # A light-weight image viewer to set backgrounds
    haskellPackages.libmpd   # Shows MPD status in xmobar
    haskellPackages.xmobar   # A Minimalistic Text Based Status Bar
    libnotify                # Notification client for my Xmonad setup
    lxqt.lxqt-notificationd  # The notify daemon itself
    mpc_cli                  # CLI for MPD, called from xmonad
    scrot                    # CLI screen capture utility
    trayer                   # A system tray for use with xmonad
    xbrightness              # X11 brigthness and gamma software control
    xcompmgr                 # X composting manager
    xorg.xrandr              # CLI to X11 RandR extension
    xscreensaver             # My preferred screensaver
    xsettingsd               # A lightweight desktop settings server
  ];

}

This provides my xmonad environment with everything I need for xmonad to run as configured.

Secure Data in Public Configuration Management With Propellor

Posted by Craige McWhirter on

Steampunk propeller ring by Daniel Proulx

TL;DR

List fields and contexts:

$ propellor --list-fields

Set a field for a particular context:

$ propellor --set 'SshAuthorizedKeys "myuser"' yourServers < authKeys

Dump a field from a specific context:

$ propellor --dump 'SshAuthorizedKeys "myuser"' yourServers

An Example

When using Propellor for configuration management, you can utilise GPG encryption to encrypt data sets. This enables you to leverage public git repositories for your centralised configuration management needs.

To list existing fields, you can run:

$ propellor --list-fields

which will not only list existing fields but will helpfully also list fields that would be used if set:

Missing data that would be used if set:
Field                             Context          Used by
-----                             -------          -------
'Password "myuser"'               'yourDesktops'   your.host.name
'CryptPassword "myuser"'          'yourServers'    your.server.name
'PrivFile "/etc/mail/dkim.key"'   'mailServers'    your.mail.server

You can set these fields with input from either STDIN or files prepared earlier.

For example, if you have public SSH keys you wish to distribute, you can place then into a file then use that file to populate the fields of an appropriate context. The contents of an example authorized_keys, we'll call authKeys, may look like this:

ssh-ed25519 eetohm9doJ4ta2Joo~P2geetoh6aBah9efu4ta5ievoongah5feih2eY4fie9xa1ughi you@host1
ssh-ed25519 choi7moogh<i2Jie6uejoo6ANoMei;th2ahm^aiR(e5Gohgh5Du-oqu1roh6Mie4shie you@host2
ssh-ed25519 baewah%vooPho2Huofaicahnob=i^ph;o1Meod:eugohtiuGeecho2eiwi.a7cuJain6 you@host3

To add these keys to the appropriate users for the hosts of a particular context you could run:

$ propellor --set 'SshAuthorizedKeys "myuser"' yourServers < authKeys

To verify that the fields for this context have the correct data, you can dump it:

$ propellor --dump 'SshAuthorizedKeys "myuser"' yourServers
gpg: encrypted with 256-bit ECDH key, ID 5F4CEXB7GU3AHT1E, created 2019-03-08
      "My User <myuser@my.domain.tld>"
      ssh-ed25519 eetohm9doJ4ta2Joo~P2geetoh6aBah9efu4ta5ievoongah5feih2eY4fie9xa1ughi you@host1
      ssh-ed25519 choi7moogh<i2Jie6uejoo6ANoMei;th2ahm^aiR(e5Gohgh5Du-oqu1roh6Mie4shie you@host2
      ssh-ed25519 baewah%vooPho2Huofaicahnob=i^ph;o1Meod:eugohtiuGeecho2eiwi.a7cuJain6 you@host3

When you next spin Propellor for the desired hosts, those SSH public keys with be installed into the authorized_keys_ filefor the user myuser for hosts that belong to the allServers context.

Setting and Storing Passwords

One of the most obvious and practical uses of this feature is to set secure data that needs to be distributed, such as passwords or certificates. We'll use passwords for this example.

Create a hash of the password you wish to distribute:

$ mkpasswd -m sha-512 > /tmp/deleteme
Password:
$ cat /tmp/deleteme
$6$cyxX.TmGPZWuqQu$LxhbVBaUnFmevOVi1V1NApZA0TCcSkK1241eiZwhhBQTm/PpjoLHe3OMnbjeswa6rgzNAq3pXTB4KjvfF1iXA1

Now that we have that file, we can use it as input for Propellor:

$ propellor --set 'CryptPassword "myuser"' yourServers < /tmp/deleteme
Enter private data on stdin; ctrl-D when done:
gpg: encrypted with 256-bit ECDH key, ID 5F4CEXB7GU3AHT1E, created 2019-03-08
      "My User <myuser@my.domain.tld>"
gpg: WARNING: standard input reopened
Private data set.

Tidy up:

$ rm /tmp/deletem

You're now ready to deploy that password for that user to those servers.

Propagating Native Plants

Posted by Craige McWhirter on

by Alec M. Blomberry & Betty Maloney

Propagating Australian Plants

I have over 1,000 Diospyrus Geminata (scaly ebony) seedlings growing in my shade house (in used toilet rolls). I'd collected the seeds from the (delicious) fruit in late 2017 (they appear to fruit based on rainfall - no fruit in 2018) and they're all still rather small.

All the literature stated that they were slow growing. I may have been more dismissive of this than I needed to be.

I'm growing these for landscape scale planting, it's going to be a while between gathering the seeds (mid 2017) and planting the trees (maybe mid 2019).

So I needed to look into other forms of propagation and either cutting or aerial layering appear to be the way to go, as I already have large numbers of of mature Diospyros Geminata on our property or nearby.

The catch being that I know nothing of either cutting or aerial layering and in particular I want to do this at a reasonable scale (ie: possibly thousands).

So this is where Propagating Australian Plants comes in.

Aerial Layering

It's a fairly dry and academic read, that feels like it may be more of an introductory guide for botanic students than a lay person such as myself.

Despite being last published in 1994 by a publisher that no longer exists and having a distinct antique feel to it, the information within is crisp and concise with clear and helpful illustrations.

Highly recommended if you're starting to propagate natives as I am.

Although I wish you luck picking up a copy - I got mine from an Op Shop. At least the National Library of Australia appears to have a copy.

New Dark Age: Technology and the End of the Future

Posted by Craige McWhirter on

by James Bridle

New Dark Age: Technology and the End of the Future

It may be my first book for 2019 but I'm going to put it out there, this is my must read book for 2109 already. Considering it was published in 2018 to broad acclaim, it may be a safe call.

tl;dr; Read this book. It's well resourced, thoroughly referenced, well thought out with the compiled information and lines drawn potentially redrawing the way you see our industry and the world. If you're already across the issues, the hard facts will still cause you to draw breath.

I read this book in bursts over 4 weeks. Each chapter packing it's own informative punch. The narrative first grabbed my attention on page 4 where the weakness of learning to code alone was fleshed out.

"Computational thinking is predominant in the world today, driving the worst trends in our societies and interactions, and must be opposed by real systemic literacy." page 4

Where it is argued that systemic literacy is much more important than learning to code - with a humorous but fitting plumbing analogy in the mix.

One of the recurring threads in the book is the titular "Dark New Age", with points being drawn back to the various actions present in modern society that are actively reducing our knowledge.

"And so we find ourselves today connected to vast repositories of knowledge, and yet we have not learned to think. In fact, the opposite is true: that which was intended to enlighten the world in practice darkens it. The abundance of information and the plurality of world-views now accessible to us through the Internet are not producing a coherent consensus reality, but one riven by fundamentalist insistence on simplistic narratives, conspiracy theories, and post-factual politics." page 10

Also covered are more well known instances of corporate and government censorship, the traps of the modern convenience technologies.

"When an ebook is purchased from an online service, it remains the property of the seller, it's loan subject to revocation at any time - as happened when Amazon remotely deleted thousands of copies of 1984 and Animal Farm from customers' Kindles in 2009. Streaming music and video services filter the media available by legal jurisdiction and algorithmically determine 'personal' preferences. Academic journals determine access to knowledge by institutional affiliation and financial contribution as physical, open-access libraries close down." page 39

It was the "Climate" chapter that packed the biggest punch for me, as an issue I considered myself rather well across over the last 30 years, it turns out there was a significant factor I'd missed. A hint that surprise was coming came in an interesting diversion into clear air turbulence.

"An advisory circular on preventing turbulence-related injuries, published by the US Federal Aviation Administration in 2006, states that the frequency of turbulence accidents has increased steadily for more than a decade, from 0.3 accidents per million flights in 1989 to 1.7 in 2003." page 68

The reason for this increase was laid at the feet of increased CO2 levels in the atmosphere by Paul Williams of the National Centre for Atmospheric Science and the implications were expounded upon in his paper Nature Climate Change (2013) thusly:

"...in winter, most clear air turbulence measures show a 10-40 per cent increase in the median strength...40-70 per cent increase in the frequency of occurrence of moderate or greater turbulence." page 69

The real punch in the guts came on page 73, where I first came across the concept of "Peak Knowledge" and how the climate change was playing it's defining role in that decline, where President of the American Meteorological Society William B Gail wonders if:

"we have already passed through 'peak knowledge", just as we may have already passed 'peak oil'." page 73

Wondering what that claim was based on, the next few paragraphs of information can be summarised in the following points:

  • From 1000 - 1750 CE CO2 was at 275-285 parts / million.
  • 295ppm by the start of the 20th century
  • 310ppm by 1950
  • 325ppm in 1970
  • 350ppm in 1988
  • 375ppm by 2004
  • 400ppm by 2015 - the first time in 800,000 years
  • 1,000ppm is projected to be passed by the end of this century.

"At 1,000ppm, human cognitive ability drops by 21%" page 74

Then a couple of bombshells:

"CO2 already reaches 500ppm in industrial cities"

"indoors in poorly ventilated schools, homes and workplaces it can regularly exceed 1,000ppm - substantial numbers of schools in California and Texas measured in 2012 breached 2,000ppm."

The implications of this are fairly obvious.

All this is by the end of chapter 3. It's a gritty, honest look at where we're at and where going. It's not pretty but as the old saying goes, to be forewarned is to be forearmed.

Do yourself a favour, read it.

Installing NixOS on an ASUS EeePC 701

Posted by Craige McWhirter on

Those of you familiar with the ASUS EeePC 701 will be aware of it's limited memory (512M) and small internal drive (4G) which doesn't render it useless but does reduce it's modern usage.

I have two of these still in perfect working order and wanted to extend their functional lives. I have no need of any more routers and there are Raspberry Pi's everywhere here. I do have kids though and decided these would make great, ready made portable retro gaming consoles.

This blog post details how I installed NixOS and configured the 701's to overcome their short comings to extend their life.

At a Glance

  1. Download the latest NixOS minimal installer for 32-bit Intel/AMD.
  2. Boot off USB
  3. Set forcepae in Grub
  4. Connect networking
  5. Partition then format the SD card as / and the internal drive as swap
  6. Run the configuration builder
  7. Copy across nix files
  8. Install
  9. Enjoy

Process Detail

Have a copy of the NixOS manual handy. It will also be at [ALT]+[F8] once the installer has booted.

Booting

  1. Download the minimal installation CD, 32-bit Intel/AMD image and burn it to a USB stick.
  2. Insert the SD card and USB stick into the 701 (I used a spare 8G SD card I had handy).
  3. Power the 701 on and press [ESC], select the USB stick as the boot device,
  4. [TAB] at grub menu, append forcepae
  5. Continue the boot process until it reaches a root prompt
  6. If you have not connected Ethernet, connect to WiFi using wpa_supplicant, as per manual.

Partitioning and Formatting

With only a little deviation from section 2.2.2. Legacy Boot (MBR) we format the SD card to be the root disk and the internal drive as swap:

  • Create an MBR on the internal drive:

    # parted /dev/sda -- mklabel msdos

  • Create the root partition on the SD card:

    # parted /dev/sdc -- mkpart primary 1MiB 100%

  • Create the swap partition on the internal drive:

    # parted /dev/sda -- mkpart primary linux-swap 1MiB 100%

As per section 2.2.3 Formatting we now format the drives appropriately.

  • Format and label the / partition:

    # mkfs.ext4 -L nixos /dev/sdc1

  • Format the swap partion:

    # mkswap -L swap /dev/sda1

Installation and Configuration:

Now you can just continue to follow section 2.3 Installing and configure the system as you desire. I initially use a bare bones install and it can be read here. It's worth taking a brief look at if you're new to NixOS.

The section worth copying is related to how the kernel uses memory on this old i386 system:

  nixpkgs.config = {
    packageOverrides = pkgs: {
      stdenv = pkgs.stdenv // {
        platform = pkgs.stdenv.platform // {
          kernelExtraConfig = ''
            HIGHMEM64G? n  # 32-bit proc with > 4G RAM
            HIGHMEM4G y # 32-bit # proc # with # =< # 4G # RAM
          '';
        };
      };
    };
  };

Do not copy my import of retro-gaming.nix, that's a for after a successful install and a future blog post.

Once you've completed the install, the EeePC 701 ought to reboot into NixOS successfully.

Happy New Workbench

Posted by Craige McWhirter on

For the summer solstice I got a brand new second hand stainless steel bench top. Which by coincidence turns out to be the answer to the question "What do you get the man who has everything", apparently.

Brand new second hand stainless steel bench top

Turning to my cliché handbook, it turns out that when life gives you bench tops, you make workbenches. I needed a second standing desk for out on the deck and for hardware hacking, so under the watchful eye of a pair of local King Parrots I gathered some spare timber to cobble together a standing workbench for the bench top.

Stainless steel workbench upside down

Stainless steel workbench bare

Stainless steel workbench stage 1

There's a lot more work to be done on that desk but with stage 1 at least completed, it was time to install it on the deck, ready to hack 2019 away :-D

Stainless steel workbench in place

Yes, that is the Australian Sun reaching in, in the background to kill us all.

The astute amongst you will have also noticed the (empty) Lagavulin and Talisker bottles propping up my laptop so they're both physically and metaphorically supporting my work.

Looks like I've already put my hand up for some hacks on Termonad to be the first piece of work completed from the new deck desk, apart from this post of course :-D

So now that leaves me with an inside and an outside standing desk as well as a hammock to work from. Not sure what says about me, I'll leave that up to you.