Implement Bootable Container (bootc) image & deployment #22

Open
opened 2026-01-09 13:07:49 +00:00 by janhalen · 9 comments
janhalen commented 2026-01-09 13:07:49 +00:00 (Migrated from github.com)

1. Image Creation & Local Build

  • Draft Containerfile: Create a multi-stage Containerfile based on a bootc-compatible image

  • Local Build: Use Podman Desktop/CLI to build the image locally to verify there are no layer errors.

  • Decide directory stucture and make a PR with the Container file and a minimal documentation for how to test and use it

2. Registry Integration (GitHub Packages)

  • GHCR Authentication: Configure local Podman to authenticate with ghcr.io using a Personal Access Token (PAT).

  • Initial Push: Manually push the first stable image to the GitHub Container Registry associated with the repo.

3. Provisioning & Deployment

  • Boot test device (or VM) with a bootc distro.

  • Use bootc swith to deploy the image from the container repo (e.g. with bootc switch ghcr.io/os2sandbox/openclient-core:0.02)

  • Status Verification: Confirm the node is running the containerized OS (e.g. with bootc status)

4. Auto-Update Testing

  • Trigger Update: Modify a small component in the Containerfile, rebuild, and push a new version to GHCR.

  • Verify Pull: Ensure the remote node detects the new image version via the bootc-fetcher or a manual bootc update command.

  • Reboot Validation: Confirm the system performs a transactional update and reboots into the new image state without manual intervention.

Definition of Done (DoD)

  • The system boots successfully from an image hosted on GHCR.
  • bootc status shows the system is tracking the GitHub registry correctly.
  • A change pushed to the registry is automatically pulled and applied to the device.
  • Documentation provided for the Containerfile structure.
## 1. Image Creation & Local Build - [ ] Draft Containerfile: Create a multi-stage Containerfile based on a bootc-compatible image - [ ] Local Build: Use Podman Desktop/CLI to build the image locally to verify there are no layer errors. - [ ] Decide directory stucture and make a PR with the Container file and a minimal documentation for how to test and use it ## 2. Registry Integration (GitHub Packages) - [ ] GHCR Authentication: Configure local Podman to authenticate with ghcr.io using a Personal Access Token (PAT). - [ ] Initial Push: Manually push the first stable image to the GitHub Container Registry associated with the repo. ## 3. Provisioning & Deployment - [ ] Boot test device (or VM) with a bootc distro. - [ ] Use bootc swith to deploy the image from the container repo (e.g. with `bootc switch ghcr.io/os2sandbox/openclient-core:0.02`) - [ ] Status Verification: Confirm the node is running the containerized OS (e.g. with `bootc status`) ## 4. Auto-Update Testing - [ ] Trigger Update: Modify a small component in the Containerfile, rebuild, and push a new version to GHCR. - [ ] Verify Pull: Ensure the remote node detects the new image version via the bootc-fetcher or a manual bootc update command. - [ ] Reboot Validation: Confirm the system performs a transactional update and reboots into the new image state without manual intervention. ## Definition of Done (DoD) - The system boots successfully from an image hosted on GHCR. - bootc status shows the system is tracking the GitHub registry correctly. - A change pushed to the registry is automatically pulled and applied to the device. - Documentation provided for the Containerfile structure.
janhalen commented 2026-01-09 13:12:19 +00:00 (Migrated from github.com)

@ChatBotBerg : Please confirm that @turegjorup can start estimating this.

@turegjorup : Can you estmate this pro-bono? Otherwise hold on until @ChatBotBerg has given the go!

@ChatBotBerg : Please confirm that @turegjorup can start estimating this. @turegjorup : Can you estmate this pro-bono? Otherwise hold on until @ChatBotBerg has given the go!
rriemann commented 2026-03-19 20:07:39 +00:00 (Migrated from github.com)

Dear all,

we demonstrate how this work with our https://eu-os.eu PoC project.

More on this PoC: https://eu-os.eu/poc/

The relevant code to create the image:

As you find in our PoC documentation on the website, we load this image straight info Foreman and deploy via PXE boot to laptops (in our case Thinkpads).

The image is built very night using Gitlab CI.

The tool bluebuild supports Github and its registry even better than Gitlab, but we anticipate to run on sovereign code forges and have thus avoided dependencies on Github.

Happy to answer any more questions you may have.

Dear all, we demonstrate how this work with our https://eu-os.eu PoC project. More on this PoC: https://eu-os.eu/poc/ The relevant code to create the image: - Gitlab CI https://gitlab.com/eu-os/workspace-images/eu-os-base-demo/-/blob/main/.gitlab-ci.yml?ref_type=heads (`bluebuild build -vv -S sigstore --push ./recipes/$RECIPE`) - Recipe file: https://gitlab.com/eu-os/workspace-images/eu-os-base-demo/-/blob/main/recipes/almalinux-10.yml?ref_type=heads (we have also one for Fedora in the same folder) - Container files are created internally and only generated explicitly for transparency reasons: https://gitlab.com/eu-os/workspace-images/eu-os-base-demo/-/jobs/13556255166/artifacts/browse/recipes/ As you find in our PoC documentation on the website, we load this image straight info Foreman and deploy via PXE boot to laptops (in our case Thinkpads). The image is built very night using Gitlab CI. The tool bluebuild supports Github and its registry even better than Gitlab, but we anticipate to run on sovereign code forges and have thus avoided dependencies on Github. Happy to answer any more questions you may have.
janhalen commented 2026-03-23 07:48:07 +00:00 (Migrated from github.com)

@0xf1e: You are more than welcome to chip in with estimates for @ChatBotBerg to assemble into a development budget that can be presented to the steering comittee

@0xf1e: You are more than welcome to chip in with estimates for @ChatBotBerg to assemble into a development budget that can be presented to the steering comittee
janhalen commented 2026-03-23 08:09:46 +00:00 (Migrated from github.com)

Hey @rriemann! Thank you for the additional context and for walking us through your PoC.

Your approach is a clear demonstration of your choice of a more traditional provisioning stack, and we appreciate the transparency in sharing your GitLab CI and recipe files.

As we evaluate the long-term trajectory of our reference architecture, we are moving in a different direction regarding the "on-device" lifecycle. We have a few specific architectural requirements that are central to our goals:

  1. Minimizing Infrastructure Overhead: We are prioritizing a decentralized, "pull-based" model to reduce the number of moving parts. While PXE and management consoles like Foreman are established tools, they introduce significant external infrastructure dependencies. Our goal is to ensure the system is as resilient as possible by minimizing reliance on complex server-side environments.

  2. GitOps as the Single Source of Truth: For our security and robustness model, we build on a GitOps workflow where the Git repository is the sole authoritative state of the fleet. By avoiding intermediate "admin consoles", statefull "device databases" and manual management practises, we proactively eliminate configuration drift—a core requirement for our project's stability.

  3. Application and Config Delivery: We are leveraging modern patterns for modularity. Applications will be delivered either as part of the "core-apps" (e.g., LibreWolf) or as supplemental containerized apps via Logically Bound Images. This allows us to handle domain-specific or granular location-based configs (e.g., specific tags for self-service-pc or aarhus-municipal-library) entirely within the image structure, maintaining our "everything-is-an-image" philosophy.

  4. Standardization over Custom DSLs: As mentioned previously, we are staying strictly within the OCI-native Containerfile DSL. This ensures our images remain fully portable and compatible with the broader cloud-native ecosystem without requiring specific CLI wrappers or emerging community-specific abstractions.

We genuinely appreciate you sharing these details—it helps us clarify the boundaries of our own requirements. We’d be happy to keep the dialogue open as our respective projects evolve, particularly if there are future opportunities to align on raw OCI and GitOps-native workflows!

