12 Commits

Author SHA1 Message Date
eda903911d Merge branch 'main' into niri-tiling-compositor
Some checks failed
Build container image / Build and push image (pull_request) Failing after 3m59s
2025-11-13 18:56:25 +09:00
d35c6f88ba Merge pull request 'Attempt: Use Vanilla Silverblue as Base' (#1) from vanilla-silverblue-base into main
All checks were successful
Build container image / Build and push image (push) Successful in 25m12s
Reviewed-on: https://davejansen.dev/davejansen/fedora-bootc/pulls/1
2025-11-13 18:54:44 +09:00
03fce0dbd8 Disable rechunker for now
All checks were successful
Build container image / Build and push image (pull_request) Successful in 18m22s
2025-11-13 17:50:24 +09:00
a675b9e51c Add Niri
Some checks failed
Build container image / Build and push image (pull_request) Has been cancelled
2025-11-13 17:48:52 +09:00
aff8f8eb23 Build label name change test for Rechunker
Some checks failed
Build container image / Build and push image (pull_request) Failing after 20m19s
2025-11-13 17:23:37 +09:00
3bcb1f840b Fix typo, remove some unused blocks
Some checks failed
Build container image / Build and push image (pull_request) Failing after 15m54s
2025-11-02 18:48:28 +09:00
f1c09b70b4 Check out Rechunker
Some checks failed
Build container image / Build and push image (pull_request) Failing after 16m27s
2025-11-02 18:05:02 +09:00
dc7950a1ec Only add tags when needed
All checks were successful
Build container image / Build and push image (pull_request) Successful in 17m28s
Temporarily by line-by-line iffing them out.
2025-11-02 17:43:10 +09:00
9456f1065f Add quick debug echo
All checks were successful
Build container image / Build and push image (pull_request) Successful in 18m41s
2025-11-02 17:07:13 +09:00
5c60ac07d3 First attempt at using vanilla Silverblue base
Some checks failed
Build container image / Build and push image (pull_request) Failing after 1m31s
2025-11-02 16:37:21 +09:00
1291cf7dcf Bump to Fedora 43
All checks were successful
Build container image / Build and push image (push) Successful in 21m20s
2025-10-29 15:36:06 +09:00
f36fd9d04d Initial Setup
Re-worked to support my Gitea environment, along with some other customizations
and removals.

Currently based off of their `silverblue-main` base image, with 1Password and
Tailscale layered.
2025-10-29 15:35:01 +09:00
16 changed files with 633 additions and 271 deletions

16
.editorconfig Normal file
View File

@@ -0,0 +1,16 @@
# Stop the editor from looking for .editorconfig files in the parent directories
root = true
[*]
# Non-configurable Prettier behaviors
charset = utf-8
insert_final_newline = true
# Caveat: Prettier wont trim trailing whitespace inside template strings, but your editor might.
trim_trailing_whitespace = true
# Configurable Prettier behaviors
end_of_line = lf
indent_style = space
indent_size = 2
max_line_length = 80

187
.gitea/workflows/build.yml Normal file
View File

@@ -0,0 +1,187 @@
---
name: Build container image
on:
pull_request:
branches:
- main
schedule:
- cron: "05 10 * * *" # 10:05am UTC everyday
push:
branches:
- main
paths-ignore:
- "**/README.md"
workflow_dispatch:
env:
REGISTRY_USER: ${{ github.actor }}
REGISTRY_AUTH_FILE: /root/.podman/auth.json
IMAGE_DESC: "My customized Fedora bootc image, based on Universal Blue"
IMAGE_KEYWORDS: "bootc,fedora,silverblue,ublue,universal-blue"
IMAGE_LOGO_URL: "https://davejansen.dev/avatars/940c9cc684fa03784359f97d591a389ecd90cd912acf2335a60acd616922000a?size=48"
IMAGE_NAME: "${{ github.event.repository.name }}" # output image name, usually same as repo name
IMAGE_REGISTRY: davejansen.dev
IMAGE_OWNER: ${{ github.repository_owner }}
FEDORA_BASE: 43
REPO_URL:
https://davejansen.dev/${{ github.repository_owner }}/${{
github.event.repository.name }}
concurrency:
group:
${{ github.workflow }}-${{ github.ref || github.run_id }}-${{
inputs.brand_name}}-${{ inputs.stream_name }}
cancel-in-progress: true
jobs:
build_push:
name: Build and push image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Prepare environment
run: |
# Lowercase the image uri
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
# These stage versions are pinned by https://github.com/renovatebot/renovate
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
- name: Get current date
id: date
run: |
# This generates a timestamp like what is defined on the ArtifactHub documentation
# E.G: 2022-02-08T15:38:15Z'
# https://artifacthub.io/docs/topics/repositories/container-images/
# https://linux.die.net/man/1/date
echo "date=$(date -u +%Y\-%m\-%d\T%H\:%M\:%S\Z)" >> $GITHUB_OUTPUT
# Image metadata for https://artifacthub.io/ - This is optional but is highly recommended so we all can get a index of all the custom images
# The metadata by itself is not going to do anything, you choose if you want your image to be on ArtifactHub or not.
- name: Image Metadata
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5
id: metadata
env:
README_URL: ${{ env.REPO_URL }}/raw/commit/${{ github.sha }}/README.md
with:
# This generates all the tags for your image, you can add custom tags here too!
tags: |
type=sha
type=raw,value=latest,enable=${{ github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=raw,value=${{ env.FEDORA_BASE }},enable=${{ github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=raw,value=${{ env.FEDORA_BASE }}-{{date 'YYYYMMDD'}},enable=${{ github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=ref,event=pr
labels: |
io.artifacthub.package.readme-url=${{ env.README_URL }}
org.opencontainers.image.created=${{ steps.date.outputs.date }}
org.opencontainers.image.description=${{ env.IMAGE_DESC }}
org.opencontainers.image.documentation=${{ env.README_URL }}
org.opencontainers.image.source=${{ env.REPO_URL }}/raw/commit/${{ github.sha }}/Containerfile
org.opencontainers.image.title=${{ env.IMAGE_NAME }}
org.opencontainers.image.url=${{ env.REPO_URL }}
org.opencontainers.image.vendor=${{ github.repository_owner }}
org.opencontainers.image.version=${{ env.FEDORA_BASE }}-{{date 'YYYYMMDD'}}
io.artifacthub.package.deprecated=false
io.artifacthub.package.keywords=${{ env.IMAGE_KEYWORDS }}
io.artifacthub.package.license=Apache-2.0
io.artifacthub.package.logo-url=${{ env.IMAGE_LOGO_URL }}
io.artifacthub.package.prerelease=false
containers.bootc=1
sep-tags: " "
sep-annotations: " "
- name: Install build dependencies
run: |
apt-get -y update && apt-get -y install buildah podman
- name: Build Image
id: build_image
uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2
with:
containerfiles: |
./Containerfile
build-args: |
FEDORA_BASE=${{ env.FEDORA_BASE }}
image: ${{ env.IMAGE_NAME }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
#labels: "localhost/${{ env.IMAGE_NAME }}:${{ env.FEDORA_BASE }}"
extra-args: --isolation=chroot
oci: false
# Rechunk is a script that we use on Universal Blue to make sure there isnt a single huge layer when your image gets published.
# This does not make your image faster to download, just provides better resumability and fixes a few errors.
# Documentation for Rechunk is provided on their github repository at https://github.com/hhd-dev/rechunk
# You can enable it by uncommenting the following lines:
# - name: Run Rechunker
# id: rechunk
# uses: hhd-dev/rechunk@v1.2.4
# with:
# rechunk: "ghcr.io/hhd-dev/rechunk:v1.2.4"
# ref: "localhost/${{ env.IMAGE_NAME }}:${{ env.FEDORA_BASE }}"
# prev-ref:
# "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.FEDORA_BASE
# }}"
# skip_compression: true
# version: ${{ env.FEDORA_BASE }}
# labels: ${{ steps.metadata.outputs.labels }} # Rechunk strips out all the labels during build, this needs to be reapplied here with newline separator
- name: Login to Container Registry
if:
github.event_name != 'pull_request' && github.ref ==
format('refs/heads/{0}', github.event.repository.default_branch)
run: |
podman login \
--verbose \
--authfile "${{ env.REGISTRY_AUTH_FILE }}" \
--username "${{ env.REGISTRY_USER }}" \
--password "${{ secrets.CONTAINER_TOKEN }}" \
${{ env.IMAGE_REGISTRY }}
- name: Push To Registry
uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2
if:
github.event_name != 'pull_request' && github.ref ==
format('refs/heads/{0}', github.event.repository.default_branch)
id: push
env:
REGISTRY_PASSWORD: ${{ secrets.CONTAINER_TOKEN }}
with:
extra-args: --authfile=${{ env.REGISTRY_AUTH_FILE }}
registry: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_OWNER }}
image: ${{ env.IMAGE_NAME }}
tags: ${{ steps.metadata.outputs.tags }}
# This section is optional and only needs to be enabled if you plan on distributing
# your project for others to consume. You will need to create a public and private key
# using Cosign and save the private key as a repository secret in Github for this workflow
# to consume. For more details, review the image signing section of the README.
- name: Install Cosign
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
if:
github.event_name != 'pull_request' && github.ref ==
format('refs/heads/{0}', github.event.repository.default_branch)
- name: Sign container image
if:
github.event_name != 'pull_request' && github.ref ==
format('refs/heads/{0}', github.event.repository.default_branch)
env:
IMAGE_FULL:
${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_NAME
}}
TAGS: ${{ steps.push.outputs.digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
COSIGN_PASSWORD: ""
run: |
for tag in ${{ steps.metadata.outputs.tags }}; do
cosign sign -y --key env://COSIGN_PRIVATE_KEY $IMAGE_FULL:$tag
done

View File

@@ -1,11 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -1,187 +0,0 @@
---
name: Build container image
on:
pull_request:
branches:
- main
schedule:
- cron: '05 10 * * *' # 10:05am UTC everyday
push:
branches:
- main
paths-ignore:
- '**/README.md'
workflow_dispatch:
env:
IMAGE_DESC: "My Customized Universal Blue Image"
IMAGE_KEYWORDS: "bootc,ublue,universal-blue"
IMAGE_LOGO_URL: "https://avatars.githubusercontent.com/u/120078124?s=200&v=4" # Put your own image here for a fancy profile on https://artifacthub.io/!
IMAGE_NAME: "${{ github.event.repository.name }}" # output image name, usually same as repo name
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" # do not edit
DEFAULT_TAG: "latest"
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.brand_name}}-${{ inputs.stream_name }}
cancel-in-progress: true
jobs:
build_push:
name: Build and push image
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Prepare environment
run: |
# Lowercase the image uri
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
# These stage versions are pinned by https://github.com/renovatebot/renovate
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
# This is optional, but if you see that your builds are way too big for the runners, you can enable this by uncommenting the following lines:
# - name: Maximize build space
# uses: ublue-os/remove-unwanted-software@517622d6452028f266b7ba4cc9a123b5f58a6b53 # v7
# with:
# remove-codeql: true
- name: Mount BTRFS for podman storage
id: container-storage-action
uses: ublue-os/container-storage-action@911baca08baf30c8654933e9e9723cb399892140
# Fallback to the remove-unwanted-software-action if github doesn't allocate enough space
# See: https://github.com/ublue-os/container-storage-action/pull/11
continue-on-error: true
with:
target-dir: /var/lib/containers
mount-opts: compress-force=zstd:2
- name: Get current date
id: date
run: |
# This generates a timestamp like what is defined on the ArtifactHub documentation
# E.G: 2022-02-08T15:38:15Z'
# https://artifacthub.io/docs/topics/repositories/container-images/
# https://linux.die.net/man/1/date
echo "date=$(date -u +%Y\-%m\-%d\T%H\:%M\:%S\Z)" >> $GITHUB_OUTPUT
# Image metadata for https://artifacthub.io/ - This is optional but is highly recommended so we all can get a index of all the custom images
# The metadata by itself is not going to do anything, you choose if you want your image to be on ArtifactHub or not.
- name: Image Metadata
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5
id: metadata
with:
# This generates all the tags for your image, you can add custom tags here too!
# Default tags are "$DEFAULT_TAG" and "$DEFAULT_TAG.$date".
tags: |
type=raw,value=${{ env.DEFAULT_TAG }}
type=raw,value=${{ env.DEFAULT_TAG }}.{{date 'YYYYMMDD'}}
type=raw,value={{date 'YYYYMMDD'}}
type=sha,enable=${{ github.event_name == 'pull_request' }}
type=ref,event=pr
labels: |
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/refs/heads/main/README.md
org.opencontainers.image.created=${{ steps.date.outputs.date }}
org.opencontainers.image.description=${{ env.IMAGE_DESC }}
org.opencontainers.image.documentation=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/refs/heads/main/README.md
org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/blob/main/Containerfile
org.opencontainers.image.title=${{ env.IMAGE_NAME }}
org.opencontainers.image.url=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
org.opencontainers.image.vendor=${{ github.repository_owner }}
org.opencontainers.image.version=${{ env.DEFAULT_TAG }}.{{date 'YYYYMMDD'}}
io.artifacthub.package.deprecated=false
io.artifacthub.package.keywords=${{ env.IMAGE_KEYWORDS }}
io.artifacthub.package.license=Apache-2.0
io.artifacthub.package.logo-url=${{ env.IMAGE_LOGO_URL }}
io.artifacthub.package.prerelease=false
containers.bootc=1
sep-tags: " "
sep-annotations: " "
- name: Build Image
id: build_image
uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2
with:
containerfiles: |
./Containerfile
# Postfix image name with -custom to make it a little more descriptive
# Syntax: https://docs.github.com/en/actions/learn-github-actions/expressions#format
image: ${{ env.IMAGE_NAME }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
oci: false
# Rechunk is a script that we use on Universal Blue to make sure there isnt a single huge layer when your image gets published.
# This does not make your image faster to download, just provides better resumability and fixes a few errors.
# Documentation for Rechunk is provided on their github repository at https://github.com/hhd-dev/rechunk
# You can enable it by uncommenting the following lines:
# - name: Run Rechunker
# id: rechunk
# uses: hhd-dev/rechunk@f153348d8100c1f504dec435460a0d7baf11a9d2 # v1.1.1
# with:
# rechunk: 'ghcr.io/hhd-dev/rechunk:v1.0.1'
# ref: "localhost/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
# prev-ref: "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
# skip_compression: true
# version: ${{ env.CENTOS_VERSION }}
# labels: ${{ steps.metadata.outputs.labels }} # Rechunk strips out all the labels during build, this needs to be reapplied here with newline separator
# This is necessary so that the podman socket can find the rechunked image on its storage
# - name: Load in podman and tag
# run: |
# IMAGE=$(podman pull ${{ steps.rechunk.outputs.ref }})
# sudo rm -rf ${{ steps.rechunk.outputs.output }}
# for tag in ${{ steps.metadata.outputs.tags }}; do
# podman tag $IMAGE ${{ env.IMAGE_NAME }}:$tag
# done
# These `if` statements are so that pull requests for your custom images do not make it publish any packages under your name without you knowing
# They also check if the runner is on the default branch so that things like the merge queue (if you enable it), are going to work
- name: Login to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Push To GHCR
uses: redhat-actions/push-to-registry@5ed88d269cf581ea9ef6dd6806d01562096bee9c # v2
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
id: push
env:
REGISTRY_USER: ${{ github.actor }}
REGISTRY_PASSWORD: ${{ github.token }}
with:
registry: ${{ env.IMAGE_REGISTRY }}
image: ${{ env.IMAGE_NAME }}
tags: ${{ steps.metadata.outputs.tags }}
username: ${{ env.REGISTRY_USER }}
password: ${{ env.REGISTRY_PASSWORD }}
# This section is optional and only needs to be enabled if you plan on distributing
# your project for others to consume. You will need to create a public and private key
# using Cosign and save the private key as a repository secret in Github for this workflow
# to consume. For more details, review the image signing section of the README.
- name: Install Cosign
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
- name: Sign container image
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
run: |
IMAGE_FULL="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}"
for tag in ${{ steps.metadata.outputs.tags }}; do
cosign sign -y --key env://COSIGN_PRIVATE_KEY $IMAGE_FULL:$tag
done
env:
TAGS: ${{ steps.push.outputs.digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}

8
.markdownlint.json Normal file
View File

@@ -0,0 +1,8 @@
{
"line-length": {
"tables": false
},
"no-inline-html": {
"allowed_elements": ["abbr", "pre", "kbd", "samp"]
}
}

4
.prettierrc.json Normal file
View File

@@ -0,0 +1,4 @@
{
"printWidth": 80,
"proseWrap": "always"
}

View File

@@ -1,18 +1,12 @@
ARG FEDORA_BASE=42
# Allow build scripts to be referenced without being copied into the final image
FROM scratch AS ctx
COPY build_files /
COPY /sys_files /sys_files
# Base Image
FROM ghcr.io/ublue-os/bazzite:stable
## Other possible base images include:
# FROM ghcr.io/ublue-os/bazzite:latest
# FROM ghcr.io/ublue-os/bluefin-nvidia:stable
#
# ... and so on, here are more base images
# Universal Blue Images: https://github.com/orgs/ublue-os/packages
# Fedora base image: quay.io/fedora/fedora-bootc:41
# CentOS base images: quay.io/centos-bootc/centos-bootc:stream10
FROM quay.io/fedora-ostree-desktops/silverblue:$FEDORA_BASE
### [IM]MUTABLE /opt
## Some bootable images, like Fedora, have /opt symlinked to /var/opt, in order to
@@ -23,18 +17,18 @@ FROM ghcr.io/ublue-os/bazzite:stable
## Uncomment the following line if one desires to make /opt immutable and be able to be used
## by the package manager.
# RUN rm /opt && mkdir /opt
RUN rm /opt && mkdir /opt
### MODIFICATIONS
## make modifications desired in your image and install packages by modifying the build.sh script
## the following RUN directive does all the things required to run "build.sh" as recommended.
RUN --mount=type=bind,from=ctx,source=/,target=/ctx \
--mount=type=cache,dst=/var/cache \
--mount=type=cache,dst=/var/log \
--mount=type=tmpfs,dst=/tmp \
/ctx/build.sh
--mount=type=cache,dst=/var/cache \
--mount=type=cache,dst=/var/log \
--mount=type=tmpfs,dst=/tmp \
/ctx/build.sh
### LINTING
## Verify final image and contents are correct.
RUN bootc container lint

View File

@@ -1,4 +1,4 @@
export image_name := env("IMAGE_NAME", "image-template") # output image name, usually same as repo name, change as needed
export image_name := env("IMAGE_NAME", "fedora-jibsaram") # output image name, usually same as repo name, change as needed
export default_tag := env("DEFAULT_TAG", "latest")
export bib_image := env("BIB_IMAGE", "quay.io/centos-bootc/bootc-image-builder:latest")

197
README.md
View File

@@ -1,40 +1,54 @@
# image-template
This repository is meant to be a template for building your own custom [bootc](https://github.com/bootc-dev/bootc) image. This template is the recommended way to make customizations to any image published by the Universal Blue Project.
This repository is meant to be a template for building your own custom
[bootc](https://github.com/bootc-dev/bootc) image. This template is the
recommended way to make customizations to any image published by the Universal
Blue Project.
# Community
If you have questions about this template after following the instructions, try the following spaces:
If you have questions about this template after following the instructions, try
the following spaces:
- [Universal Blue Forums](https://universal-blue.discourse.group/)
- [Universal Blue Discord](https://discord.gg/WEu6BdFEtp)
- [bootc discussion forums](https://github.com/bootc-dev/bootc/discussions) - This is not an Universal Blue managed space, but is an excellent resource if you run into issues with building bootc images.
- [bootc discussion forums](https://github.com/bootc-dev/bootc/discussions) -
This is not an Universal Blue managed space, but is an excellent resource if
you run into issues with building bootc images.
# How to Use
To get started on your first bootc image, simply read and follow the steps in the next few headings.
If you prefer instructions in video form, TesterTech created an excellent tutorial, embedded below.
To get started on your first bootc image, simply read and follow the steps in
the next few headings. If you prefer instructions in video form, TesterTech
created an excellent tutorial, embedded below.
[![Video Tutorial](https://img.youtube.com/vi/IxBl11Zmq5w/0.jpg)](https://www.youtube.com/watch?v=IxBl11Zmq5wE)
## Step 0: Prerequisites
These steps assume you have the following:
- A Github Account
- A machine running a bootc image (e.g. Bazzite, Bluefin, Aurora, or Fedora Atomic)
- A machine running a bootc image (e.g. Bazzite, Bluefin, Aurora, or Fedora
Atomic)
- Experience installing and using CLI programs
## Step 1: Preparing the Template
### Step 1a: Copying the Template
Select `Use this Template` on this page. You can set the name and description of your repository to whatever you would like, but all other settings should be left untouched.
Select `Use this Template` on this page. You can set the name and description of
your repository to whatever you would like, but all other settings should be
left untouched.
Once you have finished copying the template, you need to enable the Github Actions workflows for your new repository.
To enable the workflows, go to the `Actions` tab of the new repository and click the button to enable workflows.
Once you have finished copying the template, you need to enable the Github
Actions workflows for your new repository. To enable the workflows, go to the
`Actions` tab of the new repository and click the button to enable workflows.
### Step 1b: Cloning the New Repository
Here I will defer to the much superior GitHub documentation on the matter. You can use whichever method is easiest.
Here I will defer to the much superior GitHub documentation on the matter. You
can use whichever method is easiest.
[GitHub Documentation](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)
Once you have the repository on your local drive, proceed to the next step.
@@ -43,29 +57,37 @@ Once you have the repository on your local drive, proceed to the next step.
### Step 2a: Creating a Cosign Key
Container signing is important for end-user security and is enabled on all Universal Blue images. By default the image builds *will fail* if you don't.
Container signing is important for end-user security and is enabled on all
Universal Blue images. By default the image builds _will fail_ if you don't.
First, install the [cosign CLI tool](https://edu.chainguard.dev/open-source/sigstore/cosign/how-to-install-cosign/#installing-cosign-with-the-cosign-binary)
First, install the
[cosign CLI tool](https://edu.chainguard.dev/open-source/sigstore/cosign/how-to-install-cosign/#installing-cosign-with-the-cosign-binary)
With the cosign tool installed, run inside your repo folder:
```bash
COSIGN_PASSWORD="" cosign generate-key-pair
```
The signing key will be used in GitHub Actions and will not work if it is password protected.
The signing key will be used in GitHub Actions and will not work if it is
password protected.
> [!WARNING]
> Be careful to *never* accidentally commit `cosign.key` into your git repo. If this key goes out to the public, the security of your repository is compromised.
> [!WARNING] Be careful to _never_ accidentally commit `cosign.key` into your
> git repo. If this key goes out to the public, the security of your repository
> is compromised.
Next, you need to add the key to GitHub. This makes use of GitHub's secret signing system.
Next, you need to add the key to GitHub. This makes use of GitHub's secret
signing system.
<details>
<summary>Using the Github Web Interface (preferred)</summary>
Go to your repository settings, under `Secrets and Variables` -> `Actions`
![image](https://user-images.githubusercontent.com/1264109/216735595-0ecf1b66-b9ee-439e-87d7-c8cc43c2110a.png)
Add a new secret and name it `SIGNING_SECRET`, then paste the contents of `cosign.key` into the secret and save it. Make sure it's the .key file and not the .pub file. Once done, it should look like this:
Add a new secret and name it `SIGNING_SECRET`, then paste the contents of
`cosign.key` into the secret and save it. Make sure it's the .key file and not
the .pub file. Once done, it should look like this:
![image](https://user-images.githubusercontent.com/1264109/216735690-2d19271f-cee2-45ac-a039-23e6a4c16b34.png)
</details>
<details>
<summary>Using the Github CLI</summary>
@@ -75,12 +97,16 @@ If you have the `github-cli` installed, run:
```bash
gh secret set SIGNING_SECRET < cosign.key
```
</details>
### Step 2b: Choosing Your Base Image
To choose a base image, simply modify the line in the container file starting with `FROM`. This will be the image your image derives from, and is your starting point for modifications.
For a base image, you can choose any of the Universal Blue images or start from a Fedora Atomic system. Below this paragraph is a dropdown with a non-exhaustive list of potential base images.
To choose a base image, simply modify the line in the container file starting
with `FROM`. This will be the image your image derives from, and is your
starting point for modifications. For a base image, you can choose any of the
Universal Blue images or start from a Fedora Atomic system. Below this paragraph
is a dropdown with a non-exhaustive list of potential base images.
<details>
<summary>Base Images</summary>
@@ -91,91 +117,153 @@ For a base image, you can choose any of the Universal Blue images or start from
- Universal Blue Base: `ghcr.io/ublue-os/base-main:latest`
- Fedora: `quay.io/fedora/fedora-bootc:42`
You can find more Universal Blue images on the [packages page](https://github.com/orgs/ublue-os/packages).
You can find more Universal Blue images on the
[packages page](https://github.com/orgs/ublue-os/packages).
</details>
If you don't know which image to pick, choosing the one your system is currently on is the best bet for a smooth transition. To find out what image your system currently uses, run the following command:
If you don't know which image to pick, choosing the one your system is currently
on is the best bet for a smooth transition. To find out what image your system
currently uses, run the following command:
```bash
sudo bootc status
```
This will show you all the info you need to know about your current image. The image you are currently on is displayed after `Booted image:`. Paste that information after the `FROM` statement in the Containerfile to set it as your base image.
This will show you all the info you need to know about your current image. The
image you are currently on is displayed after `Booted image:`. Paste that
information after the `FROM` statement in the Containerfile to set it as your
base image.
### Step 2c: Changing Names
Change the first line in the [Justfile](./Justfile) to your image's name.
To commit and push all the files changed and added in step 2 into your Github repository:
To commit and push all the files changed and added in step 2 into your Github
repository:
```bash
git add Containerfile Justfile cosign.pub
git commit -m "Initial Setup"
git push
```
Once pushed, go look at the Actions tab on your Github repository's page. The green checkmark should be showing on the top commit, which means your new image is ready!
Once pushed, go look at the Actions tab on your Github repository's page. The
green checkmark should be showing on the top commit, which means your new image
is ready!
## Step 3: Switch to Your Image
From your bootc system, run the following command substituting in your Github username and image name where noted.
From your bootc system, run the following command substituting in your Github
username and image name where noted.
```bash
sudo bootc switch ghcr.io/<username>/<image_name>
```
This should queue your image for the next reboot, which you can do immediately after the command finishes. You have officially set up your custom image! See the following section for an explanation of the important parts of the template for customization.
This should queue your image for the next reboot, which you can do immediately
after the command finishes. You have officially set up your custom image! See
the following section for an explanation of the important parts of the template
for customization.
# Repository Contents
## Containerfile
The [Containerfile](./Containerfile) defines the operations used to customize the selected image.This file is the entrypoint for your image build, and works exactly like a regular podman Containerfile. For reference, please see the [Podman Documentation](https://docs.podman.io/en/latest/Introduction.html).
The [Containerfile](./Containerfile) defines the operations used to customize
the selected image.This file is the entrypoint for your image build, and works
exactly like a regular podman Containerfile. For reference, please see the
[Podman Documentation](https://docs.podman.io/en/latest/Introduction.html).
## build.sh
The [build.sh](./build_files/build.sh) file is called from your Containerfile. It is the best place to install new packages or make any other customization to your system. There are customization examples contained within it for your perusal.
The [build.sh](./build_files/build.sh) file is called from your Containerfile.
It is the best place to install new packages or make any other customization to
your system. There are customization examples contained within it for your
perusal.
## build.yml
The [build.yml](./.github/workflows/build.yml) Github Actions workflow creates your custom OCI image and publishes it to the Github Container Registry (GHCR). By default, the image name will match the Github repository name. There are several environment variables at the start of the workflow which may be of interest to change.
The [build.yml](./.github/workflows/build.yml) Github Actions workflow creates
your custom OCI image and publishes it to the Github Container Registry (GHCR).
By default, the image name will match the Github repository name. There are
several environment variables at the start of the workflow which may be of
interest to change.
# Building Disk Images
This template provides an out of the box workflow for creating disk images (ISO, qcow, raw) for your custom OCI image which can be used to directly install onto your machines.
This template provides an out of the box workflow for creating disk images (ISO,
qcow, raw) for your custom OCI image which can be used to directly install onto
your machines.
This template provides a way to upload the disk images that is generated from the workflow to a S3 bucket. The disk images will also be available as an artifact from the job, if you wish to use an alternate provider. To upload to S3 we use [rclone](https://rclone.org/) which is able to use [many S3 providers](https://rclone.org/s3/).
This template provides a way to upload the disk images that is generated from
the workflow to a S3 bucket. The disk images will also be available as an
artifact from the job, if you wish to use an alternate provider. To upload to S3
we use [rclone](https://rclone.org/) which is able to use
[many S3 providers](https://rclone.org/s3/).
## Setting Up ISO Builds
The [build-disk.yml](./.github/workflows/build-disk.yml) Github Actions workflow creates a disk image from your OCI image by utilizing the [bootc-image-builder](https://osbuild.org/docs/bootc/). In order to use this workflow you must complete the following steps:
The [build-disk.yml](./.github/workflows/build-disk.yml) Github Actions workflow
creates a disk image from your OCI image by utilizing the
[bootc-image-builder](https://osbuild.org/docs/bootc/). In order to use this
workflow you must complete the following steps:
1. Modify `disk_config/iso.toml` to point to your custom container image before generating an ISO image.
2. If you changed your image name from the default in `build.yml` then in the `build-disk.yml` file edit the `IMAGE_REGISTRY`, `IMAGE_NAME` and `DEFAULT_TAG` environment variables with the correct values. If you did not make changes, skip this step.
3. Finally, if you want to upload your disk images to S3 then you will need to add your S3 configuration to the repository's Action secrets. This can be found by going to your repository settings, under `Secrets and Variables` -> `Actions`. You will need to add the following
- `S3_PROVIDER` - Must match one of the values from the [supported list](https://rclone.org/s3/)
- `S3_BUCKET_NAME` - Your unique bucket name
- `S3_ACCESS_KEY_ID` - It is recommended that you make a separate key just for this workflow
- `S3_SECRET_ACCESS_KEY` - See above.
- `S3_REGION` - The region your bucket lives in. If you do not know then set this value to `auto`.
- `S3_ENDPOINT` - This value will be specific to the bucket as well.
1. Modify `disk_config/iso.toml` to point to your custom container image before
generating an ISO image.
2. If you changed your image name from the default in `build.yml` then in the
`build-disk.yml` file edit the `IMAGE_REGISTRY`, `IMAGE_NAME` and
`DEFAULT_TAG` environment variables with the correct values. If you did not
make changes, skip this step.
3. Finally, if you want to upload your disk images to S3 then you will need to
add your S3 configuration to the repository's Action secrets. This can be
found by going to your repository settings, under `Secrets and Variables` ->
`Actions`. You will need to add the following
Once the workflow is done, you'll find the disk images either in your S3 bucket or as part of the summary under `Artifacts` after the workflow is completed.
- `S3_PROVIDER` - Must match one of the values from the
[supported list](https://rclone.org/s3/)
- `S3_BUCKET_NAME` - Your unique bucket name
- `S3_ACCESS_KEY_ID` - It is recommended that you make a separate key just for
this workflow
- `S3_SECRET_ACCESS_KEY` - See above.
- `S3_REGION` - The region your bucket lives in. If you do not know then set
this value to `auto`.
- `S3_ENDPOINT` - This value will be specific to the bucket as well.
Once the workflow is done, you'll find the disk images either in your S3 bucket
or as part of the summary under `Artifacts` after the workflow is completed.
# Artifacthub
This template comes with the necessary tooling to index your image on [artifacthub.io](https://artifacthub.io). Use the `artifacthub-repo.yml` file at the root to verify yourself as the publisher. This is important to you for a few reasons:
This template comes with the necessary tooling to index your image on
[artifacthub.io](https://artifacthub.io). Use the `artifacthub-repo.yml` file at
the root to verify yourself as the publisher. This is important to you for a few
reasons:
- The value of artifacthub is it's one place for people to index their custom images, and since we depend on each other to learn, it helps grow the community.
- You get to see your pet project listed with the other cool projects in Cloud Native.
- Since the site puts your README front and center, it's a good way to learn how to write a good README, learn some marketing, finding your audience, etc.
- The value of artifacthub is it's one place for people to index their custom
images, and since we depend on each other to learn, it helps grow the
community.
- You get to see your pet project listed with the other cool projects in Cloud
Native.
- Since the site puts your README front and center, it's a good way to learn how
to write a good README, learn some marketing, finding your audience, etc.
[Discussion Thread](https://universal-blue.discourse.group/t/listing-your-custom-image-on-artifacthub/6446)
# Justfile Documentation
The `Justfile` contains various commands and configurations for building and managing container images and virtual machine images using Podman and other utilities.
To use it, you must have installed [just](https://just.systems/man/en/introduction.html) from your package manager or manually. It is available by default on all Universal Blue images.
The `Justfile` contains various commands and configurations for building and
managing container images and virtual machine images using Podman and other
utilities. To use it, you must have installed
[just](https://just.systems/man/en/introduction.html) from your package manager
or manually. It is available by default on all Universal Blue images.
## Environment Variables
- `image_name`: The name of the image (default: "image-template").
- `default_tag`: The default tag for the image (default: "latest").
- `bib_image`: The Bootc Image Builder (BIB) image (default: "quay.io/centos-bootc/bootc-image-builder:latest").
- `bib_image`: The Bootc Image Builder (BIB) image (default:
"quay.io/centos-bootc/bootc-image-builder:latest").
## Building The Image
@@ -188,12 +276,16 @@ just build $target_image $tag
```
Arguments:
- `$target_image`: The tag you want to apply to the image (default: `$image_name`).
- `$target_image`: The tag you want to apply to the image (default:
`$image_name`).
- `$tag`: The tag for the image (default: `$default_tag`).
## Building and Running Virtual Machines and ISOs
The below commands all build QCOW2 images. To produce or use a different type of image, substitute in the command with that type in the place of `qcow2`. The available types are `qcow2`, `iso`, and `raw`.
The below commands all build QCOW2 images. To produce or use a different type of
image, substitute in the command with that type in the place of `qcow2`. The
available types are `qcow2`, `iso`, and `raw`.
### `just build-qcow2`
@@ -251,7 +343,8 @@ Runs shfmt on all Bash scripts.
## Community Examples
These are images derived from this template (or similar enough to this template). Reference them when building your image!
These are images derived from this template (or similar enough to this
template). Reference them when building your image!
- [m2Giles' OS](https://github.com/m2giles/m2os)
- [bOS](https://github.com/bsherman/bos)

View File

@@ -2,6 +2,9 @@
set -ouex pipefail
# Copy System Files onto root
rsync -rvK /ctx/sys_files/ /
### Install packages
# Packages can be installed from any enabled yum repo on the image.
@@ -9,8 +12,124 @@ set -ouex pipefail
# List of rpmfusion packages can be found here:
# https://mirrors.rpmfusion.org/mirrorlist?path=free/fedora/updates/39/x86_64/repoview/index.html&protocol=https&redirect=1
# this installs a package from fedora repos
dnf5 install -y tmux
# Install RPMFusion and enable fedora-multimedia with a higher priority than default
if ! grep -q fedora-multimedia <(dnf5 repolist); then
# Enable or Install Repofile
#dnf5 install \
# https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm \
# https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm
# Enable fedora-multimedia
dnf5 config-manager setopt fedora-multimedia.enabled=1 ||
dnf5 config-manager addrepo --from-repofile="https://negativo17.org/repos/fedora-multimedia.repo"
fi
# Set higher priority
dnf5 config-manager setopt fedora-multimedia.priority=90
# Remove system-installed Firefox as I prefer to use the Flatpak version
dnf5 remove -y firefox firefox-langpacks fedora-flathub-remote
# Add Flathub to the image for eventual application
mkdir -p /etc/flatpak/remotes.d/
curl --retry 3 -Lo /etc/flatpak/remotes.d/flathub.flatpakrepo https://dl.flathub.org/repo/flathub.flatpakrepo
# use override to replace mesa and others with less crippled versions
OVERRIDES=(
"intel-gmmlib"
"intel-mediasdk"
"intel-vpl-gpu-rt"
"libheif"
"libva"
"libva-intel-media-driver"
"mesa-dri-drivers"
"mesa-filesystem"
"mesa-libEGL"
"mesa-libGL"
"mesa-libgbm"
"mesa-va-drivers"
"mesa-vulkan-drivers"
)
dnf5 distro-sync --skip-unavailable -y --repo='fedora-multimedia' "${OVERRIDES[@]}"
dnf5 versionlock add "${OVERRIDES[@]}"
# Remove additional repositories Fedora comes with out of the box
rm \
/etc/yum.repos.d/fedora-cisco-openh264.repo \
/etc/yum.repos.d/google-chrome.repo \
/etc/yum.repos.d/rpmfusion-nonfree-nvidia-driver.repo \
/etc/yum.repos.d/rpmfusion-nonfree-steam.repo \
/etc/yum.repos.d/_copr:copr.fedorainfracloud.org:phracek:PyCharm.repo
# Add country query to all repo metalinks
# shellcheck disable=SC2016
sed -i -e '/^metalink\=/s/\$releasever\&arch\=\$basearch$/\$releasever\&arch\=\$basearch\&country\=KR,JP,TW/g' /etc/yum.repos.d/*.repo
# Add 1Password repo
#rpmkeys --import https://downloads.1password.com/linux/keys/1password.asc
cp /ctx/rpm-keys/1password.asc /etc/pki/rpm-gpg/1password.asc
sh -c 'echo -e "[1password]\nname=1Password Stable Channel\nbaseurl=https://downloads.1password.com/linux/rpm/stable/\$basearch\nenabled=1\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=\"file:///etc/pki/rpm-gpg/1password.asc\"" > /etc/yum.repos.d/1password.repo'
# Add Tailscale repo
#rpmkeys --import https://pkgs.tailscale.com/stable/fedora/repo.gpg
#dnf5 config-manager addrepo --from-repofile=https://pkgs.tailscale.com/stable/fedora/tailscale.repo
cp /ctx/rpm-keys/tailscale.gpg /etc/pki/rpm-gpg/tailscale.gpg
sh -c 'echo -e "[tailscale-stable]\nname=Tailscale stable\nbaseurl=https://pkgs.tailscale.com/stable/fedora/\$basearch\nenabled=1\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=\"file:///etc/pki/rpm-gpg/tailscale.gpg\"" > /etc/yum.repos.d/tailscale.repo'
# Update all existing packages
# dnf5 update -y
# Install my own layered packages
dnf5 install -y \
gvfs-nfs \
openssl \
wl-clipboard \
ffmpeg ffmpeg-libs ffmpegthumbnailer \
heif-pixbuf-loader intel-vaapi-driver libavcodec libheif \
libcamera libcamera-gstreamer libcamera-ipa libcamera-tools pipewire-plugin-libcamera \
gnome-shell-extension-appindicator \
1password 1password-cli \
tailscale
# Install Niri, the scrollable-tiling window compositor
# https://yalter.github.io/niri/
dnf5 -y copr enable avengemedia/dms
dnf5 -y install niri dms
systemctl --user add-wants niri.service dms
dnf5 -y copr disable avengemedia/dms
## CLEANUP
# Delete 1Password and Tailscale repos once packages are installed
# so they don't end up in the final image.
rm \
/etc/yum.repos.d/1password.repo \
/etc/yum.repos.d/tailscale.repo \
/etc/pki/rpm-gpg/1password.asc \
/etc/pki/rpm-gpg/tailscale.gpg
# Or just disable:
# dnf5 config-manager setopt 1password.enabled=0 tailscale-stable.enabled=0
# sed -i 's/enabled=1/enabled=0/' \
# /etc/yum.repos.d/1password.repo \
# /etc/yum.repos.d/tailscale.repo \
# Fedora Flatpak service is a part of the flatpak package, ensure it's overridden by moving to replace it at the end of the build.
mv -f /usr/lib/systemd/system/flatpak-add-flathub-repos.service /usr/lib/systemd/system/flatpak-add-fedora-repos.service
# Re-install all pre-installed (GNOME) applications from Flathub
#flatpak install --reinstall flathub "$(flatpak list --app-runtime=org.fedoraproject.Platform --columns=application | tail -n +1 )"
# ...and remove the fedora flatpak remotes
#flatpak remote-delete --force fedora
#flatpak remote-delete --force fedora-testing
# TODO: Add flathub remove, enable, and remove filter
# TODO: Install core GNOME Flatpak apps
# TODO: Install my own commonly used Flatpak apps
# IDEA: Can I set certain dconf settings, like Ptyxis config, temperature settings, etc?
# IDEA: Can I set certain Flatpak system defaults (ie. no read/write anywhere by default)
# Use a COPR Example:
#
@@ -19,6 +138,24 @@ dnf5 install -y tmux
# Disable COPRs so they don't end up enabled on the final image:
# dnf5 -y copr disable ublue-os/staging
#### Example for enabling a System Unit File
# Enable Tailscale service
systemctl enable tailscaled
systemctl enable podman.socket
# Cleanup
# Remove dnf5 versionlocks
dnf5 versionlock clear
# Remove tmp files and everything in dirs that make bootc unhappy
rm -rf /tmp/* || true
rm -rf /usr/etc
rm -rf /boot && mkdir /boot
# Preserve cache mounts
find /var/* -maxdepth 0 -type d \! -name cache \! -name log -exec rm -rf {} \;
find /var/cache/* -maxdepth 0 -type d \! -name libdnf5 -exec rm -rf {} \;
# Make sure /var/tmp is properly created
mkdir -p /var/tmp
chmod -R 1777 /var/tmp
echo "Done."

View File

@@ -0,0 +1,50 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
P4I7jHwe0BN3iNAG1nKbGg==
=+LeX
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=AIVM
-----END PGP PUBLIC KEY BLOCK-----

4
cosign.pub Normal file
View File

@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEbqurTRq1JqXbd6tkZiz8zcVPpPZ
5fLB+kybMeF4IxgaAw7JKyiemBvtgwBbbsk6HTP7BUoEHXBbGqtUwBD6NA==
-----END PUBLIC KEY-----

View File

@@ -0,0 +1,15 @@
[Unit]
Description=Add Flathub flatpak repositories. This replaces a service included by Fedora that normally installs their repo.
ConditionPathExists=!/var/lib/flatpak/.ublue-initialized
Before=flatpak-system-helper.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/flatpak remote-add --system --if-not-exists flathub /etc/flatpak/remotes.d/flathub.flatpakrepo
ExecStart=/usr/bin/flatpak remote-add --system --if-not-exists --disable --title "Fedora Flatpaks" fedora oci+https://registry.fedoraproject.org
ExecStart=/usr/bin/flatpak remote-add --system --if-not-exists --disable --title "Fedora Flatpaks (testing)" fedora-testing oci+https://registry.fedoraproject.org#testing
ExecStartPost=/usr/bin/touch /var/lib/flatpak/.ublue-initialized
[Install]
WantedBy=multi-user.target