Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sd-image: Fix Raspberry Pi 4 image builder #78090

Closed

Conversation

cmacrae
Copy link
Contributor

@cmacrae cmacrae commented Jan 20, 2020

Motivation for this change

These changes address the issues outlined in #73487.
They allow for rebuilds of system configuration to persist on the
Raspberry Pi 4. Without these changes, SD images generated from this
expression won't write their boot configs correctly, and thus the Pi
will just reboot to the installer configuration.

Along with this, also create /var/empty to allow for sshd to
start up correctly.

Things done
  • Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
  • Built on platform(s)
    • NixOS
    • macOS
    • other Linux distributions
  • Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Determined the impact on package closure size (by running nix path-info -S before and after)
  • Ensured that relevant documentation is up to date
  • Fits CONTRIBUTING.md.

@diamondburned
Copy link

Is this tested? I'm not too confident in what I wrote...

@@ -20,12 +20,23 @@
firmwareSize = 128;
# This is a hack to avoid replicating config.txt from boot.loader.raspberryPi
populateFirmwareCommands =
"${config.system.build.installBootLoader} ${config.system.build.toplevel} -d ./firmware";
"${config.system.build.installBootLoader} ${config.system.build.toplevel} -d ./";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this line even necessary?

As far as I can tell, it only runs for the initial SD card image build... and yet, my bootloader is properly configured everytime that I update the system, so I don't understand what this is doing one-time that is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, very good point. I think with the removal of ./firmware, it's probably not necessary at all.
I'll remove it and take it for a spin later when I get home

@colemickens
Copy link
Member

This looks like what I've been using, but I haven't tested from scratch with a new SD Card. Also, I have one question about one of the lines.

@cmacrae
Copy link
Contributor Author

cmacrae commented Jan 21, 2020

Is this tested? I'm not too confident in what I wrote...

@diamondburned Yep, I've tested it on a fresh card. Boots fine and config changes work nicely 🙂

This looks like what I've been using, but I haven't tested from scratch with a new SD Card. Also, I have one question about one of the lines.
@colemickens Thanks for taking a look over this - I'll address your comments in the thread 👍

These changes address the issues outlined in NixOS#73487.
They allow for rebuilds of system configuration to persist on the
Raspberry Pi 4. Without these changes, SD images generated from this
expression won't write their boot configs correctly, and thus the Pi
will just reboot to the installer configuration.

Along with this, also create '/files/var/empty' to allow for sshd to
start up correctly.
@cmacrae cmacrae force-pushed the raspbery_pi_4/fix_sdimage_builder branch from 3470a8a to febcf75 Compare January 21, 2020 08:33
@colemickens
Copy link
Member

There's another issue that I've had to work around and I've seen others mention - this module is still not really able to be included by the end user in a day-to-day usage device - you can't remove the installation-device profile and thus can't remove the nixos user, enable SSH at boot, etc.

cc: @samueldr

# As the boot process is done entirely in the firmware partition.
populateRootCommands = "";
# /var/empty is needed for some services, such as sshd
populateRootCommands = "mkdir -p ./files/var/empty";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is required, this shouldn't be handled here. This should be fixed upstream in NixOS so that when it is missing, it works. I think this explains an issue I saw on another board, but did not investigate.

At the very least, if it's not part of some tmpfiles declaration, it should be part of the first boot commands in the generic sd image builder.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc Pi images are treated as if they're live CDs, which doesn't run this. I'm not sure though, I just know that without those commands, there wouldn't be a /var/empty.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that sounds right, might need this for the other rpi images too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I've used this same for rpi3:

                systemd.tmpfiles.rules = [
                    "d /var/empty - - - -"
                ];

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what's the failure mode here. Why isn't it required for other systems than the ARM images?

Copy link
Member

@DavHau DavHau Feb 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On rpi3 I'm also experiencing sshd crashing with Missing privilege separation directory: /var/empty. Only on the first boot. If i reboot once, it's fine.
On the first boot when it's not working dmesg | grep /var/empty gives me:

[    8.485396] stage-2-init: mkdir: cannot create directory '/var/empty': No space left on device
[    8.536393] stage-2-init: find: '/var/empty': No such file or directory
[    8.545242] stage-2-init: chmod: cannot access '/var/empty': No such file or directory
[    8.556068] stage-2-init: chown: cannot access '/var/empty': No such file or directory

Seems like there is no space left on the sd card at this point? Maybe because resizing hasn't have happened yet?
On the second boot there is nothing in dmesg related to /var/empty.
Should i open a bug report for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that could be the root cause of this issue I guess. I would rather this gets fixed appropriately rather than patched over.

If you open a bug, it is not likely sshd-specific, but really this one issue. And please do, cc me once you do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vote for merging this immediately, since a hack that fixes broken sshd is better than broken sshd.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

t. person that has wasted the last hours trying to log into sshd on his raspberrypi.

@samueldr
Copy link
Member

@colemickens:

This is the installer image, as described by the path of the file. It shouldn't be included on a running end-user system.

