Rasperry PI 3 with official firmware and bootloader

Hi guys

I’m trying to set up a raspberry PI with NixOS using the official firmware and bootloader.
Most of the wiki examples and code out there uses u-boot, which I specifically do not want to use, because then I can use the official device trees and hardware support should be better.

I already got it working to a point where it boots and it works using the official touch screen display, which didn’t work in my older attempts using u-boot.

But it doesn’t reliably boot to the login prompt, and logging in using SSH takes about 2 minutes, so something still not good, and I can’t figure out the cause.

Here’s the configuration I currently have:

{config,pkgs,lib,...}:{
  boot.loader.raspberryPi = {
    enable = true;
    version = 3;
    firmwareConfig = ''
      gpu_mem=256
      dispmanx_offline=1
      display_rotate=1
    '';
  };
  i18n.defaultLocale = "de_CH.UTF-8";
  console = {
    font = "Lat2-Terminus16";
    keyMap = "de_CH-latin1";
  };

  boot.kernelPackages = pkgs.linuxPackages_rpi3;
  hardware.enableRedistributableFirmware = true;
  boot.kernelModules = lib.mkForce [ "vc4" "i2c_bcm2835" ];
  boot.initrd.availableKernelModules = lib.mkForce [ ];
  boot.kernelParams = [ "root=/dev/mmcblk0p2" "rw" "rootwait" "smsc95xx.turbo_mode=N" ];
  boot.initrd.supportedFilesystems = lib.mkForce ["ext4" "fat32"];
  boot.supportedFilesystems = lib.mkForce ["ext4" "fat32"];

  services.openssh.enable = true;
  services.openssh.permitRootLogin = "yes";

  networking.firewall.enable = false;

  networking.hostName = "display";
  users.users.root.openssh.authorizedKeys.keys = [
    "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA289vddtq4A1/TNluSFhWE9VZY5CXXa/458iSUzeXtfC5mN/+dZe8kzCQmqBIqhYETdhMi/dvJyzL7oADJUFKL1cxLjF4A+MoBbRD1lsk9a0Fk08SsGGeJkW3Xb/B/NJbHGEYIB58ALS8kWJgFP0YH6gvZGXn8Fv2Odkorj65H702TOrKCib/CfWrwXd21cDPrXihFgKifsPKtk1odnobJS1h1ADOoIZqRpOKyQBr6+H352BuWhQpARmlII5soKpVxbTANrBvLEl6dhFzRf6dw2ftgdwRfJYjFlyxFArp4MweQ+9bi+D5YjeBi6uwGsRZfemdelXS3u/oxi4SDCJkLw=="
  ];

  nix.extraOptions = ''
    keep-outputs = true
    keep-derivations = true
    experimental-features = nix-command flakes
  '';

  boot.loader.grub.enable = false;

  sdImage = {
    populateFirmwareCommands = "${config.system.build.installBootLoader} ${config.system.build.toplevel} -d $NIX_BUILD_TOP/firmware/";
    populateRootCommands = ''
      mkdir -p ./files/nix/var/nix/profiles/
      ln -s ${config.system.build.toplevel} ./files/nix/var/nix/profiles/system
    '';
    firmwareSize = 512;
    compressImage = false;
  };

  # to mount: https://thomasheinz.net/img-file-disk-image-unter-linux-mounten/

  system.stateVersion = "23.05"; # Did you read the comment?
}

And the flake.nix

{
  description = "A very basic flake";
  outputs = { self, nixpkgs }: rec {
    nixosConfigurations.default = nixpkgs.lib.nixosSystem {
      system = "aarch64-linux";
      modules = [
        "${nixpkgs}/nixos/modules/profiles/base.nix"
        "${nixpkgs}/nixos/modules/installer/sd-card/sd-image.nix"
         ./configuration.nix
      ];
      specialArgs = { inherit nixpkgs; };
    };
    images.default = nixosConfigurations.default.config.system.build.sdImage;
  };
}

and lock file

{
  "nodes": {
    "nixpkgs": {
      "locked": {
        "lastModified": 1669320964,
        "narHash": "sha256-EBFw+ge12Pcr3qCk8If3/eMBAoQLR7ytndXZoRevUtM=",
        "path": "/nix/store/dd636dqmf0s78wnv83rssk6qbj6jan1f-source",
        "rev": "27ccd29078f974ddbdd7edc8e38c8c8ae003c877",
        "type": "path"
      },
      "original": {
        "id": "nixpkgs",
        "type": "indirect"
      }
    },
    "root": {
      "inputs": {
        "nixpkgs": "nixpkgs"
      }
    }
  },
  "root": "root",
  "version": 7
}

