I recently moved, and my new place has a relatively small footprint. (Yes, I moved during the COVID-19 pandemic. And yes, it was crazy.) I quickly realized that was going to need a wireless router of some sort, or more formally, a wireless access point (WAP). Using my Ubuntu laptop’s “wireless hotspot” capability was a nice temporary solution, but it had a few serious drawbacks.

Drawbacks of hotspotting with a laptop

  • The wireless internet goes out whenever I would travel with the laptop,
  • The laptop had to be close to the modem, so that it could be plugged into ethernet, making my laptop not even portable within the apartment,
  • The SSID was my laptop’s hostname,
  • The WPA password would be set to a random string whenever the hotspot was started, and so
  • Whenever I moved my laptop I would also need to reset the credentials on all of my wireless devices!

Additionally, some of my coworkers are Nix true believers. While I had read the NixOS docs, I had never actually taken it for a spin. Consider this my first few steps down the /etc/nixos path, because, while I lacked a WiFi router, I did have an errant Raspberry Pi 3B+ lying around…

Too Long; Didn’t Read

Be sure to fill out the SSID and WPA passphrase in the file below.

/etc/nixos/configuration.nix

{ 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;

  ## use an older kernel, so that we can actually boot
  boot.kernelPackages = pkgs.linuxPackages_4_19;

  ## 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";
    };
  };

  ## Recommended swap file is optional
  swapDevices = [ { device = "/swapfile"; size = 1024; } ];

  ## packages
  environment.systemPackages = with pkgs; [ hostapd dnsmasq bridge-utils ];

  ## add wireless service
  hardware.enableRedistributableFirmware = true;
  networking.wireless.enable = true;

  ## set up wireless access point
  networking.networkmanager.unmanaged = [ "interface-name:wlan*" ]
    ++ lib.optional config.services.hostapd.enable "interface-name:${config.services.hostapd.interface}";
  services.hostapd = {
    enable = true;
    interface = "wlan0";
    hwMode = "g";
    ssid = "<YOUR NETWORK NAME HERE>";
    wpaPassphrase = "<YOUR PASSWORD HERE>";
  };

  ## set up wireless static IP address
  networking.interfaces.wlan0.ip4 = lib.mkOverride 0 [ ];
  networking.interfaces.wlan0.ipv4.addresses =
    lib.optionals config.services.hostapd.enable [{ address = "192.168.0.1"; prefixLength = 24; }];

  ## set up wireless DNS
  services.dnsmasq = lib.optionalAttrs config.services.hostapd.enable {
    enable = true;
    extraConfig = ''
      interface=wlan0
      bind-interfaces
      dhcp-range=192.168.0.10,192.168.0.254,24h
    '';
  };
  networking.firewall.allowedUDPPorts = lib.optionals config.services.hostapd.enable [53 67];
  services.haveged.enable = config.services.hostapd.enable;

  ## Finally, bridge ethernet and wifi
  networking.bridges.br0.interfaces = [ "eth0" "wlan0" ];
}

#nixos #raspberry pi #wireless router #python

2.65 GEEK