#!/bin/bash # macbook-setup/setup-base.sh # System-Setup: Pakete, Konfiguration, Locale, Services # Verwendung: curl ... | sudo bash -s -- 16 # Kann mehrfach ausgeführt werden (idempotent) FORGEJO="https://git.motocamp.de" SETUP_RAW="$FORGEJO/rene/macbook-setup/raw/branch/main" # ── Farben ────────────────────────────────────────────────────────────── RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' ok() { echo -e "${GREEN}✓ $*${NC}"; } warn() { echo -e "${YELLOW}⚠ $*${NC}"; } fail() { echo -e "${RED}✗ $*${NC}"; } # ── Lokales Repo erkennen (falls nicht via curl|bash) ───────────────── SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" if [[ -n "$SCRIPT_DIR" && -f "$SCRIPT_DIR/mbpfan-13.conf" ]]; then REPO_DIR="$SCRIPT_DIR" ok "Lokales Repo erkannt: $REPO_DIR" else REPO_DIR="" fi # ── Modell ermitteln ───────────────────────────────────────────────────── if [[ "$1" == "13" || "$1" == "16" ]]; then MODEL="$1" else echo "" echo "Welches MacBook Pro?" echo " 13 = MBP 13\" Late 2013" echo " 16 = MBP 16\" Mid 2014 (Intel + AMD Radeon)" read -rp "Modell [13/16]: " MODEL < /dev/tty [[ "$MODEL" != "13" && "$MODEL" != "16" ]] && { fail "Ungültiges Modell: $MODEL"; exit 1; } fi ok "Modell: MacBook Pro $MODEL\"" echo "" echo "════════════════════════════════════════════" echo " setup-base.sh für MBP $MODEL\" startet" echo "════════════════════════════════════════════" # ── 0. sudoers reparieren (macOS-Installer hinterlässt macOS-sudoers) ────── echo -e "\n=== 0/12 sudoers ===" cat > /etc/sudoers <<'SUDOEOF' Defaults env_reset Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" root ALL=(ALL:ALL) ALL %sudo ALL=(ALL:ALL) ALL @includedir /etc/sudoers.d SUDOEOF chmod 440 /etc/sudoers # Passwordless sudo fuer rene echo "rene ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/rene chmod 440 /etc/sudoers.d/rene ok "sudoers: Linux-Standard + NOPASSWD fuer rene" # ── 1. Kritische Hardware-Fixes ZUERST (vor allem anderen) ─────────────── echo -e "\n=== 1/12 Hardware-Fixes ===" # GPU: AMD Radeon blacklisten (MBP 16") if [[ "$MODEL" == "16" ]]; then cat > /etc/modprobe.d/blacklist-radeon.conf < /etc/modprobe.d/blacklist-bcm.conf < /etc/modprobe.d/hid_apple.conf ok "hid_apple: fnmode=2, iso_layout=1" # Tastaturbelegung (deadkeys + lv3:lalt_switch: @=Alt+Q, |=Alt+<) cat > /etc/default/keyboard </dev/null || true ok "Tastatur: mac_deadkeys" # cloud-init deaktivieren (blockiert Boot ohne Cloud-Provider) if command -v cloud-init &>/dev/null; then touch /etc/cloud/cloud-init.disabled ok "cloud-init deaktiviert" fi # initramfs aktualisieren (GPU-Blacklist + hid_apple wirksam machen) update-initramfs -u 2>/dev/null || true ok "initramfs aktualisiert" # ── 2. Sleep/Suspend verhindern während Installation ───────────────────── echo -e "\n=== 2/12 Sleep verhindern ===" systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target 2>/dev/null || true ok "Sleep/Suspend deaktiviert (für Installation)" # ── 3. Eventuelle unterbrochene Installationen reparieren ──────────────── echo -e "\n=== 3/12 dpkg reparieren ===" dpkg --configure -a 2>/dev/null || true apt install -f -y 2>/dev/null || true ok "dpkg/apt repariert" # ── 4. System aktualisieren ────────────────────────────────────────────── echo -e "\n=== 4/12 System aktualisieren ===" apt update && apt upgrade -y || warn "apt upgrade hatte Probleme" ok "System aktuell" # ── 5. Pakete installieren ─────────────────────────────────────────────── echo -e "\n=== 5/12 Pakete installieren ===" apt install -y \ xubuntu-core \ bcmwl-kernel-source \ mbpfan thermald \ lm-sensors xfce4-sensors-plugin \ tlp tlp-rdw \ git curl wget stow \ zsh neovim \ build-essential dkms \ python3 python3-pip python3-venv \ nodejs npm \ wireguard wireguard-tools \ openssh-server \ libheif-examples imagemagick \ pipx \ zoxide \ micro \ flatpak \ keepassxc \ htop btop cmatrix libcurses-perl cowsay fortune-mod fortunes-de \ bat eza fd-find fzf ripgrep tldr ncdu duf xclip \ timeshift \ vlc \ language-pack-de \ wngerman \ bc \ || { fail "apt install fehlgeschlagen"; dpkg --configure -a; apt install -f -y; } ok "Pakete installiert (apt)" # asciiquarium-ng (Python-Port, von git.motocamp.de) if ! command -v asciiquarium &>/dev/null; then if command -v python3 &>/dev/null; then curl -fsSL "https://git.motocamp.de/rene/asciiquarium/raw/branch/main/asciiquarium_ng.py" \ -o /usr/local/bin/asciiquarium \ && chmod +x /usr/local/bin/asciiquarium \ && ok "asciiquarium-ng installiert" \ || warn "asciiquarium-ng uebersprungen" else warn "asciiquarium: python3 nicht gefunden, uebersprungen" fi fi # fastfetch (nicht in apt verfuegbar, .deb von GitHub) if ! command -v fastfetch &>/dev/null; then curl -fsSL https://github.com/fastfetch-cli/fastfetch/releases/latest/download/fastfetch-linux-amd64.deb -o /tmp/fastfetch.deb \ && dpkg -i /tmp/fastfetch.deb \ && ok "fastfetch installiert" \ || warn "fastfetch uebersprungen" rm -f /tmp/fastfetch.deb fi # WezTerm (offizielles apt-Repository) if ! command -v wezterm &>/dev/null; then curl -fsSL https://apt.fury.io/wez/gpg.key \ | gpg --yes --dearmor -o /usr/share/keyrings/wezterm-fury.gpg echo 'deb [signed-by=/usr/share/keyrings/wezterm-fury.gpg] https://apt.fury.io/wez/ * *' \ > /etc/apt/sources.list.d/wezterm.list apt update -qq apt install -y wezterm && ok "WezTerm installiert" || warn "WezTerm uebersprungen" fi if command -v wezterm &>/dev/null; then update-alternatives --install /usr/bin/x-terminal-emulator x-terminal-emulator /usr/bin/wezterm 50 update-alternatives --set x-terminal-emulator /usr/bin/wezterm ok "WezTerm: als x-terminal-emulator gesetzt" fi # FreeCAD + LibreOffice + Bitwarden via Snap snap install freecad 2>/dev/null || warn "FreeCAD Snap uebersprungen" snap install libreoffice 2>/dev/null || warn "LibreOffice Snap uebersprungen" snap install bitwarden 2>/dev/null || warn "Bitwarden Snap uebersprungen" snap install thunderbird 2>/dev/null || warn "Thunderbird Snap uebersprungen" # ── 6. FaceTime HD Webcam (Broadcom 1570, PCIe) ───────────────────────── echo -e "\n=== 6/12 FaceTime HD Webcam ===" if lspci | grep -qi "facetime"; then if ! dkms status 2>/dev/null | grep -q "facetimehd"; then # Firmware extrahieren FTMP=$(mktemp -d) git clone --depth 1 https://github.com/patjak/facetimehd-firmware.git "$FTMP/fw" \ && make -C "$FTMP/fw" \ && make -C "$FTMP/fw" install \ && ok "facetimehd Firmware installiert" \ || warn "facetimehd Firmware fehlgeschlagen" # Treiber bauen und via DKMS installieren git clone --depth 1 https://github.com/patjak/bcwc_pcie.git /usr/src/facetimehd-1.0 \ && cat > /usr/src/facetimehd-1.0/dkms.conf <<'DKMSEOF' PACKAGE_NAME="facetimehd" PACKAGE_VERSION="1.0" MAKE[0]="make -C /lib/modules/${kernelver}/build M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build modules" CLEAN="make -C /lib/modules/${kernelver}/build M=${dkms_tree}/${PACKAGE_NAME}/${PACKAGE_VERSION}/build clean" BUILT_MODULE_NAME[0]="facetimehd" DEST_MODULE_LOCATION[0]="/updates" AUTOINSTALL="yes" DKMSEOF dkms add facetimehd/1.0 \ && dkms build facetimehd/1.0 \ && dkms install facetimehd/1.0 \ && ok "facetimehd DKMS-Treiber installiert" \ || warn "facetimehd DKMS fehlgeschlagen" rm -rf "$FTMP" else ok "facetimehd bereits via DKMS installiert" fi # Modul beim Boot laden echo "facetimehd" > /etc/modules-load.d/facetimehd.conf # Modul jetzt laden (falls nicht in chroot) if [[ "$(stat -c %d:%i /)" == "$(stat -c %d:%i /proc/1/root/.)" ]] 2>/dev/null; then modprobe facetimehd 2>/dev/null || true fi else ok "Keine FaceTime-Kamera erkannt — uebersprungen" fi # ── 7. Brave Browser (apt-Repo) ────────────────────────────────────────── echo -e "\n=== 7/12 Brave Browser ===" if ! command -v brave-browser &>/dev/null; then curl -fsSLo /tmp/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg install -o root -g root -m 644 /tmp/brave-browser-archive-keyring.gpg /usr/share/keyrings/brave-browser-archive-keyring.gpg echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" > /etc/apt/sources.list.d/brave-browser-release.list apt update -qq && apt install -y brave-browser rm -f /tmp/brave-browser-archive-keyring.gpg fi ok "Brave Browser installiert (apt)" # ── 8. Systemkonfigurationen ───────────────────────────────────────────── echo -e "\n=== 8/12 Systemkonfigurationen ===" # mbpfan (modellabhängig) if [[ -n "$REPO_DIR" && -f "$REPO_DIR/mbpfan-${MODEL}.conf" ]]; then cp "$REPO_DIR/mbpfan-${MODEL}.conf" /etc/mbpfan.conf ok "mbpfan.conf (lokal)" else wget -q -O /etc/mbpfan.conf "$SETUP_RAW/mbpfan-${MODEL}.conf" || warn "mbpfan.conf Download fehlgeschlagen" fi # Temperatur-Watch-Skript if [[ -n "$REPO_DIR" && -f "$REPO_DIR/temp-watch.sh" ]]; then cp "$REPO_DIR/temp-watch.sh" /usr/local/bin/temp-watch.sh chmod +x /usr/local/bin/temp-watch.sh ok "temp-watch.sh (lokal)" else wget -q -O /usr/local/bin/temp-watch.sh "$SETUP_RAW/temp-watch.sh" && \ chmod +x /usr/local/bin/temp-watch.sh || warn "temp-watch.sh Download fehlgeschlagen" fi # WireGuard via wg-quick (einfacher als NetworkManager, Config 1:1 verwendbar) WG_CONF="$REPO_DIR/wireguard/m${MODEL}.conf" if [[ -n "$REPO_DIR" && -f "$WG_CONF" ]]; then # Alte NM-WireGuard-Verbindung entfernen falls vorhanden nmcli connection delete wg0 2>/dev/null || true rm -f /etc/NetworkManager/system-connections/wg0.nmconnection # wg-quick Config installieren (Dateiname = Interface-Name) WG_NAME="wg-vps" cp "$WG_CONF" "/etc/wireguard/${WG_NAME}.conf" chmod 600 "/etc/wireguard/${WG_NAME}.conf" # Service aktivieren (startet automatisch beim Boot) systemctl enable wg-quick@${WG_NAME} 2>/dev/null || true # Starten falls nicht in chroot if [[ "$(stat -c %d:%i /)" == "$(stat -c %d:%i /proc/1/root/.)" ]] 2>/dev/null; then wg-quick up "$WG_NAME" 2>/dev/null || true fi ok "WireGuard ${WG_NAME} installiert (wg-quick, DNS: Pihole, autostart)" else warn "WireGuard: keine lokale Config gefunden — manuell einrichten" fi ok "Systemkonfigurationen gesetzt" # ── 8. XFCE-Konfiguration (beide MBPs haben Retina-Displays) ───────────── echo -e "\n=== 8/12 XFCE-Konfiguration (HiDPI) ===" XFCE_XML_DIR="/home/rene/.config/xfce4/xfconf/xfce-perchannel-xml" mkdir -p "$XFCE_XML_DIR" # Compositor deaktivieren + HiDPI-Theme + Titelschrift cat > "$XFCE_XML_DIR/xfwm4.xml" < XFEOF # Display-Skalierung für Retina (2x) cat > "$XFCE_XML_DIR/xsettings.xml" < XSEOF # xfce4-display-settings deaktivieren (Endlosschleife) dpkg-divert --local --rename --divert /usr/bin/xfce4-display-settings.real /usr/bin/xfce4-display-settings 2>/dev/null || true ln -sf /usr/bin/true /usr/bin/xfce4-display-settings # Panel-Konfiguration (Höhe passend zur Schriftgröße) PANEL_XML="$XFCE_XML_DIR/xfce4-panel.xml" if [[ ! -f "$PANEL_XML" ]]; then cat > "$PANEL_XML" < PEOF fi chown -R 1000:1000 /home/rene/.config/xfce4 ok "XFCE: Compositor aus, Retina-Skalierung, Schriften 10pt, Panel 28px, Display-Settings deaktiviert" # ── 10. Netzwerk: NetworkManager statt netplan ──────────────────────────── echo -e "\n=== 10/12 Netzwerk ===" # WLAN-Zugangsdaten aus bestehender netplan-Config übernehmen (falls vorhanden) WLAN_SSID="" WLAN_PASS="" for npfile in /etc/netplan/*.yaml; do if [[ -f "$npfile" ]] && grep -q "wifis:" "$npfile" 2>/dev/null; then WLAN_SSID=$(grep -A5 'wifis:' "$npfile" | grep -oP '"\K[^"]+' | head -1) WLAN_PASS=$(grep -oP 'password:\s*"\K[^"]+' "$npfile" | head -1) [[ -n "$WLAN_SSID" ]] && ok "WLAN-Config gefunden: $WLAN_SSID" fi done cat > /etc/netplan/01-network-manager.yaml </dev/null || true systemctl enable NetworkManager-wait-online.service 2>/dev/null || true ok "NetworkManager als Netzwerk-Renderer" # /etc/hosts: Synology-Dienste im LAN (intern nicht per DNS erreichbar) # dsm -> Synology direkt, git -> Nginx Proxy Manager (macvlan) for entry in "10.47.11.10 dsm.motocamp.de" "10.47.11.23 git.motocamp.de"; do host="${entry##* }" if ! grep -q "$host" /etc/hosts; then echo "$entry" >> /etc/hosts ok "/etc/hosts: $host" else ok "/etc/hosts: $host (bereits vorhanden)" fi done # Auto-Boot beim Anstecken des Netzteils deaktivieren EFI_VAR="/sys/firmware/efi/efivars/auto-boot-7c436110-ab2a-4bbb-a880-fe41995c9f82" if [ -f "$EFI_VAR" ]; then chattr -i "$EFI_VAR" 2>/dev/null printf '\x07\x00\x00\x00\x66\x61\x6c\x73\x65' > "$EFI_VAR" ok "auto-boot deaktiviert (kein Start beim Netzteil-Anstecken)" fi # ── 11. Energieeinstellungen & Lokalisierung ───────────────────────────── echo -e "\n=== 11/12 Energie & Lokalisierung ===" tee /etc/systemd/sleep.conf > /dev/null < /dev/null </dev/null || ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime ok "Energie & Lokalisierung gesetzt" # ── 12. Services aktivieren ────────────────────────────────────────────── echo -e "\n=== 12/12 Services & Shell ===" systemctl enable mbpfan 2>/dev/null || true systemctl enable thermald 2>/dev/null || true systemctl enable tlp 2>/dev/null || true systemctl enable ssh 2>/dev/null || true # Services starten (nur wenn nicht in chroot) if [[ "$(stat -c %d:%i /)" == "$(stat -c %d:%i /proc/1/root/.)" ]] 2>/dev/null; then systemctl start mbpfan 2>/dev/null || true systemctl start thermald 2>/dev/null || true systemctl start ssh 2>/dev/null || true sensors-detect --auto 2>/dev/null || true fi # WLAN-Verbindung als NetworkManager-Profil anlegen (überlebt Reboot) if [[ -n "$WLAN_SSID" && -n "$WLAN_PASS" ]]; then NM_CONN_DIR="/etc/NetworkManager/system-connections" mkdir -p "$NM_CONN_DIR" cat > "$NM_CONN_DIR/$WLAN_SSID.nmconnection" </dev/null || true # Autostart für setup-desktop.sh anlegen (als root, da setup.sh-Eintrag # beim ersten XFCE-Start verloren gehen kann) REPO_DIR_USER="/home/rene/git-projekte/macbook-setup" if [[ -f "$REPO_DIR_USER/setup-desktop.sh" ]]; then AUTOSTART_DIR="/home/rene/.config/autostart" mkdir -p "$AUTOSTART_DIR" cat > "$AUTOSTART_DIR/macbook-setup-desktop.desktop" <&1 | tee /tmp/setup-desktop.log; echo; echo Setup abgeschlossen - Enter zum Schliessen; read' Hidden=false X-GNOME-Autostart-enabled=true ASEOF chown -R 1000:1000 "$AUTOSTART_DIR" ok "Autostart für setup-desktop.sh eingerichtet" fi # Sleep wieder erlauben systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target 2>/dev/null || true ok "Services aktiviert, zsh als Standard-Shell" # ── Zusammenfassung ────────────────────────────────────────────────────── echo "" echo "════════════════════════════════════════════" echo -e " ${GREEN}setup-base.sh abgeschlossen!${NC}" echo "════════════════════════════════════════════" echo "" echo "Nächste Schritte:" echo " 1. sudo reboot" echo " 2. In XFCE einloggen" echo " 3. Terminal öffnen und setup-desktop.sh starten:" echo " curl -fsSL $SETUP_RAW/setup-desktop.sh | bash"