Change from openbox to xfce4

parent 5de4db6d
#!/bin/bash
# MBetter Offline Automatic Installer Script
# Copies the live system to disk for completely offline installation
# NO internet connection required
set -e
INSTALL_LOG="/var/log/auto-installer.log"
TARGET_DISK="" # Will be detected automatically
TARGET_MOUNT="/target"
PRESEED_FILE=""
LIVE_SYSTEM="/"
USB_DEVICE="" # Will track USB device to avoid installing over it
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Progress tracking
TOTAL_STEPS=10
CURRENT_STEP=0
log() {
echo "$(date): $1" | tee -a "$INSTALL_LOG"
}
# Progress tracking functions
update_progress() {
local step=$1
local message="$2"
CURRENT_STEP=$step
local percent=$((step * 100 / TOTAL_STEPS))
# Terminal-based progress bar
local width=50
local filled=$((percent * width / 100))
local empty=$((width - filled))
# Create progress bar
local bar=""
for ((i=0; i<filled; i++)); do bar="${bar}█"; done
for ((i=0; i<empty; i++)); do bar="${bar}░"; done
# Clear previous progress and show new one
echo -ne "\r${BLUE}[PROGRESS]${NC} $message\n${BLUE}[${bar}]${NC} ${percent}%"
print_status "$message ($percent%)"
}
start_progress_display() {
# Terminal progress - no initialization needed
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}MBetter Installation Progress${NC}"
echo -e "${BLUE}========================================${NC}"
}
cleanup_progress() {
# Terminal cleanup - just add newline
echo -e "\n${GREEN}[INFO]${NC} Progress tracking completed"
}
print_status() {
echo -e "${GREEN}[INFO]${NC} $1"
log "INFO: $1"
}
print_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
log "WARNING: $1"
}
print_error() {
echo -e "${RED}[ERROR]${NC} $1"
log "ERROR: $1"
}
print_header() {
echo -e "${BLUE}================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}================================${NC}"
}
# Detect USB device we're booting from
detect_usb_device() {
print_status "Detecting USB boot device..."
# Find the device containing the live system
local live_dev=""
# Check different possible mount points for live media
for mount_point in /lib/live/mount/medium /cdrom /run/live/medium; do
if [ -d "$mount_point" ]; then
live_dev=$(df "$mount_point" 2>/dev/null | tail -1 | awk '{print $1}' | sed 's/[0-9]*$//')
if [ -n "$live_dev" ] && [ -b "$live_dev" ]; then
USB_DEVICE="$live_dev"
print_status "Detected live media device: $USB_DEVICE"
return 0
fi
fi
done
# Fallback: check for mounted filesystems with live or boot labels
USB_DEVICE=$(lsblk -rno NAME,MOUNTPOINT,LABEL | grep -E "(live|boot|LIVE)" | head -1 | awk '{print "/dev/" $1}' | sed 's/[0-9]*$//')
if [ -n "$USB_DEVICE" ] && [ -b "$USB_DEVICE" ]; then
print_status "Detected USB device: $USB_DEVICE"
else
print_warning "Could not detect USB device, assuming /dev/sdb"
USB_DEVICE="/dev/sdb" # Common fallback when sda is the target
fi
}
# Find available target disk (not the USB device)
detect_target_disk() {
print_status "Detecting target installation disk..."
# Get all available disk devices
local disks=$(lsblk -rno NAME,TYPE | grep disk | awk '{print "/dev/" $1}')
for disk in $disks; do
# Skip the USB device we're booting from
if [ "$disk" = "$USB_DEVICE" ]; then
print_status "Skipping USB boot device: $disk"
continue
fi
# Skip if disk is too small (less than 4GB)
local size_bytes=$(lsblk -rbno SIZE "$disk" 2>/dev/null | head -1 | tr -d ' ' || echo 0)
# Ensure size_bytes is a valid number
if ! [[ "$size_bytes" =~ ^[0-9]+$ ]]; then
size_bytes=0
fi
local size_gb=$((size_bytes / 1024 / 1024 / 1024))
if [ "$size_gb" -lt 4 ]; then
print_status "Skipping small disk: $disk ($size_gb GB)"
continue
fi
# Found suitable target disk
TARGET_DISK="$disk"
print_status "Selected target disk: $TARGET_DISK ($size_gb GB)"
return 0
done
print_error "No suitable target disk found!"
print_error "Available disks:"
lsblk -rno NAME,SIZE,TYPE | grep disk
return 1
}
# Find preseed file (USB-aware)
find_preseed() {
print_status "Searching for preseed file..."
# Extended search paths for USB environments
local search_paths=(
"/cdrom/preseed.cfg"
"/lib/live/mount/medium/preseed.cfg"
"/run/live/medium/preseed.cfg"
"/tmp/installer/preseed.cfg"
"/media/*/preseed.cfg"
"/mnt/*/preseed.cfg"
)
for path in "${search_paths[@]}"; do
# Handle wildcard paths
if [[ "$path" == *"*"* ]]; then
for expanded_path in $path; do
if [ -f "$expanded_path" ]; then
PRESEED_FILE="$expanded_path"
break 2
fi
done
elif [ -f "$path" ]; then
PRESEED_FILE="$path"
break
fi
done
if [ -z "$PRESEED_FILE" ]; then
print_warning "Preseed file not found, using defaults"
return 0
fi
print_status "Using preseed file: $PRESEED_FILE"
}
# Parse preseed for values
get_preseed_value() {
local key="$1"
if [ -f "$PRESEED_FILE" ]; then
grep "^d-i $key" "$PRESEED_FILE" | cut -d' ' -f3- | sed 's/^password //' || echo ""
fi
}
# Enhanced network configuration for installed system
configure_network() {
print_header "Network Configuration for Installed System"
# Network configuration variables
NETWORK_CONFIG=""
SELECTED_INTERFACE=""
WIFI_SSID=""
WIFI_PASSWORD=""
WIFI_SECURITY=""
STATIC_IP=""
STATIC_GATEWAY=""
STATIC_DNS=""
# Skip network config if user doesn't want it
echo ""
echo "Do you want to configure network for the installed system?"
echo -n "(y/n, default=n): "
read -r config_network
case "$config_network" in
y|Y|yes|YES)
;;
*)
print_status "Skipping network configuration - can be done after installation"
return 0
;;
esac
# Detect available interfaces
print_status "Scanning network interfaces..."
# Get ethernet interfaces
ETHERNET_INTERFACES=$(ip link show | grep -E '^[0-9]+:.*e(n|th)' | cut -d: -f2 | tr -d ' ')
# Get wireless interfaces
WIRELESS_INTERFACES=$(iw dev 2>/dev/null | grep Interface | awk '{print $2}' || true)
# Show available interfaces
echo ""
echo "Available network interfaces:"
interface_count=0
for iface in $ETHERNET_INTERFACES; do
interface_count=$((interface_count + 1))
echo " $interface_count. $iface (Ethernet)"
done
for iface in $WIRELESS_INTERFACES; do
interface_count=$((interface_count + 1))
echo " $interface_count. $iface (Wireless)"
done
if [ $interface_count -eq 0 ]; then
print_warning "No network interfaces detected"
return 0
fi
# Select interface
echo ""
echo -n "Select interface number (1-$interface_count): "
read -r interface_selection
# Get selected interface name
current_count=0
for iface in $ETHERNET_INTERFACES; do
current_count=$((current_count + 1))
if [ "$current_count" = "$interface_selection" ]; then
SELECTED_INTERFACE="$iface"
INTERFACE_TYPE="ethernet"
break
fi
done
if [ -z "$SELECTED_INTERFACE" ]; then
for iface in $WIRELESS_INTERFACES; do
current_count=$((current_count + 1))
if [ "$current_count" = "$interface_selection" ]; then
SELECTED_INTERFACE="$iface"
INTERFACE_TYPE="wireless"
break
fi
done
fi
if [ -z "$SELECTED_INTERFACE" ]; then
print_error "Invalid interface selection"
return 1
fi
print_status "Selected interface: $SELECTED_INTERFACE ($INTERFACE_TYPE)"
# Configure wireless if needed
if [ "$INTERFACE_TYPE" = "wireless" ]; then
print_status "Scanning for wireless networks..."
# Enable interface for scanning
ip link set "$SELECTED_INTERFACE" up
sleep 2
# Scan for networks
AVAILABLE_NETWORKS=$(iw dev "$SELECTED_INTERFACE" scan | grep -E "SSID:" | sed 's/.*SSID: //' | sort -u | head -20)
if [ -n "$AVAILABLE_NETWORKS" ]; then
echo ""
echo "Available wireless networks:"
network_count=0
echo "$AVAILABLE_NETWORKS" | while read -r network; do
network_count=$((network_count + 1))
echo " $network_count. $network"
done
echo ""
echo -n "Select network number or type SSID manually: "
read -r wifi_selection
# Check if it's a number or manual SSID
if echo "$wifi_selection" | grep -q '^[0-9]\+$'; then
WIFI_SSID=$(echo "$AVAILABLE_NETWORKS" | sed -n "${wifi_selection}p")
else
WIFI_SSID="$wifi_selection"
fi
else
echo ""
echo -n "No networks found. Enter SSID manually: "
read -r WIFI_SSID
fi
if [ -n "$WIFI_SSID" ]; then
print_status "Selected WiFi network: $WIFI_SSID"
# Ask for security type
echo ""
echo "WiFi Security:"
echo " 1. WPA/WPA2 (most common)"
echo " 2. WEP (legacy)"
echo " 3. Open (no password)"
echo -n "Select security type (1-3, default=1): "
read -r security_choice
case "$security_choice" in
2) WIFI_SECURITY="WEP" ;;
3) WIFI_SECURITY="NONE" ;;
*) WIFI_SECURITY="WPA" ;;
esac
# Ask for password if needed
if [ "$WIFI_SECURITY" != "NONE" ]; then
echo -n "Enter WiFi password: "
read -s WIFI_PASSWORD
echo ""
fi
fi
fi
# Ask for IP configuration method
echo ""
echo "IP Configuration:"
echo " 1. DHCP (automatic)"
echo " 2. Static IP (manual)"
echo -n "Select method (1-2, default=1): "
read -r ip_method
case "$ip_method" in
2)
# Manual IP configuration
echo ""
echo -n "Enter IP address (e.g., 192.168.1.100): "
read -r STATIC_IP
echo -n "Enter gateway (e.g., 192.168.1.1): "
read -r STATIC_GATEWAY
echo -n "Enter DNS server (e.g., 8.8.8.8): "
read -r STATIC_DNS
NETWORK_CONFIG="static"
;;
*)
NETWORK_CONFIG="dhcp"
;;
esac
print_status "Network configuration collected for installed system"
print_status " Interface: $SELECTED_INTERFACE ($INTERFACE_TYPE)"
if [ "$INTERFACE_TYPE" = "wireless" ] && [ -n "$WIFI_SSID" ]; then
print_status " WiFi SSID: $WIFI_SSID"
print_status " WiFi Security: $WIFI_SECURITY"
fi
print_status " IP Method: $NETWORK_CONFIG"
# Store configuration for use during system configuration
cat > /tmp/network_config << EOF
SELECTED_INTERFACE="$SELECTED_INTERFACE"
INTERFACE_TYPE="$INTERFACE_TYPE"
WIFI_SSID="$WIFI_SSID"
WIFI_PASSWORD="$WIFI_PASSWORD"
WIFI_SECURITY="$WIFI_SECURITY"
NETWORK_CONFIG="$NETWORK_CONFIG"
STATIC_IP="$STATIC_IP"
STATIC_GATEWAY="$STATIC_GATEWAY"
STATIC_DNS="$STATIC_DNS"
EOF
print_status "Network configuration will be applied to installed system"
}
# Interactive timezone selection using tzselect
select_timezone() {
print_header "Timezone Selection"
echo ""
echo "Please select your timezone for the installed system."
echo "This will determine the correct local time display."
echo ""
# Use tzselect to interactively select timezone
SELECTED_TIMEZONE=$(tzselect)
if [ -n "$SELECTED_TIMEZONE" ] && [ "$SELECTED_TIMEZONE" != "UTC" ]; then
print_status "Selected timezone: $SELECTED_TIMEZONE"
# Store timezone for use during system configuration
echo "$SELECTED_TIMEZONE" > /tmp/selected_timezone
else
print_status "Using default timezone: UTC"
echo "UTC" > /tmp/selected_timezone
fi
}
# User confirmation before destructive operations
confirm_installation() {
print_header "Installation Confirmation Required"
# Show what will happen
print_status "READY TO BEGIN INSTALLATION"
print_status ""
print_status "Installation Summary:"
print_status " Source: Live system (USB/CD: ${USB_DEVICE:-unknown})"
print_status " Target: $TARGET_DISK (will be completely erased)"
# Get disk size for display
local size_bytes=$(lsblk -rbno SIZE "$TARGET_DISK" 2>/dev/null | head -1 | tr -d ' ' || echo 0)
# Ensure size_bytes is a valid number
if ! [[ "$size_bytes" =~ ^[0-9]+$ ]]; then
size_bytes=0
fi
local size_gb=$((size_bytes / 1024 / 1024 / 1024))
print_status " Target size: ${size_gb} GB"
# Show disk model if available
local model=$(lsblk -rno MODEL "$TARGET_DISK" 2>/dev/null || echo "Unknown")
print_status " Target model: $model"
print_status ""
print_warning "WARNING: This will COMPLETELY ERASE all data on $TARGET_DISK!"
print_warning "All existing partitions and data will be permanently destroyed!"
print_status ""
# Use terminal confirmation for reliable operation
# GUI dialogs can hang in some terminal environments
print_status "Using terminal confirmation for reliable operation..."
echo ""
echo -e "${RED}==================== INSTALLATION WARNING ====================${NC}"
echo -e "${RED}This will COMPLETELY ERASE all data on $TARGET_DISK!${NC}"
echo -e "${RED}All existing partitions and data will be permanently destroyed!${NC}"
echo -e "${RED}=============================================================${NC}"
echo ""
echo "Target disk: $TARGET_DISK ($size_gb GB)"
echo "Model: $model"
echo ""
echo -e "${YELLOW}Ready to begin installation?${NC}"
echo -n "Continue with installation? (type 'YES' to confirm): "
read -r confirmation
case "$confirmation" in
YES|yes|Y|y)
return 0
;;
*)
return 1
;;
esac
}
# Partition disk automatically
partition_disk() {
print_header "Disk Partitioning"
if [ ! -b "$TARGET_DISK" ]; then
print_error "Target disk $TARGET_DISK not found!"
return 1
fi
print_status "Partitioning disk $TARGET_DISK..."
# Unmount any existing partitions
umount "${TARGET_DISK}"* 2>/dev/null || true
# Create partition table
parted -s "$TARGET_DISK" mklabel msdos
parted -s "$TARGET_DISK" mkpart primary ext4 1MiB 100%
parted -s "$TARGET_DISK" set 1 boot on
# Wait for kernel to recognize partitions
sleep 2
partprobe "$TARGET_DISK" || true
# Format partition
print_status "Creating ext4 filesystem..."
mkfs.ext4 -F "${TARGET_DISK}1" -L "root"
print_status "Disk partitioning completed"
}
# Mount target
mount_target() {
print_status "Mounting target filesystem..."
mkdir -p "$TARGET_MOUNT"
mount "${TARGET_DISK}1" "$TARGET_MOUNT"
print_status "Target mounted at $TARGET_MOUNT"
}
# Copy live system to target (OFFLINE approach)
copy_live_system() {
print_header "Copying Live System (Offline Installation)"
print_status "This is an OFFLINE installation - copying the live system to disk"
print_status "NO internet connection required!"
# Copy the live system excluding certain directories
print_status "Copying system files..."
rsync -av --progress \
--exclude=/target \
--exclude=/proc \
--exclude=/sys \
--exclude=/dev \
--exclude=/tmp \
--exclude=/run \
--exclude=/mnt \
--exclude=/media \
--exclude=/lost+found \
--exclude=/lib/live \
--exclude=/cdrom \
--exclude=/var/cache/apt/archives/*.deb \
--exclude=/var/log/* \
--exclude=/var/log/auto-installer.log \
/ "$TARGET_MOUNT/"
print_status "Live system copied successfully"
}
# Configure target system
configure_target_system() {
print_header "Configuring Target System"
# Create necessary directories
mkdir -p "$TARGET_MOUNT"/{proc,sys,dev,tmp,run,mnt,media}
# Bind mount for configuration
mount -t proc proc "$TARGET_MOUNT/proc"
mount -t sysfs sysfs "$TARGET_MOUNT/sys"
mount -o bind /dev "$TARGET_MOUNT/dev"
mount -t devpts devpts "$TARGET_MOUNT/dev/pts"
chroot "$TARGET_MOUNT" apt-get -y -qq remove live-config live-config-sysvinit live-boot-doc live-boot-initramfs-tools live-config-doc live-tools user-setup
# Set root password from preseed, live system, or use default
ROOT_PASS=$(get_preseed_value "passwd/root-password")
ROOT_PASS_CRYPTED=$(get_preseed_value "passwd/root-password-crypted")
if [ -n "$ROOT_PASS_CRYPTED" ]; then
print_status "Setting root password from crypted preseed file..."
log "Setting root password from crypted preseed"
# Extract the crypted password (remove "password " prefix)
CRYPTED_PASS=$(echo "$ROOT_PASS_CRYPTED" | sed 's/^password //')
# Ensure we have a clean shadow file first - remove any duplicate root entries
sed -i '/^root:/d' "$TARGET_MOUNT/etc/shadow"
# Add the root entry with the crypted password
echo "root:$CRYPTED_PASS:19453:0:99999:7:::" >> "$TARGET_MOUNT/etc/shadow"
elif [ -n "$ROOT_PASS" ]; then
print_status "Setting root password from preseed file..."
log "Setting root password from preseed: ${ROOT_PASS:0:10}..."
# Set the password using chpasswd
echo "root:$ROOT_PASS" | chroot "$TARGET_MOUNT" chpasswd
else
# Try to copy password from live system
LIVE_ROOT_HASH=$(grep '^root:' /etc/shadow | cut -d: -f2)
if [ -n "$LIVE_ROOT_HASH" ] && [ "$LIVE_ROOT_HASH" != "*" ] && [ "$LIVE_ROOT_HASH" != "!" ] && [ "$LIVE_ROOT_HASH" != "x" ]; then
# Copy the live system's root password hash directly to target shadow file
print_status "Copying live system root password to installed system..."
log "Copying live system root password hash to installed system"
# Get the full root line from live shadow
LIVE_ROOT_LINE=$(grep '^root:' /etc/shadow)
# Ensure clean shadow file and add the live system's root entry
sed -i '/^root:/d' "$TARGET_MOUNT/etc/shadow"
echo "$LIVE_ROOT_LINE" >> "$TARGET_MOUNT/etc/shadow"
if [ $? -eq 0 ]; then
print_status "Live system root password copied successfully"
log "Live system root password hash copied to target system"
else
print_warning "Failed to copy live password, using default"
echo "root:mbetter123" | chroot "$TARGET_MOUNT" chpasswd
fi
else
# Set default password if none available
print_status "No root password available, using default password: mbetter123"
log "Using default root password: mbetter123"
echo "root:mbetter123" | chroot "$TARGET_MOUNT" chpasswd
fi
fi
# Verify password was set and ensure account is properly configured
print_status "Ensuring root account is properly configured..."
# Make sure the root account is unlocked and has proper password aging
chroot "$TARGET_MOUNT" passwd -u root 2>/dev/null || print_warning "Could not unlock root account"
chroot "$TARGET_MOUNT" chage -d 99999 root 2>/dev/null || print_warning "Could not remove password expiration"
chroot "$TARGET_MOUNT" chage -E -1 root 2>/dev/null || print_warning "Could not remove account expiration"
chroot "$TARGET_MOUNT" chage -m 0 root 2>/dev/null || print_warning "Could not set minimum password age"
chroot "$TARGET_MOUNT" chage -M 99999 root 2>/dev/null || print_warning "Could not set maximum password age"
# Verify the shadow entry is correct
ROOT_SHADOW_ENTRY=$(grep '^root:' "$TARGET_MOUNT/etc/shadow")
if [ -n "$ROOT_SHADOW_ENTRY" ]; then
ROOT_PASS_FIELD=$(echo "$ROOT_SHADOW_ENTRY" | cut -d: -f2)
if [ "$ROOT_PASS_FIELD" != "x" ] && [ "$ROOT_PASS_FIELD" != "*" ] && [ "$ROOT_PASS_FIELD" != "!" ]; then
print_status "Root password verification successful"
log "Root password hash: ${ROOT_PASS_FIELD:0:20}..."
else
print_warning "Root password appears to be disabled or invalid"
log "Root password field: $ROOT_PASS_FIELD"
fi
else
print_error "No root entry found in shadow file!"
fi
# Create mbetterclient user with no password for autologin
print_status "Creating mbetterclient user for autologin..."
chroot "$TARGET_MOUNT" useradd -m -s /bin/bash mbetterclient 2>/dev/null || true
chroot "$TARGET_MOUNT" passwd -d mbetterclient 2>/dev/null || true # Remove password
# Configure mbetterclient user to launch startx on login
print_status "Configuring mbetterclient user to launch startx..."
cat > "$TARGET_MOUNT/home/mbetterclient/.bashrc" << 'EOF'
# X session autolaunch configuration
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
# SSH session - don't autolaunch
return
fi
# Check if we're on tty1 (autologin terminal)
if [ "$(tty)" = "/dev/tty1" ]; then
# Set XKB environment variables to fix keyboard issues
export XKB_DEFAULT_LAYOUT="us"
export XKB_DEFAULT_MODEL="pc105"
export XKB_DEFAULT_VARIANT=""
export XKB_DEFAULT_OPTIONS=""
# Launch X session (MBetterClient will be started by .xinitrc)
exec startx
fi
EOF
# Create .xinitrc for proper X session startup
cat > "$TARGET_MOUNT/home/mbetterclient/.xinitrc" << 'EOF'
#!/bin/sh
# X session initialization for mbetterclient
# Set keyboard layout
setxkbmap us
# Launch Openbox window manager
exec openbox-session &
# Give Openbox a moment to start
sleep 1
# Launch MBetterClient in a terminal
xterm -e '/usr/local/bin/MbetterClient_wrapper.sh --ssl --web-host 0.0.0.0'
EOF
chmod +x "$TARGET_MOUNT/home/mbetterclient/.xinitrc"
# Set proper ownership
chroot "$TARGET_MOUNT" chown mbetterclient:mbetterclient /home/mbetterclient/.bashrc
chroot "$TARGET_MOUNT" chown mbetterclient:mbetterclient /home/mbetterclient/.xinitrc
# Set timezone from selection or preseed or default
if [ -f /tmp/selected_timezone ]; then
TIMEZONE=$(cat /tmp/selected_timezone)
print_status "Setting timezone to selected: $TIMEZONE"
else
TIMEZONE=$(get_preseed_value "time/zone" || echo "UTC")
print_status "Setting timezone to $TIMEZONE..."
fi
chroot "$TARGET_MOUNT" ln -sf "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime
# Set hostname
echo "debian" > "$TARGET_MOUNT/etc/hostname"
# Create fstab
ROOT_UUID=$(blkid -s UUID -o value "${TARGET_DISK}1")
cat > "$TARGET_MOUNT/etc/fstab" << EOF
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=$ROOT_UUID / ext4 errors=remount-ro 0 1
proc /proc proc defaults 0 0
EOF
# Configure inittab for mbetterclient autologin
print_status "Configuring inittab for mbetterclient autologin..."
cat > "$TARGET_MOUNT/etc/inittab" << EOF
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $
# The default runlevel.
id:2:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevel 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
# <id>:<runlevels>:<action>:<process>
#
# Autologin for mbetterclient on tty1
1:2345:respawn:/sbin/getty --autologin mbetterclient --noclear 38400 tty1
# Normal getty for other terminals
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6
# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3
EOF
# Configure network for installed system if configuration was collected
if [ -f /tmp/network_config ]; then
print_status "Applying network configuration to installed system..."
# Source the network configuration
. /tmp/network_config
if [ -n "$SELECTED_INTERFACE" ]; then
# Create interfaces configuration
cat > "$TARGET_MOUNT/etc/network/interfaces" << NETEOF
# Network configuration applied during installation
auto lo
iface lo inet loopback
auto $SELECTED_INTERFACE
NETEOF
if [ "$INTERFACE_TYPE" = "wireless" ] && [ -n "$WIFI_SSID" ]; then
# Configure WiFi
echo "iface $SELECTED_INTERFACE inet $NETWORK_CONFIG" >> "$TARGET_MOUNT/etc/network/interfaces"
if [ "$NETWORK_CONFIG" = "static" ] && [ -n "$STATIC_IP" ]; then
echo " address $STATIC_IP" >> "$TARGET_MOUNT/etc/network/interfaces"
echo " gateway $STATIC_GATEWAY" >> "$TARGET_MOUNT/etc/network/interfaces"
fi
# WiFi-specific configuration
echo " wireless-essid $WIFI_SSID" >> "$TARGET_MOUNT/etc/network/interfaces"
if [ "$WIFI_SECURITY" != "NONE" ] && [ -n "$WIFI_PASSWORD" ]; then
if [ "$WIFI_SECURITY" = "WPA" ]; then
echo " wpa-passphrase $WIFI_PASSWORD" >> "$TARGET_MOUNT/etc/network/interfaces"
else # WEP
echo " wireless-key $WIFI_PASSWORD" >> "$TARGET_MOUNT/etc/network/interfaces"
fi
fi
print_status "WiFi configuration applied: $WIFI_SSID ($WIFI_SECURITY)"
else
# Configure Ethernet
echo "iface $SELECTED_INTERFACE inet $NETWORK_CONFIG" >> "$TARGET_MOUNT/etc/network/interfaces"
if [ "$NETWORK_CONFIG" = "static" ] && [ -n "$STATIC_IP" ]; then
echo " address $STATIC_IP" >> "$TARGET_MOUNT/etc/network/interfaces"
echo " gateway $STATIC_GATEWAY" >> "$TARGET_MOUNT/etc/network/interfaces"
fi
print_status "Ethernet configuration applied: $SELECTED_INTERFACE ($NETWORK_CONFIG)"
fi
# Configure DNS if static
if [ "$NETWORK_CONFIG" = "static" ] && [ -n "$STATIC_DNS" ]; then
echo "nameserver $STATIC_DNS" > "$TARGET_MOUNT/etc/resolv.conf"
print_status "DNS server configured: $STATIC_DNS"
fi
print_status "Network configuration written to installed system"
fi
else
print_status "No network configuration to apply - using defaults"
fi
# Generate SSH host keys for installed system
print_status "Generating SSH host keys for installed system..."
# Remove any existing host keys
rm -f "$TARGET_MOUNT/etc/ssh/ssh_host_*_ke"*
# Generate new SSH host keys silently
chroot "$TARGET_MOUNT" ssh-keygen -q -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N "" || true
chroot "$TARGET_MOUNT" ssh-keygen -q -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N "" || true
chroot "$TARGET_MOUNT" ssh-keygen -q -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" || true
# Remove live-specific configurations
rm -f "$TARGET_MOUNT/etc/systemd/system/getty@tty1.service.d/live-config.conf" 2>/dev/null || true
rm -rf "$TARGET_MOUNT/lib/live" 2>/dev/null || true
rm -f "$TARGET_MOUNT/etc/profile.d/zz-live-config_xinit.sh" 2>/dev/null || true
rm -rf "$TARGET_MOUNT/usr/share/initramfs-tools/hooks/live" 2>/dev/null || true
# Set suid on X server and xkbcomp for mbetterclient user to start X
print_status "Setting suid on X server and xkbcomp for user X startup..."
chmod u+s "$TARGET_MOUNT/usr/bin/Xorg" 2>/dev/null || true
chmod u+s "$TARGET_MOUNT/usr/lib/xorg/Xorg" 2>/dev/null || true
chmod u+s "$TARGET_MOUNT/usr/bin/xkbcomp" 2>/dev/null || true
# Configure NTP for clock synchronization
print_status "Configuring NTP for clock synchronization..."
# Enable systemd-timesyncd for automatic time synchronization
chroot "$TARGET_MOUNT" systemctl enable systemd-timesyncd 2>/dev/null || true
# Configure NTP servers
cat > "$TARGET_MOUNT/etc/systemd/timesyncd.conf" << EOF
[Time]
NTP=pool.ntp.org
FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org
EOF
print_status "Target system configuration completed"
}
# Install bootloader
install_bootloader() {
print_header "Installing Bootloader"
# Ensure dhcpcd.conf has IPv6 disabled if it exists
if [ -f "$TARGET_MOUNT/etc/dhcpcd.conf" ]; then
if ! grep -q "noipv6rs" "$TARGET_MOUNT/etc/dhcpcd.conf"; then
echo "noipv6rs" >> "$TARGET_MOUNT/etc/dhcpcd.conf"
fi
if ! grep -q "noipv6" "$TARGET_MOUNT/etc/dhcpcd.conf"; then
echo "noipv6" >> "$TARGET_MOUNT/etc/dhcpcd.conf"
fi
fi
print_status "Installing GRUB to $TARGET_DISK..."
chroot "$TARGET_MOUNT" grub-install "$TARGET_DISK"
chroot "$TARGET_MOUNT" update-grub
print_status "Bootloader installation completed"
}
# Run post-installation setup
run_post_install() {
print_header "Post-Installation Setup"
# Run our post-install script if available
if [ -f /cdrom/setup-installed-system.sh ]; then
print_status "Running post-installation setup..."
bash /cdrom/setup-installed-system.sh "$TARGET_MOUNT"
fi
print_status "Post-installation setup completed"
}
# Cleanup and unmount
cleanup() {
print_header "Installation Complete"
# Remove auto-installer from installed system (cleanup)
print_status "Removing auto-installer from installed system..."
rm -f "$TARGET_MOUNT/usr/local/bin/auto-installer.sh" 2>/dev/null || true
rm -f "$TARGET_MOUNT/var/log/auto-installer.log" 2>/dev/null || true
print_status "Unmounting filesystems..."
umount "$TARGET_MOUNT/dev/pts" 2>/dev/null || true
umount "$TARGET_MOUNT/dev" 2>/dev/null || true
umount "$TARGET_MOUNT/sys" 2>/dev/null || true
umount "$TARGET_MOUNT/proc" 2>/dev/null || true
umount "$TARGET_MOUNT" 2>/dev/null || true
print_header "SUCCESS: Installation completed successfully!"
print_status "The system has been installed to $TARGET_DISK"
print_status "Installed system will:"
print_status " - Autologin as mbetterclient user"
print_status " - Start MbetterClient automatically on tty1"
print_status " - Include VPN configuration if provided"
print_status " - Allow root SSH login with configured password"
print_status ""
print_status "System will reboot in 10 seconds..."
sleep 10
reboot
}
# Main installation process
main() {
print_header "MBetter Offline Automatic Installer"
print_status "Starting OFFLINE automated installation..."
print_status "This installer copies the live system - NO internet required!"
print_status "USB-aware: Works from CD/DVD or USB drive"
log "Starting offline installation process"
# Start visual progress display
start_progress_display
trap cleanup_progress EXIT
# Step 1: Device Detection
update_progress 1 "Detecting USB device and target disk..."
detect_usb_device
detect_target_disk || {
print_error "Cannot proceed without a target disk"
exit 1
}
print_status "Installation will use:"
print_status " Source: Live system (USB/CD: ${USB_DEVICE:-unknown})"
print_status " Target: $TARGET_DISK"
# Step 2: Timezone Selection
update_progress 2 "Selecting timezone..."
select_timezone
# Step 3: Network Configuration
update_progress 3 "Configuring network (optional)..."
configure_network
# Step 4: Find Configuration
update_progress 4 "Loading installation configuration..."
find_preseed
# Step 5: User Confirmation (REQUIRED before destructive operations)
update_progress 5 "Waiting for user confirmation..."
confirm_installation || {
print_error "Installation cancelled by user"
exit 0
}
# Step 6: Disk Partitioning
update_progress 6 "Partitioning target disk..."
partition_disk
mount_target
# Step 7: System Copy (longest step)
update_progress 7 "Copying live system to disk (this may take several minutes)..."
copy_live_system
# Step 8: System Configuration
update_progress 8 "Configuring target system..."
configure_target_system
# Step 9: Bootloader Installation
update_progress 9 "Installing bootloader..."
install_bootloader
# Step 10: Post-Installation Setup
update_progress 10 "Finalizing installation..."
run_post_install
# Complete - terminal notification
print_header "Installation Complete!"
print_status "Installation completed successfully!"
print_status "System will reboot in 10 seconds..."
cleanup
}
# Trap to cleanup on exit
trap 'umount "$TARGET_MOUNT"/{dev/pts,dev,sys,proc,} 2>/dev/null || true' EXIT
# Run main function
main "$@"
......@@ -6,7 +6,9 @@ openssh-server
openvpn
xserver-xorg
xinit
openbox
xfce4
lightdm
lightdm-gtk-greeter
debian-keyring
debian-archive-keyring
......@@ -59,6 +61,10 @@ xserver-xorg-video-intel
xserver-xorg-video-amd
xserver-xorg-video-nouveau
xserver-xorg-video-nvidia
nvidia-modprobe
glx-alternative-nvidia
nvtop
linux-headers-amd64
xserver-xorg-video-radeon
xserver-xorg-video-ati
xserver-xorg-video-vmware
......@@ -104,6 +110,14 @@ gstreamer1.0-pipewire
# Text editors
vim
# Font packages
fonts-noto-color-emoji
fonts-symbola
fonts-twemoji
fonts-recommended
fonts-dejavu
fonts-liberation
# Core utilities (essential command-line tools)
coreutils
......@@ -169,3 +183,8 @@ libdrm2
libgtk-3-dev
libxcb1-dev
libxss1
# Additional packages
python3-pyconify
fontconfig
xfonts-utils
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment