diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index baa4153d113..94fedb183ab 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,45 +1,33 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/alpine +// For format details, see https://aka.ms/devcontainer.json. { "name": "Bluefin-devcontainer", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/base:alpine-3.19", - + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", "customizations": { "vscode": { "extensions": [ + "eamodio.gitlens", "hangxingliu.vscode-systemd-support", "mads-hartmann.bash-ide-vscode", "ms-azuretools.vscode-docker", + "sclu1034.justfile", "timonwong.shellcheck" ] } }, - - "containerEnv": { - "HOME": "/home/vscode" - }, - + // Likely need to add "--userns=keep-id, --group-add=keep-groups" for podman support + "runArgs": ["--init"], + "remoteEnv": { "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" }, "securityOpt": [ "label=disable" ], - - "runArgs": [ - "--userns=keep-id" - ] - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "uname -a", - - // Configure tool-specific properties. - // "customizations": {}, - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" + "features": { + "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, + "ghcr.io/guiyomh/features/just:0": {}, + "ghcr.io/lukewiwa/features/shellcheck:0": {} + }, + "onCreateCommand": { + "bash-completions": "sudo apt-get install -y bash-completion; echo 'source /etc/profile.d/bash_completion.sh' | sudo tee -a /etc/bash.bashrc > /dev/null", + "just-completions": "just --completions bash | sudo tee -a /etc/bash_completion.d/just > /dev/null", + "docker-completions": "docker completion bash | sudo tee -a /etc/bash_completion.d/docker.sh > /dev/null" + } } diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..423160ad33c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.iso +*_flatpaks/flatpaks_with_deps +flatpak.* + +scripts/files/home/ublue-os/* \ No newline at end of file diff --git a/Containerfile b/Containerfile index 05631c5b3a7..2a95bfaefb3 100644 --- a/Containerfile +++ b/Containerfile @@ -1,11 +1,17 @@ ARG BASE_IMAGE_NAME="${BASE_IMAGE_NAME:-silverblue}" ARG IMAGE_FLAVOR="${IMAGE_FLAVOR:-main}" ARG AKMODS_FLAVOR="${AKMODS_FLAVOR:-main}" -ARG SOURCE_IMAGE="${SOURCE_IMAGE:-$BASE_IMAGE_NAME-$IMAGE_FLAVOR}" +ARG SOURCE_IMAGE="${SOURCE_IMAGE:-${BASE_IMAGE_NAME}-${IMAGE_FLAVOR}}" ARG BASE_IMAGE="ghcr.io/ublue-os/${SOURCE_IMAGE}" ARG FEDORA_MAJOR_VERSION="${FEDORA_MAJOR_VERSION:-40}" ARG TARGET_BASE="${TARGET_BASE:-bluefin}" +# KMODs +ARG KMOD_SOURCE_COMMON="ghcr.io/ublue-os/akmods:${AKMODS_FLAVOR}-${FEDORA_MAJOR_VERSION}" +ARG KMOD_SOURCE_EXTRA="ghcr.io/ublue-os/akmods-extra:${AKMODS_FLAVOR}-${FEDORA_MAJOR_VERSION}" +FROM ${KMOD_SOURCE_COMMON} as akmod-common +FROM ${KMOD_SOURCE_EXTRA} as akmod-extra + ## bluefin image section FROM ${BASE_IMAGE}:${FEDORA_MAJOR_VERSION} AS base @@ -28,7 +34,7 @@ COPY /system_files/shared/usr/etc/ublue-update/ublue-update.toml /tmp/ublue-upda 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 # COPY ublue kmods, add needed negativo17 repo and then immediately disable due to incompatibility with RPMFusion -COPY --from=ghcr.io/ublue-os/akmods:${AKMODS_FLAVOR}-${FEDORA_MAJOR_VERSION} /rpms /tmp/akmods-rpms +COPY --from=akmod-common /rpms /tmp/akmods-rpms # Build, cleanup, commit. RUN rpm-ostree cliwrap install-to-root / && \ @@ -54,7 +60,7 @@ COPY system_files/dx / COPY packages.json /tmp/packages.json # Copy akmods-extra from ublue -COPY --from=ghcr.io/ublue-os/akmods-extra:${AKMODS_FLAVOR}-${FEDORA_MAJOR_VERSION} /rpms /tmp/akmods-rpms +COPY --from=akmod-extra /rpms /tmp/akmods-rpms # Build, Clean-up, Commit RUN bash -c ". /tmp/build/build-dx.sh" && \ diff --git a/Justfile b/Justfile new file mode 100644 index 00000000000..87392a039ff --- /dev/null +++ b/Justfile @@ -0,0 +1,91 @@ +export project_root := `git rev-parse --show-toplevel` +export gts := "39" +export latest := "40" + +alias run := run-booted-guest + +_default: + @just help + +_container_mgr: + @{{project_root}}/scripts/container_mgr.sh + +_base_image image: + @{{project_root}}/scripts/base-image.sh {{image}} + +_tag image target: + @{{project_root}}/scripts/make-tag.sh {{image}} {{target}} + +# Build Image +build image="" target="" version="": + @{{project_root}}/scripts/build-image.sh {{image}} {{target}} {{version}} + +# Run image +run-container image="" target="" version="": + @{{project_root}}/scripts/run-image.sh {{image}} {{target}} {{version}} + +# Run Booted Image Session w/ Guest +run-booted-guest image="" target="" version="": + @{{project_root}}/scripts/run-booted-guest.sh {{image}} {{target}} {{version}} + +# Run Booted Image Session w/ mounted in $USER and $HOME +run-booted-home image="" target="" version="": + @{{project_root}}/scripts/run-booted-home.sh {{image}} {{target}} {{version}} + +# Create ISO from local dev build image +build-iso image="" target="" version="": + @{{project_root}}/scripts/build-iso.sh {{image}} {{target}} {{version}} + +# Create ISO from currenct ghcr image +build-iso-ghcr image="" target="" version="": + @{{project_root}}/scripts/build-iso-ghcr.sh {{image}} {{target}} {{version}} + +# Clean Directory. Remove ISOs and Build Files +clean: + @{{project_root}}/scripts/cleanup-dir.sh + +# Remove built images +clean-images: + @{{project_root}}/scripts/cleanup-images.sh + +# List Built Images +list-images: + @{{project_root}}/scripts/list-images.sh + +[private] +help: + #!/usr/bin/bash + echo " " + echo "These are helper scripts for building and testing development images " + echo " " + echo "You can run dev images either in 'booted like' setup with 'just run-booted' " + echo "Or in a more stripped down version with 'just run' " + echo "Specify which image you wish to build and run by name. " + echo "Example: 'just run-container aurora' -> runs aurora without systemd " + echo "Example: 'just run bluefin-dx' -> runs bluefin-dx with systemd " + echo " " + echo "Helper scripts are in 'project_root/scripts'. " + echo " " + echo "Modify the 'devcontainer.json' in 'project_root/.devcontainer' to support " + echo "Running the devcontainer with podman or docker " + echo "Manually specify container manager with '$CONTAINER_MGR' enviornment variable " + echo " " + just --list + +# Build Bluefin +bluefin: (build "bluefin" "base" "{{gts}}") + +# Build Bluefin-DX +bluefin-dx: (build "bluefin" "dx" "{{gts}}") + +# Build Bluefin Latest +bluefin-latest: (build "bluefin" "base" "{{latest}}") + +# Build Bluefin-DX Latest +bluefin-dx-latest: (build "bluefin" "dx" "{{latest}}") + +# Build Aurora +aurora: (build "aurora" "base" "{{latest}}") + +# Builed Aurora-DX +aurora-dx: (build "aurora" "dx" "{{latest}}") diff --git a/build_files/base/copr-repos.sh b/build_files/base/copr-repos.sh index 62869d19381..4a9b2101605 100644 --- a/build_files/base/copr-repos.sh +++ b/build_files/base/copr-repos.sh @@ -8,7 +8,6 @@ curl -Lo /etc/yum.repos.d/ublue-os-staging-fedora-"${FEDORA_MAJOR_VERSION}".repo # Add Bling repo curl -Lo /etc/yum.repos.d/ublue-os-bling-fedora-"${FEDORA_MAJOR_VERSION}".repo https://copr.fedorainfracloud.org/coprs/ublue-os/bling/repo/fedora-"${FEDORA_MAJOR_VERSION}"/ublue-os-bling-fedora-"${FEDORA_MAJOR_VERSION}".repo - # 39 Ptyxis if [ "${FEDORA_MAJOR_VERSION}" -eq "39" ]; then curl -Lo /etc/yum.repos.d/_copr_kylegospo-gnome-vrr.repo https://copr.fedorainfracloud.org/coprs/kylegospo/gnome-vrr/repo/fedora-"${FEDORA_MAJOR_VERSION}"/kylegospo-gnome-vrr-fedora-"${FEDORA_MAJOR_VERSION}".repo diff --git a/build_files/base/systemd.sh b/build_files/base/systemd.sh index b1e6186a5d0..910cc12327f 100644 --- a/build_files/base/systemd.sh +++ b/build_files/base/systemd.sh @@ -8,5 +8,7 @@ systemctl enable dconf-update.service systemctl --global enable ublue-flatpak-manager.service systemctl enable ublue-update.timer systemctl enable ublue-system-setup.service +systemctl enable ublue-etc-merge.service +systemctl enable ublue-guest-user.service systemctl --global enable ublue-user-setup.service systemctl --global enable podman-auto-update.timer \ No newline at end of file diff --git a/scripts/base-image.sh b/scripts/base-image.sh new file mode 100755 index 00000000000..f798f2b57d2 --- /dev/null +++ b/scripts/base-image.sh @@ -0,0 +1,12 @@ +#!/usr/bin/bash +set -euo pipefail + +image=$1 + +if [[ ${image} =~ "bluefin" ]]; then + echo silverblue +elif [[ ${image} =~ "aurora" ]]; then + echo kinoite +else + exit 1 +fi \ No newline at end of file diff --git a/scripts/build-image.sh b/scripts/build-image.sh new file mode 100755 index 00000000000..854139d7501 --- /dev/null +++ b/scripts/build-image.sh @@ -0,0 +1,32 @@ +#!/usr/bin/bash +set -eo pipefail +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi + +# Get Inputs +image=$1 +target=$2 +version=$3 + +# Set image/target/version based on inputs +# shellcheck disable=SC2154,SC1091 +. "${project_root}/scripts/get-defaults.sh" + +# Get info +container_mgr=$(just _container_mgr) +base_image=$(just _base_image "${image}") +tag=$(just _tag "${image}" "${target}") + +# Build Image +$container_mgr build -f Containerfile \ + --build-arg="AKMODS_FLAVOR=main" \ + --build-arg="BASE_IMAGE_NAME=${base_image}" \ + --build-arg="SOURCE_IMAGE=${base_image}-main" \ + --build-arg="FEDORA_MAJOR_VERSION=${version}" \ + --build-arg="IMAGE_NAME=${tag}" \ + --build-arg="IMAGE_FLAVOR=main" \ + --build-arg="IMAGE_VENDOR=localhost" \ + --tag localhost/"${tag}":"${version}" \ + --target "${target}" \ + "${project_root}" \ No newline at end of file diff --git a/scripts/build-iso-ghcr.sh b/scripts/build-iso-ghcr.sh new file mode 100755 index 00000000000..0a8955ab627 --- /dev/null +++ b/scripts/build-iso-ghcr.sh @@ -0,0 +1,27 @@ +#!/usr/bin/bash +#shellcheck disable=SC2154 + +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi + +# Common Build ISO +# shellcheck disable=SC2154,SC1091 +. "${project_root}/scripts/common-build-iso.sh" + +# Make ISO +${container_mgr} run --rm --privileged --volume "${workspace}":/build-container-installer/build \ + ghcr.io/jasonn3/build-container-installer:latest \ + ARCH="x86_64" \ + ENABLE_CACHE_DNF="false" \ + ENABLE_CACHE_SKOPEO="false" \ + ENABLE_FLATPAK_DEPENDENCIES="false" \ + ENROLLMENT_PASSWORD="ublue-os" \ + FLATPAK_REMOTE_REFS_DIR="${flatpak_dir_shortname}" \ + IMAGE_NAME="${ghcr_tag}" \ + IMAGE_REPO="ghcr.io/ublue-os" \ + IMAGE_TAG="${version}" \ + ISO_NAME="${ghcr_tag}-${version}-ghcr.iso" \ + SECURE_BOOT_KEY_URL='https://github.com/ublue-os/akmods/raw/main/certs/public_key.der' \ + VARIANT="${variant}" \ + VERSION="${version}" \ No newline at end of file diff --git a/scripts/build-iso.sh b/scripts/build-iso.sh new file mode 100755 index 00000000000..6923cd40b6f --- /dev/null +++ b/scripts/build-iso.sh @@ -0,0 +1,29 @@ +#!/usr/bin/bash +#shellcheck disable=SC2154 + +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi + +# Common Build ISO +# shellcheck disable=SC1091 +. "${project_root}/scripts/common-build-iso.sh" + +# Make ISO +${container_mgr} run --rm --privileged \ + --volume "${workspace}"/scripts/files/build-iso-makefile-patch:/build-container-intaller/container/Makefile \ + --volume "${workspace}":/build-container-installer/build \ + ghcr.io/jasonn3/build-container-installer:latest \ + ARCH="x86_64" \ + ENABLE_CACHE_DNF="false" \ + ENABLE_CACHE_SKOPEO="false" \ + ENABLE_FLATPAK_DEPENDENCIES="false" \ + ENROLLMENT_PASSWORD="ublue-os" \ + FLATPAK_REMOTE_REFS_DIR="${flatpak_dir_shortname}" \ + IMAGE_NAME="${tag}" \ + IMAGE_REPO="localhost" \ + IMAGE_TAG="${version}" \ + ISO_NAME="${tag}-${version}.iso" \ + SECURE_BOOT_KEY_URL='https://github.com/ublue-os/akmods/raw/main/certs/public_key.der' \ + VARIANT="${variant}" \ + VERSION="${version}" \ No newline at end of file diff --git a/scripts/cleanup-dir.sh b/scripts/cleanup-dir.sh new file mode 100755 index 00000000000..ff6aae67711 --- /dev/null +++ b/scripts/cleanup-dir.sh @@ -0,0 +1,12 @@ +#!/usr/bin/bash +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi + +set -euox pipefail + +#shellcheck disable=SC2154 +rm -f "${project_root}"/*.iso +rm -f "${project_root}"/*_flatapks/flatpaks_with_deps +rm -rf "${project_root}"/flatpak.* +rm -rf "${project_root}"/scripts/files/home/ublue-os/* \ No newline at end of file diff --git a/scripts/cleanup-images.sh b/scripts/cleanup-images.sh new file mode 100755 index 00000000000..6be2a4713e1 --- /dev/null +++ b/scripts/cleanup-images.sh @@ -0,0 +1,15 @@ +#!/usr/bin/bash +set -euox pipefail +container_mgr=( + docker + podman + podman-remote +) +for i in "${container_mgr[@]}"; do + if [[ $(command -v "$i") ]]; then + echo "Container Manager: ${i}" + ID=$(${i} images --filter "reference=localhost/bluefin*-build" --filter "reference=localhost/aurora*-build" --format "{{.ID}}") + xargs -I {} "${i}" image rm {} <<< "$ID" + echo "" + fi +done \ No newline at end of file diff --git a/scripts/common-build-iso.sh b/scripts/common-build-iso.sh new file mode 100644 index 00000000000..67a4b78b6ea --- /dev/null +++ b/scripts/common-build-iso.sh @@ -0,0 +1,107 @@ +#!/usr/bin/bash +#shellcheck disable=SC2154,SC2034 + +# Check if inside rootless container +if [[ -f /run/.containerenv ]]; then + #shellcheck disable=SC1091 + source /run/.containerenv + #shellcheck disable=SC2154 + if [[ "${rootless}" -eq "1" ]]; then + echo "Cannot build ISO inside rootless podman container... Exiting..." + exit 1 + fi +fi +container_mgr=$(just _container_mgr) +# If using rootless container manager, exit. Might not be best check +if "${container_mgr}" info | grep Root | grep -q /home; then + echo "Cannot build ISO with rootless container..." + exit 1 +fi +function work-in-process(){ + echo "ISO Builder script is a Work In Process" + secs=5 + while [ $secs -gt 0 ] + do + printf "\r\033[KWaiting %.d seconds." $((secs--)) + sleep 1 + done +} +work-in-process + +# Get Inputs +image=$1 +target=$2 +version=$3 + +# Set image/target/version based on inputs +# shellcheck disable=SC2154,SC1091 +. "${project_root}/scripts/get-defaults.sh" + +# Set Container tag name +tag=$(just _tag "${image}" "${target}") + +# Don't use -build suffix, flatpak dependency using ghcr +ghcr_tag=${tag::-6} + + +# Set Base Image +base_image=$(just _base_image "${image}") + +# Set variant and flatpak dir +if [[ "${base_image}" =~ "silverblue" ]]; then + variant=Silverblue + flatpak_dir_shortname="bluefin_flatpaks" +elif [[ "${base_image}" =~ "kinoite" ]]; then + variant=Kinoite + flatpak_dir_shortname="aurora_flatpaks" +else + exit 1 +fi + +# Make sure image actually exists, build if it doesn't +ID=$(${container_mgr} images --filter reference=localhost/"${tag}":"${version}" --format "{{.ID}}") +if [[ -z ${ID} ]]; then + just build "${image}" "${target}" "${version}" +fi + +# Make temp space +TEMP_FLATPAK_INSTALL_DIR=$(mktemp -d -p "${project_root}" flatpak.XXX) +# Get list of refs from directory +FLATPAK_REFS_DIR=${project_root}/${flatpak_dir_shortname} +FLATPAK_REFS_DIR_LIST=$(tr '\n' ' ' < "${FLATPAK_REFS_DIR}/flatpaks") + +# Generate install script +cat << EOF > "${TEMP_FLATPAK_INSTALL_DIR}/script.sh" +cat /temp_flatpak_install_dir/script.sh +mkdir -p /flatpak/flatpak /flatpak/triggers +mkdir /var/tmp || true +chmod -R 1777 /var/tmp +flatpak config --system --set languages "*" +flatpak remote-add --system flathub https://flathub.org/repo/flathub.flatpakrepo +flatpak install --system -y ${FLATPAK_REFS_DIR_LIST} +ostree refs --repo=\${FLATPAK_SYSTEM_DIR}/repo | grep '^deploy/' | grep -v 'org\.freedesktop\.Platform\.openh264' | sed 's/^deploy\///g' > /output/flatpaks_with_deps +EOF + +workspace=${project_root} +if [[ -f /.dockerenv ]]; then + FLATPAK_REFS_DIR=${LOCAL_WORKSPACE_FOLDER}/${flatpak_dir_shortname} + TEMP_FLATPAK_INSTALL_DIR="${LOCAL_WORKSPACE_FOLDER}/$(echo "${TEMP_FLATPAK_INSTALL_DIR}" | rev | cut -d / -f 1 | rev)" + workspace=${LOCAL_WORKSPACE_FOLDER} +fi + +# Generate Flatpak Dependency List +if [[ ! -f ${project_root}/${flatpak_dir_shortname}/flatpaks_with_deps ]]; then + "${container_mgr}" run --rm --privileged \ + --entrypoint bash \ + -e FLATPAK_SYSTEM_DIR=/flatpak/flatpak \ + -e FLATPAK_TRIGGERSDIR=/flatpak/triggers \ + --volume "${FLATPAK_REFS_DIR}":/output \ + --volume "${TEMP_FLATPAK_INSTALL_DIR}":/temp_flatpak_install_dir \ + "ghcr.io/ublue-os/${ghcr_tag}:${version}" /temp_flatpak_install_dir/script.sh +fi + +# Remove Temp Directory +if [[ -f /.dockerenv ]]; then + TEMP_FLATPAK_INSTALL_DIR=${project_root}/$(echo "${TEMP_FLATPAK_INSTALL_DIR}" | rev | cut -d / -f 1 | rev) +fi +rm -rf "${TEMP_FLATPAK_INSTALL_DIR}" \ No newline at end of file diff --git a/scripts/container_mgr.sh b/scripts/container_mgr.sh new file mode 100755 index 00000000000..2b41042a459 --- /dev/null +++ b/scripts/container_mgr.sh @@ -0,0 +1,21 @@ +#!/usr/bin/bash +valid_manager=( + docker + podman + podman-remote +) +if [[ -n ${CONTAINER_MGR} ]]; then + if [[ "${valid_manager[*]}" =~ ${CONTAINER_MGR} ]]; then + echo "${CONTAINER_MGR}" + else + exit 1 + fi +elif [[ $(command -v docker) ]]; then + echo docker +elif [[ $(command -v podman) ]]; then + echo podman +elif [[ $(command -v podman-remote) ]];then + echo podman-remote +else + exit 1 +fi diff --git a/scripts/files/build-iso-makefile-patch b/scripts/files/build-iso-makefile-patch new file mode 100644 index 00000000000..ee2f6fb4b0b --- /dev/null +++ b/scripts/files/build-iso-makefile-patch @@ -0,0 +1,11 @@ +$(IMAGE_NAME)-$(IMAGE_TAG): + skopeo copy docker-daemon:$(IMAGE_REPO)/$(IMAGE_NAME):$(IMAGE_TAG) oci:$(IMAGE_NAME)-$(IMAGE_TAG) + +install-deps: + $(install_pkg) skopeo + +FILES=$(filter-out Makefile,$(wildcard *)) +clean: +ifneq ($(FILES),) + rm -Rf $(FILES) +endif \ No newline at end of file diff --git a/scripts/files/etc/group b/scripts/files/etc/group new file mode 100644 index 00000000000..efe7aef409b --- /dev/null +++ b/scripts/files/etc/group @@ -0,0 +1,22 @@ +root:x:0: +wheel:x:10:ublue-os +adbusers:x:968: +plugdev:x:967: +wbpriv:x:88: +clevis:x:966: +gluster:x:965: +unbound:x:964: +setroubleshoot:x:963: +qemu:x:107: +saslauth:x:76:saslauth +libvirt:x:962:ublue-os +libvirtdbus:x:961: +stapusr:x:156: +stapsys:x:157: +stapdev:x:158: +pcp:x:960: +docker:x:959:ublue-os +lxd:x:958:ublue-os +incus:x:251: +incus-admin:x:250:ublue-os +ublue-os:x:1000: diff --git a/scripts/files/etc/hostname b/scripts/files/etc/hostname new file mode 100644 index 00000000000..ba1acf23325 --- /dev/null +++ b/scripts/files/etc/hostname @@ -0,0 +1 @@ +ContainerTestUblueOS \ No newline at end of file diff --git a/scripts/files/etc/passwd b/scripts/files/etc/passwd new file mode 100644 index 00000000000..adf0e7019c8 --- /dev/null +++ b/scripts/files/etc/passwd @@ -0,0 +1,10 @@ +root:x:0:0:root:/root:/bin/bash +clevis:x:992:966:Clevis Decryption Framework unprivileged user:/var/cache/clevis:/usr/sbin/nologin +gluster:x:977:965:GlusterFS daemons:/run/gluster:/sbin/nologin +unbound:x:976:964:Unbound DNS resolver:/var/lib/unbound:/sbin/nologin +setroubleshoot:x:975:963:SELinux troubleshoot server:/var/lib/setroubleshoot:/usr/sbin/nologin +saslauth:x:974:76:Saslauthd user:/run/saslauthd:/sbin/nologin +libvirtdbus:x:973:961:Libvirt D-Bus bridge:/:/sbin/nologin +qemu:x:107:107:qemu user:/:/usr/sbin/nologin +pcp:x:960:960:Performance Co-Pilot:/var/lib/pcp:/usr/sbin/nologin +ublue-os:x:1000:1000:ublue-os:/home/ublue-os:/usr/bin/bash \ No newline at end of file diff --git a/scripts/files/etc/shadow b/scripts/files/etc/shadow new file mode 100644 index 00000000000..c8698549d0d --- /dev/null +++ b/scripts/files/etc/shadow @@ -0,0 +1,59 @@ +root:!::0:99999:7::: +bin:*::0:99999:7::: +daemon:*::0:99999:7::: +adm:*::0:99999:7::: +lp:*::0:99999:7::: +sync:*::0:99999:7::: +shutdown:*::0:99999:7::: +halt:*::0:99999:7::: +mail:*::0:99999:7::: +operator:*::0:99999:7::: +games:*::0:99999:7::: +ftp:*::0:99999:7::: +nobody:*::0:99999:7::: +dbus:*::0:99999:7::: +polkitd:*::0:99999:7::: +etcd:*::0:99999:7::: +tss:*::0:99999:7::: +avahi-autoipd:*::0:99999:7::: +rpc:*::0:99999:7::: +sssd:*::0:99999:7::: +dockerroot:*::0:99999:7::: +rpcuser:*::0:99999:7::: +nfsnobody:*::0:99999:7::: +kube:*::0:99999:7::: +sshd:*::0:99999:7::: +chrony:*::0:99999:7::: +tcpdump:*::0:99999:7::: +systemd-timesync:*::0:99999:7::: +systemd-network:*::0:99999:7::: +systemd-resolve:*::0:99999:7::: +systemd-bus-proxy:*::0:99999:7::: +cockpit-ws:*::0:99999:7::: +apache:!::::::: +avahi:!::::::: +geoclue:!::::::: +usbmuxd:!::::::: +rtkit:!::::::: +pipewire:!::::::: +openvpn:!::::::: +nm-openvpn:!::::::: +colord:!::::::: +nm-openconnect:!::::::: +flatpak:!::::::: +gdm:!::::::: +gnome-initial-setup:!::::::: +vboxadd:!::::::: +dnsmasq:!::::::: +systemd-coredump:!*::::::: +systemd-oom:!*::::::: +clevis:!:19686:::::: +gluster:!:19686:::::: +unbound:!:19686:::::: +setroubleshoot:!:19686:::::: +saslauth:!:19686:::::: +libvirtdbus:!:19686:::::: +qemu:!*:19686:::::: +pcp:!*:19686:::::: +sddm:!::::::: +ublue-os:$y$j9T$uQkZGY3QpPmddmtkavB0Z/$c2rwYgbGPq6lcdpTeof0S7YjOGgfKaKXWxoKy3HjKhC:19816:0:99999:7::: \ No newline at end of file diff --git a/scripts/get-defaults.sh b/scripts/get-defaults.sh new file mode 100755 index 00000000000..bedfae2a7fd --- /dev/null +++ b/scripts/get-defaults.sh @@ -0,0 +1,38 @@ +#!/usr/bin/bash +#shellcheck disable=SC2154 + +# If image has -dx, assume they want the target to be dx and that version might be $2 +if [[ ${image} =~ "-dx" ]]; then + image=$(cut -d - -f 1 <<< "${image}") + version=${target} + target="dx" +fi + +# if no image, bluefin +if [[ -z "${image}" ]]; then + image="bluefin" +fi + +# if no target, base +if [[ -z "${target}" ]]; then + target="base" + +# if $2 is numeric, assume that is version and target is base +elif [[ ${target} =~ ^[0-9]+$ ]]; then + version=${target} + target="base" +fi + +# if no version, bluefin is GTS, Aurora is Latest +if [[ -z "${version}" ]]; then + if [[ "${image}" =~ "bluefin" ]]; then + version=${gts} + elif [[ "${image}" =~ "aurora" ]]; then + version=${latest} + fi +# if gts then convert to just variable ${gts}, same with Latest +elif [[ ${version} =~ "gts" ]]; then + version=${gts} +elif [[ ${version} =~ "latest" ]]; then + version=${latest} +fi \ No newline at end of file diff --git a/scripts/list-images.sh b/scripts/list-images.sh new file mode 100755 index 00000000000..cf23cc44308 --- /dev/null +++ b/scripts/list-images.sh @@ -0,0 +1,14 @@ +#!/usr/bin/bash +set -euo pipefail +container_mgr=( + docker + podman + podman-remote +) +for i in "${container_mgr[@]}"; do + if [[ $(command -v "$i") ]]; then + echo "Container Manager: ${i}" + ${i} images --filter "reference=localhost/bluefin*-build" --filter "reference=localhost/aurora*-build" + echo "" + fi +done \ No newline at end of file diff --git a/scripts/make-tag.sh b/scripts/make-tag.sh new file mode 100755 index 00000000000..74a74559b5e --- /dev/null +++ b/scripts/make-tag.sh @@ -0,0 +1,12 @@ +#!/usr/bin/bash +set -euo pipefail + +image=$1 +target=$2 + +# Add build to images to distinguish from ghcr +if [[ "${target}" =~ "base" ]]; then + echo "${image}-build" +elif [[ "${target}" =~ "dx" ]]; then + echo "${image}-${target}-build" +fi \ No newline at end of file diff --git a/scripts/run-booted-guest.sh b/scripts/run-booted-guest.sh new file mode 100755 index 00000000000..8d2c0fde647 --- /dev/null +++ b/scripts/run-booted-guest.sh @@ -0,0 +1,90 @@ +#!/usr/bin/bash +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi + +# Get inputs +image=$1 +target=$2 +version=$3 + +# Set image/target/version based on inputs +# shellcheck disable=SC2154,SC1091 +. "${project_root}/scripts/get-defaults.sh" + +# Get items +container_mgr=$(just _container_mgr) +tag=$(just _tag "${image}" "${target}") + +# Graphical Warning +if "${container_mgr}" info | grep Root | grep -q /home; then + echo "Cannot run Graphical Session wiht rootless container..." + secs=5 + while [ $secs -gt 0 ] + do + printf "\r\033[KWaiting %.d seconds." $((secs--)) + sleep 1 + done +fi + +# Check to see if image exists, build it if it doesn't +ID=$(${container_mgr} images --filter reference=localhost/"${tag}:${version}" --format "{{.ID}}") +if [[ -z ${ID} ]]; then + just build "${image}" "${target}" "${version}" +fi + +# Set workspace variable +workspace=${project_root} +if [[ -f /.dockerenv ]]; then + workspace=${LOCAL_WORKSPACE_FOLDER} +fi +workspace_files=${workspace}/scripts/files + +# Start building run command +run_cmd+=(run -it --rm --privileged) + +# Mount in $HOME. +run_cmd+=(-v /var/home) +mkdir -p "${project_root}"/scripts/files/home/ublue-os +if [[ -n "${SUDO_USER}" ]]; then + chown "${SUDO_USER}:${SUDO_GID}" "${project_root}"/scripts/files/home/ublue-os +fi +run_cmd+=(-v "${workspace_files}"/home/ublue-os:/var/home/ublue-os:rslave) + +# Mount in System Flatpaks and TMP +run_cmd+=(-v /tmp:/tmp:rslave) +run_cmd+=(-v /var/lib/flatpak:/var/lib/flatpak:rslave) + +# Blank out items SystemD units / don't mess with journal/selinux +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/auditd.service) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/cups.path) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/cups.service) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/cups.socket) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/rtkit-daemon.service) +run_cmd+=(-v /var/log/journal) +run_cmd+=(-v /sys/fs/selinux) + +# Mount in passwd/group for user account to work +run_cmd+=(-v "${workspace_files}"/etc/passwd:/etc/passwd:ro) +run_cmd+=(-v "${workspace_files}"/etc/group:/etc/group:ro) +run_cmd+=(-v "${workspace_files}"/etc/shadow:/etc/shadow:ro) + +# Set Hostname +run_cmd+=(-v "${workspace_files}"/etc/hostname:/etc/hostname) + +# Host Network Option +if [[ -n ${HOST_NETWORK} ]]; then + run_cmd+=(--network host) + run_cmd+=(-v /etc/NetworkManager:/etc/NetworkManager) + run_cmd+=(-v /etc/hosts:/etc/hosts) + run_cmd+=(-v /etc/resolv.conf:/etc/resolv.conf) +fi + +# Boot the container +"$container_mgr" "${run_cmd[@]}" "localhost/${tag}:${version}" /sbin/init + +# Clean Up +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi +rm -rf "${project_root}/scripts/files/home/ublue-os" \ No newline at end of file diff --git a/scripts/run-booted-home.sh b/scripts/run-booted-home.sh new file mode 100755 index 00000000000..3761695ab57 --- /dev/null +++ b/scripts/run-booted-home.sh @@ -0,0 +1,75 @@ +#!/usr/bin/bash +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi + +# Get inputs +image=$1 +target=$2 +version=$3 + +# Set image/target/version based on inputs +# shellcheck disable=SC2154,SC1091 +. "${project_root}/scripts/get-defaults.sh" + +# Get items +container_mgr=$(just _container_mgr) +tag=$(just _tag "${image}" "${target}") + +# Graphical Warning +if "${container_mgr}" info | grep Root | grep -q /home; then + echo "Cannot run Graphical Session with rootless container..." + secs=5 + while [ $secs -gt 0 ] + do + printf "\r\033[KWaiting %.d seconds." $((secs--)) + sleep 1 + done +fi + +# Check to see if image exists, build it if it doesn't +ID=$(${container_mgr} images --filter reference=localhost/"${tag}:${version}" --format "{{.ID}}") +if [[ -z ${ID} ]]; then + just build "${image}" "${target}" "${version}" +fi + +# Start building run command +run_cmd+=(run -it --rm --privileged) + +# Mount in passwd/group for user account to work +run_cmd+=(-v /etc/passwd:/etc/passwd:ro) +run_cmd+=(-v /etc/group:/etc/group:ro) +run_cmd+=(-v /etc/shadow:/etc/shadow:ro) + +# Mount in System Flatpaks and TMP +run_cmd+=(-v /tmp:/tmp:rslave) +run_cmd+=(-v /var/lib/flatpak:/var/lib/flatpak:rslave) + +# Mount in $HOME. +home_location=/home +if [[ -L /home ]]; then + home_location=/$(readlink /home) +fi +run_cmd+=(-v "${home_location}":/var/home:rslave) + +# Blank out items +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/auditd.service) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/cups.path) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/cups.service) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/cups.socket) +run_cmd+=(-v /dev/null:/usr/lib/systemd/system/rtkit-daemon.service) +run_cmd+=(-v /var/log/journal) +run_cmd+=(-v /sys/fs/selinux) + +# Host Network Option +if [[ -n ${HOST_NETWORK} ]]; then + run_cmd+=(--network host) + run_cmd+=(-v /etc/NetworkManager:/etc/NetworkManager) + run_cmd+=(-v /etc/hosts:/etc/hosts) + run_cmd+=(-v /etc/resolv.conf:/etc/resolv.conf) +fi + +# Boot the container +"$container_mgr" "${run_cmd[@]}" "localhost/${tag}:${version}" /sbin/init + +exit 0 \ No newline at end of file diff --git a/scripts/run-image.sh b/scripts/run-image.sh new file mode 100755 index 00000000000..8cfe06e2a62 --- /dev/null +++ b/scripts/run-image.sh @@ -0,0 +1,27 @@ +#!/usr/bin/bash +if [[ -z ${project_root} ]]; then + project_root=$(git rev-parse --show-toplevel) +fi +set -eo pipefail + +# Get Inputs +image=$1 +target=$2 +version=$3 + +# Get image/target/version based on inputs +# shellcheck disable=SC2154,SC1091 +. "${project_root}/scripts/get-defaults.sh" + +# Get variables +container_mgr=$(just _container_mgr) +tag=$(just _tag "${image}" "${target}") + +# Check if requested image exist, if it doesn't build it +ID=$(${container_mgr} images --filter reference=localhost/"${tag}":"${version}" --format "{{.ID}}") +if [[ -z ${ID} ]]; then + just build "${image}" "${target}" "${version}" +fi + +# Run image +"${container_mgr}" run -it --rm localhost/"${tag}":"${version}" /usr/bin/bash \ No newline at end of file diff --git a/system_files/shared/usr/lib/systemd/system/ublue-etc-merge.service b/system_files/shared/usr/lib/systemd/system/ublue-etc-merge.service new file mode 100644 index 00000000000..df2335c2fb6 --- /dev/null +++ b/system_files/shared/usr/lib/systemd/system/ublue-etc-merge.service @@ -0,0 +1,16 @@ +[Unit] +Description=Merge /etc files +After=local-fs.target +Before=ublue-guest-user.service +ConditionVirtualization=yes +ConditionPathExists=!/run/ostree-booted +ConditionPathExists=!/etc/.%N.stamp + +[Service] +Type=oneshot +ExecStart=/usr/bin/bash -c "for i in /usr/etc/*; do cp -r -n $i /etc; done" +ExecStart=/usr/bin/systemctl restart dconf-update.service +ExecStart=/usr/bin/touch /etc/.%N.stamp + +[Install] +WantedBy=multi-user.target default.target \ No newline at end of file diff --git a/system_files/shared/usr/lib/systemd/system/ublue-guest-user.service b/system_files/shared/usr/lib/systemd/system/ublue-guest-user.service new file mode 100644 index 00000000000..c6aea5a4271 --- /dev/null +++ b/system_files/shared/usr/lib/systemd/system/ublue-guest-user.service @@ -0,0 +1,19 @@ +[Unit] +Description=Setup Guest User dotfiles +After=local-fs.target +After=ublue-etc-merge.service +ConditionHost=ContainerTestUblueOS +ConditionVirtualization=yes +ConditionPathExists=/var/home/ublue-os +ConditionPathExists=!/run/ostree-booted +ConditionPathExists=!/var/home/ublue-os/.%N.stamp + +[Service] +User=ublue-os +Type=oneshot +ExecStart=/usr/bin/cp -r /etc/skel/.* /var/home/ublue-os/ +ExecStart=/usr/bin/touch /var/home/ublue-os/.%N.stamp +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target default.target \ No newline at end of file