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 0
sudo 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:latest
rpm-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.yml
Yaml 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: signing
common_modules/fonts.yml
type: fonts
fonts:
nerd-fonts:
- FiraCode # don't add "Nerd Font" suffix.
- SourceCodePro
google-fonts:
- Roboto
- Open Sans
common_modules/rpm-ostree.yml
type: 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-gui
Alternative 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/kubectl
common_modules/scripts.sh
type: script
scripts:
- signing.sh
- workarounds.sh
files/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}
done
common_modules/akmods.yml
type: akmods
install:
- v4l2loopback
Images die auf blue-build basieren bringen bereits die bluebuild cli mit
Ausgabe des Rezepts:
bluebuild generate -d recipes/recipe-main.yml
Ausgabe des Containerfiles
bluebuild generate recipes/recipe-main.yml
Lokaler 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 test
distrobox.ini
[test]
additional_packages="vim tmux"
image=docker.io/almalinux/8-init
init=true
nvidia=false
pull=true
root=false
replace=true
Container 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)}"
fi
Default container teilen sich $HOME
home
erstellendistrobox create --name test --image your-chosen-image:tag --home /your/custom/home
root
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 --root
docker
podman
neovim (Beispiel Kali)
/usr/bin/distrobox-host-exec /usr/bin/podman
distrobox.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 copy
Oder 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.fedora
packages.fedora
— Liste mit PaketenImageMagick
ansifilter
automake
bat
chromium
curl
FROM 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/kubectx
Meine 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