#!/bin/bash # ====================================================================== # # Copyright (c) 2022-2026, Sony Group Corporation. # All rights reserved. # # CLASSIFICATION: INTERNAL USE # # ====================================================================== # # Hmph! Nezuko will get mad at you if you distribute or mess with this script! # # This script is for onboarding Linux Laptops, and is completely USELESS to # anyone outside Sony. It requires you to have access the internal Sony network, # and have a Sony M365 account + MFA, with proper access... # # WARNING: If you do not work for Sony, LEAVE NOW! This script will NOT work for you, # and may damage and/or modify your system **irreversibly**! # # Nezuko is watching you... # # ⠏⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⢉⣩⣭⣿⣿⣿⣿⣿⣿⣽⣿⣿⣭⣭⣍⡉⠉⠉⠉⠉⢹⠙⠛⠯⣍⡉⠉⠉⠉⠉⠉⠉⡩ # ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⣿⣿⣿⣿⡿⠿⠿⠿⢿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⡞⠀⠀⠀⢀⡽⠀⠀⠀⠀⡤⠊⠀ # ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣟⣭⣶⣿⣿⣿⣿⣿⣶⣯⣿⣿⣿⣿⣞⢿⣿⣿⣶⠁⠀⠀⣠⠞⠀⠀⠀⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⡿⠟⠁⣠⡞⠁⠀⠀⠀⣀⣤⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣾⣿⡿⠛⠉⠛⠉⠁⠀⠀⠀⠀⠀⠙⠛⠻⠿⣿⣿⣿⣟⡟⢦⠤⠺⠿⢿⡤⠴⠚⠉⠁⣾⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⢿⣶⣧⣀⠀⠀⠀⠀⠀⠀⠀⢠⡇⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡟⠁⠲⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡀⠀⠀⠀⢿⣿⣿⢿⣶⣤⣤⣤⣤⠤⠟⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⡟⠀⠀⠀⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠈⣿⣿⡏⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠁⠀⢀⣀⢀⣈⡲⣄⠀⠀⠀⠀⠀⠀⢀⣀⡴⠋⣠⣀⡀⠀⠀⠀⠀⣿⣿⣿⢹⣿⣿⣽⣿⡇⠀⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⣾⡿⣿⡇⠀⢀⣥⣤⣶⣶⣬⣉⠀⠀⠀⠀⠀⠀⢹⣿⠶⠶⢶⣤⣭⣑⠢⡀⠀⣿⣿⣿⣿⣿⣿⣿⢿⣿⠀⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⣿⣿⣿⣇⣼⠟⢉⡠⠄⠲⢄⠉⠓⠀⠀⠀⠀⠐⠁⣠⠔⠂⠒⠢⣍⠻⣷⣄⣀⣿⣿⣟⣿⣿⣿⣿⡾⣿⠀⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⠀⣿⣿⣾⣯⠃⣸⠋⡤⠀⡆⠀⠱⡄⠀⠀⠀⠀⠀⣾⠡⣋⣀⡆⠀⠈⣧⠈⢻⡌⣿⣿⣿⡏⠻⣿⣿⣿⢿⡄⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⠀⢿⡀⠈⠿⡇⠀⢀⡇⠀⠀⠀⠀⠀⣇⠀⠉⠛⠃⠀⠀⡟⠀⠀⠀⣿⣿⣿⣏⠂⢹⣿⣿⣾⡇⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⡆⣼⠣⠀⠀⠀⢀⡼⠁⠀⠀⠀⠀⠀⠙⠤⢀⡀⠀⡀⢜⣁⠀⠀⠀⣿⣿⣿⡏⠁⢸⣿⣿⣿⣧⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⢨⣿⣿⠟⢻⣇⡿⠷⡂⠈⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣈⣩⠴⣟⣁⣀⠀⢰⣿⣿⣿⡇⢀⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⠀⣾⡿⠁⢠⠏⡸⠀⢰⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⡿⠉⡼⢩⠃⢠⠈⣇⣸⣿⣿⣿⣶⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀ # ⠀⠀⠀⠀⢰⣿⡇⠀⠈⠀⡇⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⠀⢸⠀⡎⠀⣼⣿⡿⣿⣿⣿⣿⢹⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀ # ⠀⠀⠀⠀⣾⣿⣷⡀⠸⣶⢳⡀⢳⣤⣤⣤⣀⣀⠀⠀⠀⠀⠀⠂⠀⣯⠀⢸⣤⣧⠀⣿⢿⣾⣿⣿⣿⣿⣼⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀ # ⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⡿⢟⣿⣿⣿⠛⠛⢿⡿⠉⠹⠿⠿⠾⠛⣦⠼⠛⠿⣦⣬⣿⣯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀ # ⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠀⠀⠀⠱⣄⠀⠀⢀⠔⠋⠀⠀⢀⣴⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠹⣿⣿⣿⣆⠀⠀ # ⠀⠀⢀⣿⣿⣿⡿⢛⣵⡿⣿⣿⣿⠟⠁⢧⠀⠀⠀⠀⠈⣢⠞⠁⠀⠀⠀⡰⠋⢀⣰⣿⣧⣿⣿⣿⣿⣸⣿⣿⣯⡻⣿⡇⢻⣿⣿⣿⣆⠀ # ⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⢁⠜⢁⣸⣇⠀⢀⡠⠊⠁⠀⠀⠀⣠⠊⣠⠔⠉⢀⣿⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠈⣿⣿⣿⣿⣆ # ⣴⣿⣿⣿⢟⣽⣿⣿⣿⣿⣿⡿⣣⠔⣩⠛⡏⢷⠋⠀⠀⠀⠀⡠⣎⠉⠁⢱⠀⠀⢸⢻⡿⣿⣿⣿⣿⢻⣿⣿⣿⣿⣿⣿⡄⢹⣿⣿⣿⣿ # ⣿⣿⣿⣫⣿⣿⣿⣿⣿⣿⣿⠟⠁⡴⠁⢸⠀⠈⠣⠀⣀⣴⠋⡙⢌⠳⡀⠀⢇⠀⡏⢸⣿⡹⣿⣿⣿⣧⣻⣿⣿⣿⣿⣿⣷⡀⣿⣿⣿⣿ # ⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⡤⠎⠀⠀⢸⠀⣀⡴⠋⡱⠃⢠⠁⠈⠢⡘⢆⠸⠀⠇⢸⣿⣷⣽⣿⣿⣿⣧⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ # # ====================================================================== # ====================================================================== # ====================================================================== # ==========================================================Oi!========= # ====================================================================== # # # # # # # # # # # ====================================================================== # Display Functions # ====================================================================== # ANSI color codes RED='\e[0;31m' BOLD_RED='\e[1;31m' GREEN='\e[0;32m' BOLD_GREEN='\e[1;32m' YELLOW='\e[0;33m' CYAN='\e[0;36m' NC='\e[0m' # No Color # Display formatted error message and exit die() { local error_message="$1" echo -e "" echo -e "${BOLD_RED} ███████╗██████╗ ██████╗ ██████╗ ██████╗ ${NC}" echo -e "${BOLD_RED} ██╔════╝██╔══██╗██╔══██╗██╔═══██╗██╔══██╗${NC}" echo -e "${BOLD_RED} █████╗ ██████╔╝██████╔╝██║ ██║██████╔╝${NC}" echo -e "${BOLD_RED} ██╔══╝ ██╔══██╗██╔══██╗██║ ██║██╔══██╗${NC}" echo -e "${BOLD_RED} ███████╗██║ ██║██║ ██║╚██████╔╝██║ ██║${NC}" echo -e "${BOLD_RED} ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝${NC}" echo -e "${RED}════════════════════════════════════════════════════════════════════════════════${NC}" echo -e "${BOLD_RED} ERROR: ${error_message}${NC}" echo -e "${RED}════════════════════════════════════════════════════════════════════════════════${NC}" echo "" exit 1 } # Display the SonyLinux onboarding banner banner() { echo -e "" echo -e "════════════════════════════════════════════════════════════════════════════════" echo -e "███████╗ ██████╗ ███╗ ██╗██╗ ██╗ ██╗ ██╗███╗ ██╗██╗ ██╗██╗ ██╗" echo -e "██╔════╝██╔═══██╗████╗ ██║╚██╗ ██╔╝ ██║ ██║████╗ ██║██║ ██║╚██╗██╔╝" echo -e "███████╗██║ ██║██╔██╗ ██║ ╚████╔╝ ██║ ██║██╔██╗ ██║██║ ██║ ╚███╔╝ " echo -e "╚════██║██║ ██║██║╚██╗██║ ╚██╔╝ ██║ ██║██║╚██╗██║██║ ██║ ██╔██╗ " echo -e "███████║╚██████╔╝██║ ╚████║ ██║ ███████╗██║██║ ╚████║╚██████╔╝██╔╝ ██╗" echo -e "╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝" echo -e "════════════════════════════════════════════════════════════════════════════════" echo -e "" echo -e " Onboarding to SonyLinux..." echo -e "" echo -e "════════════════════════════════════════════════════════════════════════════════" echo -e "" } # Display installation success message success() { local client_id="$1" local show_next_steps="${2:-true}" echo -e "" echo -e "${BOLD_GREEN}███████╗██╗ ██╗ ██████╗ ██████╗███████╗███████╗███████╗${NC}" echo -e "${BOLD_GREEN}██╔════╝██║ ██║██╔════╝██╔════╝██╔════╝██╔════╝██╔════╝${NC}" echo -e "${BOLD_GREEN}███████╗██║ ██║██║ ██║ █████╗ ███████╗███████╗${NC}" echo -e "${BOLD_GREEN}╚════██║██║ ██║██║ ██║ ██╔══╝ ╚════██║╚════██║${NC}" echo -e "${BOLD_GREEN}███████║╚██████╔╝╚██████╗╚██████╗███████╗███████║███████║${NC}" echo -e "${BOLD_GREEN}╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝╚══════╝╚══════╝╚══════╝${NC}" echo -e "${GREEN}════════════════════════════════════════════════════════════════════════════════${NC}" echo -e "${BOLD_GREEN} Installation completed successfully! (Client ID: $client_id)${NC}" echo -e "${GREEN}════════════════════════════════════════════════════════════════════════════════${NC}" if [ "$show_next_steps" = "true" ]; then echo -e "" echo -e " ${CYAN}NEXT STEPS:${NC}" echo -e "" echo -e " ${CYAN}[STEP 1]${YELLOW} Cache your AD credentials (if connected via VPN):${NC}" echo -e "" echo -e " ${GREEN}$ sudo su${NC}" echo -e " ${GREEN}$ login${NC}" echo -e "" echo -e " Use your AD username and password when you run 'login'." echo -e " This allows offline authentication after reboot" echo -e "" echo -e " ${CYAN}[STEP 2]${NC}${YELLOW} Reboot your machine to complete installation:${NC}" echo -e "" echo -e " ${GREEN}$ sudo reboot${NC}" echo -e "" echo -e "════════════════════════════════════════════════════════════════════════════" fi echo -e " SonyLinux Support @ https://sonyeur.sharepoint.com/sites/S022-SonyLinux/" echo -e "════════════════════════════════════════════════════════════════════════════════" } # ====================================================================== # Script Initialization # ====================================================================== set -u # Exit on undefined variable set -o pipefail # Exit if any command in a pipeline fails # Trap errors and provide informative message trap 'die "Unexpected error occurred. Please review the output above and contact SonyLinux Support."' ERR # ====================================================================== # OS Detection # ====================================================================== # Return the OS family label based on which package manager exists. # ubuntu = Debian-family (apt-get) # rhel = RHEL-family (dnf) detect_os() { command -v apt-get &>/dev/null && echo "ubuntu" && return command -v dnf &>/dev/null && echo "rhel" && return echo "unknown" } OS_TYPE=$(detect_os) # ====================================================================== # Main Execution # ====================================================================== # Display onboarding banner banner # ====================================================================== # Pre-Installation Validation # ====================================================================== # Verify root privileges [ "$(id -u)" = "0" ] || die "This script must be run as root. Please use sudo." # Validate and normalize hostname do_validate_hostname() { local raw_hostname raw_hostname="$(hostname -s)" # Must be 1-63 chars, start with a letter, contain only letters, digits, and hyphens if [ -z "$raw_hostname" ] || [ "${#raw_hostname}" -gt 63 ] || [[ ! "$raw_hostname" =~ ^[a-zA-Z][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$ ]]; then die "Invalid hostname: '$raw_hostname'. Must match ^[a-zA-Z][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]\$ (1-63 chars, no trailing hyphen)." fi local lower_hostname lower_hostname=$(printf '%s' "$raw_hostname" | tr '[:upper:]' '[:lower:]') # Source the shared validation library from the prod CDN. # Fetches the approved prefix SHA-512 hash list from # cdn.lx.sony.com/install/prefixes.txt. # # To update the prefix list: # 1. Edit PREFIXES in ~/cloud/autoinstall/generate-prefix-hashes.sh # 2. Run it to regenerate data/install/prefixes.txt # 3. Deploy: nonprod apply -> uplift core/cdn -> prod apply local hostname_lib_url="https://cdn.lx.sony.com/install/hostname-lib.sh" if command -v wget &>/dev/null; then . /dev/stdin <<<"$(wget -qO- "$hostname_lib_url")" fi if ! command -v validate_hostname_prefix &>/dev/null; then die "Failed to load hostname validation library from ${hostname_lib_url}." fi if ! validate_hostname_prefix "$lower_hostname"; then die "Hostname does not match any approved prefix. Please contact SonyLinux Support to reserve a valid hostname." fi echo "$lower_hostname" } # ====================================================================== # Network Configuration # ====================================================================== # Office machines sometimes install with IPv6 disabled in NetworkManager. # Re-enable it (set to "auto") on any active ethernet connections before # running the package manager, so we can contact internal infrastructure # over IPv6 if needed. do_fix_ipv6() { if ! command -v nmcli &>/dev/null; then return fi echo -e "Checking IPv6 configuration on active ethernet connections..." while IFS= read -r conn_name; do [ -z "$conn_name" ] && continue ipv6_method=$(nmcli -g ipv6.method connection show "$conn_name" 2>/dev/null || true) if [ "$ipv6_method" = "disabled" ]; then echo -e " Re-enabling IPv6 (auto) on: $conn_name" nmcli connection modify "$conn_name" ipv6.method auto \ || die "Failed to set IPv6 method on connection: $conn_name" device=$(nmcli -g GENERAL.DEVICES connection show "$conn_name" 2>/dev/null || true) if [ -n "$device" ]; then nmcli device reapply "$device" \ || die "Failed to reapply connection after IPv6 change: $conn_name" fi fi done < <(nmcli -t -f NAME,TYPE c show --active | grep ':ethernet$' | cut -d: -f1) } # ====================================================================== # System Maintenance # ====================================================================== # Upgrade system packages. do_upgrade_system() { echo -e "Updating system packages..." case "$OS_TYPE" in ubuntu) apt update || die "Failed to update package lists." apt upgrade -y || die "Failed to upgrade system packages." ;; rhel) dnf upgrade -y || die "Failed to upgrade system packages." ;; *) die "Unsupported OS: $OS_TYPE. This script supports Ubuntu/Debian and RHEL-family (Rocky, Alma, RHEL)." ;; esac } # ====================================================================== # SaltStack Configuration # ====================================================================== # Write SaltStack minion configuration do_salt_write_config() { local minion_id="${1:?minion_id is required}" echo -e "Configuring SaltStack minion..." mkdir -p /etc/salt || die "Failed to create /etc/salt directory." chown -R root:root /etc/salt printf '%s\n' \ 'master: salt.lx.sony.com' \ 'minion_id_lowercase: True' \ 'minion_id_remove_domain: True' \ 'rejected_retry: True' \ 'master_tries: -1' \ "master_finger: 'c3:e9:3e:48:19:96:dc:c3:7f:b7:71:bd:7e:a1:e0:86:a3:73:67:1f:2c:c6:d3:ce:12:12:76:12:14:5d:04:d9'" \ 'top_file_merging_strategy: same' \ > /etc/salt/minion || die "Failed to write minion configuration." # Set secure permissions for minion configuration chmod 0444 /etc/salt/minion || die "Failed to set permissions on minion config." # Configure minion ID with lowercase hostname echo "$minion_id" > /etc/salt/minion_id || die "Failed to write minion ID." chmod 0644 /etc/salt/minion_id || die "Failed to set permissions on minion ID." } # ====================================================================== # SaltStack Installation # ====================================================================== # SaltStack GPG public key (shared between apt and rpm paths) SALT_GPG_KEY=$(cat <<'SALTKEY' -----BEGIN PGP PUBLIC KEY BLOCK----- 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 =ZKPF -----END PGP PUBLIC KEY BLOCK----- SALTKEY ) # Add the SaltStack package repository for the detected OS. do_salt_setup_repo() { case "$OS_TYPE" in ubuntu) mkdir -p /etc/apt/keyrings || die "Failed to create keyrings directory." printf '%s\n' "$SALT_GPG_KEY" | gpg --yes --dearmor -o /etc/apt/keyrings/salt-archive-keyring.gpg || die "Failed to install SaltStack GPG key." echo -e "deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg] https://packages.broadcom.com/artifactory/saltproject-deb/ stable main" \ > /etc/apt/sources.list.d/salt.list \ || die "Failed to add SaltStack repository." apt update || die "Failed to update package lists after adding SaltStack repository." ;; rhel) mkdir -p /etc/pki/rpm-gpg || die "Failed to create RPM GPG key directory." printf '%s\n' "$SALT_GPG_KEY" > /etc/pki/rpm-gpg/salt-archive-keyring.asc || die "Failed to install SaltStack GPG key." rpm --import /etc/pki/rpm-gpg/salt-archive-keyring.asc \ || die "Failed to import SaltStack GPG key." cat < /etc/yum.repos.d/salt.repo || die "Failed to add SaltStack repository." [salt-repo] name=SaltStack repo for RHEL-family baseurl=https://packages.broadcom.com/artifactory/saltproject-rpm/ enabled=1 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/salt-archive-keyring.asc EOF dnf clean all || die "Failed to clean dnf cache." ;; *) die "Unsupported OS: $OS_TYPE. This script supports Ubuntu/Debian and RHEL-family (Rocky, Alma, RHEL)." ;; esac } # Install the SaltStack minion package. do_salt_install_minion() { SALT_VERSION="3007.8" case "$OS_TYPE" in ubuntu) apt install -y "salt-minion=${SALT_VERSION}" "salt-common=${SALT_VERSION}" --allow-downgrades \ || die "Failed to install SaltStack version ${SALT_VERSION}. This specific version is required." ;; rhel) dnf install -y "salt-minion-${SALT_VERSION}" \ || die "Failed to install SaltStack version ${SALT_VERSION}. This specific version is required." ;; *) die "Unsupported OS: $OS_TYPE. This script supports Ubuntu/Debian and RHEL-family (Rocky, Alma, RHEL)." ;; esac } # Main installation function do_install() { # Validate hostname before anything else local LOWER_HOSTNAME LOWER_HOSTNAME=$(do_validate_hostname) # Fix IPv6 on ethernet connections before contacting package repos do_fix_ipv6 # Upgrade system packages (unless skip flag exists) if [ ! -f /root/sony-skip-compliance ]; then do_upgrade_system else echo -e "Skipping system package update (/root/sony-skip-compliance detected)..." fi # Configure SaltStack echo -e "Writing SaltStack configuration..." do_salt_write_config "$LOWER_HOSTNAME" # Setup repo and install SaltStack packages do_salt_setup_repo do_salt_install_minion # Verify installation command -v salt-call &> /dev/null || die "SaltStack installation failed - salt-call not found." # Reapply configuration and restart service echo -e "Finalizing SaltStack configuration..." do_salt_write_config "$LOWER_HOSTNAME" systemctl daemon-reload systemctl enable salt-minion || die "Failed to enable salt-minion service." systemctl restart salt-minion || die "Failed to restart salt-minion service." # Wait for service to start (poll up to 10 seconds) local salt_attempts=0 until systemctl is-active --quiet salt-minion 2>/dev/null; do salt_attempts=$((salt_attempts + 1)) if [ "$salt_attempts" -ge 10 ]; then die "salt-minion service failed to start." fi sleep 1 done # Synchronize SaltStack modules echo -e "Synchronizing SaltStack modules and system information..." salt-call saltutil.sync_all || die "Failed to sync SaltStack modules." salt-call grains.items || die "Failed to retrieve system information." # Establish baseline system registration echo -e "Completing system registration..." salt-call -l debug state.apply salt.minion || die "Failed to complete system registration." # Enable Sony compliance mode (unless skip flag exists) if [ ! -f /root/sony-skip-compliance ]; then if ! /usr/local/sbin/sony-compliance --yes; then echo -e " ${YELLOW}WARNING:${NC} sony-compliance failed, killing stuck processes and retrying..." killall -9 /opt/saltstack/salt/bin/python3.10 2>/dev/null || true systemctl restart salt-minion || die "Failed to restart salt-minion." /usr/local/sbin/sony-compliance --yes || die "Failed to apply Sony Linux configuration." fi else echo -e "Skipping Sony compliance mode (/root/sony-skip-compliance detected)..." fi # Display completion message local show_next="true" if [[ "$LOWER_HOSTNAME" =~ ^(ap|in) ]] || [ -f /root/sony-skip-compliance ]; then show_next="false" fi success "$LOWER_HOSTNAME" "$show_next" } # Execute installation # Note: Wrapped in a function to protect against incomplete downloads during # piped execution (e.g., wget | sh) do_install # End of script