Reviving an Old iMac with NixOS

People have been using computers for decades. Information technology advances by leaps and bounds. As a result, yesterday’s new, powerful machines quickly become today’s obsolete hardware, gathering dust on shelves and in closets.

However, these old computers can still be useful for low-resource tasks, such as working with documents, surfing the web, and watching videos. In general, the obsolete hardware is supported by very old software — operating systems and applications — which is vulnerable and unsafe to use. New software cannot be installed or runs too slowly due to a slow CPU and a lack of memory and disk space.

I personally have two examples of such obsolete computers: an Acer Extensa 5220 laptop and an 18-year-old iMac. The iMac has a large display, and it is a shame that I cannot use it safely since its hardware is supported by the very old MacOS Lion. I tried to install several lightweight Linux distributions on it but failed because of:

  1. It was not easy to get the Wi-Fi card to work properly.
  2. The software was not responsive.

That is why I decided to experiment with NixOS on my old computers, since I know that NixOS allows fine-tuning of the operating system and other software.

Goals

  1. Get the old computer working.
  2. Use modern and secure software with available security and feature updates.
  3. Ensure a pleasant and responsive user experience.

Breathing new life into the old iMac

Generally, the following steps are suitable for any low-spec computer. However, we will focus more on the iMac, as it is a bit more challenging and requires more effort.

We have an iMac made in 2007:

  • CPU: Core2 Duo 2.4Ghz
  • RAM: 2GB
  • SSD: 120GB (upgraded some time ago from HDD)
  • Wi-Fi, Bluetooth

Problems we have to solve:

  1. First of all, we need to remove the thick layer of dust that has collected on it.

  2. The computer’s hardware is very limited, so we cannot use the graphical installer.

Furthermore, Apple computers have a Broadcom Wi-Fi card that requires a proprietary driver, which is not included in the default NixOS installation image. Of course, it’s possible to connect to the network using an Ethernet cable or tethering, but I don’t have a suitable cable and don’t want to use my mobile data.

That is why we are going to create a custom minimal ISO image with Broadcom Wi-Fi support to be able to install NixOS conveniently.

  1. We are going to create a NixOS configuration that is sufficient to meet the requirements of Goal 3.

Creating custom minimal installation image

Note: This step is required only for Apple computers and should be skiped for all other hardware. Simply download the minimal installation image from the NixOS website.

Prerequisites: Nix should be installed on the computer which you are going to use for creating the installation image.

Create a working directory, say custom-nixos-iso.

Creating image with nix flakes

Create flake.nix file with the following content:

{
  description = "Custom NixOS ISO with Broadcom";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";

  outputs = { self, nixpkgs }:
    let
      system = "x86_64-linux";
    in {
      nixosConfigurations.install-iso = nixpkgs.lib.nixosSystem {
        inherit system;
        modules = [
          ({ config, pkgs, ... }: {
            imports = [
              "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
            ];
            hardware.enableRedistributableFirmware = true;
            # boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
            boot.kernelModules = [ "b43" ];
            boot.blacklistedKernelModules = [ "wl" ];
            networking.enableB43Firmware = true;
          })
        ];
      };
    };
}

After that run in the working directory the following command:

nix build .#nixosConfigurations.install-iso.config.system.build.isoImage

The image will be placed in the result directory.

Creating image without flakes

If you don’t want to use flake you can create installation image with ordinary nix. Create iso.nix file with the following content:

{ config, pkgs, ... }:

{
  imports = [
    <nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix>
    <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
  ];

  hardware.enableRedistributableFirmware = true;
  boot.kernelModules = [ "b43" ];
  networking.enableB43Firmware = true;
  # boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
  boot.blacklistedKernelModules = [ "wl" ];
}

Run in the working directory:

nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage -I nixpkgs=channel:nixos-25.05 -I nixos-config=iso.nix

Notes on selecting Wi-Fi drivers

Actually, there are only two options:

  1. The original proprietary driver, broadcom_sta, which provides the kernel module wl.

  2. The free driver b43, which requires redistributable proprietary firmware.

The best driver is the one that works for you. My experience shows that both can get the Wi-Fi card working. However, broadcom_sta is vulnerable and, in my case, it does not work correctly and creates an incorrect ARP configuration. This means that although the Wi-Fi card obtains an IP address, it does not have access to the gateway. That is why I have enabled b43 in my Nix configurations.