Pinging the PI works flawlessly, and I tried running a simple web server on it and it responded quickly, so there don’t seem to be network issues. I just can’t figure out what the issue with SSH is…

Does someone have any advice?

My end goal is to turn the PI into a kiosk system, displaying a web page.
If I can’t get it to work I also thought about using the official minimal raspbian image, and then installing the whole graphical stack onto it using nix, but that would be worst case…

The log of a login attempt looks like this:

Jan 08 23:10:32 display systemd[1]: Reached target User and Group Name Lookups.
Jan 08 23:10:32 display systemd[1]: Reached target Host and Network Name Lookups.
Jan 08 23:10:32 display systemd[1]: Reached target Multi-User System.
Jan 08 23:10:32 display systemd[1]: Started Name Service Cache Daemon.
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/nsswitch.conf` (8)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/nsswitch.conf` (8)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/nsswitch.conf` (8)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/nsswitch.conf` (8)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/nsswitch.conf` (8)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/netgroup` (7)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/services` (6)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/resolv.conf` (5)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/hosts` (4)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/group` (3)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring directory `/etc` (2)
Jan 08 23:10:32 display nscd[1077]: 1077 monitoring file `/etc/passwd` (1)
Jan 08 23:10:32 display systemd[1]: Starting Name Service Cache Daemon...
Jan 08 23:10:32 display systemd[1]: Stopped Name Service Cache Daemon.
Jan 08 23:10:32 display systemd[1]: nscd.service: Failed with result 'timeout'.
Jan 08 23:10:32 display systemd[1]: nscd.service: Processes still around after final SIGKILL. Entering failed mode.
Jan 08 23:10:18 display sshd[1021]: pam_systemd(sshd:session): Failed to create session: Connection timed out
Jan 08 23:09:23 display systemd[1]: user@0.service: Killing process 937 (systemd) with signal SIGKILL.
Jan 08 23:09:23 display systemd[1]: user@0.service: State 'stop-sigterm' timed out. Killing.
Jan 08 23:09:01 display systemd[1]: nscd.service: Killing process 651 (nscd) with signal SIGKILL.
Jan 08 23:09:01 display systemd[1]: nscd.service: Killing process 647 (nscd) with signal SIGKILL.
Jan 08 23:09:01 display systemd[1]: nscd.service: State 'final-sigterm' timed out. Killing.
Jan 08 23:08:18 display systemd-logind[587]: New session 3 of user root.
Jan 08 23:08:18 display sshd[1021]: pam_unix(sshd:session): session opened for user root(uid=0) by (uid=0)
Jan 08 23:08:18 display sshd[1021]: Accepted publickey for root from 192.168.1.60 port 34694 ssh2: RSA SHA256:X82AQ1Qim54HWi1k30G5E6G6Bgy8pzFUZ9O/rMgUJNE

NixOS very much wants to use u-boot because without it you can’t get generations in a boot menu. It’s worth noting that you will be using the official DTs if you configure NixOS to use kernelPackages = pkgs.linuxPackages_rpi3;

1 Like

I think I’ve read somewhere that the official DTs cannot be used using u-boot. Is this incorrect?

If so, I should probably try again with u boot. But not having generations isn’t really a problem to me. If it breaks, i’ll just flash the image again.

I have a different reason to want to avoid u-boot: I have a GPS hat (for an ntp server) that sits on the serial uart, and there’s no effective way I can find to avoid u-boot getting interrupted by the serial output from the GPS.

I tried (with not particularly great persistence) but failed to get it booting using the native method, even though the setup looked simple enough, it would just hang at the GPU rainbow-square stage.

I’ve now managed to modify the configuration to use u-boot.
Interestingly, it has the exact same problem with ssh and it not always displaying the login prompt after boot (this is a bit flaky…)

I’m not even sure if it has something to do with the bootloader or the firmware at this point…

Yes, it’s not a problem with the configuration, but with some nixos packages or something.
I went back to NixOS 20.09 and with that it boots reliably to the login prompt, and SSH connections are instant.

I’ll do further experimenting and eventually post the configuration I came up with here.