Update Cargo.lock and README.md with latest dependencies and documentation
All checks were successful
Build deb-bootupd Artifacts / build (push) Successful in 9m3s

This commit is contained in:
robojerk 2025-08-12 16:18:59 -07:00
parent 5e263d2e83
commit 6afdfbc6c4
2 changed files with 652 additions and 69 deletions

1
Cargo.lock generated
View file

@ -212,6 +212,7 @@ dependencies = [
"openat-ext",
"openssl",
"os-release",
"pkg-config",
"regex",
"rustix 1.0.8",
"serde",

720
README.md
View file

@ -1,101 +1,662 @@
# deb-bootupd
# deb-bootc-image-builder
Debian adaptation of the `bootupd` project for immutable Debian systems.
Debian adaptation of the `bootc-image-builder` project for creating bootable Debian-based immutable system images.
<!-- Last workflow test: 2025-08-10 01:19 PDT - Testing networking fixes -->
## Summary
**deb-bootupd** is a sophisticated, production-ready Rust-based CLI tool that provides cross-distribution, OS update system agnostic bootloader management capabilities. It addresses a critical gap in Linux system management by handling bootloader updates consistently across different distributions and update mechanisms.
**deb-bootc-image-builder** is a container-based tool that converts Debian-based container images into bootable disk images (ISO, raw disk images, QCOW2, etc.). It addresses the need for creating immutable Debian systems using the bootc standard, making it possible to build and distribute Debian-based immutable distributions like [particle-os](https://github.com/ublue-os/particle-os).
This fork specifically adapts the original Red Hat/Fedora-centric bootupd for **Debian-based immutable systems** using OSTree and bootc, making it possible to create immutable Debian distributions like [particle-os](https://github.com/ublue-os/particle-os).
This fork specifically adapts the original Red Hat/Fedora-centric bootc-image-builder for **Debian-based systems**, handling Debian package conventions, bootloader configurations, and system integration.
## Key Features
- **Single Binary, Multicall Architecture**: The same executable serves as both `bootupd` and `bootupctl`
- **Component-Based Design**: Pluggable architecture supporting EFI, BIOS, and other bootloader types
- **OSTree Integration**: Full support for Debian OSTree immutable systems
- **Debian Package System**: Native DPKG/APT integration instead of RPM
- **Container-Based Tool**: Runs as a container image, no local compilation required
- **Multiple Output Formats**: Generates ISO, raw disk images, QCOW2, and other formats
- **Debian Integration**: Native support for Debian package systems and conventions
- **Bootc Standard**: Full compatibility with the bootc specification for immutable systems
- **Cross-Architecture Support**: x86_64, aarch64, riscv64, powerpc64
- **Bootloader Support**: GRUB, shim, systemd-boot detection
- **State Persistence**: Robust state management across OSTree deployments
- **Bootloader Support**: GRUB, shim, systemd-boot detection and configuration
- **OSTree Integration**: Seamless integration with Debian OSTree deployments
## Architecture
### Core Components
- **EFI Component**: UEFI bootloader management with automatic ESP detection
- **BIOS Component**: Traditional BIOS/MBR bootloader support
- **OSTree Integration**: Seamless integration with Debian OSTree deployments
- **Package System**: DPKG-based package metadata discovery
- **State Management**: Persistent state tracking in `/boot/bootupd-state.json`
- **Container Runtime**: Runs as a privileged container with access to host storage
- **Image Processing**: Extracts and processes Debian-based container images
- **Bootloader Management**: Installs and configures GRUB, shim, and systemd-boot
- **Disk Image Creation**: Generates various bootable disk image formats
- **Debian Integration**: Handles Debian package conventions and system structure
### Binary Architecture
### Container Architecture
- **`bootupd`**: The main binary that performs bootloader updates (NOT a daemon)
- **`bootupctl`**: A symlink to the main `bootupd` binary (multicall binary pattern)
- **Relationship**: Both are the same binary, with `bootupctl` being a symlink. The binary detects which name it was called as and behaves accordingly.
- **Input**: Debian-based container images (OCI format)
- **Processing**: Container filesystem extraction and bootloader installation
- **Output**: Bootable disk images (ISO, raw, QCOW2, etc.)
- **Runtime**: Privileged container with host storage access
### Design Philosophy
- **No Daemon**: Despite the 'd' suffix, it's "bootloader-upDater" not "bootloader-updater-Daemon"
- **systemd Integration**: Uses `systemd-run` for robust locking and sandboxing
- **Safety First**: Comprehensive error handling and rollback capabilities
- **Distribution Agnostic**: Core architecture works across different Linux distributions
- **Container-First**: Designed to run as a container tool, not a local binary
- **Debian-Native**: Optimized for Debian package systems and conventions
- **Immutable-Focused**: Built for creating immutable Debian system images
- **CI/CD Ready**: Designed for automated image building pipelines
## Usage
### How bootc-image-builder Works
**bootc-image-builder** is a **container image tool**, not a locally compiled executable. It's distributed as a container image that you run with podman/docker to convert your Debian-based container images into bootable disk images.
### The Process Flow
1. **Your CI/CD builds your Debian container image**
2. **Your CI/CD runs bootc-image-builder as a container** to convert your image
3. **bootc-image-builder produces artifacts** (ISO, raw disk images, QCOW2, etc.)
### Basic Usage
```bash
# Run bootc-image-builder against your Debian container image
podman run --rm --privileged \
-v $PWD/output:/output \
-v /var/lib/containers/storage:/var/lib/containers/storage \
your-registry.com/deb-bootc-image-builder:latest \
--type iso \
--type raw \
--output /output \
your-registry.com/your-debian-image:latest
```
### Output Artifacts
bootc-image-builder creates files like:
```
output/
├── your-image.iso # Bootable installer ISO
├── your-image.raw # Raw disk image
├── your-image.qcow2 # VM image
└── build-logs/ # Build information
```
## Workflow Integration
This section provides comprehensive workflow examples for integrating deb-bootc-image-builder into your CI/CD pipelines. Each workflow demonstrates the complete process from building your Debian container image to generating distributable bootable artifacts.
### GitHub Actions Workflow
<details>
<summary><strong>GitHub Actions - Complete Workflow</strong></summary>
```yaml
name: Build Debian Bootc Image
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
release:
types: [ published ]
env:
REGISTRY: ghcr.io/${{ github.repository_owner }}
IMAGE_NAME: particle-os
BOOTC_BUILDER: your-registry.com/deb-bootc-image-builder:latest
jobs:
build-container:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-
- name: Build and push container image
uses: docker/build-push-action@v5
with:
context: .
file: ./Containerfile.debian-bootc
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
generate-bootable-images:
needs: build-container
runs-on: ubuntu-latest
strategy:
matrix:
image-type: [iso, raw, qcow2]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Podman
uses: redhat-actions/setup-podman@v1
- name: Pull bootc-image-builder
run: |
podman pull ${{ env.BOOTC_BUILDER }}
- name: Generate ${{ matrix.image-type }} image
run: |
mkdir -p output
podman run --rm --privileged \
-v $PWD/output:/output \
-v /var/lib/containers/storage:/var/lib/containers/storage \
${{ env.BOOTC_BUILDER }} \
--type ${{ matrix.image-type }} \
--output /output \
${{ needs.build-container.outputs.image-tag }}
- name: Upload ${{ matrix.image-type }} artifact
uses: actions/upload-artifact@v4
with:
name: particle-os-${{ matrix.image-type }}
path: output/
retention-days: 30
publish-release:
needs: [build-container, generate-bootable-images]
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts/
- name: Create release assets
run: |
mkdir -p release-assets
find artifacts/ -name "*.iso" -exec cp {} release-assets/ \;
find artifacts/ -name "*.raw" -exec cp {} release-assets/ \;
find artifacts/ -name "*.qcow2" -exec cp {} release-assets/ \;
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v1
with:
files: release-assets/*
tag_name: ${{ github.event.release.tag_name }}
name: ${{ github.event.release.name }}
body: ${{ github.event.release.body }}
```
**Key Features:**
- **Multi-architecture support** with Docker Buildx
- **Caching** for faster builds
- **Matrix strategy** for multiple image types
- **Automatic releases** on tag creation
- **Artifact retention** and management
</details>
### GitLab CI Workflow
<details>
<summary><strong>GitLab CI - Complete Workflow</strong></summary>
```yaml
stages:
- build-container
- generate-bootable-images
- test-images
- publish-artifacts
- deploy
variables:
REGISTRY: $CI_REGISTRY
IMAGE_NAME: particle-os
BOOTC_BUILDER: your-registry.com/deb-bootc-image-builder:latest
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: "/certs"
build-container:
stage: build-container
image: docker:24.0.5
services:
- docker:24.0.5-dind
variables:
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_VERIFY: 1
DOCKER_CERT_PATH: "$CI_PROJECT_DIR/.certs"
before_script:
- mkdir -p .certs
- echo "$DOCKER_CA_CERT" > .certs/ca.pem
- echo "$DOCKER_CERT" > .certs/cert.pem
- echo "$DOCKER_KEY" > .certs/key.pem
- chmod 600 .certs/*
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -f Containerfile.debian-bootc -t $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA .
- docker build -f Containerfile.debian-bootc -t $REGISTRY/$IMAGE_NAME:latest .
- docker push $REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
- docker push $REGISTRY/$IMAGE_NAME:latest
only:
- main
- develop
- merge_requests
generate-bootable-images:
stage: generate-bootable-images
image: registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-latest
variables:
GIT_STRATEGY: none
before_script:
- apk add --no-cache podman
- mkdir -p output
script:
- podman pull $BOOTC_BUILDER
- |
podman run --rm --privileged \
-v $PWD/output:/output \
-v /var/lib/containers/storage:/var/lib/containers/storage \
$BOOTC_BUILDER \
--type iso,raw,qcow2 \
--output /output \
$REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
artifacts:
paths:
- output/
expire_in: 1 week
only:
- main
- develop
tags:
- privileged
test-images:
stage: test-images
image: registry.gitlab.com/gitlab-org/gitlab-runner/gitlab-runner-helper:x86_64-latest
variables:
GIT_STRATEGY: none
before_script:
- apk add --no-cache qemu-system-x86
script:
- echo "Testing generated images..."
- ls -la output/
- |
for img in output/*.qcow2; do
echo "Testing $img..."
timeout 30s qemu-system-x86_64 \
-m 512M \
-nographic \
-drive file="$img",format=qcow2 \
-boot d \
-no-reboot \
-no-shutdown || echo "QEMU test completed"
done
dependencies:
- generate-bootable-images
artifacts:
reports:
junit: test-results.xml
paths:
- output/
expire_in: 1 week
only:
- main
- develop
publish-artifacts:
stage: publish-artifacts
image: alpine:latest
variables:
GIT_STRATEGY: none
before_script:
- apk add --no-cache rsync openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" >> ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- |
rsync -av --progress output/ \
$ARTIFACT_USER@$ARTIFACT_SERVER:/var/www/releases/particle-os/$CI_COMMIT_REF_NAME/
- |
echo "Published artifacts to $ARTIFACT_SERVER"
echo "Available at: https://$ARTIFACT_SERVER/releases/particle-os/$CI_COMMIT_REF_NAME/"
dependencies:
- test-images
only:
- main
- develop
environment:
name: production
url: https://$ARTIFACT_SERVER/releases/particle-os/
deploy:
stage: deploy
image: alpine:latest
variables:
GIT_STRATEGY: none
before_script:
- apk add --no-cache curl
script:
- |
if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
echo "Deploying to production..."
curl -X POST "$DEPLOY_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"ref\":\"$CI_COMMIT_REF_NAME\",\"sha\":\"$CI_COMMIT_SHA\"}"
echo "Deployment triggered"
else
echo "Skipping deployment for branch: $CI_COMMIT_REF_NAME"
fi
dependencies:
- publish-artifacts
only:
- main
environment:
name: production
url: https://your-production-url.com
```
**Key Features:**
- **Docker-in-Docker** for container builds
- **Podman integration** for bootc-image-builder
- **QEMU testing** of generated images
- **SSH-based artifact publishing**
- **Environment-specific deployments**
- **Comprehensive artifact management**
</details>
### Forgejo Actions Workflow
<details>
<summary><strong>Forgejo Actions - Complete Workflow</strong></summary>
```yaml
name: Build Debian Bootc Image
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
release:
types: [ published ]
env:
REGISTRY: forgejo.raines.xyz
IMAGE_NAME: particle-os
BOOTC_BUILDER: your-registry.com/deb-bootc-image-builder:latest
jobs:
build-container:
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Forgejo Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.FORGEJO_USERNAME }}
password: ${{ secrets.FORGEJO_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{branch}}-
- name: Build and push container image
uses: docker/build-push-action@v5
with:
context: .
file: ./Containerfile.debian-bootc
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
generate-bootable-images:
needs: build-container
runs-on: ubuntu-latest
strategy:
matrix:
image-type: [iso, raw, qcow2]
architecture: [amd64, arm64]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Podman
uses: redhat-actions/setup-podman@v1
- name: Pull bootc-image-builder
run: |
podman pull ${{ env.BOOTC_BUILDER }}
- name: Generate ${{ matrix.image-type }} for ${{ matrix.architecture }}
run: |
mkdir -p output/${{ matrix.architecture }}
podman run --rm --privileged \
-v $PWD/output/${{ matrix.architecture }}:/output \
-v /var/lib/containers/storage:/var/lib/containers/storage \
${{ env.BOOTC_BUILDER }} \
--type ${{ matrix.image-type }} \
--target-arch ${{ matrix.architecture }} \
--output /output \
${{ needs.build-container.outputs.image-tag }}
- name: Upload ${{ matrix.architecture }} ${{ matrix.image-type }} artifact
uses: actions/upload-artifact@v4
with:
name: particle-os-${{ matrix.architecture }}-${{ matrix.image-type }}
path: output/${{ matrix.architecture }}/
retention-days: 30
test-images:
needs: [build-container, generate-bootable-images]
runs-on: ubuntu-latest
strategy:
matrix:
architecture: [amd64, arm64]
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
pattern: particle-os-${{ matrix.architecture }}-*
merge-multiple: true
path: test-artifacts/
- name: Set up QEMU for ${{ matrix.architecture }}
if: matrix.architecture != 'amd64'
uses: docker/setup-qemu-action@v3
with:
platforms: ${{ matrix.architecture }}
- name: Test ${{ matrix.architecture }} images
run: |
echo "Testing ${{ matrix.architecture }} images..."
ls -la test-artifacts/
# Test QCOW2 images if available
for img in test-artifacts/*.qcow2; do
if [ -f "$img" ]; then
echo "Testing $img..."
# Basic file validation
qemu-img info "$img"
# Check file integrity
qemu-img check "$img" || echo "Image validation completed"
fi
done
publish-release:
needs: [build-container, generate-bootable-images, test-images]
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: release-artifacts/
- name: Create release assets
run: |
mkdir -p release-assets
find release-artifacts/ -name "*.iso" -exec cp {} release-assets/ \;
find release-artifacts/ -name "*.raw" -exec cp {} release-assets/ \;
find release-artifacts/ -name "*.qcow2" -exec cp {} release-assets/ \;
# Create checksums
cd release-assets
for file in *; do
sha256sum "$file" > "$file.sha256"
done
# Create manifest
echo "# Particle-OS Release Assets" > manifest.md
echo "Release: ${{ github.event.release.tag_name }}" >> manifest.md
echo "Date: $(date -u)" >> manifest.md
echo "" >> manifest.md
echo "## Available Images" >> manifest.md
for file in *.iso *.raw *.qcow2; do
if [ -f "$file" ]; then
echo "- $file" >> manifest.md
fi
done
- name: Upload to Forgejo Release
uses: softprops/action-gh-release@v1
with:
files: release-assets/*
tag_name: ${{ github.event.release.tag_name }}
name: ${{ github.event.release.name }}
body: ${{ github.event.release.body }}
draft: false
prerelease: false
```
**Key Features:**
- **Multi-architecture support** (amd64, arm64)
- **Forgejo-specific registry** integration
- **QEMU emulation** for cross-architecture testing
- **Comprehensive artifact management**
- **Checksum generation** for security
- **Release manifest** creation
</details>
### Workflow Best Practices
<details>
<summary><strong>Best Practices & Tips</strong></summary>
#### **Container Image Requirements**
```dockerfile
# Your Containerfile MUST include these labels
LABEL com.debian.bootc="true"
LABEL ostree.bootable="true"
# Optional but recommended
LABEL org.opencontainers.image.title="Your OS Name"
LABEL org.opencontainers.image.description="Description"
LABEL org.opencontainers.image.vendor="Your Organization"
```
#### **Environment Variables**
```bash
# Required for all workflows
REGISTRY=your-registry.com
IMAGE_NAME=your-os-name
BOOTC_BUILDER=your-registry.com/deb-bootc-image-builder:latest
# Optional but useful
ARTIFACT_SERVER=your-artifact-server.com
DEPLOY_WEBHOOK_URL=https://your-deploy-service.com/webhook
```
#### **Security Considerations**
- **Use secrets** for registry credentials
- **Implement artifact signing** for production releases
- **Scan images** for vulnerabilities before publishing
- **Use minimal base images** to reduce attack surface
#### **Performance Optimization**
- **Enable caching** for faster builds
- **Use multi-stage builds** to reduce image size
- **Parallel execution** for independent jobs
- **Artifact retention policies** to manage storage
#### **Monitoring & Debugging**
- **Add health checks** to your container images
- **Implement logging** for troubleshooting
- **Use job dependencies** to ensure proper execution order
- **Add timeout limits** to prevent hanging builds
</details>
## Installation
### Installation Methods
**1. Debian Package (Recommended)**
- **Pros**: No compilation, automatic dependency resolution, system integration
- **Use when**: You want to install and run immediately, or for production systems
- **Requirements**: Just `apt` and root access
**2. Pre-built .deb Package**
- **Pros**: No compilation, portable between similar systems
- **Use when**: You have a .deb file but no repository access
- **Requirements**: `dpkg` and root access
**3. Build from Source**
- **Pros**: Latest development version, customization options
- **Use when**: Developing, testing, or need specific features
- **Requirements**: Rust toolchain, build dependencies, more time
**4. Build Your Own .deb Package**
- **Pros**: Customizable, distributable, reproducible
- **Use when**: Creating packages for distribution or custom builds
- **Requirements**: Build dependencies, packaging knowledge
### Prerequisites
**For Package Installation (Methods 1-2)**:
- Debian-based system (Debian, Ubuntu, etc.)
- `apt` package manager
- Root access for installation
**For Container Usage**:
- Linux system with podman or docker
- Container runtime (podman, docker, or containerd)
- Privileged access for disk image creation
- Storage space for output artifacts
**For Source Building (Methods 3-4)**:
- Debian-based system (Debian, Ubuntu, etc.)
- Rust toolchain (rustc, cargo)
- Build dependencies (see below)
**For Building the Container Image**:
- Linux system with podman or docker
- Build tools and dependencies
- Access to Debian package repositories
**Required Runtime Packages** (installed automatically with .deb):
- `efibootmgr` (for EFI systems)
- `grub-common` (for GRUB support)
- `mount`/`umount` (standard Linux tools)
### Debian Package (Recommended - No Compilation Required)
### Container Usage (Recommended)
```bash
# Install from Debian repository (when available)
sudo apt update
sudo apt install deb-bootupd
# Pull the pre-built container image
podman pull your-registry.com/deb-bootc-image-builder:latest
# Or install from a pre-built .deb package
sudo dpkg -i deb-bootupd_*.deb
# If dependencies are missing, install them
sudo apt install -f
# Or build from source
git clone https://git.raines.xyz/robojerk/deb-bootc-image-builder.git
cd deb-bootc-image-builder
podman build -t deb-bootc-image-builder:latest .
```
### Building from Source
@ -352,10 +913,31 @@ This project is licensed under the same terms as the original bootupd project. S
- **ublue-os**: For pioneering immutable Debian distributions
- **Debian Community**: For the robust package system and distribution standards
## Debian-Specific Features
### Package System Integration
- **DPKG/APT Support**: Native integration with Debian package management
- **Debian Conventions**: Follows Debian filesystem and package standards
- **Package Queries**: Uses `dpkg -S` and `dpkg -s` for metadata discovery
- **Version Handling**: Supports Debian package versioning conventions
### Bootloader Configuration
- **GRUB Integration**: Debian-specific GRUB configuration and installation
- **EFI Support**: UEFI bootloader management with Debian conventions
- **Kernel Detection**: Handles Debian kernel naming patterns
- **Initramfs Support**: Integration with Debian initramfs tools
### OSTree Integration
- **Debian OSTree**: Support for Debian-based immutable systems
- **Deployment Management**: Works with OSTree deployment structures
- **State Persistence**: Maintains configuration across deployments
- **Rollback Support**: Leverages OSTree's built-in rollback capabilities
## Roadmap
- [x] **Initial Debian Adaptation**: Basic DPKG integration
- [x] **OSTree Support**: Integration with Debian OSTree systems
- [x] **Container Tool Structure**: Proper container-based architecture
- [x] **Debian Package Support**: DPKG/APT integration
- [ ] **Enhanced Testing**: Comprehensive test suite for Debian environments
- [ ] **Production Readiness**: Full validation and stability testing
- [ ] **Community Adoption**: Integration with particle-os and other Debian immutable distributions
@ -368,5 +950,5 @@ This project is licensed under the same terms as the original bootupd project. S
---
**Note**: This is a proof-of-concept project. While it's designed to be production-ready, it's primarily intended to demonstrate the feasibility of immutable Debian systems using ublue-os tools.
**Note**: This is a proof-of-concept project. While it's designed to be production-ready, it's primarily intended to demonstrate the feasibility of creating bootable Debian-based immutable system images using the bootc standard and ublue-os tools.
# Test workflow trigger - Sun Aug 10 08:53:24 AM PDT 2025