If you want to try broadcom_sta, you need to:

  • Uncomment the line that enables this driver
  • Activate the kernel module wl.
  • Disable the B43Firmware option.
  • Blacklist the b43 kernel module.

Write the image to a USB stick

You can use any suitable software for this. However, note that Ventoy should not be used for installing NixOS on Apple computers.

Booting from the USB stick

When booting your old computer, you must select the USB stick as the boot device. On Apple computers, this is done by pressing the Option key immediately after powering it on.

Setting up the Internet connection

Before you start installation you should make sure that you have working Internet connection.

First, run command

ip link

and check if you can see your Wi-Fi card in the output. In my case, it’s the wlan0 interface. If you don’t see a Wi-Fi card, it means the driver does not support your hardware. Make sure the driver is loaded (lsmod) and try setting up an alternative driver when creating the installation image.

If Wi-Fi driver works and recognizes your hardware, configure and run your Wi-Fi connection.

wpa_passphrase YOUR_SSID > wpa.conf
sudo wpa_supplicant -B -i wlan0 -c wpa.conf

Please adjust values for your Wi-Fi network SSID and network interface name to match your setup.

Normally, the dhcpcd daemon is running after boot, so you should get a working Internet connection shortly. If not, make sure you have entered correct values for the SSID and password. To check your connection run the following commands:

ip addr # check that you got an IP address
ping 8.8.8.8 # check if the Internet is accessible

Installing NixOS

Create and mount disk partitions

Notes:

  1. This guide assumes your disk has no existing partitions. If it does, ensure you have backed up any important data and remove all partitions before proceeding.
  2. In all following commands, replace sdX with your actual device name (e.g., sda, nvme0n1). You can use the lsblk command to list all available block devices.
  3. You are free to partition the disk according to your needs. However, the layout below is a rather optimal setup for an older computer with limited disk space.
  4. The size of the swap partition should correspond to the amount of RAM in your system. In this guide, we will create a swap partition equal to system’s memory size.

To remove existing partitions use the following commands:

sudo parted /dev/sdX -- print # prints existing partitions
sudo parted /dev/sdX -- rm n # remove partition with number n

Create new partitions:

# Create partition table GPT
sudo parted /dev/sdX -- mklabel gpt 

# Create boot partition
sudo parted /dev/sdX -- mkpart ESP fat32 1Mib 512Mib
sudo parted /dev/sdX -- set 1 esp on

# Create swap partition (size 2048 MiB)
sudo parted /dev/sdX -- mkpart primary linux-swap 512MiB 2560MiB

# Create root partition
sudo parted /dev/sdX -- mkpart primary ext4 2560MiB 100%

Format new partitions:

sudo mkfs.fat -F 32 -n boot /dev/sdX1
sudo mkswap -L swap /dev/sdX2
sudo mkfs.ext4 -L nixos /dev/sdX3

Mount partitions:

sudo mount /dev/disk/by-label/nixos /mnt

sudo mkdir -p /mnt/boot
sudo mount /dev/disk/by-label/boot /mnt/boot

sudo swapon /dev/disk/by-label/swap

Create NixOS configuration

sudo nixos-generate-config --root /mnt

After that open /mnt/etc/nixos/hardware-configuration.nix

sudo -e /mnt/etc/nixos/hardware-configuration.nix

If you use b43 Wi-Fi driver then make sure that broadcom_sta is not set up.

Add noatime option to root file system configuration.

Replace the entire contents of /mnt/etc/nixos/configuration.nix with the following configuration. Adjust it according to your needs.

# This configuration.nix file is optimized for an old (2007) iMac.
# It can be adapted for any old computer with weak hardware.
# To do this, you just need to configure it for your specific hardware:
# Wi-Fi card, video driver, printer, etc. Along with that, you may
# choose your preferences for locale, basic system software, themes, etc.
{ config, lib, pkgs, ... }:

