Created
February 20, 2026 14:37
-
-
Save unixabg/5d7f8c1e02f5da3efbe4712618334520 to your computer and use it in GitHub Desktop.
VelvetOS Install helpers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| #set -x | |
| set -Eeuo pipefail | |
| _VER='20260208.0-beta' | |
| clear | |
| echo "Script chromebook_x86_uefi-x86_64-trixie.sh installer version: $_VER" | |
| MNT="/tmp/p3" | |
| _cleaned_up=0 | |
| cleanup() { | |
| # prevent double cleanup if multiple traps fire | |
| if [[ "${_cleaned_up}" -eq 1 ]]; then return 0; fi | |
| _cleaned_up=1 | |
| echo "Cleaning up mounts..." | |
| # If anything is still running inside the chroot and holding mounts busy, try to kill it. | |
| # (Safe even if not mounted / no processes) | |
| if command -v fuser >/dev/null 2>&1; then | |
| fuser -km "$MNT" 2>/dev/null || true | |
| fi | |
| # Unmount in reverse order: proc/sys/dev first, then the root mount | |
| for mp in "$MNT/proc" "$MNT/sys" "$MNT/dev" "$MNT"; do | |
| if mountpoint -q "$mp"; then | |
| echo "Unmounting $mp" | |
| umount "$mp" 2>/dev/null || umount -l "$mp" 2>/dev/null || true | |
| fi | |
| done | |
| # Remove mount dir if not mounted anymore | |
| if [[ -d "$MNT" ]] && ! mountpoint -q "$MNT"; then | |
| rmdir "$MNT" 2>/dev/null || true | |
| fi | |
| } | |
| # Always try to clean up on exit; also stop on signals/errors (EXIT will still run cleanup) | |
| trap cleanup EXIT | |
| trap 'echo "Interrupted."; exit 1' INT TERM | |
| trap 'echo "Error on line $LINENO: $BASH_COMMAND"; exit 1' ERR | |
| # Clean up leftovers from any previous failed run *before* starting fresh | |
| cleanup | |
| # allow cleanup again later | |
| _cleaned_up=0 | |
| # Check if TGTDEV is passed as an argument | |
| if [ -z "${1:-}" ]; then | |
| echo "Usage: $0 <target_device>" | |
| echo "Please provide the target device (e.g., sda or mmcblk0)." | |
| exit 1 | |
| fi | |
| export TGTDEV="$1" | |
| # Confirm the target device | |
| echo "WARNING: You are about to overwrite /dev/$TGTDEV. Make sure this is correct." | |
| lsblk -p -o name,size,label | grep -w "/dev/$TGTDEV" || true | |
| read -p "Do you want to proceed with this target device? (yes/no) " confirm_target | |
| if [ "$confirm_target" != "yes" ]; then | |
| echo "Exiting... Please double-check your target device." | |
| exit 1 | |
| fi | |
| # Determine partition prefix (e.g., /dev/sda3 vs /dev/mmcblk0p3) | |
| if [[ "$TGTDEV" == mmcblk* ]]; then | |
| PART_PREFIX="p" | |
| else | |
| PART_PREFIX="" | |
| fi | |
| PART3="/dev/${TGTDEV}${PART_PREFIX}3" | |
| # dd the image to the target | |
| echo "Summary:" | |
| echo " Image to install: chromebook_x86_uefi-x86_64-trixie.img" | |
| echo " Target device: /dev/$TGTDEV" | |
| echo " Partition prefix: $PART_PREFIX" | |
| echo "This will overwrite all data on /_attach to /dev/$TGTDEV." | |
| read -p "Do you want to proceed? (yes/no) " yn | |
| case $yn in | |
| yes ) | |
| echo "Running dd to install image to emmc..." | |
| dd if=chromebook_x86_uefi-x86_64-trixie.img of="/dev/$TGTDEV" bs=1024k status=progress | |
| sync | |
| echo "...completed attempt to install image to emmc!" | |
| ;; | |
| no ) | |
| echo "Exiting..." | |
| exit 0 | |
| ;; | |
| * ) | |
| echo "Invalid response" | |
| exit 1 | |
| ;; | |
| esac | |
| echo "Doing some tasks on the btrfs file system on $TGTDEV" | |
| mkdir -p "$MNT" | |
| mount "$PART3" "$MNT" | |
| echo "Resizing to max the emmc root partition on $TGTDEV" | |
| bash extend-rootfs-installer.sh | |
| # Mount necessary filesystems for chroot environment | |
| # Use rbind so nested mounts under /dev etc. are handled more robustly | |
| mount --rbind /dev "$MNT/dev" | |
| mount --rbind /sys "$MNT/sys" | |
| mount --rbind /proc "$MNT/proc" | |
| # Reduce mount propagation surprises (best effort; ignore if unsupported) | |
| mount --make-rslave "$MNT/dev" 2>/dev/null || true | |
| mount --make-rslave "$MNT/sys" 2>/dev/null || true | |
| mount --make-rslave "$MNT/proc" 2>/dev/null || true | |
| # Function to run a script in chroot and handle errors | |
| run_in_chroot() { | |
| local script_path="$1" | |
| shift | |
| local script_name | |
| script_name="$(basename "$script_path")" | |
| echo "Copying $script_path to chroot environment..." | |
| cp "$script_path" "$MNT/$script_name" | |
| echo "Running $script_name in chroot with arguments: $*" | |
| chroot "$MNT" /bin/bash "/$script_name" "$@" | |
| local status=$? | |
| if [ $status -ne 0 ]; then | |
| echo "Error: Script $script_name failed with exit code $status." | |
| echo "Stopping for inspection. Fix the issue, then continue manually." | |
| exit 1 | |
| else | |
| echo "$script_name completed successfully." | |
| fi | |
| echo "Deleting $script_name from chroot environment..." | |
| rm -f "$MNT/$script_name" || echo "Warning: Failed to delete $script_name from chroot environment." | |
| } | |
| # Run scripts one by one in chroot environment | |
| #run_in_chroot "./kiosk-install.sh" | |
| #run_in_chroot "./setup-dosi-phonehome" "kiosk" | |
| run_in_chroot "./google-chrome-install.sh" | |
| run_in_chroot "./macify-user.sh" "linux" | |
| run_in_chroot "./final-things.sh" | |
| # No manual unmount section needed anymore — cleanup() (trap EXIT) handles it. | |
| # But we still do sync + partprobe before exiting, while mounts are still present. | |
| sync | |
| partprobe || { echo "Warning: partprobe failed"; } | |
| echo "Here is an output for sanity check" | |
| lsblk -o name,size,label | |
| read -p "Do you want to reboot now? (yes/no) " reboot_ans | |
| if [ "$reboot_ans" == "yes" ]; then | |
| echo "Rebooting now..." | |
| reboot | |
| else | |
| echo "Ready for any extra changes you may want. Enjoy Linux on your emmc of $TGTDEV" | |
| fi | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| echo "" | |
| echo "resizing target /tmp/p3 uefi install root filesystem" | |
| echo "" | |
| ROOTDEVICE=$(mount | grep 'on /tmp/p3 type' | awk '{print $1}' | sed 's,^/dev/,,g') | |
| ROOTFSTYPE=$(mount | grep 'on /tmp/p3 type' | awk '{print $5}') | |
| ROOTPARTUUID=$(blkid | grep "/dev/$ROOTDEVICE" | awk '{print $5}' | sed 's,",,g' | awk -F= '{print $2}') | |
| ROOTDEVICEBASE=$(echo $ROOTDEVICE | grep "mmcblk" | sed 's,p.*,,g') | |
| ROOTDEVICEPARTNUMBER=$(echo $ROOTDEVICE | sed 's,mmcblk.p,,g') | |
| # the above is for the mmcblkx case - below is for the sdx case | |
| if [ "$ROOTDEVICEBASE" = "" ]; then | |
| ROOTDEVICEBASE=$(echo $ROOTDEVICE | grep "sd" | head -c 3) | |
| ROOTDEVICEPARTNUMBER=$(echo $ROOTDEVICE | sed 's,sd.,,g') | |
| fi | |
| # in case we cannot determine the root device base | |
| if [ "$ROOTDEVICEBASE" = "" ]; then | |
| echo "" | |
| echo "cannot determine the root device base - giving up" | |
| echo "" | |
| exit 1 | |
| fi | |
| PARTITIONTYPE=$(fdisk -l /dev/${ROOTDEVICEBASE} | grep "Disklabel type" | awk -F: '{print $2}' | sed 's,^ ,,g') | |
| if [ "$PARTITIONTYPE" = "dos" ]; then | |
| ROOTPARTITIONSTART=$(sfdisk -d /dev/$ROOTDEVICEBASE | grep $ROOTDEVICE | awk '{print $4}' | sed 's/,//g') | |
| fdisk /dev/$ROOTDEVICEBASE << EOF | |
| d | |
| $ROOTDEVICEPARTNUMBER | |
| n | |
| p | |
| $ROOTDEVICEPARTNUMBER | |
| $ROOTPARTITIONSTART | |
| p | |
| w | |
| EOF | |
| elif [ "$PARTITIONTYPE" = "gpt" ]; then | |
| ROOTPARTITIONSTART=$(sfdisk -d /dev/$ROOTDEVICEBASE | grep $ROOTDEVICE | awk '{print $4}' | sed 's/,//g') | |
| fdisk /dev/$ROOTDEVICEBASE << EOF | |
| d | |
| $ROOTDEVICEPARTNUMBER | |
| n | |
| $ROOTDEVICEPARTNUMBER | |
| $ROOTPARTITIONSTART | |
| x | |
| u | |
| $ROOTDEVICEPARTNUMBER | |
| $ROOTPARTUUID | |
| r | |
| p | |
| w | |
| EOF | |
| fi | |
| partprobe /dev/$ROOTDEVICE | |
| if [ "$ROOTFSTYPE" = "btrfs" ]; then | |
| btrfs filesystem resize max /tmp/p3 | |
| else | |
| resize2fs /dev/$ROOTDEVICE | |
| fi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| echo "Setting system timezone to US Central (America/Chicago)..." | |
| ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime | |
| echo "America/Chicago" > /etc/timezone | |
| date | |
| echo "Dropping /etc/apt/sources.list.d/velvet_repo.sources..." | |
| rm -f /etc/apt/sources.list.d/velvet_repo.sources | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -e | |
| echo "Updating package list..." | |
| apt update | |
| echo "Installing required dependencies..." | |
| apt install -y wget gnupg ca-certificates | |
| echo "Adding Google Chrome GPG key..." | |
| wget -qO- https://dl.google.com/linux/linux_signing_key.pub | \ | |
| gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg | |
| echo "Adding Google Chrome repository..." | |
| echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | \ | |
| tee /etc/apt/sources.list.d/google-chrome.list > /dev/null | |
| echo "Updating package list again..." | |
| apt update | |
| echo "Installing Google Chrome..." | |
| apt install -y google-chrome-stable | |
| echo "Installation complete!" | |
| echo "You can launch Chrome with: google-chrome" | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| if [[ $# -ne 1 ]]; then | |
| echo "Usage: sudo $0 <targetUserID>" | |
| exit 1 | |
| fi | |
| TARGET_USER="$1" | |
| TS="$(date +%Y%m%d-%H%M%S)" | |
| # ===== Desired look ===== | |
| GTK_THEME_NAME="${GTK_THEME_NAME:-Adwaita-dark}" | |
| # IMPORTANT: icon theme folder name must match what's in /usr/share/icons | |
| ICON_THEME_NAME="${ICON_THEME_NAME:-WhiteSur-dark}" | |
| # Cursor: keep Adwaita by default (safe), or set to WhiteSur if you have it installed | |
| CURSOR_THEME_NAME="${CURSOR_THEME_NAME:-Adwaita}" | |
| # Window manager: keep user's current xfwm theme unless you want to force one. | |
| # If you DO want a WhiteSur xfwm theme, set XFWM_THEME_NAME accordingly. | |
| XFWM_THEME_NAME="${XFWM_THEME_NAME:-}" | |
| FONT_NAME="${FONT_NAME:-Inter 10}" | |
| MONO_FONT_NAME="${MONO_FONT_NAME:-Fira Code 10}" | |
| WORKDIR="${WORKDIR:-/opt/mactheme-build}" | |
| # ======================= | |
| require_root() { [[ "${EUID}" -eq 0 ]] || { echo "ERROR: run with sudo/root"; exit 1; }; } | |
| user_exists() { id "$TARGET_USER" >/dev/null 2>&1; } | |
| user_home() { getent passwd "$TARGET_USER" | cut -d: -f6; } | |
| backup_path_if_exists() { | |
| local path="$1" | |
| local backup_dir="$2" | |
| if [[ -e "$path" ]]; then | |
| mkdir -p "$backup_dir" | |
| cp -a "$path" "$backup_dir/" || true | |
| fi | |
| } | |
| apt_install() { | |
| echo "[*] Installing required packages (best effort)..." | |
| apt-get update | |
| apt-get install -y --no-install-recommends \ | |
| git ca-certificates \ | |
| fonts-inter fonts-noto fonts-noto-color-emoji fonts-firacode \ | |
| gtk2-engines-murrine gtk2-engines-pixbuf \ | |
| xfce4-settings \ | |
| || true | |
| } | |
| clone_or_update() { | |
| local url="$1" | |
| local dir="$2" | |
| if [[ -d "${dir}/.git" ]]; then | |
| git -C "$dir" fetch --depth=1 origin || true | |
| git -C "$dir" reset --hard origin/master 2>/dev/null || git -C "$dir" reset --hard origin/main | |
| else | |
| git clone --depth=1 "$url" "$dir" | |
| fi | |
| } | |
| install_whitesur_icons() { | |
| # You asked for WhiteSur icons (dark). We'll install the icon theme repo system-wide. | |
| echo "[*] Installing WhiteSur icon theme system-wide..." | |
| mkdir -p "$WORKDIR" | |
| local dir="${WORKDIR}/WhiteSur-icon-theme" | |
| clone_or_update "https://github.com/vinceliuice/WhiteSur-icon-theme.git" "$dir" | |
| # Install into /usr/share/icons. Keep name default "WhiteSur" unless user sets -n. | |
| # The repo supports -t (variant). We'll install all variants so "WhiteSur-dark" can exist if provided by theme. | |
| ( cd "$dir" && bash ./install.sh -d /usr/share/icons -t all ) || true | |
| } | |
| # ---------- Apply appearance WITHOUT touching panel ---------- | |
| write_xsettings_xml() { | |
| cat <<EOF | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <channel name="xsettings" version="1.0"> | |
| <property name="Net" type="empty"> | |
| <property name="ThemeName" type="string" value="${GTK_THEME_NAME}"/> | |
| <property name="IconThemeName" type="string" value="${ICON_THEME_NAME}"/> | |
| </property> | |
| <property name="Gtk" type="empty"> | |
| <property name="CursorThemeName" type="string" value="${CURSOR_THEME_NAME}"/> | |
| <property name="FontName" type="string" value="${FONT_NAME}"/> | |
| <property name="MonospaceFontName" type="string" value="${MONO_FONT_NAME}"/> | |
| <property name="MenuImages" type="bool" value="true"/> | |
| <property name="ButtonImages" type="bool" value="true"/> | |
| </property> | |
| </channel> | |
| EOF | |
| } | |
| write_xfwm4_xml_preserve_theme() { | |
| # Only enforce mac-style button layout + title font. | |
| # Preserve user's existing xfwm theme unless XFWM_THEME_NAME is set. | |
| local theme_line="" | |
| if [[ -n "${XFWM_THEME_NAME}" ]]; then | |
| theme_line=" <property name=\"theme\" type=\"string\" value=\"${XFWM_THEME_NAME}\"/>" | |
| fi | |
| cat <<EOF | |
| <?xml version="1.0" encoding="UTF-8"?> | |
| <channel name="xfwm4" version="1.0"> | |
| <property name="general" type="empty"> | |
| ${theme_line} | |
| <property name="button_layout" type="string" value="CHM|O"/> | |
| <property name="title_font" type="string" value="${FONT_NAME}"/> | |
| </property> | |
| </channel> | |
| EOF | |
| } | |
| apply_appearance_preserve_panel() { | |
| local home="$1" | |
| local base="${home}/.config/xfce4/xfconf/xfce-perchannel-xml" | |
| mkdir -p "$base" | |
| # Do NOT write xfce4-panel.xml, do NOT touch ~/.config/xfce4/panel | |
| write_xsettings_xml > "${base}/xsettings.xml" | |
| write_xfwm4_xml_preserve_theme > "${base}/xfwm4.xml" | |
| } | |
| remove_plank_for_user() { | |
| # In case previous attempts enabled it, remove user plank config and autostart entry. | |
| local home="$1" | |
| rm -rf "${home}/.config/plank" || true | |
| # Remove autostart launchers for plank if present | |
| if [[ -d "${home}/.config/autostart" ]]; then | |
| rm -f "${home}/.config/autostart/plank.desktop" || true | |
| fi | |
| # Also remove system-wide plank autostart file if you had created one earlier | |
| # (safe to ignore if it doesn't exist) | |
| rm -f /etc/xdg/autostart/plank.desktop 2>/dev/null || true | |
| } | |
| verify_icon_theme_exists() { | |
| # If the user requested ICON_THEME_NAME but it's not installed, fall back to "WhiteSur" or "Adwaita". | |
| if [[ -d "/usr/share/icons/${ICON_THEME_NAME}" ]]; then | |
| return 0 | |
| fi | |
| # Common fallback for this icon theme repo is "WhiteSur" | |
| if [[ -d "/usr/share/icons/WhiteSur" ]]; then | |
| echo "[!] Icon theme '${ICON_THEME_NAME}' not found; falling back to 'WhiteSur'." | |
| ICON_THEME_NAME="WhiteSur" | |
| return 0 | |
| fi | |
| echo "[!] Icon theme '${ICON_THEME_NAME}' not found; falling back to 'Adwaita'." | |
| ICON_THEME_NAME="Adwaita" | |
| } | |
| main() { | |
| require_root | |
| user_exists || { echo "ERROR: user '$TARGET_USER' not found"; exit 1; } | |
| local home | |
| home="$(user_home)" | |
| [[ -n "$home" && -d "$home" ]] || { echo "ERROR: home for '$TARGET_USER' not found"; exit 1; } | |
| apt_install | |
| install_whitesur_icons | |
| verify_icon_theme_exists | |
| # Backup what we might touch (and panel too, just in case) | |
| local backup="${home}/desktop-macify-backup-${TS}" | |
| echo "[*] Backing up to: $backup" | |
| mkdir -p "$backup" | |
| chown "$TARGET_USER:$TARGET_USER" "$backup" || true | |
| backup_path_if_exists "${home}/.config/xfce4" "$backup" | |
| backup_path_if_exists "${home}/.config/autostart" "$backup" | |
| backup_path_if_exists "${home}/.config/plank" "$backup" | |
| echo "[*] Preserving top bar functionality (no panel changes), applying new look..." | |
| apply_appearance_preserve_panel "$home" | |
| echo "[*] Removing Plank settings/autostart for the user..." | |
| remove_plank_for_user "$home" | |
| echo "[*] Fixing ownership..." | |
| chown -R "$TARGET_USER:$TARGET_USER" "${home}/.config" "${home}/.cache" || true | |
| echo | |
| echo "============================================================" | |
| echo "Done for '${TARGET_USER}'." | |
| echo "Top bar/panel layout untouched." | |
| echo "GTK theme: ${GTK_THEME_NAME}" | |
| echo "Icon theme: ${ICON_THEME_NAME}" | |
| echo "Backup: ${backup}" | |
| echo "Next: log out and log back in to reload settings cleanly." | |
| echo "============================================================" | |
| } | |
| main | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| echo "Setting system timezone to US Central (America/Chicago)..." | |
| timedatectl set-timezone America/Chicago | |
| echo "Timezone now set to:" | |
| timedatectl | grep "Time zone" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment