
Christoph Stoettner
stoeps@vegardit.com
@stoeps@infosec.exchange
Christoph Stoettner stoeps@vegardit.com
Macht seit 30 Jahren was mit Computern
Amiga, OS/2, Linux
Beruflich auch Windows (wenn es sein muss)
Started with Linux / OSS around 1994/1995
Linux Kernel < 1.0
Slackware
mag vi, vim, neovim
zu doof für emacs
Mehrere Rechner
Linux
Windows mit WSL
Dotfiles in git
Oft fehlt auf einem Rechner das eine Tool
2023 Versuch mit Ansible
Sehr aufwändig
siehe auch: Froscon 2023
YT videos von Jorge Castro (CNCF) machten neugierig

Schreibgeschützt / Read-only File System
das laufende System kann von Benutzern oder Anwendungen nicht direkt verändert werden
Atomare Updates / Atomic Updates
Updates werden entweder vollständig und erfolgreich angewendet oder gar nicht
Vorhersehbar / Reproducible
Das Kernbetriebssystem ändert sich nicht
Verhalten ist auf verschiedenen Geräten vorhersehbar
Isolierte Anwendungen / Isolated Applications
Anwendungen sind vom Kernbetriebssystem und voneinander isoliert, meist durch Containerisierung
Sicherheit / Security
Schadsoftware kann nur begrenzt Änderungen am System vorzunehmen
Stabilität / Stability
Systemdateien können nicht versehentlich verändert oder gelöscht werden
Atomare Updates sorgen dafür, dass Systemaktualisierungen das System nicht in einem teilweise aktualisierten und potenziell instabilen Zustand hinterlassen.
Reproduzierbarkeit
Es einfacher, das System zu testen, zu prüfen und zu verifizieren
Troubleshooting am eigenen System möglich und Ergebnis übertragbar
Läuft auf meiner Maschine :D
Cloud native
Anpassung mittel Containerfiles und Github Actions
Reduzierte Flexibilität
Benutzer können Systemdateien nicht in gleichem Maße ändern oder ihr System anpassen
Eingeschränkte Kompatibilität
Nicht alle Anwendungen und Dienste sind mit den containerisierten oder isolierten Umgebungen eines unveränderlichen Betriebssystems kompatibel
Speicheranforderungen
Update-Mechanismen erfordern oft die Speicherung von Image-Snapshots
Isolierte Anwendungen können zu Redundanzen in der Speicherung von Anwendungsabhängigkeiten führen.
Entwicklererfahrung
Dockerfile / Containerfile (eh nur Yaml)
rpm-ostree
Applikationen als Flatpak
Toolbx (OCI Container für CLI und GUI Applikationen)
Varianten:
Fedora Silverblue (Gnome)
Fedora Kinoite (KDE)
Fedora Sway Atomic (Sway WM)
Fedora Budgie Atomic (Budgie)


Build Umgebung für eigene Images auf Basis von Fedora Atomic Desktop
Aurora (KDE)
Bazzite (Linux Gaming)
Project Bluefin (Gnome)
Nvidia Support
Steamdeck
Framework Laptop
und vieles mehr (Surface, Asus)
Mittels rebase kann man von jeder Silverblue Variante diese Images testen




OSTree-enabled OCI compliant images
Hosted auf ghcr.io
90 Tage Image Archiv
Images sind signiert mit cosign
Kernel Module vorinstalliert (je nach Image Nivida, Framework etc)
Daten und Applikationen getrennt
Rebase zurück zu Fedora jederzeit ohne Neuinstallation möglich
Keine eigene Distributionen
Angepasste Layer, die man auch wieder entfernen kann
rpm-ostree ist ein hybrides Image-/Paketsystem
kombiniert libostree und libdnf
atomare und sichere Upgrades mit lokaler RPM-Paketschichtung (Layer)
Rebase
Rollback
temoraer: Reboot and select prior version
permanent: rpm-ostree rollback
Pinning von Images
Ich pinne unregelmässig, aber damit habe ich immer mindestens ein funktionierendes Image
Theoretisch, ich habe in 8 Monaten keinen Rollback durchgeführt


Weisser Punkt zeigt das aktuell gebootet Image
Es wird ein weiteres Image vorgehalten (2. in der Liste)
Drittes Image Pinned: yes bleibt zusätzlich
sudo ostree admin pin 0sudo ostree admin pin -u 2
rpm-ostree status

# rebase to special tag
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/stoeps13/bluefin-dx:39-20231217
# rebase Bluefin-dx (Developer edition) latest
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/stoeps13/bluestoeps-dx:latest
# rebase auf Ublue-os main image
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/ublue-os/sericea-main:latest
# rebase auf custom bluefin image latest
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/stoeps13/bluestoeps-dx:latest
# rebase auf custom image mit universal-blue template
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/stoeps13/ublue-stoeps-main:latest
# rebase auf sway wm image (custom, latest)
rpm-ostree rebase ostree-image-signed:docker://ghcr.io/stoeps13/ublue-stoeps-sericea-main:latestrpm-ostree kann auch geänderte lokale Images per commit in neue Images verwandeln (analog Container)
Dateisystem
/etc mutable Konfigurationsverzeichnis
/usr Read-only (Binaries und Data)
/var All anderen Stati
/opt muss man beim Image build erstellen, oder nach /var/opt umziehen
https://github.com/ublue-os/image-template
Erstellt images auf Basis von Containerfile
Blue build: https://blue-build.org
Build über yaml Datei(en), modular erweiterbar
Recipes / Rezepte werden in Containerfile übersetzt
Die folgenden Beispiele nutzen Blue Build
https://blue-build.org/how-to/setup/
Automatic setup using the BlueBuild Workshop
Web Service (Login with Github)
Erstellt Repository with Default Konfiguration und cosign
Manual setup with git and cosign
Selbst ist der Mensch
Prozess ist gut dokumentiert, daher direkt weiter mit unserem Rezept
├── boot_menu.yml
├── Containerfile
├── cosign.key
├── cosign.pub
├── files
├── LICENSE
├── README.md
└── recipes─── recipes
├── common_modules
│ ├── akmods.yml
│ ├── bling.yml
│ ├── containerfile.yml
│ ├── default-flatpaks.yml
│ ├── files.yml
│ ├── fonts.yml
│ ├── rpm-ostree-gnome.yml
│ ├── rpm-ostree-sway.yml
│ ├── rpm-ostree.yml
│ ├── script-sericea.yml
│ ├── script.yml
│ ├── systemd.yml
│ └── yafti.yml
├── README.md
├── recipe-main.yml
├── recipe-nvidia.yml
├── recipe-sericea-main.yml
└── recipe-sericea-nvidia.yml├── files
│ ├── etc
│ │ └── systemd
│ │ └── system
│ │ └── flatpak-system-update.timer
│ ├── scripts
│ │ ├── example.sh
│ │ ├── signing.sh
│ │ ├── workarounds-sericea.sh
│ │ └── workarounds.sh
│ └── usr
│ ├── etc
│ │ ├── containers
│ │ │ └── registries.d
│ │ │ └── ublue-os.yaml
│ │ └── distrobox
│ │ └── distrobox.ini
│ └── share
│ ├── backgrounds
│ │ ├── default.png
│ │ ├── iceland.png
│ │ └── README.md
│ └── ublue-os
│ ├── cosign.pub
│ └── firstboot
│ └── yafti.ymlYaml Datei
# image will be published to ghcr.io/<user>/<name>
name: ublue-stoeps-main
# description will be included in the image's metadata
description: My ublue image for my personal and working devices
base-image: ghcr.io/ublue-os/silverblue-main
image-version: latest # latest is also supported if you want new updates ASAP
modules:
- from-file: common_modules/files.yml
#- from-file: common_modules/akmods.yml
- from-file: common_modules/bling.yml
- from-file: common_modules/default-flatpaks.yml
- from-file: common_modules/fonts.yml
- from-file: common_modules/rpm-ostree.yml
- from-file: common_modules/rpm-ostree-gnome.yml
- from-file: common_modules/yafti.yml
- from-file: common_modules/systemd.yml
- from-file: common_modules/script.yml
- from-file: common_modules/containerfile.yml
- type: signingcommon_modules/fonts.ymltype: fonts
fonts:
nerd-fonts:
- FiraCode # don't add "Nerd Font" suffix.
- SourceCodePro
google-fonts:
- Roboto
- Open Sanscommon_modules/rpm-ostree.ymltype: rpm-ostree
install:
- bat
- eza
- fd-find
- firewall-config
- flameshot
- fzf
- stow
- tmux
- vdirsyncer
- vim
- virt-install
- virt-manager
- virt-viewer
- zsh
remove:
- firefox
- firefox-langpacks.common_modules/default_flatpaks.yaml
type: default-flatpaks
notify: true
system:
repo-url: https://dl.flathub.org/repo/flathub.flatpakrepo
repo-name: flathub
install:
- com.mattjakeman.ExtensionManager
- org.davmail.DavMail
- org.gnome.font-viewer
- org.localsend.localsend_app
user:
repo-url: https://dl.flathub.org/repo/flathub.flatpakrepo
repo-name: flathub
install:
- com.bitwarden.desktop
- com.github.tchx84.Flatseal
- com.logseq.Logseq
- io.github.java_decompiler.jd-guiAlternative Liste in yafti.yml bereitstellen
Wird beim 1. Boot aufgerufen und BenutzerInnen können Flatpaks zur Installation auswählen
Werden als zusätzliche Layer ins Image kopiert
type: containerfile
snippets:
- COPY --from=cgr.dev/chainguard/dive:latest /usr/bin/dive /usr/bin/dive
- COPY --from=cgr.dev/chainguard/helm:latest /usr/bin/helm /usr/bin/helm
- COPY --from=cgr.dev/chainguard/kubectl:latest /usr/bin/kubectl /usr/bin/kubectlcommon_modules/scripts.shtype: script
scripts:
- signing.sh
- workarounds.shfiles/scripts/workaround.sh#!/bin/sh
set -oue pipefail
echo 'This is the workaround shell script'
# Disable wayland on Lenovo T470 (prevents OBS crashes)
/usr/libexec/gdm-runtime-config set daemon WaylandEnable false
# Edit vdirsyncer google.py to make it work with gmail
sed -i 's!urn:ietf:wg:oauth:2.0:oob!http://127.0.0.1:8088!g' \
$(fd google.py /usr/lib | grep vdirsyncer)
# Clean up repos, everything is on the image so we don't need them
for i in $(ls /etc/yum.repos.d/ | grep -v '^fedora' | grep -v rpmfusion); do
rm -f /etc/yum.repos.de/${i}
donecommon_modules/akmods.ymltype: akmods
install:
- v4l2loopbackImages die auf blue-build basieren bringen bereits die bluebuild cli mit
Ausgabe des Rezepts:
bluebuild generate -d recipes/recipe-main.ymlAusgabe des Containerfiles
bluebuild generate recipes/recipe-main.ymlLokaler Build des Images
bluebuild build recipes/recipe-main.yml| Ich habe keinen Weg gefunden auf ein lokales Images rebase auszuführen. |
Verschiedene Linux Distributionen im Terminal
Container basiert
Integriert in den Host
Teilt sich $HOME mit dem Host
Zugriff auf externe Disks
Graphische Apps mit X11 und Wayland
GPU Zugriff
Keine speziellen Container notwendig
jegliches Container Image von Docker Hub, Quay.io oder Custom Registry funktioniert
Unterstützt Podman, Docker oder Lilipod
distrobox create -i docker.io/almalinux/8-init --init --name testdistrobox.ini[test]
additional_packages="vim tmux"
image=docker.io/almalinux/8-init
init=true
nvidia=false
pull=true
root=false
replace=trueContainer nutzen normal die gleich $SHELL wie unser host
chsh im Container wechselt die Shell
Prompt im Container anpassen
if [ -n "$CONTAINER_ID" ]; then
# show container name inside distrobox containers
psvar[1]="@${(%):-$CONTAINER_ID 🧰}"
else
# show hostname inside podman containers
psvar[1]="@${(%):-$(hostname)}"
fiDefault container teilen sich $HOME
home erstellendistrobox create --name test --image your-chosen-image:tag --home /your/custom/homeroot Zugriff aus dem ContainerNormale Container verlangen sudo für die Installation von Paketen
Manchmal braucht man aber root z.B. für Netzwerkanalyse
Mit podman hat ein Container nur den Zugriff den ein normaler User auch hat
sudo gibt hier keinen vollständigen root Zugriff
sudo distrobox ist nicht supportet!
Container mit -r oder --root erstellen
distrobox create --name test --image your-chosen-image:tag --rootdocker
podman
neovim (Beispiel Kali)
/usr/bin/distrobox-host-exec /usr/bin/podmandistrobox.ini...
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/podman;/usr/etc/distrobox/distrobox.ini[kali]
additional_packages="burpsuite zaproxy bloodhound neo4j"
image=ghcr.io/stoeps13/kali-toolbox:latest
icon=/home/stoeps/Pictures/Kali-dragon-icon.svg.png
exported_apps="burpsuite zaproxy"
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/podman;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/podman-compose;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/xdg-open;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/buildah;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/rpm-ostree;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/flatpak;
init_hooks=ln -sf /usr/bin/distrobox-host-exec /usr/bin/nvim;
init=false
nvidia=false
pull=true
root=true
replace=trueüber tmux oder terminal per Maus
Direkt aus der Console
wlroots (wayland) oder xsel (X11)
wl-copy < file-to-copy
wl-copy text to copyOder man verwendet die Maus und Ctrl+Shift+c im Terminal
in der distrobox.ini können zusätzliche Apps beim Laden auf den Client hinzugefügt werden
Containererstellung dauert dann länger
Falls etwas schief geht, muss man den alten Container wiederherstellen
Besser die wichtigsten Tools automatisiert hinzufügen
Containerfile
packages
toolboxes/fedora-toolbox
├── Containerfile.fedora
└── packages.fedorapackages.fedora — Liste mit PaketenImageMagick
ansifilter
automake
bat
chromium
curlFROM quay.io/fedora/fedora-toolbox:40
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/fedora-toolbox/packages.fedora /toolbox-packages
RUN dnf -y upgrade && dnf -y install $(<toolbox-packages) && rm /toolbox-packages
# Install lazygit
RUN dnf copr enable atim/lazygit -y && dnf install -y lazygit && dnf clean all
# Install language server for neovim
RUN npm install -g dockerfile-language-server-nodejs && npm install -g vscode-json-languageserver && \
npm i -g vscode-langservers-extracted && npm install -g yaml-language-server
# Install mkdocs
RUN pip install mkdocs mkdocs-material mkdocs-section-index ansible-core\<2.17
# Install Asciidoctor
RUN gem install asciidoctor-diagram asciidoctor-pdf asciidoctor-revealjs asciidoctor rouge
# Fix vdirsyncer
RUN sed -i 's!urn:ietf:wg:oauth:2.0:oob!http://127.0.0.1:8088!g' $(fd google.py /usr/lib | grep vdirsyncer)
COPY --from=cgr.dev/chainguard/helm:latest /usr/bin/helm /usr/bin/helm
RUN wget https://raw.githubusercontent.com/ahmetb/kubectx/master/kubectx -O /usr/bin/kubectx && \
chmod +x /usr/bin/kubectxMeine dotfiles liegen in einem privaten git-Repository
Noch keine Lösung um einen OAuth Token nicht einchecken zu müssen
Passwörter mit pass abgespeichert und in den dotfiles ausgeführt
Ins jeweilige Home clonen
git clone https://.../mydotfiles.git ~/.dotfiles
Ursprünglich entstand stow um Dateien in unabhängigen Softwarepaketen (perl) zu verwalten
Sehr gut für die Verwaltung von Konfigurationsdateien im Home-Verzeichnis geeignet
Einfach versionierbar
Verlinkt die Dateien aus ~/.dotfiles
cd ~/.dotfiles
stow neovim

Bluebuild hat ein Chezmoi Module
Systemd service der Dotfiles aus Repo abgleicht
Habe ich aber noch nicht getestet
Ersatz / Ergänzung zu make / Makefile
/usr/share/ublue-os/just/00-default.just...
# Show all messages from this boot
logs-this-boot:
sudo journalctl -b 0
# Show all messages from last boot
logs-last-boot:
sudo journalctl -b -1
# Regenerate GRUB config, useful in dual-boot scenarios where a second operating system isn't listed
regenerate-grub:
#!/usr/bin/bash
if [ -d /sys/firmware/efi ]; then
sudo grub2-mkconfig -o /etc/grub2-efi.cfg
else
sudo grub2-mkconfig -o /etc/grub2.cfg
fi
...Eigene Shortcuts für Kommandos erstellen
/usr/share/ublue-os/just/60-custom.just# vim: set ft=make :
# This file can be modified downstream to add custom just commands