We don't usually provide hardware-specific configurations in the Nixpkgs repo. For this there is nixos-hardware where we probably should begin adding SBCs too.

But you're right that this is some kind of expectations mismatch. The end-user wants to run the raspberry pi system on their sd card, so why can't they include sd-image-raspberrypi4? Well, that's the installer/ profile.


In fact, that profile file, I announce, will be removed from 20.03 once 20.03 is branched off.

Noting again: as previously stated, it will be kept in unstable up until the moment mainline Linux runs on the Raspberry Pi 4. Once mainline boots on the Pi 4, the generic aarch64 image will be the image for both the pi 3 and 4.

Comment on lines +30 to +33
"/boot" = {
device = "/dev/disk/by-label/FIRMWARE";
fsType = "vfat";
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was changed in #62462, I think mostly because /boot can get quite big if it stores multiple versions of the kernel. @samueldr, you authored the original PR and you've commented here, but have not addressed this particular difference. Any thoughts?

@VanCoding
Copy link

@samueldr On my Raspberry PI, when I change boot.loader.raspberryPi.firmwareConfig and run nixos-rebuild switch the config.txt on the /dev/sda1 partition does not get changed at all. Is this what this pull request tries to solve?

Shouldn't the content of /dev/sda1 be replaced on every nixos-rebuild switch?

I stumbled upon this while trying to bring a RPI Kisok to work using NixOS and also requested for help here: https://discourse.nixos.org/t/raspberry-pi-3-official-touch-screen-not-working/5735/5?u=vancoding

@kwohlfahrt
Copy link
Contributor

I think this just the installer image, so it won't affect running systems (i.e. nixos-rebuild switch). I also think that your suggestion about replacing the firmware partition on configuration change (though mine is on /dev/mmcblk0p1) is reasonable but not related to this PR. I'll hopefully get around to implementing that soon...

@VanCoding
Copy link

@kwohlfahrt Ah, okay.

Yeah, having the same configuration for image generation and updating is what I'm trying to achieve.

I want to manage many Raspberry PIs, which should have all the same configuration (which gets updated from time to time). And adding an additional Raspberry PI should be as easy as taking this configuration and generating an image for it.

But that's OT, sorry.

@samueldr
Copy link
Member

If you can reproduce your issues, can you validate that, with #90119 in the commit you are using to build the image, the installer image works as expected?

It should now:

  • Mount the boot partition correctly
  • Use a less confusing label for the boot partition

@Profpatsch
Copy link
Member

Profpatsch commented Jun 22, 2020 via email

@Profpatsch
Copy link
Member

Profpatsch commented Jun 22, 2020 via email

@samueldr
Copy link
Member

Note that as with all images using the installer profile, the SSHD will not start by default. Furthermore, it would require additional credentials on the device. This is all assuming you are not using a custom build.

Now, what I understand from this discussion is that this is a first-boot only issue, and is not specific to the raspberry pi. Re-doing and fixing the hack here is not a solution, it needs to be done for all sd images.

BUT, note that we just added a patch that changes something with how the images are built, and it's possible it also fixes that issue with starting sshd since it may now have enough space on the partition during boot for this to work.

The proper solution is the one from @danbst

                systemd.tmpfiles.rules = [
                    "d /var/empty - - - -"
                ];

Which I think would be appropriate to add to the generic sd-image expressions, at worst it's a no-op, at best here it'll fix that specific issue.

I do not have a setup with a reproduction of the issue, so I'm not in the best situation to validate that issue.

@samueldr
Copy link
Member

The build of the image stopped working, but I didn’t get my Raspberri Pi 4
Model B (armv7l) to accept ssh (I don’t have a mini-HDMI cable here so I
can’t attach a monitor).

The Raspberry Pi 4 Model B is an aarch64 device, but since you said "(armv7l)" I am assuming this comes from raspios (née Raspbian) which is running on 32 bit. I don't know that you can successfully infect a 32 bit ARM system with an aarch64 NixOS system.

@Profpatsch
Copy link
Member

The Raspberry Pi 4 Model B is an aarch64 device, but since you said "(armv7l)" I am assuming this comes from raspios (née Raspbian) which is running on 32 bit.

Ah, I was super confused by that. So uname shows armv7l if it’s running on a 32bit system, which raspios is, but the system itself is 64 bit.

I think I’m gonna try again with the /var/empty fix, I only used the PR that was merged into master last week.

I don't know that you can successfully infect a 32 bit ARM system with an aarch64 NixOS system.

I wonder, nixos-infect should not require running any 64bit executables before reboot, and after reboot it has a 64bit kernel … though the question is whether the boot partition stuff is set up correctly by nixos-infect anyway, and if it’s not I would be in the same situation as with the SD image.

Thank you for the help!

Copy link
Contributor

@urbas urbas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RPi4 SD image has since moved on quite a bit and the sshd bug also seems to have been fixed. We might want to consider closing this PR at this point.

@matthewbauer
Copy link
Member

Feel free to reopen if it's still relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet