954 lines
29 KiB
Markdown
954 lines
29 KiB
Markdown
# deb-bootc-image-builder
|
|
|
|
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-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 bootc-image-builder for **Debian-based systems**, handling Debian package conventions, bootloader configurations, and system integration.
|
|
|
|
## Key Features
|
|
|
|
- **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 and configuration
|
|
- **OSTree Integration**: Seamless integration with Debian OSTree deployments
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
|
|
- **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
|
|
|
|
### Container Architecture
|
|
|
|
- **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
|
|
|
|
- **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
|
|
|
|
### Prerequisites
|
|
|
|
**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 Building the Container Image**:
|
|
- Linux system with podman or docker
|
|
- Build tools and dependencies
|
|
- Access to Debian package repositories
|
|
|
|
### Container Usage (Recommended)
|
|
|
|
```bash
|
|
# Pull the pre-built container image
|
|
podman pull your-registry.com/deb-bootc-image-builder:latest
|
|
|
|
# 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
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone https://git.raines.xyz/robojerk/deb-bootupd.git
|
|
cd deb-bootupd
|
|
|
|
# Build the project
|
|
cargo build --release
|
|
|
|
# Install (requires root)
|
|
sudo cargo install --path .
|
|
```
|
|
|
|
### Running as Rust Script (Development)
|
|
|
|
```bash
|
|
# Clone the repository
|
|
git clone https://git.raimes.xyz/robojerk/deb-bootupd.git
|
|
cd deb-bootupd
|
|
|
|
# Run directly without installing (development mode)
|
|
cargo run -- status # Run bootupctl status
|
|
cargo run -- update # Run bootupctl update
|
|
cargo run -- adopt-and-update # Run bootupctl adopt-and-update
|
|
|
|
# Run with specific binary name (multicall binary)
|
|
cargo run --bin bootupd -- status # Run as bootupd binary
|
|
cargo run --bin bootupctl -- status # Run as bootupctl binary
|
|
|
|
# Run with debug output
|
|
RUST_LOG=debug cargo run -- status
|
|
|
|
# Run with custom log level
|
|
RUST_LOG=info cargo run -- status
|
|
|
|
# Run specific tests
|
|
cargo test # Run all tests
|
|
cargo test --package deb-bootupd # Run package tests
|
|
cargo test --test integration # Run integration tests
|
|
|
|
# Development workflow
|
|
cargo check # Check compilation without building
|
|
cargo clippy # Run linter
|
|
cargo fmt --check # Check code formatting
|
|
cargo fmt # Auto-format code
|
|
```
|
|
|
|
### How the Multicall Binary Works
|
|
|
|
deb-bootupd uses a **multicall binary pattern** - a single Rust executable that behaves differently based on how it's called:
|
|
|
|
```bash
|
|
# When called as 'bootupd' (main binary)
|
|
cargo run --bin bootupd -- install --src-root /src --dest-root /dest
|
|
|
|
# When called as 'bootupctl' (CLI interface)
|
|
cargo run --bin bootupctl -- status
|
|
cargo run --bin bootupctl -- update
|
|
|
|
# The binary detects argv[0] and switches behavior accordingly
|
|
```
|
|
|
|
**Benefits for Development:**
|
|
- **Single codebase**: All functionality in one Rust project
|
|
- **Easy testing**: Test both modes from one source
|
|
- **Consistent behavior**: Same binary, different interfaces
|
|
- **Simplified deployment**: One executable to install
|
|
|
|
### Building Your Own Debian Package
|
|
|
|
```bash
|
|
# Install build dependencies
|
|
sudo apt install build-essential dh-cargo rustc cargo pkg-config libssl-dev libsystemd-dev
|
|
|
|
# Build Debian package
|
|
dpkg-buildpackage -b
|
|
|
|
# Install the resulting package
|
|
sudo dpkg -i ../deb-bootupd_*.deb
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
### Install and Run (No Compilation)
|
|
|
|
```bash
|
|
# 1. Install the package (when available in repositories)
|
|
sudo apt update && sudo apt install deb-bootupd
|
|
|
|
# 2. Check if it's working
|
|
bootupctl status
|
|
|
|
# 3. You're ready to use deb-bootupd!
|
|
```
|
|
|
|
### Automated Builds with Forgejo Actions
|
|
|
|
This repository includes Forgejo Actions workflows for automated building and artifact management:
|
|
|
|
- **`.forgejo/workflows/build-artifacts.yml`** - Full build pipeline with Forgejo Package Registry upload
|
|
- **`.forgejo/workflows/simple-build.yml`** - Simple build with artifact upload
|
|
|
|
**Setup Requirements:**
|
|
1. Add `ACCESS_TOKEN` secret to repository settings
|
|
2. Token needs `repo` and `write:packages` permissions
|
|
3. Workflows trigger on push/PR to main/master branches
|
|
|
|
**What Gets Built:**
|
|
- Rust binaries (release mode)
|
|
- Source code artifacts
|
|
- Debian packaging files
|
|
- Systemd service files
|
|
|
|
## Usage
|
|
|
|
### Basic Commands
|
|
|
|
```bash
|
|
# Check system status
|
|
bootupctl status
|
|
|
|
# Update all bootloader components
|
|
bootupctl update
|
|
|
|
# Adopt existing bootloaders and update them
|
|
bootupctl adopt-and-update
|
|
|
|
# Validate system state
|
|
bootupctl validate
|
|
```
|
|
|
|
### Advanced Operations
|
|
|
|
```bash
|
|
# Generate update metadata (for image builders)
|
|
bootupd generate-update-metadata
|
|
|
|
# Install bootloader components
|
|
bootupd install --src-root /path/to/source --dest-root /path/to/destination
|
|
```
|
|
|
|
## OSTree Integration
|
|
|
|
deb-bootupd is specifically designed for **Debian OSTree immutable systems**:
|
|
|
|
- **Image-based Updates**: Updates come from new bootc images, not traditional package repositories
|
|
- **Deployment Coordination**: Works seamlessly with OSTree deployment system
|
|
- **State Persistence**: Bootloader state survives across OSTree deployments
|
|
- **Rollback Support**: Leverages OSTree's built-in rollback capabilities
|
|
|
|
### Particle-OS Integration
|
|
|
|
This fork is specifically designed to work with [particle-os](https://github.com/ublue-os/particle-os), a Debian-based immutable distribution:
|
|
|
|
- **Hybrid Approach**: Debian packages within immutable OSTree structure
|
|
- **Bootc Integration**: Full integration with bootc image builder
|
|
- **Debian Conventions**: Follows Debian filesystem and package conventions
|
|
|
|
## Configuration
|
|
|
|
### State File Location
|
|
|
|
- **State File**: `/boot/bootupd-state.json`
|
|
- **Lock File**: `/run/bootupd-lock`
|
|
- **Updates Directory**: `/usr/lib/bootupd/updates`
|
|
|
|
### Component Configuration
|
|
|
|
Components are automatically detected and configured based on your system:
|
|
|
|
- **EFI Systems**: Automatic ESP detection and UEFI boot entry management
|
|
- **BIOS Systems**: Direct MBR manipulation for traditional bootloaders
|
|
- **Hybrid Systems**: Support for both EFI and BIOS configurations
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
deb-bootupd/
|
|
├── src/ # Source code
|
|
│ ├── efi.rs # EFI component implementation
|
|
│ ├── bios.rs # BIOS component implementation
|
|
│ ├── ostreeutil.rs # OSTree integration
|
|
│ ├── packagesystem.rs # DPKG package system integration
|
|
│ └── ...
|
|
├── systemd/ # Systemd service files
|
|
├── tests/ # Test suite
|
|
├── Cargo.toml # Rust dependencies
|
|
└── debian/ # Debian packaging files
|
|
```
|
|
|
|
### Key Adaptations from Upstream
|
|
|
|
1. **Package System**: Replaced RPM with DPKG/APT integration
|
|
2. **OS Detection**: Enhanced for Debian family distributions
|
|
3. **Path Conventions**: Adapted for Debian filesystem standards
|
|
4. **OSTree Integration**: Optimized for Debian OSTree deployments
|
|
|
|
### Building and Testing
|
|
|
|
```bash
|
|
# Run tests
|
|
cargo test
|
|
|
|
# Run with specific features
|
|
cargo test --features integration
|
|
|
|
# Check code quality
|
|
cargo clippy
|
|
cargo fmt
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Permission Denied**: Ensure you're running with root privileges
|
|
2. **EFI Not Detected**: Verify `efibootmgr` is installed and EFI is enabled
|
|
3. **OSTree Integration**: Check that OSTree is properly configured
|
|
4. **Package Queries**: Ensure DPKG database is accessible
|
|
|
|
### Debug Mode
|
|
|
|
```bash
|
|
# Enable debug logging
|
|
RUST_LOG=debug bootupctl status
|
|
|
|
# Check system state
|
|
cat /boot/bootupd-state.json
|
|
```
|
|
|
|
## Contributing
|
|
|
|
We welcome contributions! This project is a proof-of-concept for immutable Debian systems.
|
|
|
|
### Development Priorities
|
|
|
|
1. **Core Functionality**: Ensure basic bootloader management works on Debian
|
|
2. **OSTree Integration**: Optimize for Debian OSTree deployments
|
|
3. **Testing**: Comprehensive test coverage for Debian environments
|
|
4. **Documentation**: Clear guides for users and developers
|
|
|
|
## License
|
|
|
|
This project is licensed under the same terms as the original bootupd project. See the LICENSE file for details.
|
|
|
|
## Acknowledgments
|
|
|
|
- **Original bootupd**: [CoreOS bootupd](https://github.com/coreos/bootupd) - The excellent foundation this project builds upon
|
|
- **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] **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
|
|
|
|
## Support
|
|
|
|
- **Issues**: Report bugs and feature requests via GitLab issues
|
|
- **Discussions**: Join the conversation in GitLab discussions
|
|
- **Documentation**: Check this README and inline code documentation
|
|
|
|
---
|
|
|
|
**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
|