Initial Das OS 0.1.0: Void Linux live ISO with Xfce

- xbps-src templates: das-theme (adw-gtk3-based GTK themes, generated
  xfwm4 frames, wallpapers, logo), das-settings (Xfce, panel, LightDM
  defaults in /etc/xdg/das), adw-gtk3 and font-jetbrains-mono
- void-mklive profile in live/: packages, runit services, rootfs overlay,
  Ukrainian locale, live user with autologin
- Void builder container, build scripts, QEMU runner and Makefile
- Bilingual README with screenshots

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
das
2026-10-18 21:23:16 +03:00
co-authored by Claude Opus 5.5
commit b7399031c7
48 changed files with 1548 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Runs a command inside the Void Linux builder container.
# The project is mounted at /work; downloaded packages are cached in out/cache/xbps.
set -euo pipefail
root=$(cd "$(dirname "$0")/.." && pwd)
image=dasos-builder
docker build --quiet --tag "$image" "$root/docker/builder" >/dev/null
mkdir -p "$root/out/cache/xbps"
# --privileged: mklive mounts /proc, /sys, /dev and a loop device for the root image
exec docker run --rm --privileged \
--volume "$root:/work" \
--volume "$root/out/cache/xbps:/var/cache/xbps" \
--env HOST_UID="$(id -u)" \
--env HOST_GID="$(id -g)" \
"$image" "$@"
+62
View File
@@ -0,0 +1,62 @@
#!/usr/bin/env bash
# Builds the Das OS live ISO with void-mklive from the profile in live/.
# Runs inside the builder container, see scripts/builder.sh.
set -euo pipefail
repo=/work/out/hostdir/binpkgs
version=$(< /work/VERSION)
iso=/work/out/iso/dasos-${version}-x86_64.iso
if ! compgen -G "$repo/*-repodata" >/dev/null; then
echo "build-iso: the local package repository is missing, run 'make packages' first" >&2
exit 1
fi
# Reads a list file: one item per line, '#' starts a comment
read_list() {
sed -e 's/#.*//' -e '/^[[:space:]]*$/d' "$1" | xargs
}
work=$(mktemp -d)
mkdir -p /work/out/iso
trap 'rm -rf "$work"; chown -R "$HOST_UID:$HOST_GID" /work/out/iso' EXIT
# Root file system overlay: static files from live/include plus generated links
include=$work/include
cp -a /work/live/include "$include"
ln -sf /usr/share/zoneinfo/Europe/Kyiv "$include/etc/localtime"
# PipeWire as the sound server, wired up the same way as Void's own live images
mkdir -p "$include"/etc/xdg/autostart "$include"/etc/pipewire/pipewire.conf.d "$include"/etc/alsa/conf.d
ln -sf /usr/share/applications/pipewire.desktop "$include"/etc/xdg/autostart/
ln -sf /usr/share/examples/wireplumber/10-wireplumber.conf "$include"/etc/pipewire/pipewire.conf.d/
ln -sf /usr/share/examples/pipewire/20-pipewire-pulse.conf "$include"/etc/pipewire/pipewire.conf.d/
ln -sf /usr/share/alsa/alsa.conf.d/50-pipewire.conf "$include"/etc/alsa/conf.d/
ln -sf /usr/share/alsa/alsa.conf.d/99-pipewire-default.conf "$include"/etc/alsa/conf.d/
# mklive's dracut module creates the live user, hostname and passwords at boot.
# Rebrand its defaults in this container's copy (the image itself stays untouched).
adduser=/opt/void-mklive/dracut/vmklive/adduser.sh
for pattern in 'echo void-live >' 'voidlinux'; do
if ! grep -q "$pattern" "$adduser"; then
echo "build-iso: '$pattern' not found in $adduser, mklive changed; update this script" >&2
exit 1
fi
done
sed -i -e 's/echo void-live >/echo dasos >/' -e 's/voidlinux/live/g' "$adduser"
rsvg-convert /work/live/branding/splash.svg --output "$work/splash.png"
rm -f "$iso"
cd /opt/void-mklive
SPLASH_IMAGE=$work/splash.png ./mklive.sh \
-a x86_64 \
-r "$repo" \
-c /var/cache/xbps \
-p "$(read_list /work/live/packages.x86_64)" \
-S "$(read_list /work/live/services)" \
-I "$include" \
-l uk_UA.UTF-8 \
-k us \
-T "Das OS" \
-C "live.user=live quiet loglevel=3" \
-o "$iso"
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# Builds every template in srcpkgs/ with xbps-src into the local repository
# out/hostdir/binpkgs. Runs inside the builder container, see scripts/builder.sh.
#
# xbps-src needs the whole void-packages tree (build styles, shared hooks), so our
# templates are overlaid onto a shallow clone of it in out/void-packages.
set -euo pipefail
vp=/work/out/void-packages
hostdir=/work/out/hostdir
# xbps-src refuses to run as root. Like Void's own CI, build as an unprivileged
# member of xbuilder (allowed to use xbps-uchroot); the host's UID keeps out/ owned by the user.
useradd --uid "$HOST_UID" --groups xbuilder --no-create-home builder
as_builder() {
sudo --preserve-env=HOME -u builder "$@"
}
export HOME=/tmp
mkdir -p "$hostdir"
chown "$HOST_UID:$HOST_GID" /work/out "$hostdir"
if [[ -d $vp/.git ]]; then
echo "==> Updating void-packages"
as_builder git -C "$vp" fetch --quiet --depth 1 origin master
as_builder git -C "$vp" reset --quiet --hard FETCH_HEAD
as_builder git -C "$vp" clean --quiet -fd srcpkgs
else
echo "==> Cloning void-packages"
as_builder git clone --quiet --depth 1 https://github.com/void-linux/void-packages "$vp"
fi
cat > "$vp/etc/conf" <<CONF
XBPS_CHROOT_CMD=uchroot
XBPS_MAKEJOBS=$(nproc)
CONF
names=()
for dir in /work/srcpkgs/*/; do
name=$(basename "$dir")
if git -C "$vp" cat-file -e "HEAD:srcpkgs/$name/template" 2>/dev/null; then
echo "warning: $name is now in void-packages, consider dropping our template" >&2
fi
rm -rf "$vp/srcpkgs/$name"
as_builder cp -rL "$dir" "$vp/srcpkgs/$name"
names+=("$name")
done
cd "$vp"
# The bootstrapped masterdir stays in out/void-packages, so later builds skip this step
if [[ ! -f masterdir-x86_64/.xbps_chroot_init ]]; then
as_builder ./xbps-src -H "$hostdir" binary-bootstrap
fi
for name in "${names[@]}"; do
echo "==> Building $name"
as_builder ./xbps-src -H "$hostdir" -f pkg "$name"
done
echo "==> Repository: $hostdir/binpkgs"
ls -1 "$hostdir"/binpkgs/*.xbps
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env bash
# Boots a Das OS ISO in QEMU (KVM when available).
#
# Usage: scripts/run-qemu.sh [--bios] [--disk] [path/to/image.iso]
# --bios boot with legacy BIOS instead of UEFI
# --disk attach out/qemu/disk.qcow2 (20 GB, created on first use) to test installing
# Without a path the newest ISO in out/iso is used.
set -euo pipefail
root=$(cd "$(dirname "$0")/.." && pwd)
state=$root/out/qemu
firmware=uefi
disk=false
iso=""
die() {
echo "run-qemu: $*" >&2
exit 1
}
for arg in "$@"; do
case $arg in
--bios) firmware=bios ;;
--disk) disk=true ;;
-h | --help)
sed -n '2,8s/^# \{0,1\}//p' "$0"
exit 0
;;
-*) die "unknown option: $arg" ;;
*) iso=$arg ;;
esac
done
if [[ -z $iso ]]; then
iso=$(ls -t "$root"/out/iso/*.iso 2>/dev/null | head -n 1) || true
fi
[[ -n $iso && -f $iso ]] || die "no ISO found, run 'make iso' first"
args=(
-machine q35 -smp 4 -m 4096
-device virtio-vga -display gtk,zoom-to-fit=on
-device virtio-net-pci,netdev=net0 -netdev user,id=net0
-device qemu-xhci -device usb-tablet
-cdrom "$iso" -boot order=d
)
if [[ -w /dev/kvm ]]; then
args+=(-accel kvm -cpu host)
else
echo "run-qemu: /dev/kvm is not accessible, falling back to slow emulation" >&2
args+=(-accel tcg -cpu max)
fi
mkdir -p "$state"
if [[ $firmware == uefi ]]; then
code=""
# Debian/Ubuntu/Mint, then Arch, then Fedora file names
for candidate in /usr/share/OVMF/OVMF_CODE_4M.fd /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/edk2/ovmf/OVMF_CODE.fd; do
[[ -f $candidate ]] && code=$candidate && break
done
[[ -n $code ]] || die "UEFI firmware (OVMF) not found, install the ovmf package or use --bios"
vars_template=$(dirname "$code")/$(basename "$code" | sed 's/CODE/VARS/')
[[ -f $state/OVMF_VARS.fd ]] || cp "$vars_template" "$state/OVMF_VARS.fd"
args+=(
-drive "if=pflash,format=raw,readonly=on,file=$code"
-drive "if=pflash,format=raw,file=$state/OVMF_VARS.fd"
)
fi
if [[ $disk == true ]]; then
[[ -f $state/disk.qcow2 ]] || qemu-img create -f qcow2 "$state/disk.qcow2" 20G
args+=(-drive "file=$state/disk.qcow2,if=virtio,format=qcow2")
fi
exec qemu-system-x86_64 "${args[@]}"