-
Notifications
You must be signed in to change notification settings - Fork 39
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
run_once: execute /boot/run_once when booting #40
Conversation
Documentation pull request: raspberrypi/documentation#1701 |
I wonder if there's a security risk in that any arbitrary binary placed onto the FAT32 partition (named I think that Raspberry Pi OS still requires root access to modify files in |
I have been having these thoughts as well and I thought about adding That way I don't think its possible, even for root, to add new I decided against using it - in a totally headless environment (no monitor - no serial - no way of knowing the raspberry pi's IP address) I believe its a nice addition to be able to pull the sd card - mount /boot again on a desktop pc and edit/add a new Adding |
@XECDesign Judging on the commit logs - it seems you got quite the history in this repository so I'm reaching out to you :) Is there a formal process for getting things like this merged into the Raspberry Pi OS ? |
Sorry about the delay. Isn't the name 'firstboot' a bit misleading then? In the past, we have pushed against this idea in favour of a simple text file with user-friendly options. However, it has been over a year since I looked at that last and I don't think I'll get to it in the near future. Also, no matter what options we add, somebody will ask for their use case to be supported as well and everything quickly becomes complicated. The idea of just running a script is good because it's simple for advanced users and supports all the use cases anybody might have. So yes, I think this is a good addition. It might take a little while before it's merged though because I'll need to consult a few more people and test it out when I get some time. |
See also https://www.pibakery.org/ |
Aside from the name, another issue somebody raised is what happens if it's a network boot and there's no /boot write access. Some kind of meaningful error if /boot is read-only would be useful. |
Thanks for taking the time to look at this :) I'm not sure I agree on the naming scheme being misleading - I think it clearly states the intended purpose, other names I can think of, We could of cause just call it The network boot issue is a nice catch - I think adding |
I just added the |
|
I like Should |
I think we should go with
It certainly wouldn't hurt - it properly won't make a difference since everything is executable on the The branch has been updated :) |
Everything in |
Hey, just a short question. I am new to github therefore i am not sure if this is the right place to ask this question... Why was this not merged into the new release from 2nd december? I just wanted to tryout because its a pretty good feature! Regards |
I haven't had a chance to test it and this was a fairly big release with other changes that needed pre-release attention. |
Ah okay, thanks for the quick answer. Then i will wait for the next release to use this. If i can do something to help regarding this firstboot script testing, please contact me. Regards |
@lurch @n0nk Here's how I'm testing it quick and dirty First, clone my repository of the project
Then, to build the deb, use the usual
Now if everything went right, we should be presented with a new deb file in the parent directory, it's just a matter of moving this to an existing raspberry pi, installing it - and look for expected behavior :)
So far so good - now it's just a matter of putting anything armhf executable in /boot/run_once and see if it's executed and moved out of the way on boot:
When the pi has booted, check the output of systemctl status run_once for confirmation:
We can confirm that the exit code of the program |
@lurch @XECDesign I've just updated the documentation to once again match this pull request |
I just want to +1 this idea and thank you all for working on it! This will be a huge help for doing some quick initial customizations. |
Ah, it is quite flexible. In this case you would drop a YAML file onto the card that contains your customisations without requiring any remote servers. Some examples: |
As the original author of firstboot.sh, I always felt like cloud-init was the "right" answer. Note that you don't have to use YAML with cloud-init - you can simply paste in a shell script: |
Thanks for the heads up, that's a very useful bit of information. |
I'd not heard of cloud-init before, but just had a quick flick through its docs. Seems like it'd be something that plugs into https://github.com/raspberrypi/piserver quite nicely too? |
Just a short comment from my side. I really like the cloud-init idea. But i also like it to keep things simple. Having the possibility to add a simple executable or script to the boot partition and do whatever i want it to do is much more easier for everyone who initially starts developing/playing with the rasperry. Having cloud init is nice but its also a hurdle to take. I want to say: And even if i know cloud-init and like to use it. Maybe its .. in german we say "Shoot sparrows with cannons" for most usecases, if you know what i mean? Greetings |
@n0nk that's why nmcclain's comment is interesting. It can work with a shell script OR a YAML file in addition to other options, based on what's actually in the file. |
I'm sure that if/when cloud-init does get added to RaspiOS, there'll also be easy-to-follow instructions (on how to do the basics) added to the Raspi documentation site 🙂 |
oh sorry, i completely ignored this. Thanks for the hint |
I just wanted to mention, when reading the first few comments in this issue I kept thinking why not just use cloud-init? Ubuntu for Pi has had it enabled for a while now, and it's a breath of fresh air to be able to have almost complete control over the first initialization of a Pi (has made me switch to running Ubuntu in many cases for headless installations). I really do think something more than configuration of ssh via an
I know I've been considering doing a video just on cloud-init on Ubuntu on the Pi for some time. Having it be supported in Pi OS would be a great excuse to dust off my cloud-init docs and make a pretty good guide for the YT audience at least. I can imagine there will be good coverage of how to configure a few basics like ssh-keys, networking, and running executables, at least. |
This is a perfect example of how perfection is the worst enemy of good. For more than half a year there is a merge request with an available solution, but here we are, discussing about the perfect solution and users meanwhile still have to burn the image, find the IP, ssh to it and configure it manually. This is a 2 file PR, I don't think it will be problematic to merge it now and undo it later when the "perfect solution" arrives (if ever does 😉). |
Agreed that Two minor things, not mandatory IMO:
|
@danielo515 - Perfect is, indeed, the enemy of the good. However, for my own purposes, the thing I was most interested in has been solved by the latest feature addition to the official Raspberry Pi Imager—you can hold down Shift+Ctrl+X (Cmd on Mac) and have WiFi credentials configured, an SSH pubkey inserted, even set things like the hostname and locale! So at this point I don't have much skin in the game, but I do hope that the ability to get a script to run once is added, either via this or |
It's fun that you mention that. The way I found this issue is because I saw your post on reddit about that hidden feature of Raspberrypi Pi imager, so I thought, ok, maybe it's time to take a look at this "etcher like" tool. Reading the issues of that tool I found one issue about executing a script on first boot and that lead me here. The circle is now complete. I, in fact, used that feature, I inspected the resulting image and guess what? there is a script called firstboot. So if the tool is able to do such thing, I don't understand why they are pointing to this issue. This is all very confusing even for advanced users. Curious coming from the people that thing that an "show advanced options" button is too hard for normal people to grasp. |
But I guess the imager as well created another script/service to call that Wouldn't then make sense to make this exact method a native method, so that either the imager or the user only needs to create the |
I just did a bit of digging, and RPi Imager does it's firstrun magic by simply adding some extra text to cmdline.txt . Looks like there's no custom "firstboot service" running in Raspberry Pi OS, it just relies on |
Ah a native systemd feature: https://www.freedesktop.org/software/systemd/man/kernel-command-line.html#systemd.run= Okay, knowing this (I didn't know this feature before), everyone can easily manually setup first boot scripts (This one is called |
...but that would mean that RPi Imager wouldn't be able to "customise" any RasPiOS images that didn't already have these |
Correct, does not require anything special. And should work on any Linux distribution that uses systemd, as long as you provide the correct location of where the script would be available inside the file system after boot.
But if you where using say Ubuntu instead where FAT partition is mounted at /boot/EFI instead of /boot it would need to be:
I personally think it is always best to use standard constructs that are available in multiple Linux distributions.
Why not just teach advanced users how to add the cmdline.txt entries (and how to remove the entries at end of script)? |
True, especially it won't work with other distros. Easiest would be to first remove possibly present
We'll, everyone with enough knowledge or a good documentation can modify and apply any change and tweak to any image, but I guess the idea here was to make it easy. While teaching users skills is nice, it's a different goal then offering easy to use features. This PR aims to add an easy to use feature, similar to how RPi imager aims to make pre-configuring an image easy, and the aim is not to teach users something. That could be a topic for the documentation, e.g. as companion to explain how the first boot script feature works 🙂. |
So...are we going to add support for a firstboot script on the official Raspberry Pi images? This is the easiest and most straight forward way IMHO and I am using an outdated version of the Pi image instead of the latest official one due to it... I did run into this issue that was brought up on newer Ubuntu distros. Maybe the fix to this issue should get pulled into this PR? It's a good call. |
# This unit is heavily inspired by Ned McClain's ideas found in https://github.com/nmcclain/raspberian-firstboot | ||
[Unit] | ||
Description=run_once initialization | ||
After=network.target |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
per nmcclain/raspberian-firstboot#13 ...
Update After=network.target
to include apt-daily.service
and apt-daily-upgrade.service
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable
How does this behave on a system without network connectivity?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT: Lol, now I see the comment was more about the unattended upgrade services 😄. I wonder if they have any effect since those services are not "enabled" to be started by systemd at boot, but they are started by their respective systemd timers. As such, AFAIK they cannot be used for boot ordering at all, but I have not tested it.
network.target
is a passive unit, hence it has no meaning unless a network stack/provider gives it one (sorts itself Before=network.target
). In case of Raspbian/Debian (Raspberry Pi OS), this is most of all the networking.service
from the ifupdown
package, which brings up the loopback interface and other manually configured auto <iface>
interfaces. Theoretically it's as well the ifup@<iface>.service
's, which are created for allow-hotplug <iface>
interfaces, but since this unit is of Type=simple
, they don't need to finish but only need to start (hence do not delay the target to be reached, even if e.g. DHCP or wpa_supplicant hangs or fails).
dhcpcd
does NOT have any effect on this target, which is strange and somehow a problem since Raspberry Pi OS uses it for network configuration by default 🤔.
So if no network is configured, the target is reached once the loopback interface is available. If a network is configured, it depends on the network stack, but the way Raspberry Pi OS is configured, no additional delay happens.
Btw, network.target
is not intended to indicate that the device is online. For this, network-online.target
is intended. Since it is an active target, it needs to be pulled it:
Wants=network-online.target
After=network-online.target
But currently (with the current network stacks) it has not the intended meaning but is reached simply immediately after network.target
.
More info: https://www.freedesktop.org/wiki/Software/systemd/NetworkTarget/
- But it has to be taken care since there is quite some discrepancy between the intended meaning by systemd and the actual meaning on the system, which depends on network stack and consumer services.
- The effective meaning can be best seen with:
systemctl show -p Before,After network.target network-online.target
Hi folks Regarding cloud-init I just though I'd point out that I have been using it to bootstrap RPIs running Alpine Linux (as well as PCs, x86/x86_64/arm64 VMs and Cloud Servers) for some time using my own script. For physical machines such as RPIs I'm creating a small partition to hold the YAML files. More info here: https://github.com/dermotbradley/create-alpine-disk-image/blob/main/Physical/RaspberryPi.md |
Closing this, since it won't be done this way. For people who require this functionality right now, there is the We're experimenting with a simple customisation toml file where I'll add similar functionality. At some point, possibly for the bookworm release, we'll add support for cloud-init. It's not quite mature enough to support our use case right now, hence the stop-gap customisation method. |
Based on Ned McClain's ideas found in https://github.com/nmcclain/raspberian-firstboot this pull request will enable newly flashed Raspberry Pi's to be easily provisioned by simply adding an executable to the /boot partition right after flashing sd cards.
Let me know what you think :)