#!/usr/bin/env bash set -e script_path="$(dirname "$(realpath "$0")")" DOBU_TMP=/tmp/dobu . "$script_path/config-default.sh" [ -f "$script_path/config.sh" ] && . "$script_path/config.sh" # This function exists so that we can update the seccomp profile used update_podman_security_args() { local seccomp_profile="$1" [ -z "$seccomp_profile" ] && seccomp_profile="seccomp.json" # Default security-related arguments ALWAYS passed to podman # Install a seccomp filter that disallows sub-namespaces which could lead to exploits # and use the keep-id mode of userns, such that the user 1100 is mapped to the # current host user, and the root user inside the namespace is mapped to an unrelated # large uid on the host. podman_security_args=( --security-opt seccomp="$script_path/assets/$seccomp_profile" --userns=keep-id:uid=1100,gid=1100 ) } update_podman_security_args assert_prerequisites() { command -v podman >/dev/null 2>&1 || die "Podman is required" command -v jq >/dev/null 2>&1 || die "jq is required" [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ] || die "Dobu must be run under a compliant Wayland compositor" } die() { echo "[$(date +%Y-%m-%dT%H:%M:%S)][dobu][error] $1" >&2 exit 1 } log() { echo "[$(date +%Y-%m-%dT%H:%M:%S)][dobu] $1" } is_in_array() { local e match="$1" shift for e; do [[ "$e" == "$match" ]] && return 0; done return 1 } relative_path_to_image_name() { local context_path="$script_path/$1" [ -d "$context_path" ] || die "$context_path does not exist" local relative_path="$(realpath --relative-to="$script_path" "$context_path")" if [[ "$relative_path" =~ \.\. ]]; then die "Image path must be a subdirectory of the dobu project" fi local image_name="dobu/${relative_path/\//-}" echo "$image_name" } assert_image_exists() { podman inspect "$1" > /dev/null 2>&1 || die "Image $1 does not exist; please build the image first" } container_exists() { podman container exists $1 > /dev/null 2>&1 } get_image_label() { assert_image_exists "$1" podman inspect "$1" | jq -r ".[0].Labels.\"$2\"" } remove_stale_container() { container_exists "$1" || return 0 local is_running="$(podman inspect "$1" | jq -r '.[0].State.Running')" if [ "$is_running" == "false" ]; then podman rm -f "$1" fi } # Note: this works with __containers__, not images container_entrypoint() { podman inspect $1 | jq -r '.[0].Config.Entrypoint' } ensure_sommelier() { assert_image_exists dobu/deps-sommelier remove_stale_container dobu-deps-sommelier if container_exists dobu-deps-sommelier; then [ -S "$DOBU_TMP/X11-unix/X1" ] && [ -S "$DOBU_TMP/xdg_runtime/wayland-1" ] && return log "Killing non-functional Sommelier container" podman kill dobu-deps-sommelier podman rm -f dobu-deps-sommelier fi rm -rf "$DOBU_TMP/xdg_runtime" || true rm -rf "$DOBU_TMP/X11-unix" || true mkdir -p "$DOBU_TMP/xdg_runtime" mkdir -p "$DOBU_TMP/X11-unix" log "Starting Sommelier as a nested compositor..." podman run --rm -d "${podman_security_args[@]}" --name dobu-deps-sommelier \ -v "$DOBU_TMP/xdg_runtime":/xdg_runtime \ `# Pass through host wayland display for Sommelier always as wayland-0` \ -v "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY":/xdg_runtime/wayland-0 \ `# X11-unix uses hard-coded path` \ -v "$DOBU_TMP/X11-unix":/tmp/.X11-unix \ `# DRM render nodes` \ -v /dev/dri:/dev/dri \ dobu/deps-sommelier while [ ! -S "$DOBU_TMP/xdg_runtime/wayland-1" ] || [ ! -S "$DOBU_TMP/X11-unix/X1" ]; do sleep 0.5 done } get_archlinux_pkg_ver() { curl https://archlinux.org/packages/$1/json/ 2>/dev/null | jq -r '. | .pkgver + "-" + .pkgrel' } get_aur_pkg_ver() { curl "https://aur.archlinux.org/rpc/v5/info?arg[]=$1" 2>/dev/null | jq -r '.results[0].Version' } # Note: this does not specify which version of Ubuntu to use, because we don't actually care # this version can and will only used to invalidate Docker cache, and we only need a vague # idea of whether this package has been updated upstream. get_ubuntu_pkg_ver() { curl "https://api.launchpad.net/1.0/ubuntu/+archive/primary?ws.op=getPublishedSources&source_name=$1&exact_match=true" | jq -r '.entries[0].source_package_version' } get_github_pkg_ver() { curl "https://api.github.com/repos/$1/tags" | jq -r '.[0].name' }