Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
On Mon, May 6, 2019 at 11:28 AM Peter Kjellerstedt wrote: > > > -Original Message- > > From: openembedded-core-boun...@lists.openembedded.org > core-boun...@lists.openembedded.org> On Behalf Of Jonas Bonn > > Sent: den 6 maj 2019 06:54 > > To: Alex Kiernan ; openembedded- > > c...@lists.openembedded.org > > Subject: Re: [OE-core] [OE-Core][PATCH] systemd: Default to non- > > stateless images > > > > Hi Alex, > > > > The below is fine and looks good. The one thing that bothers me about > > this is that "stateless" isn't really a property of the "distro", > > rather > > it's a property of the image/machine. I suspect, in the same sense > > that > > we have readonly-rootfs, that we should probably have image features > > "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). > > > > Furthermore, if you want to boot with 'ro' on the command-line, I > > really > > think you need to build your image with the "readonly-rootfs" feature > > set. The default should be writable+persistent /etc as that's the > > configuration used 99% of the time (currently). "readonly-rootfs" does > > a bit more than just creating machine-id but it's all relevant to the > > 'ro' case where /etc isn't writable. > > > > Just for clarification: > > > > i) volatile-rootfs: means there's no point in prepopulating /var > > because it's on a tmpfs and needs to be populated at boot time > > This doesn't really say anything about the state of the rootfs outside > of /var, i.e., is it writable or read-only? > > > ii) stateless-rootfs: means there's no point in prepopulating neither > > /etc nor /var because they are on a tmpfs and need to be populated at > > boot time > > Same here. > > > iii) readonly-rootfs: means that /etc is really not writable so it's > > important that: the systemd first-boot stuff needs to be done at build > > time: machine-id, unit files set up, all tmpfiles.d snippets that > > touch /etc and /var need to be done in advance. > > > > /Jonas > > Maybe we need some more generic way of describing the intended > structure of the image? E.g., what are the expected behavior of > /etc, /var and the rest of the rootfs? For each they can typically > be "read-only", "persistent" (writable and survives reboots) or > "volatile" (writable, but doesn't survive a reboot). > That feels like a useful direction... Certainly there's constraints in a systemd world as to what's allowable (which is basically the three models: stateful, volatile and stateless) - violate those and you end up with all kinds of things you didn't expect happening (like a new journal being created everytime you reboot with a new machine id until you run out of disk...) -- Alex Kiernan -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
On Mon, May 6, 2019 at 12:18 PM Jonas Bonn wrote: > > Hi Alex, > > On 06/05/2019 11:36, Alex Kiernan wrote: > > On Mon, May 6, 2019 at 5:54 AM Jonas Bonn wrote: > >> > >> Hi Alex, > >> > >> The below is fine and looks good. The one thing that bothers me about > >> this is that "stateless" isn't really a property of the "distro", rather > >> it's a property of the image/machine. > > > > I agree it should be part of image, I'll respin it. > > > >> I suspect, in the same sense that > >> we have readonly-rootfs, that we should probably have image features > >> "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). > >> > > > > That makes sense to me > > > >> Furthermore, if you want to boot with 'ro' on the command-line, I really > >> think you need to build your image with the "readonly-rootfs" feature > >> set. The default should be writable+persistent /etc as that's the > >> configuration used 99% of the time (currently). "readonly-rootfs" does > >> a bit more than just creating machine-id but it's all relevant to the > >> 'ro' case where /etc isn't writable. > >> > > > > I think there's (at least) two use cases for ro boot: > > > > - systems which boot ro and stay that way > > - systems which transition to rw during systemd-remount-fs > > > > I'm in the second case as I have no initramfs and need the filesystem > > readonly until it's fscked/remounted rw. > > I'd argue that you are abusing systemd for this because systemd > explicity requires /etc to be writable. The fact that it works on a > read-only /etc is both incidental and fragile. > Not sure... systemd is explicit in its machinery for some parts of this ro->rw transition (e.g. systemd-machine-id-commit.service), though it's admittedly silent on what the state of the rest of /etc is. > That said, I understand why you want to do this. Have you considered > putting the fsck in a "systemd generator" that doesn't return until fsck > finishes? Generators are kind of like units that run before systemd > starts... or, at least, they can be (ab)used in this way. Systemd won't > start until all the generators are finished (the idea being that the > generators may be responsible for creating units dynamically). > If systemd comes along and breaks it yes... or I'll teach ostree-prepare-root how to do it, but right now the sequencing is all there in systemd. -- Alex Kiernan -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
Hi Alex, On 06/05/2019 11:36, Alex Kiernan wrote: On Mon, May 6, 2019 at 5:54 AM Jonas Bonn wrote: Hi Alex, The below is fine and looks good. The one thing that bothers me about this is that "stateless" isn't really a property of the "distro", rather it's a property of the image/machine. I agree it should be part of image, I'll respin it. I suspect, in the same sense that we have readonly-rootfs, that we should probably have image features "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). That makes sense to me Furthermore, if you want to boot with 'ro' on the command-line, I really think you need to build your image with the "readonly-rootfs" feature set. The default should be writable+persistent /etc as that's the configuration used 99% of the time (currently). "readonly-rootfs" does a bit more than just creating machine-id but it's all relevant to the 'ro' case where /etc isn't writable. I think there's (at least) two use cases for ro boot: - systems which boot ro and stay that way - systems which transition to rw during systemd-remount-fs I'm in the second case as I have no initramfs and need the filesystem readonly until it's fscked/remounted rw. I'd argue that you are abusing systemd for this because systemd explicity requires /etc to be writable. The fact that it works on a read-only /etc is both incidental and fragile. That said, I understand why you want to do this. Have you considered putting the fsck in a "systemd generator" that doesn't return until fsck finishes? Generators are kind of like units that run before systemd starts... or, at least, they can be (ab)used in this way. Systemd won't start until all the generators are finished (the idea being that the generators may be responsible for creating units dynamically). Just for clarification: i) volatile-rootfs: means there's no point in prepopulating /var because it's on a tmpfs and needs to be populated at boot time ii) stateless-rootfs: means there's no point in prepopulating neither /etc nor /var because they are on a tmpfs and need to be populated at boot time iii) readonly-rootfs: means that /etc is really not writable so it's important that: the systemd first-boot stuff needs to be done at build time: machine-id, unit files set up, all tmpfiles.d snippets that touch /etc and /var need to be done in advance. I'm assuming definitions from here? http://0pointer.net/blog/projects/stateless.html Either way, those work for me... Correct. Thanks for digging that up... I should have posted it myself. /Jonas -- Alex Kiernan -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
Hi Peter, On 06/05/2019 12:28, Peter Kjellerstedt wrote: -Original Message- From: openembedded-core-boun...@lists.openembedded.org On Behalf Of Jonas Bonn Sent: den 6 maj 2019 06:54 To: Alex Kiernan ; openembedded- c...@lists.openembedded.org Subject: Re: [OE-core] [OE-Core][PATCH] systemd: Default to non- stateless images Hi Alex, The below is fine and looks good. The one thing that bothers me about this is that "stateless" isn't really a property of the "distro", rather it's a property of the image/machine. I suspect, in the same sense that we have readonly-rootfs, that we should probably have image features "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). Furthermore, if you want to boot with 'ro' on the command-line, I really think you need to build your image with the "readonly-rootfs" feature set. The default should be writable+persistent /etc as that's the configuration used 99% of the time (currently). "readonly-rootfs" does a bit more than just creating machine-id but it's all relevant to the 'ro' case where /etc isn't writable. Just for clarification: i) volatile-rootfs: means there's no point in prepopulating /var because it's on a tmpfs and needs to be populated at boot time This doesn't really say anything about the state of the rootfs outside of /var, i.e., is it writable or read-only? ii) stateless-rootfs: means there's no point in prepopulating neither /etc nor /var because they are on a tmpfs and need to be populated at boot time Same here. iii) readonly-rootfs: means that /etc is really not writable so it's important that: the systemd first-boot stuff needs to be done at build time: machine-id, unit files set up, all tmpfiles.d snippets that touch /etc and /var need to be done in advance. /Jonas Maybe we need some more generic way of describing the intended structure of the image? E.g., what are the expected behavior of /etc, /var and the rest of the rootfs? For each they can typically be "read-only", "persistent" (writable and survives reboots) or "volatile" (writable, but doesn't survive a reboot). Alex already put this link into an earlier response but I'll repeat it here and defer to it for the terminology and justification. http://0pointer.net/blog/projects/stateless.html That said, the paradigm here is that: i) /etc MUST be writable ii) /var MUST be writable iii) For everything, it doesn't matter... writable or not. Most importantly, though, read-only is OK and no program should assume that they can write outside of /etc and /var (and /tmp and /run). /Jonas //Peter -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
> -Original Message- > From: openembedded-core-boun...@lists.openembedded.org core-boun...@lists.openembedded.org> On Behalf Of Jonas Bonn > Sent: den 6 maj 2019 06:54 > To: Alex Kiernan ; openembedded- > c...@lists.openembedded.org > Subject: Re: [OE-core] [OE-Core][PATCH] systemd: Default to non- > stateless images > > Hi Alex, > > The below is fine and looks good. The one thing that bothers me about > this is that "stateless" isn't really a property of the "distro", > rather > it's a property of the image/machine. I suspect, in the same sense > that > we have readonly-rootfs, that we should probably have image features > "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). > > Furthermore, if you want to boot with 'ro' on the command-line, I > really > think you need to build your image with the "readonly-rootfs" feature > set. The default should be writable+persistent /etc as that's the > configuration used 99% of the time (currently). "readonly-rootfs" does > a bit more than just creating machine-id but it's all relevant to the > 'ro' case where /etc isn't writable. > > Just for clarification: > > i) volatile-rootfs: means there's no point in prepopulating /var > because it's on a tmpfs and needs to be populated at boot time This doesn't really say anything about the state of the rootfs outside of /var, i.e., is it writable or read-only? > ii) stateless-rootfs: means there's no point in prepopulating neither > /etc nor /var because they are on a tmpfs and need to be populated at > boot time Same here. > iii) readonly-rootfs: means that /etc is really not writable so it's > important that: the systemd first-boot stuff needs to be done at build > time: machine-id, unit files set up, all tmpfiles.d snippets that > touch /etc and /var need to be done in advance. > > /Jonas Maybe we need some more generic way of describing the intended structure of the image? E.g., what are the expected behavior of /etc, /var and the rest of the rootfs? For each they can typically be "read-only", "persistent" (writable and survives reboots) or "volatile" (writable, but doesn't survive a reboot). //Peter -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
On Mon, May 6, 2019 at 5:54 AM Jonas Bonn wrote: > > Hi Alex, > > The below is fine and looks good. The one thing that bothers me about > this is that "stateless" isn't really a property of the "distro", rather > it's a property of the image/machine. I agree it should be part of image, I'll respin it. > I suspect, in the same sense that > we have readonly-rootfs, that we should probably have image features > "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). > That makes sense to me > Furthermore, if you want to boot with 'ro' on the command-line, I really > think you need to build your image with the "readonly-rootfs" feature > set. The default should be writable+persistent /etc as that's the > configuration used 99% of the time (currently). "readonly-rootfs" does > a bit more than just creating machine-id but it's all relevant to the > 'ro' case where /etc isn't writable. > I think there's (at least) two use cases for ro boot: - systems which boot ro and stay that way - systems which transition to rw during systemd-remount-fs I'm in the second case as I have no initramfs and need the filesystem readonly until it's fscked/remounted rw. > Just for clarification: > > i) volatile-rootfs: means there's no point in prepopulating /var > because it's on a tmpfs and needs to be populated at boot time > > ii) stateless-rootfs: means there's no point in prepopulating neither > /etc nor /var because they are on a tmpfs and need to be populated at > boot time > > iii) readonly-rootfs: means that /etc is really not writable so it's > important that: the systemd first-boot stuff needs to be done at build > time: machine-id, unit files set up, all tmpfiles.d snippets that touch > /etc and /var need to be done in advance. > I'm assuming definitions from here? http://0pointer.net/blog/projects/stateless.html Either way, those work for me... -- Alex Kiernan -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
Re: [OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
Hi Alex, The below is fine and looks good. The one thing that bothers me about this is that "stateless" isn't really a property of the "distro", rather it's a property of the image/machine. I suspect, in the same sense that we have readonly-rootfs, that we should probably have image features "stateless-rootfs" (no /etc, no /var) and "volatile-rootfs" (no /var). Furthermore, if you want to boot with 'ro' on the command-line, I really think you need to build your image with the "readonly-rootfs" feature set. The default should be writable+persistent /etc as that's the configuration used 99% of the time (currently). "readonly-rootfs" does a bit more than just creating machine-id but it's all relevant to the 'ro' case where /etc isn't writable. Just for clarification: i) volatile-rootfs: means there's no point in prepopulating /var because it's on a tmpfs and needs to be populated at boot time ii) stateless-rootfs: means there's no point in prepopulating neither /etc nor /var because they are on a tmpfs and need to be populated at boot time iii) readonly-rootfs: means that /etc is really not writable so it's important that: the systemd first-boot stuff needs to be done at build time: machine-id, unit files set up, all tmpfiles.d snippets that touch /etc and /var need to be done in advance. /Jonas On 03/05/2019 18:48, Alex Kiernan wrote: When creating images, for anything other than the explicitly stateless case, touch /etc/machine-id so that the images can be booted without an initramfs and with `ro` set on the kernel command line, otherwise system refuses to start: [7.222134] systemd[1]: No hostname configured. [7.227266] systemd[1]: Set hostname to . [7.232622] systemd[1]: System cannot boot: Missing /etc/machine-id and /etc is mounted read-only. [7.241750] systemd[1]: Booting up is supported only when: [7.247362] systemd[1]: 1) /etc/machine-id exists and is populated. [7.253752] systemd[1]: 2) /etc/machine-id exists and is empty. [7.259757] systemd[1]: 3) /etc/machine-id is missing and /etc is writable. If DISTRO_FEATURES includes `stateless` then systemctl-native is not run on the image leaving the image for population at runtime by systemd. Signed-off-by: Alex Kiernan --- meta/classes/image.bbclass| 7 +++ meta/recipes-core/systemd/systemd-systemctl/systemctl | 8 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass index a23403c0827a..3cb185dd2045 100644 --- a/meta/classes/image.bbclass +++ b/meta/classes/image.bbclass @@ -665,12 +665,11 @@ reproducible_final_image_task () { fi } -IMAGE_EXTRADEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-systemctl-native', '', d)}" - systemd_preset_all () { - systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all +systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all } -IMAGE_PREPROCESS_COMMAND_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd_preset_all;', '', d)} reproducible_final_image_task; " +IMAGE_EXTRADEPENDS += "${@ 'systemd-systemctl-native' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('DISTRO_FEATURES', 'stateless', True, False, d) else ''}" +IMAGE_PREPROCESS_COMMAND_append = " ${@ 'systemd_preset_all;' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('DISTRO_FEATURES', 'stateless', True, False, d) else ''} reproducible_final_image_task; " CVE_PRODUCT = "" diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl index d7d4e0d29a09..7da8f23ab893 100755 --- a/meta/recipes-core/systemd/systemd-systemctl/systemctl +++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl @@ -241,6 +241,14 @@ def preset_all(root): if state == "enable" or state is None: enable(root, service, location, services) +# If we populate the systemd links we also create /etc/machine-id, which +# allows systemd to boot with the filesystem read-only before generating +# a real value and then committing it back. +# +# For the stateless configuration, where /etc is generated at runtime +# (for example on a tmpfs), this script shouldn't run at all and we +# allow systemd to completely populate /etc. +(root / SYSCONFDIR / "machine-id").touch() def mask(root, *services): systemdir = root / SYSCONFDIR / "systemd" / "system" -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core
[OE-core] [OE-Core][PATCH] systemd: Default to non-stateless images
When creating images, for anything other than the explicitly stateless case, touch /etc/machine-id so that the images can be booted without an initramfs and with `ro` set on the kernel command line, otherwise system refuses to start: [7.222134] systemd[1]: No hostname configured. [7.227266] systemd[1]: Set hostname to . [7.232622] systemd[1]: System cannot boot: Missing /etc/machine-id and /etc is mounted read-only. [7.241750] systemd[1]: Booting up is supported only when: [7.247362] systemd[1]: 1) /etc/machine-id exists and is populated. [7.253752] systemd[1]: 2) /etc/machine-id exists and is empty. [7.259757] systemd[1]: 3) /etc/machine-id is missing and /etc is writable. If DISTRO_FEATURES includes `stateless` then systemctl-native is not run on the image leaving the image for population at runtime by systemd. Signed-off-by: Alex Kiernan --- meta/classes/image.bbclass| 7 +++ meta/recipes-core/systemd/systemd-systemctl/systemctl | 8 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass index a23403c0827a..3cb185dd2045 100644 --- a/meta/classes/image.bbclass +++ b/meta/classes/image.bbclass @@ -665,12 +665,11 @@ reproducible_final_image_task () { fi } -IMAGE_EXTRADEPENDS += "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-systemctl-native', '', d)}" - systemd_preset_all () { - systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all +systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all } -IMAGE_PREPROCESS_COMMAND_append = " ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd_preset_all;', '', d)} reproducible_final_image_task; " +IMAGE_EXTRADEPENDS += "${@ 'systemd-systemctl-native' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('DISTRO_FEATURES', 'stateless', True, False, d) else ''}" +IMAGE_PREPROCESS_COMMAND_append = " ${@ 'systemd_preset_all;' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('DISTRO_FEATURES', 'stateless', True, False, d) else ''} reproducible_final_image_task; " CVE_PRODUCT = "" diff --git a/meta/recipes-core/systemd/systemd-systemctl/systemctl b/meta/recipes-core/systemd/systemd-systemctl/systemctl index d7d4e0d29a09..7da8f23ab893 100755 --- a/meta/recipes-core/systemd/systemd-systemctl/systemctl +++ b/meta/recipes-core/systemd/systemd-systemctl/systemctl @@ -241,6 +241,14 @@ def preset_all(root): if state == "enable" or state is None: enable(root, service, location, services) +# If we populate the systemd links we also create /etc/machine-id, which +# allows systemd to boot with the filesystem read-only before generating +# a real value and then committing it back. +# +# For the stateless configuration, where /etc is generated at runtime +# (for example on a tmpfs), this script shouldn't run at all and we +# allow systemd to completely populate /etc. +(root / SYSCONFDIR / "machine-id").touch() def mask(root, *services): systemdir = root / SYSCONFDIR / "systemd" / "system" -- 2.17.1 -- ___ Openembedded-core mailing list Openembedded-core@lists.openembedded.org http://lists.openembedded.org/mailman/listinfo/openembedded-core