Hey @rriemann! Thank you for the additional context and for walking us through your PoC. Your approach is a clear demonstration of your choice of a more traditional provisioning stack, and we appreciate the transparency in sharing your GitLab CI and recipe files. As we evaluate the long-term trajectory of our reference architecture, we are moving in a different direction regarding the "on-device" lifecycle. We have a few specific architectural requirements that are central to our goals: 1. **Minimizing Infrastructure Overhead:** We are prioritizing a decentralized, "pull-based" model to reduce the number of moving parts. While PXE and management consoles like Foreman are established tools, they introduce significant external infrastructure dependencies. Our goal is to ensure the system is as resilient as possible by minimizing reliance on complex server-side environments. 2. **GitOps as the Single Source of Truth:** For our security and robustness model, we build on a GitOps workflow where the Git repository is the sole authoritative state of the fleet. By avoiding intermediate "admin consoles", statefull "device databases" and manual management practises, we proactively eliminate configuration drift—a core requirement for our project's stability. 3. **Application and Config Delivery:** We are leveraging modern patterns for modularity. Applications will be delivered either as part of the "core-apps" (e.g., LibreWolf) or as supplemental containerized apps via **[Logically Bound Images](https://bootc-dev.github.io/bootc/logically-bound-images.html)**. This allows us to handle domain-specific or granular location-based configs (e.g., specific tags for `self-service-pc` or `aarhus-municipal-library`) entirely within the image structure, maintaining our "everything-is-an-image" philosophy. 4. **Standardization over Custom DSLs:** As mentioned previously, we are staying strictly within the OCI-native Containerfile DSL. This ensures our images remain fully portable and compatible with the broader cloud-native ecosystem without requiring specific CLI wrappers or emerging community-specific abstractions. We genuinely appreciate you sharing these details—it helps us clarify the boundaries of our own requirements. We’d be happy to keep the dialogue open as our respective projects evolve, particularly if there are future opportunities to align on raw OCI and GitOps-native workflows!
agnetemoos commented 2026-03-26 10:46:45 +00:00 (Migrated from github.com)

I have looked into https://universal-blue.org/ and suggest using a base image from that project for the OS2BorgerPC POC.

Universal Blue is a real-world implementation of the NornNet idea. The project maintains a range of base images and builds custom distros on top of those.

They encourage the community to create custom images based on their base images, and they provide a fine, well-documented template for that: https://github.com/ublue-os/image-template.

The Universal Blue community is very active. There are discussion forums, chat, video tutorials, and lots of fine documentation.