{
  imports = [ ./hardware-configuration.nix ];

  hardware = {
    # Wi-Fi card and Bluetooth on iMac require redistributable firmware
    enableRedistributableFirmware = true;
    # Enable harware graphics support
    graphics = {
      enable = true;
      enable32Bit = true;
    };
    # Enable Bluetooth support
    bluetooth = {
      enable = true;
      powerOnBoot = true;
      package = pkgs.bluez;
      settings = {
        General = {
          Experimental = true;
	        ControllerMode = "dual";
	        FastConnectable = true;
	      };
      };
    };
  };

  boot = {
    # Use EFI bootloader
    loader = {
      systemd-boot = {
        enable = true;
        configurationLimit = 5;
      };
      efi.canTouchEfiVariables = true;
    };
  };
  # Enable compressed RAM swap. Useful for low RAM systems
  zramSwap = {
    enable = true;
    # Allow utilizing 60% of RAM for compressed swap
    memoryPercent = 60;
  };
  # Configure networking
  networking = {
    # Use network manager
    networkmanager.enable = true;
    # Set desired host name
    hostName = "nixos";
    # Enable firmware to make Wi-Fi card working (in my case BCM4321)
    enableB43Firmware = true;
  };
  # Setup time zone and locale
  time.timeZone = "Europe/Moscow";
  i18n.defaultLocale = "ru_RU.UTF-8";
  # Configure services
  services = {
    # GUI
    xserver = {
      # Enable X server
      enable = true;
      # Setup video driver. Old iMac has Radeon graphics card
      videoDrivers = [ "radeon" ];
      # Configure lightweight display manager
      displayManager = {
        lightdm = {
	        enable = true;
          greeters.gtk.enable = true;
	      };
        # The following commands are to configure a good-looking default GUI
        # theme. The script does not change the user settings made manually.
        sessionCommands = ''
          set_default() {
            local ch="$1" key="$2" val="$3" type="$4"
            if ! xfconf-query -c "$ch" -p "$key" >/dev/null 2>&1; then
              xfconf-query -c "$ch" -p "$key" -s "$val" --create -t "$type"
            fi
          }

          set_default xsettings /Net/ThemeName "Arc-Dark" string
          set_default xsettings /Net/IconThemeName "Papirus-Dark" string
          set_default xsettings /Gtk/CursorThemeName "Bibata-Modern-Classic" string
          set_default xsettings /Gtk/CursorThemeSize "24" int
          set_default xfwm4 /general/theme "Arc-Dark" string
          set_default xsettings /Gtk/FontName "Inter 10" string
        '';
      };
      # Setting XFCE as a desktop manager. It is rather lightweight but
      # feature-reach
      desktopManager.xfce.enable = true;
      # Configure multi language support. This section could be omitted because
      # XFCE supports configuring keyboard layout switching.
      xkb = {
        layout = "us,ru";
        # Swithch keyboard layouts with CMD+Space like by default on Mac
        options = "grp:win_space_toggle";
      };
    };
    # Configure autologin for your user. Weak computers usually do not intended
    # to be used by several users. So this configuration can be useful. If you
    # want more than one user just omit this section.
    displayManager = {
      autoLogin = {
        enable = true;
        user = "your-user-name";
      };
    };
    # Configure multimedia support
    pipewire = {
      enable = true;
      # Enable alsa comatibility
      alsa.enable = true;
      # Enable pulse audio comatibility
      pulse.enable = true;

      wireplumber = {
        enable = true;
        # Configure audio support via Bluetooth
	      extraConfig = {
          "50-bluez" = {
            monitor.bluez.properties = {
              bluez5 = {
	              enable-msbc = true;
                enable-sbc-xq = true;
		            enable-hw-volume = true;
		            roles = [ "a2dp_sink" "a2dp_source" "hsp_hs" "hfp_hf" ];
	            };
	          };
	        };
	      };
      };
    };
    # Enable power management
    tlp.enable = true;
    # Enable daemon for temperature monitoring
    thermald.enable = true;
    # Enable SSH.
    openssh.enable = true;
    # Configure printing
    printing = {
      enable = true;
      # Setup correct drivers. The following driver is for most Epson printers.
      drivers = [ pkgs.epson-escpr ];
    };

    avahi = {
      enable = true;
      nssmdns4 = true;
      openFirewall = true;
    };
    # Enable Bluetooth manager
    blueman.enable = true;
  };
  # Configure fonts
  fonts = {
    # Install most useful and popular fonts
    packages = with pkgs; [
      dejavu_fonts
      liberation_ttf
      noto-fonts noto-fonts-cjk-sans noto-fonts-emoji
      inter
      roboto roboto-mono
      jetbrains-mono
      fira-code
      font-awesome
      corefonts
    ];
    # Font settings
    fontconfig = {
      antialias = true;
      hinting.enable = true;
      hinting.style = "slight";
      subpixel.rgba = "rgb";
      subpixel.lcdfilter = "default";

      defaultFonts = {
        serif = [ "Noto Serif" "DejaVu Serif" "Liberation Serif" ];
        sansSerif = [ "Inter" "Noto Sans" "DejaVu Sans" "Liberation Sans" ];
        monospace = [ "JetBains Mono" "Fira Code" "DejaVu Sans Mono" "Roboto Mono" ];
        emoji = [ "Noto Color Emoji" ];
      };
    };
  };
  # By default XFCE installs thunar (file manager), but does not install
  # thunar-archive-plugin. Here we explicitly install thunar with plugins.
  # Having thunar-archive-plugin allows us cpmpress/decompress files from the
  # context menu.
  programs.thunar = {
    enable = true;
    plugins = with pkgs.xfce; [
      thunar-archive-plugin
      thunar-volman
    ];
  };
  # At the moment of creating this configuration file there is an issue with
  # thunar-archive-plugin: it does not work with xarchiver. The following hack
  # resolves the issue.
  nixpkgs.overlays = [
    (final: prev: {
      xfce= prev.xfce.overrideScope (_self: super: {
        thunar-archive-plugin = super.thunar-archive-plugin.overrideAttrs (old: {
	        postInstall = lib.concatStringsSep "\n" [
	          (old.postInstall or "")
            ''
              mkdir -p $out/libexec/thunar-archive-plugin
              cp -r ${prev.xarchiver}/libexec/thunar-archive-plugin/* \
                    $out/libexec/thunar-archive-plugin/ 2>/dev/null || true
            ''
          ];
	      });
      });
    })
  ];
  # Install system-wide packages
  environment = {
    # Do not install any package by default. We want full control of packages
    # configuration
    defaultPackages = [];
    # We install only the following minimum of packages. Other packages user can
    # install in their profile.
    systemPackages = with pkgs; [
      htop ncdu iotop lm_sensors pciutils usbutils # System utilities
      xfce.xfce4-terminal # Graphical terminal
      xfce.xfce4-xkb-plugin # plugin to display keyboard layout variant in status bar
      rofi # An utility for applications quick start and other useful features
      system-config-printer # GUI utility for printer settings
      arc-theme papirus-icon-theme bibata-cursors # Themes for XFCE
      zathura # Document viewer
      mpv # Media player
      feh # Image viewer
      micro # Tiny simple text editor used as default editor
      neovim # Text editor for advanced users
      xarchiver zip unzip p7zip xz zstd bzip2 gzip unrar # Archiver utilities
      firefox # Web browser
    ];
    # Set some environment variables
    variables = {
      # Default editor
      EDITOR = "micro";
      # Hope QT applications will look better in XFCE
      QT_QPA_PLATFORMTHEME = "gtk3";
    };
  };
  # Nix configuration
  nix = {
    # Configure garbage collection
    gc = {
      automatic = true;
      dates = "weekly";
      options = "--delete-older-than 7d";
    };
    # Additional useful settings
    settings = {
      auto-optimise-store = true;
      experimental-features = [ "nix-command" "flakes" ];
    };
  };
  # Allow proprietary software
  nixpkgs.config.allowUnfree = true;
  # Users configuration
  users.users.your-user-name = {
    isNormalUser = true;
    extraGroups = [
      "wheel" # Enables sudo for user
      "networkmanager" # Enable Wi-Fi connections for user
    ];
  };
  # Enable sudo
  security.sudo.enable = true;

  system.stateVersion = "25.05";
}

Install the system

sudo nixos-install

After the installation process finishes, reboot the system and enjoy. Of course, you can fine-tune the system now as you like.

Banner that links to Serokell Shop. You can buy stylish FP T-shirts there!
More from Serokell
Practical Nix Flakes postPractical Nix Flakes post
Nix development tool thumbnailNix development tool thumbnail
CI/CD/CT with Nix programming languageCI/CD/CT with Nix programming language