diff --git a/.github/workflows/build-bluefin-toolbox.yml b/.github/workflows/build-bluefin-toolbox.yml
deleted file mode 100644
index cc627bec394..00000000000
--- a/.github/workflows/build-bluefin-toolbox.yml
+++ /dev/null
@@ -1,104 +0,0 @@
-name: Build and Push Bluefin Toolbox Image
-on:
- schedule:
- - cron: '20 22 * * *' # 10:20pm everyday
- pull_request:
- merge_group:
- workflow_dispatch:
-env:
- IMAGE_NAME: bluefin-cli
- IMAGE_TAGS: latest
- IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- push-ghcr:
- name: Build and push image
- runs-on: ubuntu-22.04
- permissions:
- contents: read
- packages: write
- id-token: write
- strategy:
- fail-fast: false
- steps:
- # Checkout push-to-registry action GitHub repository
- - name: Checkout Push to Registry action
- uses: actions/checkout@v4
-
- # Build metadata
- - name: Image Metadata
- uses: docker/metadata-action@v5
- id: meta
- with:
- images: |
- ${{ env.IMAGE_NAME }}
- labels: |
- io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/boxkit/main/README.md
-
- # Build image using Buildah action
- - name: Build Image
- id: build_image
- uses: redhat-actions/buildah-build@v2
- with:
- containerfiles: |
- ./toolboxes/Containerfile.bluefin-cli
- image: ${{ env.IMAGE_NAME }}
- tags: ${{ env.IMAGE_TAGS }}
- labels: ${{ steps.meta.outputs.labels }}
- oci: false
-
- # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
- # https://github.com/macbre/push-to-ghcr/issues/12
- - name: Lowercase Registry
- id: registry_case
- uses: ASzc/change-string-case-action@v6
- with:
- string: ${{ env.IMAGE_REGISTRY }}
-
- # Push the image to GHCR (Image Registry)
- - name: Push To GHCR
- uses: redhat-actions/push-to-registry@v2
- if: github.event_name != 'pull_request'
- id: push
- env:
- REGISTRY_USER: ${{ github.actor }}
- REGISTRY_PASSWORD: ${{ github.token }}
- with:
- image: ${{ steps.build_image.outputs.image }}
- tags: ${{ steps.build_image.outputs.tags }}
- registry: ${{ steps.registry_case.outputs.lowercase }}
- username: ${{ env.REGISTRY_USER }}
- password: ${{ env.REGISTRY_PASSWORD }}
- extra-args: |
- --disable-content-trust
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- if: github.event_name != 'pull_request'
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- # Sign container
- - uses: sigstore/cosign-installer@v3.3.0
- if: github.event_name != 'pull_request'
-
- - name: Sign container image
- if: github.event_name != 'pull_request'
- run: |
- echo "${{ env.COSIGN_PRIVATE_KEY }}" > cosign.key
- wc -c cosign.key
- cosign sign -y --key cosign.key ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}@${TAGS}
- env:
- TAGS: ${{ steps.push.outputs.digest }}
- COSIGN_EXPERIMENTAL: false
- COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
-
- - name: Echo outputs
- run: |
- echo "${{ toJSON(steps.push.outputs) }}"
diff --git a/.github/workflows/build-fedora-toolbox.yml b/.github/workflows/build-fedora-toolbox.yml
deleted file mode 100644
index f267ee52ac8..00000000000
--- a/.github/workflows/build-fedora-toolbox.yml
+++ /dev/null
@@ -1,104 +0,0 @@
-name: Build and Push Fedora Toolbox Image
-on:
- schedule:
- - cron: '20 22 * * *' # 10:20pm everyday
- pull_request:
- merge_group:
- workflow_dispatch:
-env:
- IMAGE_NAME: fedora-toolbox
- IMAGE_TAGS: latest
- IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- push-ghcr:
- name: Build and push image
- runs-on: ubuntu-22.04
- permissions:
- contents: read
- packages: write
- id-token: write
- strategy:
- fail-fast: false
- steps:
- # Checkout push-to-registry action GitHub repository
- - name: Checkout Push to Registry action
- uses: actions/checkout@v4
-
- # Build metadata
- - name: Image Metadata
- uses: docker/metadata-action@v5
- id: meta
- with:
- images: |
- ${{ env.IMAGE_NAME }}
- labels: |
- io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/boxkit/main/README.md
-
- # Build image using Buildah action
- - name: Build Image
- id: build_image
- uses: redhat-actions/buildah-build@v2
- with:
- containerfiles: |
- ./toolboxes/Containerfile.fedora
- image: ${{ env.IMAGE_NAME }}
- tags: ${{ env.IMAGE_TAGS }}
- labels: ${{ steps.meta.outputs.labels }}
- oci: false
-
- # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
- # https://github.com/macbre/push-to-ghcr/issues/12
- - name: Lowercase Registry
- id: registry_case
- uses: ASzc/change-string-case-action@v6
- with:
- string: ${{ env.IMAGE_REGISTRY }}
-
- # Push the image to GHCR (Image Registry)
- - name: Push To GHCR
- uses: redhat-actions/push-to-registry@v2
- if: github.event_name != 'pull_request'
- id: push
- env:
- REGISTRY_USER: ${{ github.actor }}
- REGISTRY_PASSWORD: ${{ github.token }}
- with:
- image: ${{ steps.build_image.outputs.image }}
- tags: ${{ steps.build_image.outputs.tags }}
- registry: ${{ steps.registry_case.outputs.lowercase }}
- username: ${{ env.REGISTRY_USER }}
- password: ${{ env.REGISTRY_PASSWORD }}
- extra-args: |
- --disable-content-trust
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- if: github.event_name != 'pull_request'
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- # Sign container
- - uses: sigstore/cosign-installer@v3.3.0
- if: github.event_name != 'pull_request'
-
- - name: Sign container image
- if: github.event_name != 'pull_request'
- run: |
- echo "${{ env.COSIGN_PRIVATE_KEY }}" > cosign.key
- wc -c cosign.key
- cosign sign -y --key cosign.key ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}@${TAGS}
- env:
- TAGS: ${{ steps.push.outputs.digest }}
- COSIGN_EXPERIMENTAL: false
- COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
-
- - name: Echo outputs
- run: |
- echo "${{ toJSON(steps.push.outputs) }}"
diff --git a/.github/workflows/build-ubuntu-toolbox.yml b/.github/workflows/build-ubuntu-toolbox.yml
deleted file mode 100644
index 17dc9d0eab8..00000000000
--- a/.github/workflows/build-ubuntu-toolbox.yml
+++ /dev/null
@@ -1,104 +0,0 @@
-name: Build and Push Ubuntu Toolbox Image
-on:
- schedule:
- - cron: '20 22 * * *' # 10:20pm everyday
- pull_request:
- merge_group:
- workflow_dispatch:
-env:
- IMAGE_NAME: ubuntu-toolbox
- IMAGE_TAGS: latest
- IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- push-ghcr:
- name: Build and push image
- runs-on: ubuntu-22.04
- permissions:
- contents: read
- packages: write
- id-token: write
- strategy:
- fail-fast: false
- steps:
- # Checkout push-to-registry action GitHub repository
- - name: Checkout Push to Registry action
- uses: actions/checkout@v4
-
- # Build metadata
- - name: Image Metadata
- uses: docker/metadata-action@v5
- id: meta
- with:
- images: |
- ${{ env.IMAGE_NAME }}
- labels: |
- io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/boxkit/main/README.md
-
- # Build image using Buildah action
- - name: Build Image
- id: build_image
- uses: redhat-actions/buildah-build@v2
- with:
- containerfiles: |
- ./toolboxes/Containerfile.ubuntu
- image: ${{ env.IMAGE_NAME }}
- tags: ${{ env.IMAGE_TAGS }}
- labels: ${{ steps.meta.outputs.labels }}
- oci: false
-
- # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
- # https://github.com/macbre/push-to-ghcr/issues/12
- - name: Lowercase Registry
- id: registry_case
- uses: ASzc/change-string-case-action@v6
- with:
- string: ${{ env.IMAGE_REGISTRY }}
-
- # Push the image to GHCR (Image Registry)
- - name: Push To GHCR
- uses: redhat-actions/push-to-registry@v2
- if: github.event_name != 'pull_request'
- id: push
- env:
- REGISTRY_USER: ${{ github.actor }}
- REGISTRY_PASSWORD: ${{ github.token }}
- with:
- image: ${{ steps.build_image.outputs.image }}
- tags: ${{ steps.build_image.outputs.tags }}
- registry: ${{ steps.registry_case.outputs.lowercase }}
- username: ${{ env.REGISTRY_USER }}
- password: ${{ env.REGISTRY_PASSWORD }}
- extra-args: |
- --disable-content-trust
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- if: github.event_name != 'pull_request'
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- # Sign container
- - uses: sigstore/cosign-installer@v3.3.0
- if: github.event_name != 'pull_request'
-
- - name: Sign container image
- if: github.event_name != 'pull_request'
- run: |
- echo "${{ env.COSIGN_PRIVATE_KEY }}" > cosign.key
- wc -c cosign.key
- cosign sign -y --key cosign.key ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}@${TAGS}
- env:
- TAGS: ${{ steps.push.outputs.digest }}
- COSIGN_EXPERIMENTAL: false
- COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
-
- - name: Echo outputs
- run: |
- echo "${{ toJSON(steps.push.outputs) }}"
diff --git a/.github/workflows/build-wolfi-toolbox.yml b/.github/workflows/build-wolfi-toolbox.yml
deleted file mode 100644
index 22079288940..00000000000
--- a/.github/workflows/build-wolfi-toolbox.yml
+++ /dev/null
@@ -1,104 +0,0 @@
-name: Build and Push Wolfi Toolbox Image
-on:
- schedule:
- - cron: '20 22 * * *' # 10:20pm everyday
- pull_request:
- merge_group:
- workflow_dispatch:
-env:
- IMAGE_NAME: wolfi-toolbox
- IMAGE_TAGS: latest
- IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- push-ghcr:
- name: Build and push image
- runs-on: ubuntu-22.04
- permissions:
- contents: read
- packages: write
- id-token: write
- strategy:
- fail-fast: false
- steps:
- # Checkout push-to-registry action GitHub repository
- - name: Checkout Push to Registry action
- uses: actions/checkout@v4
-
- # Build metadata
- - name: Image Metadata
- uses: docker/metadata-action@v5
- id: meta
- with:
- images: |
- ${{ env.IMAGE_NAME }}
- labels: |
- io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/boxkit/main/README.md
-
- # Build image using Buildah action
- - name: Build Image
- id: build_image
- uses: redhat-actions/buildah-build@v2
- with:
- containerfiles: |
- ./toolboxes/Containerfile.wolfi
- image: ${{ env.IMAGE_NAME }}
- tags: ${{ env.IMAGE_TAGS }}
- labels: ${{ steps.meta.outputs.labels }}
- oci: false
-
- # Workaround bug where capital letters in your GitHub username make it impossible to push to GHCR.
- # https://github.com/macbre/push-to-ghcr/issues/12
- - name: Lowercase Registry
- id: registry_case
- uses: ASzc/change-string-case-action@v6
- with:
- string: ${{ env.IMAGE_REGISTRY }}
-
- # Push the image to GHCR (Image Registry)
- - name: Push To GHCR
- uses: redhat-actions/push-to-registry@v2
- if: github.event_name != 'pull_request'
- id: push
- env:
- REGISTRY_USER: ${{ github.actor }}
- REGISTRY_PASSWORD: ${{ github.token }}
- with:
- image: ${{ steps.build_image.outputs.image }}
- tags: ${{ steps.build_image.outputs.tags }}
- registry: ${{ steps.registry_case.outputs.lowercase }}
- username: ${{ env.REGISTRY_USER }}
- password: ${{ env.REGISTRY_PASSWORD }}
- extra-args: |
- --disable-content-trust
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- if: github.event_name != 'pull_request'
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- # Sign container
- - uses: sigstore/cosign-installer@v3.3.0
- if: github.event_name != 'pull_request'
-
- - name: Sign container image
- if: github.event_name != 'pull_request'
- run: |
- echo "${{ env.COSIGN_PRIVATE_KEY }}" > cosign.key
- wc -c cosign.key
- cosign sign -y --key cosign.key ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}@${TAGS}
- env:
- TAGS: ${{ steps.push.outputs.digest }}
- COSIGN_EXPERIMENTAL: false
- COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
-
- - name: Echo outputs
- run: |
- echo "${{ toJSON(steps.push.outputs) }}"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ca987c234ad..b3704937c52 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -6,6 +6,13 @@ on:
pull_request:
branches:
- main
+ - testing
+ paths-ignore:
+ - '**.md'
+ push:
+ branches:
+ - main
+ - testing
paths-ignore:
- '**.md'
workflow_dispatch:
@@ -40,20 +47,19 @@ jobs:
is_stable_version: true
is_gts_version: false
steps:
- # Checkout push-to-registry action GitHub repository
- - name: Checkout Push to Registry action
+ - name: Checkout
uses: actions/checkout@v4
- name: Verify base image
- uses: EyeCantCU/cosign-action/verify@v0.2.1
+ uses: EyeCantCU/cosign-action/verify@v0.2.2
with:
containers: silverblue-${{ matrix.image_flavor }}:${{ matrix.major_version }}
- name: Verify Chainguard images
if: matrix.base_name != 'bluefin'
- uses: EyeCantCU/cosign-action/verify@v0.2.1
+ uses: EyeCantCU/cosign-action/verify@v0.2.2
with:
- containers: flux, helm, ko, minio, kubectl
+ containers: dive, flux, helm, ko, minio, kubectl
cert-identity: https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main
oidc-issuer: https://token.actions.githubusercontent.com
registry: cgr.dev/chainguard
@@ -100,8 +106,16 @@ jobs:
BUILD_TAGS=("${MAJOR_VERSION}" "${MAJOR_VERSION}-${TIMESTAMP}")
- if [[ "${{ matrix.is_latest_version }}" == "true" ]] && \
- [[ "${{ matrix.is_stable_version }}" == "true" ]]; then
+ if [[ ${{ github.ref_name }} == "testing" ]]; then
+ BUILD_TAGS=("${MAJOR_VERSION}-testing" "${MAJOR_VERSION}-testing-${TIMESTAMP}")
+ if [[ "${{ matrix.is_latest_version }}" == "true" ]] && \
+ [[ "${{ matrix.is_stable_version }}" == "true" ]]; then
+ BUILD_TAGS+=("testing")
+ elif [[ "${{ matrix.is_gts_version }}" == "true" ]]; then
+ BUILD_TAGS+=("gts-testing")
+ fi
+ elif [[ "${{ matrix.is_latest_version }}" == "true" ]] && \
+ [[ "${{ matrix.is_stable_version }}" == "true" ]]; then
BUILD_TAGS+=("latest")
elif [[ "${{ matrix.is_gts_version }}" == "true" ]]; then
BUILD_TAGS+=("gts")
@@ -124,8 +138,14 @@ jobs:
- name: Get Current Fedora Version
id: labels
+ shell: bash
run: |
+ set -eo pipefail
ver=$(skopeo inspect docker://ghcr.io/ublue-os/silverblue-${{ matrix.image_flavor }}:${{ matrix.major_version }} | jq -r '.Labels["org.opencontainers.image.version"]')
+ if [ -z "$ver" ] || [ "null" = "$ver" ]; then
+ echo "inspected image version must not be empty or null"
+ exit 1
+ fi
echo "VERSION=$ver" >> $GITHUB_OUTPUT
# Build metadata
@@ -189,8 +209,6 @@ jobs:
registry: ${{ steps.registry_case.outputs.lowercase }}
username: ${{ env.REGISTRY_USER }}
password: ${{ env.REGISTRY_PASSWORD }}
- extra-args: |
- --disable-content-trust
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
@@ -201,7 +219,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
# Sign container
- - uses: sigstore/cosign-installer@v3.3.0
+ - uses: sigstore/cosign-installer@v3.4.0
if: github.event_name != 'pull_request'
- name: Sign container image
@@ -216,7 +234,7 @@ jobs:
- name: Echo outputs
if: github.event_name != 'pull_request'
run: |
- echo "${{ toJSON(steps.push.outputs) }}"
+ echo "${{ toJSON(steps.push.outputs) }}"
check:
name: Check all builds successful
diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml
new file mode 100644
index 00000000000..2ee8ffe3a2e
--- /dev/null
+++ b/.github/workflows/contributors.yml
@@ -0,0 +1,22 @@
+name: Update Contributors
+
+on:
+ schedule:
+ - cron: '0 0 * * *' # Every day at midnight
+ push:
+ branches:
+ - main
+
+jobs:
+ update:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - uses: akhilmhdh/contributors-readme-action@v2.3.6
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/Containerfile b/Containerfile
index cfc9aee9586..f7262afe2dc 100644
--- a/Containerfile
+++ b/Containerfile
@@ -27,10 +27,18 @@ RUN if [ ${FEDORA_MAJOR_VERSION} -ge "39" ]; then \
--experimental \
--from repo=copr:copr.fedorainfracloud.org:kylegospo:prompt \
vte291 \
- vte-profile && \
+ vte-profile \
+ libadwaita && \
rpm-ostree install \
prompt && \
- rm -f /etc/yum.repos.d/_copr_kylegospo-prompt.repo \
+ rm -f /etc/yum.repos.d/_copr_kylegospo-prompt.repo && \
+ rpm-ostree override remove \
+ power-profiles-daemon \
+ || true && \
+ rpm-ostree override remove \
+ tlp \
+ tlp-rdw \
+ || true \
; fi
COPY usr /usr
@@ -39,6 +47,7 @@ COPY etc/yum.repos.d/ /etc/yum.repos.d/
COPY packages.json /tmp/packages.json
COPY build.sh /tmp/build.sh
COPY image-info.sh /tmp/image-info.sh
+COPY fetch-quadlets.sh /tmp/fetch-quadlets.sh
# Copy ublue-update.toml to tmp first, to avoid being overwritten.
COPY usr/etc/ublue-update/ublue-update.toml /tmp/ublue-update.toml
@@ -49,18 +58,17 @@ RUN sed -i 's@enabled=0@enabled=1@g' /etc/yum.repos.d/_copr_ublue-os-akmods.repo
if [[ "${FEDORA_MAJOR_VERSION}" -ge "39" ]]; then \
rpm-ostree install \
/tmp/akmods-rpms/kmods/*xpadneo*.rpm \
- /tmp/akmods-rpms/kmods/*xpad-noone*.rpm \
/tmp/akmods-rpms/kmods/*xone*.rpm \
/tmp/akmods-rpms/kmods/*openrazer*.rpm \
/tmp/akmods-rpms/kmods/*v4l2loopback*.rpm \
/tmp/akmods-rpms/kmods/*wl*.rpm \
; fi && \
- # Don't install evdi on asus because of conflicts
if grep -qv "asus" <<< "${AKMODS_FLAVOR}"; then \
rpm-ostree install \
/tmp/akmods-rpms/kmods/*evdi*.rpm \
; fi && \
- sed -i 's@enabled=1@enabled=0@g' /etc/yum.repos.d/negativo17-fedora-multimedia.repo
+ sed -i 's@enabled=1@enabled=0@g' /etc/yum.repos.d/negativo17-fedora-multimedia.repo && \
+ wget https://copr.fedorainfracloud.org/coprs/che/nerd-fonts/repo/fedora-"${FEDORA_MAJOR_VERSION}"/che-nerd-fonts-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/_copr_che-nerd-fonts-"${FEDORA_MAJOR_VERSION}".repo
# Starship Shell Prompt
RUN curl -Lo /tmp/starship.tar.gz "https://github.com/starship/starship/releases/latest/download/starship-x86_64-unknown-linux-gnu.tar.gz" && \
@@ -68,14 +76,23 @@ RUN curl -Lo /tmp/starship.tar.gz "https://github.com/starship/starship/releases
install -c -m 0755 /tmp/starship /usr/bin && \
echo 'eval "$(starship init bash)"' >> /etc/bashrc
-RUN wget https://copr.fedorainfracloud.org/coprs/ublue-os/bling/repo/fedora-$(rpm -E %fedora)/ublue-os-bling-fedora-$(rpm -E %fedora).repo -O /etc/yum.repos.d/_copr_ublue-os-bling.repo && \
- wget https://copr.fedorainfracloud.org/coprs/ublue-os/staging/repo/fedora-"${FEDORA_MAJOR_VERSION}"/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
+# Copy atuin from bluefin-cli
+COPY --from=ghcr.io/ublue-os/bluefin-cli /usr/bin/atuin /usr/bin/atuin
+COPY --from=ghcr.io/ublue-os/bluefin-cli /usr/share/bash-prexec /usr/share/bash-prexec
+
+RUN wget https://copr.fedorainfracloud.org/coprs/ublue-os/staging/repo/fedora-"${FEDORA_MAJOR_VERSION}"/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
/tmp/build.sh && \
/tmp/image-info.sh && \
+ /tmp/fetch-quadlets.sh && \
pip install --prefix=/usr yafti && \
+ pip install --prefix=/usr topgrade && \
+ rpm-ostree install ublue-update && \
mkdir -p /usr/etc/flatpak/remotes.d && \
wget -q https://dl.flathub.org/repo/flathub.flatpakrepo -P /usr/etc/flatpak/remotes.d && \
cp /tmp/ublue-update.toml /usr/etc/ublue-update/ublue-update.toml && \
+ if [[ "${FEDORA_MAJOR_VERSION}" -ge "39" ]]; then \
+ systemctl enable tuned.service \
+ ; fi && \
systemctl enable rpm-ostree-countme.service && \
systemctl enable tailscaled.service && \
systemctl enable dconf-update.service && \
@@ -89,12 +106,12 @@ RUN wget https://copr.fedorainfracloud.org/coprs/ublue-os/bling/repo/fedora-$(rp
find /tmp/just -iname '*.just' -exec printf "\n\n" \; -exec cat {} \; >> /usr/share/ublue-os/just/60-custom.just && \
rm -f /etc/yum.repos.d/tailscale.repo && \
rm -f /etc/yum.repos.d/charm.repo && \
- rm -f /etc/yum.repos.d/_copr_ublue-os-bling.repo && \
rm -f /etc/yum.repos.d/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
- rm -f /usr/share/applications/fish.desktop && \
- rm -f /usr/share/applications/htop.desktop && \
- rm -f /usr/share/applications/nvtop.desktop && \
- rm -fr /usr/share/applications/gnome-system-monitor.desktop && \
+ echo "Hidden=true" >> /usr/share/applications/fish.desktop && \
+ echo "Hidden=true" >> /usr/share/applications/htop.desktop && \
+ echo "Hidden=true" >> /usr/share/applications/nvtop.desktop && \
+ echo "Hidden=true" >> /usr/share/applications/gnome-system-monitor.desktop && \
+ rm -f /etc/yum.repos.d/_copr_che-nerd-fonts-"${FEDORA_MAJOR_VERSION}".repo && \
sed -i 's/#DefaultTimeoutStopSec.*/DefaultTimeoutStopSec=15s/' /etc/systemd/user.conf && \
sed -i 's/#DefaultTimeoutStopSec.*/DefaultTimeoutStopSec=15s/' /etc/systemd/system.conf && \
sed -i '/^PRETTY_NAME/s/Silverblue/Bluefin/' /usr/lib/os-release && \
@@ -127,18 +144,17 @@ RUN sysctl -p
RUN wget https://copr.fedorainfracloud.org/coprs/ganto/lxc4/repo/fedora-"${FEDORA_MAJOR_VERSION}"/ganto-lxc4-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/ganto-lxc4-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
wget https://copr.fedorainfracloud.org/coprs/ublue-os/staging/repo/fedora-"${FEDORA_MAJOR_VERSION}"/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
- wget https://copr.fedorainfracloud.org/coprs/karmab/kcli/repo/fedora-"${FEDORA_MAJOR_VERSION}"/karmab-kcli-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/karmab-kcli-fedora-"${FEDORA_MAJOR_VERSION}".repo
+ wget https://copr.fedorainfracloud.org/coprs/karmab/kcli/repo/fedora-"${FEDORA_MAJOR_VERSION}"/karmab-kcli-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/karmab-kcli-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
+ wget https://copr.fedorainfracloud.org/coprs/atim/ubuntu-fonts/repo/fedora-"${FEDORA_MAJOR_VERSION}"/atim-ubuntu-fonts-fedora-"${FEDORA_MAJOR_VERSION}".repo -O /etc/yum.repos.d/atim-ubuntu-fonts-fedora-"${FEDORA_MAJOR_VERSION}".repo
# Handle packages via packages.json
RUN /tmp/build.sh && \
/tmp/image-info.sh
-## power-profiles-daemon with amd p-state support, remove when this is upstream
-RUN rpm-ostree override replace --experimental --from repo=copr:copr.fedorainfracloud.org:ublue-os:staging power-profiles-daemon
-
RUN wget https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 -O /tmp/docker-compose && \
install -c -m 0755 /tmp/docker-compose /usr/bin
+COPY --from=cgr.dev/chainguard/dive:latest /usr/bin/dive /usr/bin/dive
COPY --from=cgr.dev/chainguard/flux:latest /usr/bin/flux /usr/bin/flux
COPY --from=cgr.dev/chainguard/helm:latest /usr/bin/helm /usr/bin/helm
COPY --from=cgr.dev/chainguard/ko:latest /usr/bin/ko /usr/bin/ko
@@ -155,8 +171,11 @@ RUN wget https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx -O /usr
chmod +x /usr/bin/kubectx /usr/bin/kubens
# Set up services
-RUN systemctl enable docker.service && \
+RUN systemctl enable docker.socket && \
systemctl enable podman.socket && \
+ systemctl enable swtpm-workaround.service && \
+ systemctl enable bluefin-dx-groups.service && \
+ systemctl enable --global bluefin-dx-user-vscode.service && \
systemctl disable pmie.service && \
systemctl disable pmlogger.service
@@ -166,6 +185,7 @@ RUN /tmp/workarounds.sh
RUN rm -f /etc/yum.repos.d/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
rm -f /etc/yum.repos.d/ganto-lxc4-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
rm -f /etc/yum.repos.d/karmab-kcli-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
+ rm -f /etc/yum.repos.d/atim-ubuntu-fonts-fedora-"${FEDORA_MAJOR_VERSION}".repo && \
rm -f /etc/yum.repos.d/vscode.repo && \
rm -f /etc/yum.repos.d/docker-ce.repo && \
rm -f /etc/yum.repos.d/_copr:copr.fedorainfracloud.org:phracek:PyCharm.repo && \
diff --git a/README.md b/README.md
index 4992f7da96c..1ca5336d7c0 100644
--- a/README.md
+++ b/README.md
@@ -17,8 +17,23 @@ A familiar(ish) Ubuntu desktop for Fedora Silverblue. It strives to cover these
# Documentation
-1. [Bluefin](http://universal-blue.discourse.group/t/introduction-to-bluefin/41)
+1. [Bluefin](https://universal-blue.discourse.group/t/introduction-to-bluefin/41)
2. [Discussions and Announcements](https://universal-blue.discourse.group/c/bluefin/6) - strongly recommended!
-3. [Developer Experience Edition](http://universal-blue.discourse.group/t/bluefin-dx-the-bluefin-developer-experience/39)
-4. [Administrator's Guide](http://universal-blue.discourse.group/t/bluefin-administrators-guide/40)
+3. [Developer Experience Edition](https://universal-blue.discourse.group/t/bluefin-dx-the-bluefin-developer-experience/39)
+4. [Administrator's Guide](https://universal-blue.discourse.group/t/bluefin-administrators-guide/40)
5. [Framework Images](https://universal-blue.org/images/framework/)
+
+## Repobeats
+
+![Alt](https://repobeats.axiom.co/api/embed/40b85b252bf6ea25eb90539d1adcea013ccae69a.svg "Repobeats analytics image")
+
+## Star History
+
+
+
+
+
diff --git a/dx/usr/bin/bluefin-dx-groups b/dx/usr/bin/bluefin-dx-groups
new file mode 100755
index 00000000000..964dc9cb0f6
--- /dev/null
+++ b/dx/usr/bin/bluefin-dx-groups
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+# SCRIPT VERSION
+GROUP_SETUP_VER=1
+GROUP_SETUP_VER_FILE="/etc/ublue/dx-groups"
+GROUP_SETUP_VER_RAN=$(cat "$GROUP_SETUP_VER_FILE")
+
+# Run script if updated
+if [[ -f $GROUP_SETUP_VER_FILE && "$GROUP_SETUP_VER" = "$GROUP_SETUP_VER_RAN" ]]; then
+ echo "Group setup has already run. Exiting..."
+ exit 0
+fi
+
+# Setup Groups
+wheelarray=($(getent group wheel | cut -d ":" -f 4 | tr ',' '\n'))
+for user in $wheelarray
+do
+ usermod -aG docker $user
+ usermod -aG incus-admin $user
+ usermod -aG lxd $user
+ usermod -aG libvirt $user
+done
+
+# Prevent future executions
+echo "Writing state file"
+echo "$GROUP_SETUP_VER" > "$GROUP_SETUP_VER_FILE"
diff --git a/dx/usr/bin/bluefin-dx-user-vscode b/dx/usr/bin/bluefin-dx-user-vscode
new file mode 100755
index 00000000000..b8af1e5e196
--- /dev/null
+++ b/dx/usr/bin/bluefin-dx-user-vscode
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+# SCRIPT VERSION
+USER_SETUP_VER=2
+USER_SETUP_VER_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/ublue/vscode-configured"
+USER_SETUP_VER_RAN=$(cat "$USER_SETUP_VER_FILE")
+
+mkdir -p "$(dirname "$USER_SETUP_VER_FILE")" || exit 1
+
+USER_SETUP_VER_FILE_V1="$HOME/.bluefin-vscode-configured"
+# Upgrade from v1 to v2 changes only the location of the USER_SETUP_VER.
+# Exit if v1 file is present.
+if [[ -f $USER_SETUP_VER_FILE_V1 ]]; then
+ echo "User setup v1 has already run. Exiting..."
+ rm $USER_SETUP_VER_FILE_V1
+ echo "$USER_SETUP_VER" > "$USER_SETUP_VER_FILE"
+ exit 0
+fi
+
+# Run script if updated
+if [[ -f $USER_SETUP_VER_FILE && "$USER_SETUP_VER" = "$USER_SETUP_VER_RAN" ]]; then
+ echo "User setup v$VER has already run. Exiting..."
+ exit 0
+fi
+
+# Setup VSCode
+# Pre-install preferred VSCode Extensions
+code --install-extension ms-vscode-remote.remote-containers
+code --install-extension ms-vscode-remote.remote-ssh
+code --install-extension ms-azuretools.vscode-docker
+
+# Prevent future executions
+echo "Writing state file"
+echo "$USER_SETUP_VER" > "$USER_SETUP_VER_FILE"
diff --git a/dx/usr/bin/bluefin-incus b/dx/usr/bin/bluefin-incus
new file mode 100755
index 00000000000..6eefd779ac2
--- /dev/null
+++ b/dx/usr/bin/bluefin-incus
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+
+# All the pieces needed to enable incus on Bluefin-dx
+# This script is meant to be run on a bluefin-dx host
+
+# if current user is root, warn and exit
+
+if [ "$EUID" -eq 0 ]
+then
+ echo "This script should not be run as root"
+ exit
+fi
+
+# add user to incus-admin group
+
+sudo usermod -aG incus-admin $USER
+
+# check for, then add necessary entries to /etc/subuid and /etc/subgid
+echo ""
+echo "Checking for necessary entries in /etc/subuid and /etc/subgid"
+if grep -q "root:1000000:1000000000" /etc/subuid
+then
+ echo ""
+ echo " * subuid root range"
+else
+ echo "root:1000000:1000000000" | sudo tee -a /etc/subuid
+fi
+
+if grep -q "root:1000000:1000000000" /etc/subgid
+then
+ echo ""
+ echo " * subgid root range"
+else
+ echo "root:1000000:1000000000" | sudo tee -a /etc/subgid
+fi
+
+if grep -q "root:1000:1" /etc/subgid
+then
+ echo ""
+ echo " * subgid root->user"
+else
+ echo "root:1000:1" | sudo tee -a /etc/subgid
+fi
+
+if grep -q "root:1000:1" /etc/subuid
+then
+ echo ""
+ echo " * subuid root->user"
+else
+ echo "root:1000:1" | sudo tee -a /etc/subuid
+fi
+
+# check to see if SELinux is set to permissive or disabled
+
+echo ""
+echo "Checking SELinux status"
+SELINUX_STATUS=$(getenforce)
+
+if [ "$SELINUX_STATUS" = "Enforcing" ]
+then
+ echo ""
+ echo "SELinux must be set to Permissive or Disabled to enable Incus"
+ echo "Choose your new SELinux state:"
+ OPTION=$(gum choose Permissive Disabled Cancel)
+ if [ "$OPTION" = "Cancel" ]
+ then
+ echo "You have chosen to cancel the Incus installation process"
+ exit
+ else
+ sudo setenforce $OPTION
+ echo "You must reboot before continuing. You can run this script again."
+ exit
+ fi
+fi
+
+# create necessary directories for lxcfs and incus
+
+echo ""
+echo "Creating necessary directories for lxcfs and incus"
+sudo mkdir -p /var/lib/lxcfs
+sudo mkdir -p /var/lib/incus
+sudo mkdir -p /var/log/incus
+
+# enable incus services
+
+echo ""
+echo "Enabling incus services"
+sudo systemctl enable --now lxcfs
+sudo systemctl enable --now incus
+
+
+# run incus admin init
+echo ""
+echo "Initializing Incus"
+echo ""
+echo "Choose your Incus installation type:"
+IOPTION=$(gum choose Minimal Custom Cancel)
+if [ "$IOPTION" = "Cancel" ]
+then
+ echo "You have chosen to cancel the Incus installation process"
+ exit
+else
+ if [ "$IOPTION" = "Minimal" ]
+ then
+ sudo incus admin init --minimal
+ echo ""
+ echo "Adding the incus bridge to the trusted firewall zone"
+ sudo firewall-cmd --zone=trusted --change-interface=incusbr0 --permanent
+ sudo firewall-cmd --reload
+ else
+ sudo incus admin init
+ echo ""
+ echo "Add the incus bridge to the trusted firewall zone"
+ echo " sudo firewall-cmd --zone=trusted --change-interface=your-bridge --permanent"
+ echo " sudo firewall-cmd --reload"
+ fi
+fi
+echo ""
+echo "Incus has been installed. You can now run 'incus' to manage your containers."
\ No newline at end of file
diff --git a/dx/usr/etc/dconf/db/local.d/01-ublue-dx b/dx/usr/etc/dconf/db/local.d/01-ublue-dx
index 6480091ea23..a87443983de 100644
--- a/dx/usr/etc/dconf/db/local.d/01-ublue-dx
+++ b/dx/usr/etc/dconf/db/local.d/01-ublue-dx
@@ -1,11 +1,2 @@
[org/gnome/shell]
favorite-apps = ['org.mozilla.firefox.desktop', 'org.mozilla.Thunderbird.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Rhythmbox3.desktop', 'org.libreoffice.LibreOffice.writer.desktop', 'org.gnome.Software.desktop', 'code.desktop', 'org.gnome.Prompt.desktop', 'ubuntu.desktop', 'yelp.desktop']
-
-[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom3]
-binding='f'
-command='xdg-terminal-exec -- bluefinbox-enter fedora'
-name='Fedora Prompt'
-
-[org/gnome/settings-daemon/plugins/media-keys]
-custom-keybindings=['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom3/']
-home=['e']
diff --git a/dx/usr/etc/distrobox/distrobox.ini b/dx/usr/etc/distrobox/distrobox.ini
deleted file mode 100644
index 79dcb567878..00000000000
--- a/dx/usr/etc/distrobox/distrobox.ini
+++ /dev/null
@@ -1,15 +0,0 @@
-[ubuntu]
-image=ghcr.io/ublue-os/ubuntu-toolbox:latest
-init=false
-nvidia=false
-pull=true
-root=false
-replace=true
-
-[fedora]
-image=ghcr.io/ublue-os/fedora-toolbox:latest
-init=false
-nvidia=false
-pull=true
-root=false
-replace=true
diff --git a/dx/usr/etc/profile.d/vscode-bluefin-profile.sh b/dx/usr/etc/profile.d/vscode-bluefin-profile.sh
index 8cd70942235..631fbe3b115 100644
--- a/dx/usr/etc/profile.d/vscode-bluefin-profile.sh
+++ b/dx/usr/etc/profile.d/vscode-bluefin-profile.sh
@@ -2,6 +2,6 @@ if test "$(id -u)" -gt "0" && test -d "$HOME"; then
# Add default settings when there are no settings
if test ! -e "$HOME"/.config/Code/User/settings.json; then
mkdir -p "$HOME"/.config/Code/User
- cp -f /etc/skel.d/.config/Code/User/settings.json "$HOME"/.config/Code/User/settings.json
+ cp -f /etc/skel/.config/Code/User/settings.json "$HOME"/.config/Code/User/settings.json
fi
fi
diff --git a/dx/usr/etc/skel.d/.config/Code/User/settings.json b/dx/usr/etc/skel.d/.config/Code/User/settings.json
deleted file mode 100644
index 45b7a603e0b..00000000000
--- a/dx/usr/etc/skel.d/.config/Code/User/settings.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "dev.containers.dockerComposePath": "podman-compose",
- "dev.containers.dockerPath": "podman",
- "window.titleBarStyle": "custom",
- "editor.fontFamily": "'CaskaydiaCove Nerd Font Mono', 'Droid Sans Mono', 'monospace', monospace"
-}
diff --git a/dx/usr/etc/skel/.config/Code/User/settings.json b/dx/usr/etc/skel/.config/Code/User/settings.json
new file mode 100644
index 00000000000..592e7a8868b
--- /dev/null
+++ b/dx/usr/etc/skel/.config/Code/User/settings.json
@@ -0,0 +1,4 @@
+{
+ "window.titleBarStyle": "custom",
+ "editor.fontFamily": "'Cascadia Code', 'Droid Sans Mono', 'monospace', monospace"
+}
diff --git a/dx/usr/lib/systemd/system/bluefin-dx-groups.service b/dx/usr/lib/systemd/system/bluefin-dx-groups.service
new file mode 100644
index 00000000000..d025a7b5733
--- /dev/null
+++ b/dx/usr/lib/systemd/system/bluefin-dx-groups.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Add wheel members to docker,incus-admin, and lxd groups
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/bluefin-dx-groups
+Restart=on-failure
+RestartSec=30
+StartLimitInterval=0
+
+[Install]
+WantedBy=default.target
\ No newline at end of file
diff --git a/dx/usr/lib/systemd/system/swtpm-workaround.service b/dx/usr/lib/systemd/system/swtpm-workaround.service
new file mode 100644
index 00000000000..271ed8293ac
--- /dev/null
+++ b/dx/usr/lib/systemd/system/swtpm-workaround.service
@@ -0,0 +1,20 @@
+[Unit]
+Description=Workaround swtpm not having the correct label
+ConditionFileIsExecutable=/usr/bin/swtpm
+After=local-fs.target
+
+[Service]
+Type=oneshot
+# Copy if it doesn't exist
+ExecStartPre=/usr/bin/bash -c "[ -x /usr/local/bin/.swtpm ] || /usr/bin/cp /usr/bin/swtpm /usr/local/bin/.swtpm"
+# This is faster than using .mount unit. Also allows for the previous line/cleanup
+ExecStartPre=/usr/bin/mount --bind /usr/local/bin/.swtpm /usr/bin/swtpm
+# Fix SELinux label
+ExecStart=/usr/sbin/restorecon /usr/bin/swtpm
+# Clean-up after ourselves
+ExecStop=/usr/bin/umount /usr/bin/swtpm
+ExecStop=/usr/bin/rm /usr/local/bin/.swtpm
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/dx/usr/lib/systemd/user/bluefin-dx-user-vscode.service b/dx/usr/lib/systemd/user/bluefin-dx-user-vscode.service
new file mode 100644
index 00000000000..2cf7d94b5c4
--- /dev/null
+++ b/dx/usr/lib/systemd/user/bluefin-dx-user-vscode.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Run
+Wants=network-online.target
+After=network-online.target ublue-user-setup.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/bluefin-dx-user-vscode
+Restart=on-failure
+RestartSec=30
+StartLimitInterval=0
+
+[Install]
+WantedBy=default.target
\ No newline at end of file
diff --git a/dx/usr/lib/tmpfiles.d/swtpm-workaround.conf b/dx/usr/lib/tmpfiles.d/swtpm-workaround.conf
new file mode 100644
index 00000000000..bf20bf6457b
--- /dev/null
+++ b/dx/usr/lib/tmpfiles.d/swtpm-workaround.conf
@@ -0,0 +1,2 @@
+C /usr/local/bin/.swtpm - - - - /usr/bin/swtpm
+d /var/lib/swtpm-localca 0750 tss tss - -
\ No newline at end of file
diff --git a/fetch-quadlets.sh b/fetch-quadlets.sh
new file mode 100755
index 00000000000..6cc90904c5b
--- /dev/null
+++ b/fetch-quadlets.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+
+set -oue pipefail
+
+# Make Directory
+mkdir -p /usr/etc/containers/systemd/users
+
+# bluefin-cli
+wget --output-document="/usr/etc/containers/systemd/users/bluefin-cli.container" --quiet https://raw.githubusercontent.com/ublue-os/toolboxes/main/quadlets/bluefin-cli/bluefin-cli.container
+cat /usr/share/ublue-os/bluefin-cli/prompt-integration >> /usr/etc/containers/systemd/users/bluefin-cli.container
+printf "\n\n[Install]\nWantedBy=bluefin-cli.target" >> /usr/etc/containers/systemd/users/bluefin-cli.container
+sed -i '/AutoUpdate.*/ s/^#*/#/' /usr/etc/containers/systemd/users/bluefin-cli.container
+sed -i 's/ContainerName=bluefin/ContainerName=bluefin-cli/' /usr/etc/containers/systemd/users/bluefin-cli.container
+
+# bluefin-dx-cli
+wget --output-document="/usr/etc/containers/systemd/users/bluefin-dx-cli.container" --quiet https://raw.githubusercontent.com/ublue-os/toolboxes/main/quadlets/bluefin-cli/bluefin-dx-cli.container
+cat /usr/share/ublue-os/bluefin-cli/prompt-integration >> /usr/etc/containers/systemd/users/bluefin-dx-cli.container
+printf "\n\n[Install]\nWantedBy=bluefin-dx-cli.target" >> /usr/etc/containers/systemd/users/bluefin-dx-cli.container
+sed -i '/AutoUpdate.*/ s/^#*/#/' /usr/etc/containers/systemd/users/bluefin-dx-cli.container
+sed -i 's/ContainerName=bluefin/ContainerName=bluefin-dx-cli/' /usr/etc/containers/systemd/users/bluefin-dx-cli.container
+
+# fedora-toolbox
+wget --output-document="/usr/etc/containers/systemd/users/fedora-toolbox.container" --quiet https://raw.githubusercontent.com/ublue-os/toolboxes/main/quadlets/fedora-toolbox/fedora-distrobox-quadlet.container
+cat /usr/share/ublue-os/bluefin-cli/prompt-integration >> /usr/etc/containers/systemd/users/fedora-toolbox.container
+printf "\n\n[Install]\nWantedBy=fedora-toolbox.target" >> /usr/etc/containers/systemd/users/fedora-toolbox.container
+sed -i '/AutoUpdate.*/ s/^#*/#/' /usr/etc/containers/systemd/users/fedora-toolbox.container
+sed -i 's/ContainerName=fedora-distrobox-quadlet/ContainerName=fedora-toolbox/' /usr/etc/containers/systemd/users/fedora-toolbox.container
+
+# ubuntu-toolbox
+wget --output-document="/usr/etc/containers/systemd/users/ubuntu-toolbox.container" --quiet https://raw.githubusercontent.com/ublue-os/toolboxes/main/quadlets/ubuntu-toolbox/ubuntu-distrobox-quadlet.container
+cat /usr/share/ublue-os/bluefin-cli/prompt-integration >> /usr/etc/containers/systemd/users/ubuntu-toolbox.container
+printf "\n\n[Install]\nWantedBy=ubuntu-toolbox.target" >> /usr/etc/containers/systemd/users/ubuntu-toolbox.container
+sed -i '/AutoUpdate.*/ s/^#*/#/' /usr/etc/containers/systemd/users/ubuntu-toolbox.container
+sed -i 's/ContainerName=ubuntu-distrobox-quadlet/ContainerName=ubuntu-toolbox/' /usr/etc/containers/systemd/users/ubuntu-toolbox.container
+
+# wolfi-toolbox
+wget --output-document="/usr/etc/containers/systemd/users/wolfi-toolbox.container" --quiet https://raw.githubusercontent.com/ublue-os/toolboxes/main/quadlets/wolfi-toolbox/wolfi-distrobox-quadlet.container
+cat /usr/share/ublue-os/bluefin-cli/prompt-integration >> /usr/etc/containers/systemd/users/wolfi-toolbox.container
+printf "\n\n[Install]\nWantedBy=wolfi-toolbox.target" >> /usr/etc/containers/systemd/users/wolfi-toolbox.container
+sed -i '/AutoUpdate.*/ s/^#*/#/' /usr/etc/containers/systemd/users/wolfi-toolbox.container
+sed -i 's/ContainerName=wolfi-quadlet/ContainerName=wolfi-toolbox/' /usr/etc/containers/systemd/users/wolfi-toolbox.container
+
+# wolfi-dx-toolbox
+wget --output-document="/usr/etc/containers/systemd/users/wolfi-dx-toolbox.container" --quiet https://raw.githubusercontent.com/ublue-os/toolboxes/main/quadlets/wolfi-toolbox/wolfi-dx-distrobox-quadlet.container
+cat /usr/share/ublue-os/bluefin-cli/prompt-integration >> /usr/etc/containers/systemd/users/wolfi-dx-toolbox.container
+printf "\n\n[Install]\nWantedBy=wolfi-dx-toolbox.target" >> /usr/etc/containers/systemd/users/wolfi-dx-toolbox.container
+sed -i '/AutoUpdate.*/ s/^#*/#/' /usr/etc/containers/systemd/users/wolfi-dx-toolbox.container
+sed -i 's/ContainerName=wolfi-quadlet/ContainerName=wolfi-dx-toolbox/' /usr/etc/containers/systemd/users/wolfi-dx-toolbox.container
+
+# Make systemd targets and restart services for topgrade
+mkdir -p /usr/lib/systemd/user
+mkdir -p /usr/share/ublue-os/bluefin-cli
+QUADLET_TARGETS=(
+ "bluefin-cli"
+ "bluefin-dx-cli"
+ "fedora-toolbox"
+ "ubuntu-toolbox"
+ "wolfi-toolbox"
+ "wolfi-dx-toolbox"
+)
+for i in "${QUADLET_TARGETS[@]}"
+do
+cat > "/usr/lib/systemd/user/${i}.target" < "/usr/lib/systemd/user/${i}-update.service" < "/usr/share/ublue-os/bluefin-cli/${i}.sh" <Installing aqua ...\n\n'
- pushd "$(mktemp -d)"
- curl -sSfL -O https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.1.1/aqua-installer
- echo "c2af02bdd15da6794f9c98db40332c804224930212f553a805425441f8331665 aqua-installer" | sha256sum -c
- chmod +x aqua-installer
- ./aqua-installer
- printf '\n=> Make sure the ${AQUA_ROOT_DIR}/bin environment variable is added to your PATH (.bashrc/.zshrc):\n'
- printf '\n export PATH="${AQUA_ROOT_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/aquaproj-aqua}/bin:$PATH"\n'
- printf '\n=> see https://aquaproj.github.io/docs/tutorial for more info\n'
+# Configure Bluefin-CLI Terminal Experience
+bluefin-cli:
+ @/usr/libexec/enable-bluefin-cli.sh
+# Configure Terminal Experience
[private]
-bluefin-cli:
- #!/usr/bin/env bash
- if [ ! -f "${HOME}/.brew_pkgs" ]; then
- echo dysk > "${HOME}/.brew_pkgs"
- fi;
- distrobox-create --nvidia --image ghcr.io/ublue-os/bluefin-cli:latest -n bluefin -Y -a "--env BREW_PKGS=.brew_pkgs"
- echo "Entering bluefin-cli"
- distrobox enter bluefin
+configure-terminal:
+ @/usr/libexec/configure-terminal.sh
# Enable Cockpit for web-based system management | https://cockpit-project.org/
cockpit:
@@ -90,21 +71,6 @@ devmode:
fi
fi
-# Assemble a Pytorch distrobox (Nvidia only)
-distrobox-mlbox:
- echo 'Assembling pytorch-nvidia mlbox distrobox ...'
- distrobox assemble create --file /usr/share/ublue-os/distrobox/pytorch-nvidia.ini
-
-# Create a Wolfi OS container | https://github.com/wolfi-dev
-distrobox-wolfi:
- echo 'Creating WolfiOS distrobox ...'
- distrobox create --image ghcr.io/ublue-os/wolfi-toolbox:latest -n wolfi
-
-# Create a universal developer container
-distrobox-universal:
- echo 'Creating Universal Development distrobox ...'
- distrobox create --image mcr.microsoft.com/devcontainers/universal:latest -n universal -Y
-
# Switch to the fish shell
fish:
sudo usermod $USER --shell /usr/bin/fish
@@ -113,7 +79,6 @@ fish:
# Install recommended GNOME extensions
gnome-extensions:
pip install --upgrade gnome-extensions-cli
- gext install tailscale-status@maxgallup.github.com
gext install nightthemeswitcher@romainvigier.fr
gext install pano@elhan.io
gext install weatheroclock@CleoMenezesJr.github.io
@@ -183,6 +148,21 @@ garden:
echo ""
fi
+# Install and configure Incus
+incus:
+ #!/usr/bin/env bash
+ CURRENT_IMAGE=$(rpm-ostree status -b --json | jq -r '.deployments[0]."container-image-reference"')
+
+ if grep -q "bluefin-dx" <<< $CURRENT_IMAGE
+ then
+ echo 'Installing and configuring Incus.'
+ /usr/bin/bluefin-incus
+ else
+ echo "Developer mode is currently ${CURRENT_STATE}."
+ echo "Run `just devmode` to turn on Developer mode."
+ exit
+ fi
+
# Install nix and Devbox
nix-devbox:
echo 'Setting phasers to kill. Installing nix.'
@@ -204,47 +184,22 @@ nix-devbox-global:
echo 'run "devbox global run install-hook-zsh" to configure zsh shell'
echo 'run "devbox global run" to see other available configuration commands'
-# Enable podmansh as user shell (EXPERIMENTAL)
-podmansh:
- sudo mkdir -p /etc/containers/systemd/users/${UID}
- sudo cp /usr/share/ublue-os/quadlets/podmansh.container /etc/containers/systemd/users/${UID}/podmansh.container
- sudo usermod $USER --shell /usr/bin/podmansh
- printf "${USER}'s shell is now %s." "$(cat /etc/passwd | grep ":$UID:" | cut '-d:' '-f7')"
- systemctl --user start podman.socket
- loginctl enable-linger $(whoami)
-
- podman pull ghcr.io/ublue-os/ubuntu-toolbox:latest
-
- systemctl --user daemon-reload
- systemctl --user stop podmansh.service
- systemctl --user start podmansh.service
-
- @echo "Shell now switched to podmansh. Spawn a new terminal to get going!"
- @echo "By default, the shell will be Bash. To override it, create ~/.profile with your preferred shell"
- @echo "Note: That shell must exist in the toolbox!"
- @echo "To ensure a smooth experience within VSCode, please add the following to your settings.json:"
- @echo "---"
- @echo "\"terminal.integrated.profiles.linux\": {"
- @echo " \"podmansh zsh\": {"
- @echo " \"path\": \"podmansh\","
- @echo " \"args\": [\"-c\", \"cd \${workspaceFolder}; exec zsh\"]"
- @echo " }"
- @echo "}"
- @echo "---"
- @echo "Please make sure you have the following environment variable set WITHIN the container:"
- @echo "---"
- @echo "export DOCKER_HOST=unix:///var/run/podman/podman.sock"
- @echo "---"
- @echo "Happy Podmansh'ing!"
-
-# Switch podmansh to another image (EXPERIMENTAL)
-podmansh-switch IMAGE:
- sudo sed -i "/Image\=.*$/c Image\={{ IMAGE }}" /etc/containers/systemd/users/${UID}/podmansh.container
- podman pull {{ IMAGE }}
- podman rm -f podmansh
- systemctl --user daemon-reload
- systemctl --user start podmansh.service
- echo "Image now switched to {{ IMAGE }}"
+# Prompt terminal transparency
+prompt-transparency opacity="0.95":
+ #!/usr/bin/env bash
+ set -euxo pipefail
+ if [[ -n "$(echo "{{ opacity }}" | grep -v '^[.0-9]*$')" ]]; then
+ printf "Value must be numeric: %s.\n" "{{ opacity }}"
+ elif [[ $(echo "0<{{ opacity }} && 1>{{ opacity }}" | bc -q) -eq 1 ]]; then
+ raw="$(gsettings get org.gnome.Prompt profile-uuids)"
+ uuids="$(sed -En 's|[^0-9a-z]*||g; s|([0-9a-z]{32})|\1\n|gp' <<<${raw})"
+ for i in ${uuids}; do
+ location="org.gnome.Prompt.Profile:/org/gnome/Prompt/Profiles/${i}/"
+ gsettings set "${location}" opacity "{{ opacity }}"; done
+ printf "Prompt opacity is now %s.\n" "{{ opacity }}"
+ else
+ printf "Value must be between 0 and 1: %s.\n" "{{ opacity }}"
+ fi
# Run pytorch
pytorch:
@@ -267,15 +222,6 @@ touch:
gext install improvedosk@nick-shmyrev.dev
gext install gestureImprovements@gestures
-# A preview of what the update system would look like in the future
-update-ng:
- echo 'Upgrading system...'
- sudo bootc upgrade
- echo 'Upgrading flatpaks...'
- flatpak update -y
- echo 'Assembling and replacing distroboxes ...'
- distrobox assemble create --replace --file /etc/distrobox/distrobox.ini
-
# Upgrade Distrobox to the latest git version
distrobox-git:
echo 'Installing latest git snapshot of Distrobox'
@@ -290,8 +236,25 @@ zsh:
sudo usermod $USER --shell /usr/bin/zsh
printf "${USER}'s shell is now %s." "$(cat /etc/passwd | grep ":$UID:" | cut '-d:' '-f7')"
-# Enable docker on the system
-docker:
- sudo systemctl enable --now docker
+# Configure docker,incus-admin,lxd,libvirt container manager permissions
+dx-group:
sudo usermod -aG docker $USER
- newgrp docker
+ sudo usermod -aG incus-admin $USER
+ sudo usermod -aG lxd $USER
+ sudo usermod -aG libvirt $USER
+ @echo "Logout to use docker, incus-admin, lxd, libvirt"
+
+# Add atuin
+atuin:
+ #!/usr/bin/bash
+ shell=$(basename $SHELL)
+ if test $shell = "fish"; then
+ echo "Adding atuin to your config.fish"
+ printf '\nif status is-interactive\n\tif type -q atuin\n\t\tatuin init fish | source\n\tend\nend\n' >> ${XDG_CONFIG_HOME:-$HOME/.config}/fish/config.fish
+ elif test $shell = "zsh"; then
+ echo "Adding atuin to your .zshrc"
+ printf '\n[[ "$(command -v atuin)" ]] && eval "$(atuin init zsh)"\n' >> ${ZDOTDIR:-$HOME}/.zshrc
+ elif test $shell = "bash"; then
+ echo "Adding bash-prexec and atuin to your .bashrc"
+ printf '\n[[ -f /usr/share/bash-prexec ]] && source /usr/share/bash-prexec\n[[ "$(command -v atuin)" ]] && eval "$(atuin init bash)"\n' >> ~/.bashrc
+ fi
diff --git a/packages.json b/packages.json
index f4e71b9f867..5e3cadf189a 100644
--- a/packages.json
+++ b/packages.json
@@ -6,6 +6,7 @@
"cockpit-bridge",
"evtest",
"fish",
+ "firewall-config",
"glow",
"gum",
"gnome-shell-extension-appindicator",
@@ -24,6 +25,8 @@
"make",
"mesa-libGLU",
"nautilus-gsconnect",
+ "nerd-fonts",
+ "playerctl",
"pulseaudio-utils",
"python3-pip",
"samba-dcerpc",
@@ -35,7 +38,6 @@
"stress-ng",
"tailscale",
"tmux",
- "ublue-update",
"usbmuxd",
"wireguard-tools",
"xprop",
@@ -45,7 +47,7 @@
],
"bluefin-dx": [
"adobe-source-code-pro-fonts",
- "cascadiacode-nerd-fonts",
+ "cascadia-code-fonts",
"cockpit-machines",
"cockpit-networkmanager",
"cockpit-ostree",
@@ -57,7 +59,7 @@
"code",
"containerd.io",
"dbus-x11",
- "devpod",
+ "devpod",
"distrobuilder",
"docker-ce",
"docker-ce-cli",
@@ -95,8 +97,7 @@
"qemu-user-binfmt",
"qemu-user-static",
"qemu",
- "ubuntu-nerd-fonts",
- "ubuntumono-nerd-fonts",
+ "ubuntu-family-fonts",
"virt-manager",
"virt-viewer"
]
@@ -133,7 +134,12 @@
"bluefin": [
"gnome-shell-extension-tailscale-gnome-qs",
"input-leap",
- "nautilus-open-any-terminal"
+ "nautilus-open-any-terminal",
+ "tuned",
+ "tuned-ppd",
+ "tuned-utils",
+ "tuned-utils-systemtap",
+ "tuned-profiles-atomic"
],
"bluefin-dx": [],
"bluefin-framework": []
diff --git a/toolboxes/Containerfile.bluefin-cli b/toolboxes/Containerfile.bluefin-cli
deleted file mode 100644
index 5869946c343..00000000000
--- a/toolboxes/Containerfile.bluefin-cli
+++ /dev/null
@@ -1,21 +0,0 @@
-FROM ghcr.io/ublue-os/wolfi-toolbox
-
-LABEL com.github.containers.toolbox="true" \
- usage="This image is meant to be used with the toolbox or distrobox command" \
- summary="A new cloud-native terminal experience powered by Wolfi and Homebrew" \
- maintainer="jorge.castro@gmail.com"
-
-COPY ./toolboxes/packages.bluefin-cli /toolbox-packages
-
-# Update image
-RUN apk update && \
- apk upgrade
-
-# Add optional packages
-RUN grep -v '^#' /toolbox-packages | xargs apk add
-
-RUN rm /toolbox-packages
-
-# Change root shell to BASH
-
-RUN sed -i -e '/^root/s/\/bin\/ash/\/bin\/bash/' /etc/passwd
diff --git a/toolboxes/Containerfile.fedora b/toolboxes/Containerfile.fedora
deleted file mode 100644
index f91a21fc04b..00000000000
--- a/toolboxes/Containerfile.fedora
+++ /dev/null
@@ -1,14 +0,0 @@
-FROM ghcr.io/ublue-os/fedora-distrobox:latest
-# From https://github.com/ublue-os/fedora-distrobox
-
-LABEL com.github.containers.toolbox="true" \
- usage="This image is meant to be used with the toolbox or distrobox command" \
- summary="A cloud-native terminal experience powered by Fedora"
-
-COPY ./toolboxes/packages.fedora /toolbox-packages
-
-RUN dnf -y upgrade && \
- dnf -y install $(> /etc/sudoers
\ No newline at end of file
diff --git a/toolboxes/Containerfile.wolfi b/toolboxes/Containerfile.wolfi
deleted file mode 100644
index 1c7241d014d..00000000000
--- a/toolboxes/Containerfile.wolfi
+++ /dev/null
@@ -1,21 +0,0 @@
-FROM cgr.dev/chainguard/wolfi-base
-# Thanks to Nuno do Carmo for the initial prototype
-
-LABEL com.github.containers.toolbox="true" \
- usage="This image is meant to be used with the toolbox or distrobox command" \
- summary="A blank Wolfi distrobox, suitable for development" \
- maintainer="jorge.castro@gmail.com"
-
-COPY ./toolboxes/packages.wolfi /toolbox-packages
-
-# Update image
-RUN apk update && \
- apk upgrade
-
-# Add optional packages
-RUN grep -v '^#' /toolbox-packages | xargs apk add
-
-RUN rm /toolbox-packages
-
-# Change root shell to BASH
-RUN sed -i -e '/^root/s/\/bin\/ash/\/bin\/bash/' /etc/passwd
diff --git a/toolboxes/brew_script.bluefin-cli b/toolboxes/brew_script.bluefin-cli
deleted file mode 100644
index ede4ecc32e4..00000000000
--- a/toolboxes/brew_script.bluefin-cli
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-if [ ! -f /home/linuxbrew/.firstrun ] && [ -n "${BREW_PKGS}" ]; then
- touch /home/linuxbrew/.firstrun
- # `brew update-reset` is currently needed
- # because somekind of issue with brew
- brew update-reset
- xargs brew install < "${HOME}"/"${BREW_PKGS}"
-fi
diff --git a/toolboxes/packages.bluefin-cli b/toolboxes/packages.bluefin-cli
deleted file mode 100644
index d9bd46a6c59..00000000000
--- a/toolboxes/packages.bluefin-cli
+++ /dev/null
@@ -1,5 +0,0 @@
-bash
-#brew
-git
-procps
-sudo-rs
\ No newline at end of file
diff --git a/toolboxes/packages.fedora b/toolboxes/packages.fedora
deleted file mode 100644
index 2652bf7cbaf..00000000000
--- a/toolboxes/packages.fedora
+++ /dev/null
@@ -1,2 +0,0 @@
-vim
-ripgrep
diff --git a/toolboxes/packages.ubuntu b/toolboxes/packages.ubuntu
deleted file mode 100644
index 8a141ed3816..00000000000
--- a/toolboxes/packages.ubuntu
+++ /dev/null
@@ -1,89 +0,0 @@
-bc
-dbus-x11
-direnv
-fzf
-libegl1-mesa
-libgl1-mesa-glx
-libvte-common
-make
-neofetch
-plocate
-progress
-apt-utils
-dialog
-dirmngr
-gnupg
-gnupg-l10n
-gnupg-utils
-gnupg2
-gpg
-ca-certificates
-libnsl2
-libpython3-stdlib
-gpg-agent
-gpg-wks-client
-gpg-wks-server
-gpgsm
-libksba8
-libnpth0
-libpython3.11-minimal
-gpgconf
-libnss-myhostname
-libsqlite3-0
-libtirpc-common
-libtirpc3
-libvte-2.91-common
-openssl
-lsof
-pinentry-curses
-time
-libpython3.11-stdlib
-libvulkan1
-media-types
-mesa-vulkan-drivers
-libbsd0
-libdrm-amdgpu1
-libdrm-common
-libdrm-nouveau2
-libdrm-radeon1
-libdrm2
-libedit2
-libegl-mesa0
-libegl1
-libegl1-mesa
-libelf1
-libexpat1
-libgbm1
-libgl1
-libgl1-amber-dri
-libgl1-mesa-dri
-libgl1-mesa-glx
-libglapi-mesa
-libglvnd0
-libglx-mesa0
-libglx0
-libicu70
-libllvm15
-libpciaccess0
-libsensors-config
-libsensors5
-libwayland-client0
-libwayland-server0
-libx11-6
-libx11-data
-libx11-xcb1
-libxau6
-libxcb-dri2-0
-libxcb-dri3-0
-libxcb-glx0
-libxcb-present0
-libxcb-randr0
-libxcb-shm0
-libxcb-sync1
-libxcb-xfixes0
-libxcb1
-libxdmcp6
-libxext6
-libxfixes3
-libxml2
-pigz
diff --git a/toolboxes/packages.wolfi b/toolboxes/packages.wolfi
deleted file mode 100644
index f582ccd2a88..00000000000
--- a/toolboxes/packages.wolfi
+++ /dev/null
@@ -1,33 +0,0 @@
-bash
-bzip2
-coreutils
-curl
-diffutils
-findmnt
-findutils
-gnupg
-gpg
-iproute2
-iputils
-keyutils
-libcap
-mount
-ncurses
-ncurses-terminfo
-net-tools
-openssh-client
-pigz
-posix-libc-utils
-procps
-rsync
-su-exec
-tcpdump
-tree
-tzdata
-umount
-util-linux
-util-linux-misc
-wget
-xz
-zip
-vulkan-loader
diff --git a/usr/bin/podman-host b/usr/bin/podman-host
new file mode 100755
index 00000000000..d322cef3762
--- /dev/null
+++ b/usr/bin/podman-host
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+id="$(echo "$@" | grep -Eo ' [a-zA-Z0-9]{64} ' | tr -d ' ')"
+PODMAN_COMMAND="$(command -v podman 2> /dev/null)"
+DISTROBOX_COMMAND="$(command -v distrobox 2> /dev/null)"
+
+# if we're in a flatpak, use podman-remote
+# else we fallback to host-spawn
+if [ -n "$FLATPAK_ID" ]; then
+ if command -v podman-remote > /dev/null 2>&1; then
+ PODMAN_COMMAND="podman-remote"
+ else
+ PODMAN_COMMAND="flatpak-spawn --host podman"
+ fi
+ DISTROBOX_COMMAND="flatpak-spawn --host distrobox"
+fi
+
+# This little workaround is used to ensure
+# we use our distrobox to properly enter the container
+if echo "$@" | grep -q 'exec'; then
+ # if exec && distrobox -> use distrobox-enter --
+ if [ "$($PODMAN_COMMAND inspect --type container --format '{{ index .Config.Labels "manager" }}' "${id}")" = "distrobox" ]; then
+
+ # Ensure that our distrobox containers will use different vscode-servers by symlinking to different paths
+ if [ -n "${id}" ]; then
+ $PODMAN_COMMAND exec -u "$USER" "${id}" /bin/sh -c '
+ if [ ! -L "${HOME}/.vscode-server" ]; then
+ [ -e "${HOME}/.vscode-server" ] && mv "${HOME}/.vscode-server" /var/tmp
+ [ -d /var/tmp/.vscode-server ] && mkdir /var/tmp/.vscode-server
+ ln -sf /var/tmp/.vscode-server "$HOME"
+ elif [ ! -e "${HOME}/.vscode-server" ]; then
+ mkdir /var/tmp/.vscode-server
+ fi'
+ fi
+
+ # Remove everything from $@ and leave only the execution part, we start
+ # capturing after we meet our ID
+ dbox_args="-e A=B"
+ capture="false"
+ for i; do
+ if [ $capture = "true" ]; then
+ set -- "$@" "$i"
+ elif echo "$i" | grep -q "VSCODE"; then
+ dbox_args="$dbox_args -e $i"
+ elif echo "$i" | grep -q "\-w"; then
+ dbox_args="$dbox_args -w $2"
+ fi
+ if [ "$i" = "${id}" ]; then
+ capture="true"
+ fi
+ shift
+ done
+
+ $DISTROBOX_COMMAND enter --additional-flags "${dbox_args}" "${id}" -- "$@"
+ exit $?
+ fi
+fi
+
+$PODMAN_COMMAND "$@"
diff --git a/usr/bin/ublue-system-flatpak-manager b/usr/bin/ublue-system-flatpak-manager
index 76142f8f9c6..4011bdbe8bd 100755
--- a/usr/bin/ublue-system-flatpak-manager
+++ b/usr/bin/ublue-system-flatpak-manager
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Script Version
-VER=1
+VER=3
VER_FILE="/etc/ublue/flatpak_manager_version"
VER_RAN=$(cat $VER_FILE)
@@ -11,11 +11,17 @@ if [[ -f $VER_FILE && $VER = $VER_RAN ]]; then
exit 0
fi
-# Remove fedora flatpak repo
+# Opt out of and remove Fedora's flatpak repo
if grep -qz 'fedora' <<< $(flatpak remotes); then
- flatpak remote-delete --user fedora --force
+ /usr/lib/fedora-third-party/fedora-third-party-opt-out
+ /usr/bin/fedora-third-party disable
+ flatpak remote-delete fedora --force
fi
+# Ensure Flathub is enabled
+flatpak remote-add --if-not-exists --system flathub /usr/etc/flatpak/remotes.d/flathub.flatpakrepo
+flatpak remote-modify --system --enable flathub
+
# Lists of flatpaks
FLATPAK_LIST=$(flatpak list --columns=application)
INSTALL_LIST=$(cat /etc/flatpak/system/install)
@@ -34,25 +40,5 @@ if [[ ! -f $VER_FILE && -n $REMOVE_LIST ]]; then
flatpak remove --system --noninteractive ${REMOVE_LIST[@]}
fi
-# Opt out of and remove Fedora's flatpak repo
-if grep -qz 'fedora' <<< $(flatpak remotes); then
- /usr/lib/fedora-third-party/fedora-third-party-opt-out
- /usr/bin/fedora-third-party disable
- flatpak remote-delete fedora --force
-
- # Remove flatpak apps from origin fedora
- FEDORA_FLATPAKS=$(flatpak list --app --columns=application,origin | grep -w 'fedora' | awk '{print $1}')
- flatpak remove --system --noninteractive ${FEDORA_FLATPAKS[@]}
-
- # Remove flatpak runtimes from origin fedora
- FEDORA_FLATPAKS=$(flatpak list --runtime --columns=application,arch,branch,origin | grep -w 'fedora' | awk '{print $1"/"$2"/"$3}')
- flatpak remove --system --noninteractive ${FEDORA_FLATPAKS[@]}
-fi
-
-# Disable the system variant of the flathub repo
-flatpak remote-modify flathub --disable --system
-
-notify-send "Flatpak installer" "Finished installing system flatpaks" --app-name="Flatpak installer" -u NORMAL
-
mkdir -p /etc/ublue
echo $VER > $VER_FILE
diff --git a/usr/bin/ublue-user-flatpak-manager b/usr/bin/ublue-user-flatpak-manager
index 24340369896..1435ad4764b 100755
--- a/usr/bin/ublue-user-flatpak-manager
+++ b/usr/bin/ublue-user-flatpak-manager
@@ -1,18 +1,34 @@
#!/usr/bin/env bash
# Script Version
-VER=1
-VER_FILE="$HOME/.ublue_flatpak_manager_version"
+VER=3
+VER_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/ublue/flatpak_manager_version"
VER_RAN=$(cat $VER_FILE)
+mkdir -p "$(dirname "$VER_FILE")" || exit 1
+
+# Upgrade from v1 to v2 changes only the location of the VER_FILE.
+# Exit if v1 file is present.
+VER_1_FILE="$HOME/.ublue_flatpak_manager_version"
+if [[ -f $VER_1_FILE ]]; then
+ echo "Flatpak manager v1 has already ran. Exiting..."
+ rm $VER_1_FILE
+ echo $VER > $VER_FILE
+ exit 0
+fi
+
# Run script if updated
if [[ -f $VER_FILE && $VER = $VER_RAN ]]; then
echo "Flatpak manager v$VER has already ran. Exiting..."
exit 0
fi
-# Setup Flathub
-flatpak remote-add --if-not-exists --user flathub /etc/flatpak/remotes.d/flathub.flatpakrepo
+# Enable Flathub
+if grep -qz 'fedora' <<< $(flatpak remotes); then
+ flatpak remote-delete --user fedora --force
+fi
+flatpak remote-add --if-not-exists --user flathub /usr/etc/flatpak/remotes.d/flathub.flatpakrepo
+flatpak remote-modify --user --enable --prio=2 flathub
# Lists of flatpaks
FLATPAK_LIST=$(flatpak list --columns=application)
diff --git a/usr/bin/ublue-user-setup b/usr/bin/ublue-user-setup
index 0da279fcbed..e487798f90d 100755
--- a/usr/bin/ublue-user-setup
+++ b/usr/bin/ublue-user-setup
@@ -1,13 +1,27 @@
#!/usr/bin/env bash
# SCRIPT VERSION
-USER_SETUP_VER=1
-USER_SETUP_VER_FILE="$HOME/.ublue-configured"
+USER_SETUP_VER=3
+USER_SETUP_VER_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/ublue/user-setup"
USER_SETUP_VER_RAN=$(cat $USER_SETUP_VER_FILE)
+mkdir -p "$(dirname "$USER_SETUP_VER_FILE")" || exit 1
+
+echo "$(dirname "$USER_SETUP_VER_FILE")"
+
+# Upgrade from v1 to v2 changes only the location of the USER_SETUP_VER.
+# Exit if v1 file is present.
+USER_SETUP_VER_FILE_V1="$HOME/.ublue-configured"
+if [[ -f $USER_SETUP_VER_FILE_V1 ]]; then
+ echo "User setup v1 has already run. Exiting..."
+ rm $USER_SETUP_VER_FILE_V1
+ echo $USER_SETUP_VER > $USER_SETUP_VER_FILE
+ exit 0
+fi
+
# Run script if updated
if [[ -f $USER_SETUP_VER_FILE && $USER_SETUP_VER = $USER_SETUP_VER_RAN ]]; then
- echo "User setup has already run. Exiting..."
+ echo "User setup v$VER has already run. Exiting..."
exit 0
fi
@@ -17,6 +31,14 @@ IMAGE_NAME=$(jq -r '."image-name"' < $IMAGE_INFO)
# Enable NTP
timedatectl set-ntp true
+# Ensure custom prompt theme is present
+PROMPT_THEME_DIR="/usr/etc/skel/.local/share/org.gnome.Prompt/palettes"
+PROMPT_DIR="$HOME/.local/share/org.gnome.Prompt/palettes"
+mkdir -p "$PROMPT_DIR"
+if [[ ! -f "$PROMPT_DIR/catppuccin-dynamic.palette" ]]; then
+ cp "$PROMPT_THEME_DIR/catppuccin-dynamic.palette" "$PROMPT_DIR/catppuccin-dynamic.palette"
+fi
+
# Prevent future executions
echo "Writing state file"
-echo $USER_SETUP_VER > $USER_SETUP_VER_FILE
+echo $USER_SETUP_VER > $USER_SETUP_VER_FILE
\ No newline at end of file
diff --git a/usr/bin/vscode-distrobox b/usr/bin/vscode-distrobox
new file mode 100755
index 00000000000..ea62fcb072f
--- /dev/null
+++ b/usr/bin/vscode-distrobox
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+container_name="$(printf '{"containerName":"%s"}' "$1" | od -A n -t x1 | tr -d "\n\t ")"
+
+if flatpak list | grep -q com.visualstudio.code; then
+ code_command="flatpak run com.visualstudio.code"
+elif command -v code 2> /dev/null > /dev/null; then
+ code_command="code"
+else
+ echo "vscode not installed"
+ exit 127
+fi
+
+${code_command} --folder-uri="vscode-remote://attached-container+${container_name}/${2}"
diff --git a/usr/etc/dconf/db/local.d/01-ublue b/usr/etc/dconf/db/local.d/01-ublue
index 0c7ad2c310d..e339585e973 100644
--- a/usr/etc/dconf/db/local.d/01-ublue
+++ b/usr/etc/dconf/db/local.d/01-ublue
@@ -2,20 +2,6 @@
favorite-apps = ['org.mozilla.firefox.desktop', 'org.mozilla.Thunderbird.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Rhythmbox3.desktop', 'org.libreoffice.LibreOffice.writer.desktop', 'org.gnome.Software.desktop', 'code.desktop', 'ubuntu.desktop', 'yelp.desktop']
enabled-extensions = ['appindicatorsupport@rgcjonas.gmail.com', 'dash-to-dock@micxgx.gmail.com', 'blur-my-shell@aunetx', 'gsconnect@andyholmes.github.io', 'logomenu@aryan_k', 'tailscale@joaophi.github.com']
-[org/gnome/desktop/app-folders]
-folder-children=['Utilities', 'Distrobox', 'Wine', 'YaST', 'Pardus']
-
-[org/gnome/desktop/app-folders/folders/Distrobox]
-categories=['Distrobox']
-name='Distrobox'
-translate=false
-
-[org/gnome/desktop/app-folders/folders/Wine]
-apps=['winetricks.desktop']
-categories=['X-Wine', 'wine-wine']
-name='Wine'
-translate=false
-
[org/gnome/desktop/background]
picture-uri='file:///usr/share/backgrounds/bluefin/bluefin-winter-dynamic.xml'
picture-uri-dark='file:///usr/share/backgrounds/bluefin/bluefin-winter-dynamic.xml'
@@ -71,12 +57,12 @@ min-alpha=0.5
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0]
binding='t'
-command='xdg-terminal-exec'
-name='Prompt'
+command='prompt --tab-with-profile=2871e8027773ae74d6c87a5f659bbc74'
+name='Host Prompt'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1]
binding='u'
-command='xdg-terminal-exec -- distrobox enter ubuntu'
+command='prompt --tab-with-profile=4741cb2eb3614750b79edc5c4b8c08b3'
name='Ubuntu Prompt'
[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2]
@@ -84,8 +70,18 @@ binding='Escape'
command="flatpak run io.missioncenter.MissionCenter"
name='mission-center'
+[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom3]
+binding='Return'
+command="prompt --tab-with-profile=a21a910811504857bea4c96b3d937b93"
+name='Bluefin Prompt'
+
+[org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom4]
+binding='f'
+command="prompt --tab-with-profile=d6fe45489ed74fada5d95d715449ce7e"
+name='Fedora Prompt'
+
[org/gnome/settings-daemon/plugins/media-keys]
-custom-keybindings=['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/']
+custom-keybindings=['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom3/', '/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom4/']
home=['e']
[org/gnome/settings-daemon/plugins/power]
@@ -100,16 +96,6 @@ sort-directories-first=true
[org/gnome/mutter]
experimental-features=['scale-monitor-framebuffer']
-[com/raggesilver/BlackBox]
-command-as-login-shell=true
-use-custom-command=false
-custom-shell-command='distrobox enter ubuntu'
-theme-dark="Yaru"
-style-preference=2
-font="Ubuntu Mono 16"
-window-width=975
-window-height=650
-
[org/gnome/software]
allow-updates=false
download-updates=false
@@ -126,7 +112,20 @@ menu-button-icon-image=1
menu-button-terminal='xdg-terminal-exec'
menu-button-system-monitor='flatpak run io.missioncenter.MissionCenter'
menu-button-extensions-app='com.mattjakeman.ExtensionManager.desktop'
+menu-button-software-center='gnome-software'
+show-activities-button=true
+show-lockscreen=false
+show-power-option=false
+show-gamemode=false
+hide-forcequit=true
+show-pods=true
[org/gnome/Prompt]
+interface-style='system'
restore-session=false
restore-window-size=false
+profile-uuids=['2871e8027773ae74d6c87a5f659bbc74']
+default-profile-uuid='2871e8027773ae74d6c87a5f659bbc74'
+
+[org/gnome/Prompt/Profiles/2871e8027773ae74d6c87a5f659bbc74]
+palette='catppuccin-dynamic'
diff --git a/usr/etc/dconf/db/local.d/02-bluefin-folders b/usr/etc/dconf/db/local.d/02-bluefin-folders
new file mode 100644
index 00000000000..f5ff60224f6
--- /dev/null
+++ b/usr/etc/dconf/db/local.d/02-bluefin-folders
@@ -0,0 +1,30 @@
+[org/gnome/desktop/app-folders]
+folder-children=['Games', 'GamingUtilities', 'Utilities', 'Distrobox', 'Wine', 'YaST', 'Pardus']
+
+[org/gnome/desktop/app-folders/folders/GamingUtilities]
+apps=['protontricks.desktop', 'discover_overlay_configure.desktop', 'com.vysp3r.ProtonPlus.desktop', 'io.github.benjamimgois.goverlay.desktop', 'com.gerbilsoft.rom-properties.rp-config.desktop', 'input-remapper-gtk.desktop', 'steamos-nested-desktop.desktop']
+name='Gaming Utilities'
+translate=false
+
+[org/gnome/desktop/app-folders/folders/Utilities]
+apps=['com.github.tchx84.Flatseal.desktop', 'io.github.flattool.Warehouse.desktop', 'com.mattjakeman.ExtensionManager.desktop', 'org.gnome.tweaks.desktop', 'firewall-config.desktop', 'ca.desrt.dconf-editor.desktop']
+categories=['X-GNOME-Utilities']
+name='X-GNOME-Utilities.directory'
+translate=true
+
+[org/gnome/desktop/app-folders/folders/Games]
+excluded-apps=['steam.desktop', 'net.lutris.Lutris.desktop', 'io.github.benjamimgois.goverlay.desktop', 'com.vysp3r.ProtonPlus.desktop', 'io.github.fastrizwaan.WineZGUI.desktop']
+categories=['Game']
+name='Games'
+translate=false
+
+[org/gnome/desktop/app-folders/folders/Distrobox]
+categories=['Distrobox']
+name='Distrobox'
+translate=false
+
+[org/gnome/desktop/app-folders/folders/Wine]
+apps=['winetricks.desktop']
+categories=['X-Wine', 'wine-wine']
+name='Wine'
+translate=false
diff --git a/usr/etc/distrobox/distrobox.ini b/usr/etc/distrobox/distrobox.example
similarity index 100%
rename from usr/etc/distrobox/distrobox.ini
rename to usr/etc/distrobox/distrobox.example
diff --git a/usr/etc/fish/functions/fish_greeting.fish b/usr/etc/fish/functions/fish_greeting.fish
new file mode 100644
index 00000000000..42676df7f33
--- /dev/null
+++ b/usr/etc/fish/functions/fish_greeting.fish
@@ -0,0 +1,13 @@
+function fish_greeting
+ if test -d "$HOME"
+ if test ! -e "$HOME"/.config/no-show-user-motd
+ if test -x "/usr/libexec/ublue-motd"
+ /usr/libexec/ublue-motd
+ end
+ end
+ end
+
+ if set -q fish_private_mode
+ echo "fish is running in private mode, history will not be persisted."
+ end
+end
\ No newline at end of file
diff --git a/usr/etc/flatpak/system/install b/usr/etc/flatpak/system/install
index e69de29bb2d..5c0043fe8c5 100644
--- a/usr/etc/flatpak/system/install
+++ b/usr/etc/flatpak/system/install
@@ -0,0 +1,24 @@
+org.mozilla.firefox
+org.freedesktop.Platform.ffmpeg-full//22.08
+org.gnome.Calculator
+org.gnome.Calendar
+org.gnome.Characters
+org.gnome.Connections
+org.gnome.Contacts
+org.gnome.Evince
+org.gnome.Loupe
+org.gnome.Logs
+org.gnome.Maps
+org.gnome.NautilusPreviewer
+org.gnome.TextEditor
+org.gnome.Weather
+org.gnome.baobab
+org.gnome.clocks
+org.gnome.font-viewer
+com.mattjakeman.ExtensionManager
+com.github.tchx84.Flatseal
+io.github.flattool.Warehouse
+com.github.marhkb.Pods
+org.fedoraproject.MediaWriter
+io.missioncenter.MissionCenter
+io.github.celluloid_player.Celluloid
diff --git a/usr/etc/flatpak/user/install b/usr/etc/flatpak/user/install
index c4a26c34faa..e69de29bb2d 100644
--- a/usr/etc/flatpak/user/install
+++ b/usr/etc/flatpak/user/install
@@ -1,22 +0,0 @@
-org.mozilla.firefox
-org.freedesktop.Platform.ffmpeg-full//22.08
-org.gnome.Calculator
-org.gnome.Calendar
-org.gnome.Characters
-org.gnome.Connections
-org.gnome.Contacts
-org.gnome.Evince
-org.gnome.Loupe
-org.gnome.Logs
-org.gnome.Maps
-org.gnome.NautilusPreviewer
-org.gnome.TextEditor
-org.gnome.Weather
-org.gnome.baobab
-org.gnome.clocks
-org.gnome.font-viewer
-com.mattjakeman.ExtensionManager
-com.github.tchx84.Flatseal
-org.fedoraproject.MediaWriter
-io.missioncenter.MissionCenter
-io.github.celluloid_player.Celluloid
diff --git a/usr/etc/flatpak/user/remove b/usr/etc/flatpak/user/remove
index e69de29bb2d..5c0043fe8c5 100644
--- a/usr/etc/flatpak/user/remove
+++ b/usr/etc/flatpak/user/remove
@@ -0,0 +1,24 @@
+org.mozilla.firefox
+org.freedesktop.Platform.ffmpeg-full//22.08
+org.gnome.Calculator
+org.gnome.Calendar
+org.gnome.Characters
+org.gnome.Connections
+org.gnome.Contacts
+org.gnome.Evince
+org.gnome.Loupe
+org.gnome.Logs
+org.gnome.Maps
+org.gnome.NautilusPreviewer
+org.gnome.TextEditor
+org.gnome.Weather
+org.gnome.baobab
+org.gnome.clocks
+org.gnome.font-viewer
+com.mattjakeman.ExtensionManager
+com.github.tchx84.Flatseal
+io.github.flattool.Warehouse
+com.github.marhkb.Pods
+org.fedoraproject.MediaWriter
+io.missioncenter.MissionCenter
+io.github.celluloid_player.Celluloid
diff --git a/usr/etc/profile.d/bluefin-firstboot.sh b/usr/etc/profile.d/bluefin-firstboot.sh
index 54146b36544..84fc10e347e 100644
--- a/usr/etc/profile.d/bluefin-firstboot.sh
+++ b/usr/etc/profile.d/bluefin-firstboot.sh
@@ -1,6 +1,6 @@
if test "$(id -u)" -gt "0" && test -d "$HOME"; then
if test ! -e "$HOME"/.config/autostart/bluefin-firstboot.desktop; then
mkdir -p "$HOME"/.config/autostart
- cp -f /etc/skel.d/.config/autostart/bluefin-firstboot.desktop "$HOME"/.config/autostart
+ cp -f /etc/skel/.config/autostart/bluefin-firstboot.desktop "$HOME"/.config/autostart
fi
fi
diff --git a/usr/etc/skel.d/.config/autostart/bluefin-firstboot.desktop b/usr/etc/skel/.config/autostart/bluefin-firstboot.desktop
similarity index 100%
rename from usr/etc/skel.d/.config/autostart/bluefin-firstboot.desktop
rename to usr/etc/skel/.config/autostart/bluefin-firstboot.desktop
diff --git a/usr/etc/skel/.local/share/org.gnome.Prompt/palettes/catppuccin-dynamic.palette b/usr/etc/skel/.local/share/org.gnome.Prompt/palettes/catppuccin-dynamic.palette
new file mode 100644
index 00000000000..fcd3bfcd1af
--- /dev/null
+++ b/usr/etc/skel/.local/share/org.gnome.Prompt/palettes/catppuccin-dynamic.palette
@@ -0,0 +1,45 @@
+[Palette]
+Name=Catppuccin Dynamic
+Primary=true
+
+[Light]
+Background=#EFF1F5
+Foreground=#4C4F69
+Cursor=#4C4F69
+Color0=#5C5F77
+Color1=#D20F39
+Color2=#40A02B
+Color3=#DF8E1D
+Color4=#1E66F5
+Color5=#EA76CB
+Color6=#179299
+Color7=#ACB0BE
+Color8=#6C6F85
+Color9=#D20F39
+Color10=#40A02B
+Color11=#DF8E1D
+Color12=#1E66F5
+Color13=#EA76CB
+Color14=#179299
+Color15=#BCC0CC
+
+[Dark]
+Background=#1E1E2E
+Foreground=#CDD6F4
+Cursor=#CDD6F4
+Color0=#45475A
+Color1=#F38BA8
+Color2=#A6E3A1
+Color3=#F9E2AF
+Color4=#89B4FA
+Color5=#F5C2E7
+Color6=#94E2D5
+Color7=#BAC2DE
+Color8=#585B70
+Color9=#F38BA8
+Color10=#A6E3A1
+Color11=#F9E2AF
+Color12=#89B4FA
+Color13=#F5C2E7
+Color14=#94E2D5
+Color15=#A6ADC8
diff --git a/usr/etc/skel/.var/app/com.github.marhkb.Pods/config/pods/connections.json b/usr/etc/skel/.var/app/com.github.marhkb.Pods/config/pods/connections.json
new file mode 100644
index 00000000000..642aa829625
--- /dev/null
+++ b/usr/etc/skel/.var/app/com.github.marhkb.Pods/config/pods/connections.json
@@ -0,0 +1,8 @@
+{
+ "32218213-d8cf-444e-84c7-7f67b9765acd": {
+ "uuid": "32218213-d8cf-444e-84c7-7f67b9765acd",
+ "name": "System",
+ "url": "unix:///run/user/1000/podman/podman.sock",
+ "rgb": null
+ }
+}
\ No newline at end of file
diff --git a/usr/etc/ublue-update/ublue-update.toml b/usr/etc/ublue-update/ublue-update.toml
index efcc93c0e65..2cfa6511054 100644
--- a/usr/etc/ublue-update/ublue-update.toml
+++ b/usr/etc/ublue-update/ublue-update.toml
@@ -1,5 +1,5 @@
[checks]
- min_battery_percent = 0.0
+ min_battery_percent = 20.0
max_cpu_load_percent = 50.0
max_mem_percent = 90.0
[notify]
diff --git a/usr/etc/yafti.yml b/usr/etc/yafti.yml
index fe9abf265ea..6b530dadcc5 100644
--- a/usr/etc/yafti.yml
+++ b/usr/etc/yafti.yml
@@ -26,6 +26,7 @@ screens:
description: Start your cloud-native journey here!
default: false
packages:
+ - GNOME Boxes: org.gnome.Boxes
- Podman Desktop: io.podman_desktop.PodmanDesktop
Gaming:
description: "Rock and Stone!"
diff --git a/usr/lib/modprobe.d/nvidia.conf b/usr/lib/modprobe.d/nvidia.conf
new file mode 100644
index 00000000000..eea3f81798b
--- /dev/null
+++ b/usr/lib/modprobe.d/nvidia.conf
@@ -0,0 +1,2 @@
+# Enable GSP firmware
+options nouveau config=NvGspRm=1
diff --git a/usr/libexec/configure-terminal.sh b/usr/libexec/configure-terminal.sh
new file mode 100755
index 00000000000..73b6aef382f
--- /dev/null
+++ b/usr/libexec/configure-terminal.sh
@@ -0,0 +1,225 @@
+#!/usr/bin/env bash
+# shellcheck source=/dev/null
+source /usr/lib/ujust/ujust.sh
+
+###
+# List of possible containers
+###
+targets=(
+ "bluefin-cli"
+ "bluefin-dx-cli"
+ "fedora-toolbox"
+ "ubuntu-toolbox"
+ "wolfi-toolbox"
+ "wolfi-dx-toolbox"
+)
+
+###
+# Exit Function
+###
+# shellcheck disable=SC2154
+function Exiting(){
+ echo "${red}Exiting...${normal}"
+ echo "Rerun CLI setup using ${blue}ujust bluefin-cli${normal}..."
+ exit 0
+}
+function Good_Exit(){
+ echo ""
+ echo "Finished Bluefin-CLI setup, rerun with ${blue}ujust bluefin-cli${normal} to reconfigure"
+ exit 0
+}
+
+###
+# Exit if string is empty
+###
+function String_check(){
+ if test -z "$1"; then
+ Exiting
+ fi
+}
+
+###
+# Trap function
+###
+# shellcheck disable=SC2317
+function ctrl_c(){
+ printf "\nSignal SIGINT caught\n"
+ Exiting
+}
+
+###
+# Choose if you want to use the Host or Container for first terminal
+###
+function Terminal_choice(){
+ TERMINAL_CHOICE=$(Choose Host Container)
+ if test "$TERMINAL_CHOICE" = "Host"; then
+ echo "You have chosen to use Host Terminal."
+ fi
+ String_check "$TERMINAL_CHOICE"
+}
+
+###
+# If Host was chosen, ask if they still want to make a container
+###
+function Make_container(){
+ MAKE_CONTAINER=0
+ if test "$1" = "Host"; then
+ echo "Would you still like to setup default container?"
+ MAKE_CONTAINER=$(Confirm)
+ fi
+ if test "$MAKE_CONTAINER" -eq 1; then
+ printf "Not making a container. Existing containers will not be deleted...\n"
+ Good_Exit
+ fi
+}
+
+###
+# Choose which container they want to use
+###
+function Choose_container(){
+ echo "Which Container Toolbox would you like to use?"
+ CONTAINER_CHOICE=$(Choose "${targets[@]}")
+ String_check "$CONTAINER_CHOICE"
+}
+
+###
+# Ask how they want to manage the container.
+###
+function Container_manager(){
+ echo "Would you like to use ${blue}quadlets${normal} to manage your container?"
+ echo ""
+ echo "${blue}Quadlets automatically rebuild your container on login.${normal}"
+ echo "They will always be on the latest image you have pulled."
+ echo "However, ${red}manually installed packages using apk, apt, or dnf will not persist${normal}."
+ CONTAINER_MANAGER=$(Choose Quadlet Distrobox)
+ String_check "$CONTAINER_MANAGER"
+}
+
+###
+# Check to see if the chosen container already exists as a quadlet.
+# If it does ask to disable and remove it otherwise quit.
+# Takes chosen container as an argument.
+###
+function Is_enabled_and_stop(){
+ MATCH=0
+ for i in "${targets[@]}"
+ do
+ Enabled=0
+ Enabled=$(systemctl --user is-enabled "$i".target)
+ if test "$Enabled" = "enabled" && test "$i" != "$1"; then
+ echo "${red}$i${normal} is ${red}enabled${normal}."
+ echo "Would you like to ${red}disable and stop container${red}?"
+ Disable=$(Confirm)
+ if test "$Disable" -eq 0; then
+ systemctl --user --now disable "$i".target
+ if test "systemctl --user --quiet is-active $i.service"; then
+ systemctl --user stop "$i".service
+ fi
+ else
+ printf "Not disabling and stopping existing container %s..." "$i"
+ fi
+ unset "$Disable"
+ elif test "$Enabled" = "enabled" && test "$i" = "$1"; then
+ echo "${blue}$1 is already enabled${normal}..."
+ MATCH=1
+ fi
+ unset "$Enabled"
+ done
+ if test "$MATCH" -eq 1; then
+ Good_Exit
+ fi
+ unset $MATCH
+}
+
+###
+# Check to see if the chosen container already exists.
+# If it does ask to remove it otherwise exit.
+# Takes chosen container as an argument.
+###
+function Already_exists_and_rm(){
+ for i in "${targets[@]}"
+ do
+ Exists=0
+ Exists=$(podman ps --all --filter name="$i" | grep -q " $i\$" && echo "1" || echo "0")
+ if test "$Exists" -eq 1 && test "$i" = "$1"; then
+ echo "$1 ${red}exists${normal}, would you like to ${red}delete it?${normal}"
+ Delete=$(Confirm)
+ if test "$Delete" -eq 0; then
+ echo "Removing $1..."
+ podman rm --force "$1"
+ else
+ echo "Reuisng existing $1 container."
+ Good_Exit
+ fi
+ unset "$Delete"
+ elif test "$Exists" -eq 1 && test "$i" != "$1"; then
+ echo "$i exists, would you like to ${red}delete it?${normal}"
+ Delete=$(Confirm)
+ if test "$Delete" -eq 0; then
+ echo "Removing $i..."
+ podman rm --force "$i"
+ else
+ echo "Not removing $i..."
+ fi
+ unset "$Delete"
+ fi
+ unset "$Exists"
+ done
+}
+
+###
+# Build the container. Takes 3 inputs. 1: if you build it. 2: Container Manager. 3: The actual container
+###
+function Build_container(){
+ if test "$1" -eq 1; then
+ printf "Not Building a container..."
+ Exiting
+ fi
+ if test "$2" = "Quadlet"; then
+ echo "${blue}Building container using a Quadlet${normal}"
+ echo ""
+ systemctl --user enable "$3".target
+ systemctl --user restart "$3".service
+ elif test "$2" = "Distrobox"; then
+ echo "${blue}Building container using a Distrobox${normal}"
+ echo ""
+ distrobox-create --nvidia --no-entry -Y --image "ghcr.io/ublue-os/${3}" --name "$3"
+ else
+ printf "Unkown Choice..."
+ Exiting
+ fi
+}
+
+###
+# If ~/.bashrc.d exists and Chose Container for terminal. Make a symlink from /usr/share/ublue-os for first time shell.
+# If Host was chosen. Remove existing symlink.
+###
+# function Make_bashrc_d_file(){
+# if test -d "${HOME}/.bashrc.d" && test "$1" = "Host"; then
+# echo "${red}Removing existing ~/.bashrc.d/00-container.sh if it exists${normal}."
+# test -f "${HOME}/.bashrc.d/00-container.sh" && rm "${HOME}/.bashrc.d/00-container.sh"
+# elif test -d "${HOME}/.bashrc.d"; then
+# echo "Setting first terminal be Container for bash using ~/.bashrc.d"
+# echo "Enter into container using prompt's menu after first entry"
+# echo "${blue}This requires your bash shell to source files in ~/.bashrc.d/${normal}"
+# test -e "${HOME}/.bashrc.d/00-container.sh" && rm "${HOME}/.bashrc.d/00-container.sh"
+# cp "/usr/share/ublue-os/bluefin-cli/${2}.sh" "${HOME}/.bashrc.d/00-container.sh"
+# else
+# echo "${red}Not implemented for non-Bash shells${normal} at this time..."
+# fi
+# }
+
+function main(){
+ trap ctrl_c SIGINT
+ printf "Set Up bluefin-cli\n"
+ Terminal_choice
+ Make_container "$TERMINAL_CHOICE"
+ Container_manager
+ Choose_container
+ Is_enabled_and_stop "$CONTAINER_CHOICE"
+ Already_exists_and_rm "$CONTAINER_CHOICE"
+ Build_container "$MAKE_CONTAINER" "$CONTAINER_MANAGER" "$CONTAINER_CHOICE"
+ Good_Exit
+}
+
+main
\ No newline at end of file
diff --git a/usr/libexec/enable-bluefin-cli.sh b/usr/libexec/enable-bluefin-cli.sh
new file mode 100755
index 00000000000..cccaa935235
--- /dev/null
+++ b/usr/libexec/enable-bluefin-cli.sh
@@ -0,0 +1,81 @@
+#!/usr/bin/bash
+
+# Choose to enable or disable bluefin-cli
+
+# shellcheck disable=1091
+# shellcheck disable=2206
+# shellcheck disable=2154
+source /usr/lib/ujust/ujust.sh
+
+bluefin_cli=(${red}Disabled${n} ${red}Inactive${n} ${red}Not Default${n})
+
+function get_status(){
+ if systemctl --quiet --user is-enabled bluefin-cli.target; then
+ bluefin_cli[0]="${green}Enabled${n}"
+ else
+ bluefin_cli[0]="${red}Disabled${n}"
+ fi
+ if systemctl --quiet --user is-active bluefin-cli.service; then
+ bluefin_cli[1]="${green}Active${n}"
+ else
+ bluefin_cli[1]="${red}Inactive${n}"
+ fi
+ get_default=$(dconf read /org/gnome/Prompt/default-profile-uuid)
+ if test "$get_default" = "'a21a910811504857bea4c96b3d937b93'"; then
+ bluefin_cli[2]="${green}Default${n}"
+ else
+ bluefin_cli[2]="${red}Not-Default${n}"
+ fi
+ echo "Bluefin-cli is currently ${b}${bluefin_cli[0]}${n} (run status), ${b}${bluefin_cli[1]}${n} (on boot status), and ${b}${bluefin_cli[2]}${n} (terminal profile)."
+}
+
+function default_login(){
+ toggle=$(Choose Default Not-Default Cancel)
+ if test "$toggle" = "Default"; then
+ echo "Setting Bluefin-CLI to default Prompt Profile"
+ /usr/libexec/prompt-create-profile.sh bluefin-cli default
+ elif test "$toggle" = "Not-Default"; then
+ echo "Setting Host back to default Prompt Profile"
+ /usr/libexec/prompt-create-profile.sh Host default
+ else
+ dconf write /or
+ echo "Not Changing"
+ fi
+}
+
+function logic(){
+ if test "$toggle" = "Enable"; then
+ echo "${b}${green}Enabling${n} Bluefin-CLI"
+ systemctl --user enable --now bluefin-cli.target > /dev/null 2>&1
+ if ! systemctl --quiet --user is-active bluefin-cli.service; then
+ systemctl --user reset-failed bluefin-cli.service > /dev/null 2>&1 || true
+ echo "${b}${green}Starting${n} Bluefin-CLI"
+ systemctl --user start bluefin-cli.service
+ fi
+ default_login
+ elif test "$toggle" = "Disable"; then
+ echo "${b}${red}Disabling${n} Bluefin-CLI"
+ systemctl --user disable --now bluefin-cli.target > /dev/null 2>&1
+ if systemctl --quiet --user is-active bluefin-cli.service; then
+ echo "Do you want to ${b}${red}Stop${n} the Container?"
+ stop=$(Confirm)
+ if test "$stop" -eq 0; then
+ systemctl --user stop bluefin-cli.service > /dev/null 2>&1
+ systemctl --user reset-failed bluefin-cli.service > /dev/null 2>&1 || true
+ fi
+ fi
+ echo "Setting Host back to default Prompt Profile"
+ /usr/libexec/prompt-create-profile.sh Host default
+ else
+ echo "Not Changing"
+ fi
+}
+
+function main(){
+ get_status
+ toggle=$(Choose Enable Disable Cancel)
+ logic
+ get_status
+}
+
+main
diff --git a/usr/libexec/prompt-add-profile.sh b/usr/libexec/prompt-add-profile.sh
new file mode 100755
index 00000000000..348ae3cc482
--- /dev/null
+++ b/usr/libexec/prompt-add-profile.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/bash
+
+# Read the current value of the array
+CURRENT_VALUE=$(dconf read /org/gnome/Prompt/profile-uuids)
+guid="$1"
+
+# remove the leading and trailing brackets
+CURRENT_VALUE=${CURRENT_VALUE:1:-1}
+
+# remove any spaces
+CURRENT_VALUE=${CURRENT_VALUE// /}
+
+# split the string into an array
+IFS=',' read -r -a array <<<"$CURRENT_VALUE"
+
+# Exit if the guid already is in the array
+[[ $CURRENT_VALUE =~ $guid ]] && exit 0
+
+# add the new value
+array+=("'$guid'")
+
+# join the array back into a string
+UPDATED_VALUE=$(printf "%s," "${array[@]}")
+
+# remove the trailing comma
+UPDATED_VALUE=${UPDATED_VALUE%?}
+
+# add the leading and trailing brackets
+UPDATED_VALUE="[$UPDATED_VALUE]"
+
+# Write the updated array back to dconf
+dconf write /org/gnome/Prompt/profile-uuids "$UPDATED_VALUE"
diff --git a/usr/libexec/prompt-create-profile.sh b/usr/libexec/prompt-create-profile.sh
new file mode 100755
index 00000000000..2665e59623b
--- /dev/null
+++ b/usr/libexec/prompt-create-profile.sh
@@ -0,0 +1,89 @@
+#!/usr/bin/bash
+
+# create a Prompt profile using dconf given the guid of the instance
+# $1 = name
+
+# dconf read /org/gnome/Prompt/Profiles/d092b3519698570a3252762c658f7629/
+# /org/gnome/Prompt/Profiles/d092b3519698570a3252762c658f7629/custom-command
+# 'blincus shell myubuntu'
+# /org/gnome/Prompt/Profiles/d092b3519698570a3252762c658f7629/label
+# 'myubuntu'
+# /org/gnome/Prompt/Profiles/d092b3519698570a3252762c658f7629/login-shell
+# true
+# /org/gnome/Prompt/Profiles/d092b3519698570a3252762c658f7629/use-custom-command
+# true
+
+# if dconf doesn't exist, just return
+if ! command -v dconf >/dev/null; then
+ exit 0
+fi
+
+# shellcheck disable=SC1091
+. /usr/share/ublue-os/bluefin-cli/known-containers
+
+# shellcheck disable=SC2001
+gen_uuid() {
+ uuid="$(cat /proc/sys/kernel/random/uuid)"
+ echo "$uuid" | sed 's/-//g'
+}
+
+name="$1"
+default="$2"
+palette="$3"
+
+for check in "${!known_container[@]}"; do
+ if test "$check" = "$name"; then
+ guid=${known_container[$check]}
+ fi
+done
+
+if test -z "$guid"; then
+ guid=$(gen_uuid)
+fi
+
+default_guid=$(dconf read /org/gnome/Prompt/default-profile-uuid)
+default_guid=${default_guid:1:-1}
+
+# If default profile is trying to be made, just exit
+if test "$guid" = "$default_guid"; then
+ exit 0
+fi
+
+if test -z "$default"; then
+ make_default=0
+elif test "$default" = "default" || test "$default" -eq 1; then
+ make_default=1
+fi
+
+# Write the default value if specified
+if test "$make_default" -eq 1; then
+ dconf write /org/gnome/Prompt/default-profile-uuid "'${guid}'"
+fi
+
+profile="/org/gnome/Prompt/Profiles/${guid}/"
+opacity=$(dconf read /org/gnome/Prompt/Profiles/"${default_guid}"/opacity)
+
+if test "$name" = "Host"; then
+ dconf write "${profile}label" "'${name}'"
+else
+ dconf write "${profile}custom-command" "'sh -c \"[ ! -e /run/.containerenv ] && exec distrobox enter ${name} || ${SHELL}\"'"
+ dconf write "${profile}label" "'${name}'"
+ dconf write "${profile}use-custom-command" "true"
+ dconf write "${profile}ublue-os" "true"
+fi
+
+if test -n "$opacity"; then
+ dconf write "${profile}opacity" "'${opacity}'"
+fi
+
+if test -n "$palette"; then
+ dconf write "${profile}palette" "'${palette}'"
+elif test "$name" = "bluefin-cli" || test "$name" = "bluefin-dx-cli"; then
+ dconf write "${profile}palette" "'catppuccin-dynamic'"
+elif test "$name" = "fedora-toolbox"; then
+ dconf write "${profile}palette" "'Elio'"
+elif test "$name" = "ubuntu-toolbox"; then
+ dconf write "${profile}palette" "'Clone Of Ubuntu'"
+fi
+
+/usr/libexec/prompt-add-profile.sh "$guid"
diff --git a/usr/libexec/prompt-remove-profile.sh b/usr/libexec/prompt-remove-profile.sh
new file mode 100755
index 00000000000..40bd55a1d00
--- /dev/null
+++ b/usr/libexec/prompt-remove-profile.sh
@@ -0,0 +1,65 @@
+#!/usr/bin/bash
+# ensure that the prompt profiles for deleted instances are removed
+
+# if dconf doesn't exist, just return
+if ! command -v dconf >/dev/null; then
+ return
+fi
+
+# Cleanup any stale profiles
+for i in $(dconf list /org/gnome/Prompt/Profiles/); do
+ i=${i:0:-1}
+ [[ $(dconf read /org/gnome/Prompt/profile-uuids) =~ $i ]] || dconf reset -f "/org/gnome/Prompt/Profiles/${i}/"
+done
+
+name="$1"
+
+# Read the current value of the array
+CURRENT_VALUE=$(dconf read /org/gnome/Prompt/profile-uuids)
+
+# remove the leading and trailing brackets
+CURRENT_VALUE=${CURRENT_VALUE:1:-1}
+
+# remove any spaces
+CURRENT_VALUE=${CURRENT_VALUE// /}
+
+# split the string into an array
+IFS=',' read -r -a array <<<"$CURRENT_VALUE"
+
+# Get Default
+DEFAULT_VALUE=$(dconf read /org/gnome/Prompt/default-profile-uuid)
+
+# loop through the array and remove any that don't exist
+for i in "${!array[@]}"; do
+ guid=${array[i]}
+
+ # remove single quotes from guid
+ guid=${guid//\'/}
+
+ #echo "Checking profile for $(red $guid)"
+ profile="/org/gnome/Prompt/Profiles/${guid}/"
+
+ ublue_os=$(dconf read "${profile}ublue-os")
+ label=$(dconf read "${profile}label")
+ label=${label:1:-1}
+
+ if test "$ublue_os" = "true"; then
+ # Don't delete the profile if it's the default or if it's enabled
+ if ! test "$DEFAULT_VALUE" = "$guid" && test "$name" = "$label" && ! systemctl --user --quiet is-enabled "${name}".target; then
+ dconf reset -f "${profile}"
+ # remove the guid from the array
+ unset 'array[i]'
+ # join the array back into a string
+ UPDATED_VALUE=$(printf "%s," "${array[@]}")
+
+ # remove the trailing comma
+ UPDATED_VALUE=${UPDATED_VALUE%?}
+
+ # add the leading and trailing brackets
+ UPDATED_VALUE="[$UPDATED_VALUE]"
+
+ # Write the updated array back to dconf
+ dconf write /org/gnome/Prompt/profile-uuids "$UPDATED_VALUE"
+ fi
+ fi
+done
diff --git a/usr/libexec/ublue-motd b/usr/libexec/ublue-motd
new file mode 100755
index 00000000000..8a884e0d575
--- /dev/null
+++ b/usr/libexec/ublue-motd
@@ -0,0 +1,27 @@
+#!/usr/bin/bash
+escape() {
+ sed 's/[&/\]/\\&/g' <<< "$1"
+}
+
+TIP_FILE=$(ls "/usr/share/ublue-os/motd/tips/"*".md" | shuf -n 1)
+if [[ -f "$TIP_FILE" ]]; then
+ IMAGE_INFO="/usr/share/ublue-os/image-info.json"
+ IMAGE_NAME=$(jq -r '."image-name"' < $IMAGE_INFO)
+ IMAGE_NAME_ESCAPED=$(escape "$IMAGE_NAME")
+ IMAGE_TAG=$(jq -r '."image-tag"' < $IMAGE_INFO)
+ IMAGE_TAG_ESCAPED=$(escape "$IMAGE_TAG")
+ TIP=" $(shuf -n 1 "$TIP_FILE")"
+
+ IMAGE_DATE=$(rpm-ostree status --booted | sed -n 's/.*Timestamp: \(.*\)/\1/p')
+ IMAGE_DATE_SECONDS=$(date -d "$IMAGE_DATE" +%s)
+ CURRENT_SECONDS=$(date +%s)
+ DIFFERENCE=$((CURRENT_SECONDS - IMAGE_DATE_SECONDS))
+ MONTH=$((30 * 24 * 60 * 60))
+ if [ "$DIFFERENCE" -ge "$MONTH" ]; then
+ TIP='# Your current image is over 1 month old, run `ujust update`'
+ fi
+
+ TIP_ESCAPED=$(escape "$TIP")
+
+ sed -e "s/%IMAGE_NAME%/$IMAGE_NAME_ESCAPED/g" -e "s/%IMAGE_TAG%/$IMAGE_TAG_ESCAPED/g" -e "s/%TIP%/$TIP_ESCAPED/g" /usr/share/ublue-os/motd/bluefin.md | tr '~' '\n' | /usr/bin/glow -s auto -
+fi
\ No newline at end of file
diff --git a/usr/share/ublue-os/bluefin-cli/known-containers b/usr/share/ublue-os/bluefin-cli/known-containers
new file mode 100644
index 00000000000..0e9b3aa88d3
--- /dev/null
+++ b/usr/share/ublue-os/bluefin-cli/known-containers
@@ -0,0 +1,19 @@
+# shellcheck shell=bash
+declare -Ar known_container=(
+ ["bluefin-cli"]="a21a910811504857bea4c96b3d937b93"
+ ["bluefin-dx-cli"]="276d25e6065b497b96dd57e4f95ff50a"
+ ["fedora-toolbox"]="d6fe45489ed74fada5d95d715449ce7e"
+ ["ubuntu-toolbox"]="4741cb2eb3614750b79edc5c4b8c08b3"
+ ["wolfi-toolbox"]="33bd8e9953224e6985d8524e9b7294a1"
+ ["wolfi-dx-toolbox"]="03d42eab38f740089cbe2fa5e2d6a374"
+ ["Host"]="2871e8027773ae74d6c87a5f659bbc74"
+)
+declare -Ar known_guid=(
+ ["a21a910811504857bea4c96b3d937b93"]="bluefin-cli"
+ ["276d25e6065b497b96dd57e4f95ff50a"]="bluefin-dx-cli"
+ ["d6fe45489ed74fada5d95d715449ce7e"]="fedora-toolbox"
+ ["4741cb2eb3614750b79edc5c4b8c08b3"]="ubuntu-toolbox"
+ ["33bd8e9953224e6985d8524e9b7294a1"]="wolfi-toolbox"
+ ["03d42eab38f740089cbe2fa5e2d6a374"]="wolfi-dx-toolbox"
+ ["2871e8027773ae74d6c87a5f659bbc74"]="Host"
+)
\ No newline at end of file
diff --git a/usr/share/ublue-os/bluefin-cli/prompt-integration b/usr/share/ublue-os/bluefin-cli/prompt-integration
new file mode 100644
index 00000000000..7d93a895cae
--- /dev/null
+++ b/usr/share/ublue-os/bluefin-cli/prompt-integration
@@ -0,0 +1,6 @@
+
+
+[Service]
+ExecStartPre=-/usr/libexec/prompt-remove-profile.sh %N
+ExecStartPost=-/usr/libexec/prompt-create-profile.sh %N
+ExecStop=-/usr/libexec/prompt-remove-profile.sh %N
\ No newline at end of file
diff --git a/usr/share/ublue-os/just/10-update.just b/usr/share/ublue-os/just/10-update.just
new file mode 100644
index 00000000000..4285503bb1e
--- /dev/null
+++ b/usr/share/ublue-os/just/10-update.just
@@ -0,0 +1,8 @@
+# vim: set ft=make :
+
+alias upgrade := update
+
+# Update system, flatpaks, and containers all at once
+update:
+ #!/usr/bin/bash
+ /usr/bin/topgrade --config /usr/share/ublue-os/topgrade.toml --keep
diff --git a/usr/share/ublue-os/motd/bluefin.md b/usr/share/ublue-os/motd/bluefin.md
new file mode 100644
index 00000000000..14d3d74fe5e
--- /dev/null
+++ b/usr/share/ublue-os/motd/bluefin.md
@@ -0,0 +1,14 @@
+# Welcome to Bluefin (eta)
+ `%IMAGE_NAME%:%IMAGE_TAG%`
+
+| Command | Description |
+| ------- | ----------- |
+| `ujust` | List all available commands |
+| `ujust toggle-user-motd` | Toggle this banner on/off |
+| `ujust bluefin-cli` | Configure the terminal (Alpha) |
+
+%TIP%
+
+- [Issues](https://issues.projectbluefin.io)
+- [Documentation](http://docs.projectbluefin.io/)
+- [Discuss](https://community.projectbluefin.io/)
diff --git a/usr/share/ublue-os/motd/tips/10-tips.md b/usr/share/ublue-os/motd/tips/10-tips.md
new file mode 100644
index 00000000000..46fc5db4811
--- /dev/null
+++ b/usr/share/ublue-os/motd/tips/10-tips.md
@@ -0,0 +1,12 @@
+The Project Bluefin team will use this banner to share important information and occasional tips
+Follow us on [@UniversalBlue@fosstodon.org](https://fosstodon.org/@UniversalBlue)
+Bluefin is your gateway to Kubernetes `kind create cluster` to [get started](https://kind.sigs.k8s.io/)
+Bluefin is your gateway to Cloud Native - find your flock at [landscape.cncf.io](https://l.cncf.io)
+Support the app store! Donate to [Flatpak](https://opencollective.com/flatpak)
+Bluefin is proudly built using Fedora Atomic Desktop technology with a bit of Ubuntu flavor
+Check out Justin Garrison's [Introduction to Bluefin](https://www.youtube.com/watch?v=Nz-yyDwTfRM)
+Check out the Bluefin [announcement video](https://www.youtube.com/watch?v=YFXufAVdrw4)
+Need more indepth technical information?~Check out the [Bluefin Administrator's Guide](https://universal-blue.discourse.group/docs?topic=40)
+Support [Bluefin's Paleoartists](https://universal-blue.discourse.group/docs?topic=299)
+Like servers? Check out [ucore](https://github.com/ublue-os/ucore)
+Update break something? You can roll back and pin the previous release or build date:~[View our guide](https://universal-blue.discourse.group/docs?topic=513)
diff --git a/usr/share/ublue-os/topgrade.toml b/usr/share/ublue-os/topgrade.toml
new file mode 100644
index 00000000000..3dcc032939f
--- /dev/null
+++ b/usr/share/ublue-os/topgrade.toml
@@ -0,0 +1,9 @@
+[misc]
+no_self_update = true
+disable = ["self_update", "toolbx", "containers"]
+ignore_failures = ["distrobox", "flatpak", "brew_cask", "brew_formula", "nix", "pip3", "helm", "home_manager", "firmware"]
+assume_yes = true
+no_retry = false
+
+[linux]
+rpm_ostree = true