I have looked into [https://universal-blue.org/](https://universal-blue.org/) and suggest using a base image from that project for the OS2BorgerPC POC. Universal Blue is a real-world implementation of the NornNet idea. The project maintains a range of base images and builds custom distros on top of those. They encourage the community to create custom images based on their base images, and they provide a fine, well-documented template for that: [https://github.com/ublue-os/image-template](https://github.com/ublue-os/image-template). The Universal Blue community is very active. There are discussion forums, chat, video tutorials, and lots of fine documentation.
janhalen commented 2026-03-26 11:27:45 +00:00 (Migrated from github.com)

@agnetemoos: I certainly appreciate your desire for momentum on this. However, before we commit to an indie developer ecosystem that carries significant pre-existing configurations, it would be prudent to finalize our core "Whys." This will ensure we don't inadvertently select a base image populated with software that is incompatible with or not needed for our specific user stories.

For our foundational layer, we should seek a bootc-native distribution with a minimal footprint. While the uBlue desktop images are impressive for personal workstations, they are perhaps too "opinionated" for the "selvbetjening" (self-service) or kiosk domains we are targeting.

Having tested Bluefin as a daily driver for several months, I have found it to be heavily customized—containing very non standard software choices, such as native IDE installations on the immutable host, that do not align with a streamlined immutable production environment.

My recommendation for our architectural approach:

  • Strict Separation of Concerns: We should utilize a clean, minimal base image and layer domain-specific requirements on top.
  • Purpose-Built Design: Avoid the "universal image" approach in favor of one tailored strictly to our delivery goals.

For the Proof of Concept, I believe a "less is more" philosophy will serve us best.

@agnetemoos: I certainly appreciate your desire for momentum on this. However, before we commit to an indie developer ecosystem that carries significant pre-existing configurations, it would be prudent to finalize our core "Whys." This will ensure we don't inadvertently select a base image populated with software that is incompatible with or not needed for our specific user stories. For our foundational layer, we should seek a bootc-native distribution with a minimal footprint. While the uBlue desktop images are impressive for personal workstations, they are perhaps too "opinionated" for the "selvbetjening" (self-service) or kiosk domains we are targeting. Having tested Bluefin as a daily driver for several months, I have found it to be heavily customized—containing very non standard software choices, such as native IDE installations on the immutable host, that do not align with a streamlined immutable production environment. My recommendation for our architectural approach: - Strict Separation of Concerns: We should utilize a clean, minimal base image and layer domain-specific requirements on top. - Purpose-Built Design: Avoid the "universal image" approach in favor of one tailored strictly to our delivery goals. For the Proof of Concept, I believe a "less is more" philosophy will serve us best.
agnetemoos commented 2026-03-26 11:47:43 +00:00 (Migrated from github.com)

For a prototype, speed and evidence of real-world usability are crucial. A complete infrastructure project is not within the scope of a prototype.

An infrastructure setup will, of course, be needed if the prototype succeeds and receives further funding. But further funding is usually tied to the prototype providing evidence that it can produce the product it promises — namely a BorgerPC.

I am aware that Bluefin has too much software bundled in. I don't suggest using that as a base image

For a prototype, speed and evidence of real-world usability are crucial. A complete infrastructure project is not within the scope of a prototype. An infrastructure setup will, of course, be needed if the prototype succeeds and receives further funding. But further funding is usually tied to the prototype providing evidence that it can produce the product it promises — namely a BorgerPC. I am aware that Bluefin has too much software bundled in. I don't suggest using that as a base image
0xf1e commented 2026-03-26 12:01:52 +00:00 (Migrated from github.com)

Hello Agenete and Jan!

To quickly introduce myself, I am Fie, and I am a self-employed Cloud Engineer under the name cormora Open Source (https://cormora.dk). I have had a chat with Jan a few days ago about this project, and reading this conversation I thought I'd provide my perspective:

I have also tried to figure out the right "scope" for this PoC, and I think one way of deciding what should be in a prototype, i.e. which parts should be realistic, and which can be kept simple, the question is: Where do you currently see the most uncertainties and risks?

The goal of a PoC is usually to evaluate the highest-risk parts of a design. So what I would like to ask both of you, is: Which parts of the nornnet design make you think "I think this should work the way it is described here, but I'm not entirely sure either" (likelihood of failure)? And which parts make you think "If this part of the design doesn't work the way we expect it to, it's going to be really costly" (impact of failure)?

Every software project decisions that will inevitably fail. But with a PoC, we can ensure that we fail early, rather than late in the development process when changes will be costly.

In my opinion, any part of the system can be a fit for a PoC, as long as that is the part of the system where you see the highest risk (failure impact x failure likelihood).

Hello Agenete and Jan! To quickly introduce myself, I am Fie, and I am a self-employed Cloud Engineer under the name cormora Open Source (https://cormora.dk). I have had a chat with Jan a few days ago about this project, and reading this conversation I thought I'd provide my perspective: I have also tried to figure out the right "scope" for this PoC, and I think one way of deciding what should be in a prototype, i.e. which parts should be realistic, and which can be kept simple, the question is: Where do you currently see the most uncertainties and risks? The goal of a PoC is usually to evaluate the highest-risk parts of a design. So what I would like to ask both of you, is: Which parts of the nornnet design make you think _"I think this should work the way it is described here, but I'm not entirely sure either"_ (likelihood of failure)? And which parts make you think _"If this part of the design doesn't work the way we expect it to, it's going to be really costly"_ (impact of failure)? Every software project decisions that will inevitably fail. But with a PoC, we can ensure that we _fail early_, rather than late in the development process when changes will be costly. In my opinion, any part of the system can be a fit for a PoC, as long as that is the part of the system where you see the highest risk (failure impact x failure likelihood).
janhalen commented 2026-03-30 08:15:01 +00:00 (Migrated from github.com)

Discussing scoping of the PoC and its goals, milestones and risk assesment is not what this issue is about.

Lets keep this issue about describing the actual basic component that needs to be in place for delivering a working image and a working deployment of an image.. (whatever those might end up being)

I have done som triaging work, have created a new issue and have copied your ( @agnetemoos & @0xf1e ) comments into that new issue here: #27 and i have minimized you comments here instead of deleting them, so be able to track their origin.

Discussing scoping of the PoC and its goals, milestones and risk assesment is not what this issue is about. Lets keep this issue about describing the actual basic component that needs to be in place for delivering a working image and a working deployment of an image.. (whatever those might end up being) I have done som triaging work, have created a new issue and have copied your ( @agnetemoos & @0xf1e ) comments into that new issue here: #27 and i have minimized you comments here instead of deleting them, so be able to track their origin.
Sign in to join this conversation.
No description provided.