Last active
March 14, 2026 12:38
-
-
Save pbrilius/c522110b588927071a166dc255aa3d5e to your computer and use it in GitHub Desktop.
Kubuntu!
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 | |
| # ============================================================================= | |
| # Kubuntu 24.04 LTS — Post-Install Script | |
| # Target: CHUWI GemiBook Plus / Intel N150 (Twin Lake) / 16GB LPDDR5 | |
| # Author: prototype.in | |
| # ============================================================================= | |
| set -euo pipefail | |
| LOGFILE="$HOME/postinstall.log" | |
| exec > >(tee -a "$LOGFILE") 2>&1 | |
| GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m' | |
| info() { echo -e "${GREEN}[INFO]${NC} $*"; } | |
| warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } | |
| section() { echo -e "\n${GREEN}═══ $* ═══${NC}\n"; } | |
| [[ $EUID -eq 0 ]] && { warn "Run as regular user (not root). Script uses sudo internally."; exit 1; } | |
| # ============================================================================= | |
| # 1. BASE SYSTEM UPDATE | |
| # ============================================================================= | |
| section "1. System update" | |
| sudo apt update && sudo apt full-upgrade -y | |
| sudo apt install -y \ | |
| curl wget git unzip zip build-essential software-properties-common \ | |
| apt-transport-https ca-certificates gnupg lsb-release \ | |
| htop btop nvtop powertop neofetch inxi \ | |
| xclip xdotool \ | |
| zsh zsh-autosuggestions zsh-syntax-highlighting | |
| # ============================================================================= | |
| # 2. INTEL N150 — CPU MICROCODE + THERMAL THROTTLE GUARD | |
| # ============================================================================= | |
| section "2. Intel microcode + thermal" | |
| sudo apt install -y intel-microcode thermald cpufrequtils i7z | |
| # N150 = efficiency-only (no P-cores) — max TDP 6W design | |
| # thermald keeps Tj under control without bios tuning | |
| sudo systemctl enable --now thermald | |
| # powercap: optional hard TDP limit via RAPL (uncomment if overheating) | |
| # sudo apt install -y linux-tools-common linux-tools-generic | |
| # echo 6000000 | sudo tee /sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw | |
| # cpufreq: conservative governor for sustained workloads (vs performance spikes) | |
| sudo tee /etc/systemd/system/cpufreq-governor.service > /dev/null <<'EOF' | |
| [Unit] | |
| Description=Set CPU governor to ondemand | |
| After=multi-user.target | |
| [Service] | |
| Type=oneshot | |
| ExecStart=/bin/sh -c 'for cpu in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo ondemand > $cpu; done' | |
| RemainAfterExit=yes | |
| [Install] | |
| WantedBy=multi-user.target | |
| EOF | |
| sudo systemctl enable cpufreq-governor.service | |
| # ============================================================================= | |
| # 3. INTEL GRAPHICS — N150 UHD (24EU) | |
| # ============================================================================= | |
| section "3. Intel UHD drivers + media" | |
| sudo apt install -y \ | |
| intel-gpu-tools vainfo \ | |
| libva-intel-driver intel-media-va-driver-non-free \ | |
| i965-va-driver-shaders \ | |
| mesa-vulkan-drivers mesa-utils \ | |
| ffmpeg gstreamer1.0-vaapi | |
| # VA-API env (add to ~/.profile) | |
| grep -qxF 'export LIBVA_DRIVER_NAME=iHD' "$HOME/.profile" || \ | |
| echo 'export LIBVA_DRIVER_NAME=iHD' >> "$HOME/.profile" | |
| # ============================================================================= | |
| # 4. TLP — POWER MANAGEMENT (N150 battery life tuning) | |
| # ============================================================================= | |
| section "4. TLP power management" | |
| sudo apt install -y tlp tlp-rdw | |
| sudo systemctl enable tlp | |
| sudo tee /etc/tlp.d/01-n150-gemibook.conf > /dev/null <<'EOF' | |
| # N150 GemiBook Plus TLP profile — prototype.in | |
| CPU_SCALING_GOVERNOR_ON_AC=performance | |
| CPU_SCALING_GOVERNOR_ON_BAT=powersave | |
| CPU_ENERGY_PERF_POLICY_ON_AC=balance_performance | |
| CPU_ENERGY_PERF_POLICY_ON_BAT=power | |
| CPU_BOOST_ON_AC=1 | |
| CPU_BOOST_ON_BAT=0 | |
| NMI_WATCHDOG=0 | |
| WIFI_PWR_ON_BAT=off | |
| RUNTIME_PM_ON_AC=on | |
| RUNTIME_PM_ON_BAT=auto | |
| # GemiBook has 38Wh — protect cells | |
| START_CHARGE_THRESH_BAT0=40 | |
| STOP_CHARGE_THRESH_BAT0=80 | |
| EOF | |
| sudo tlp start | |
| # ============================================================================= | |
| # 5. KDE PLASMA — WAYLAND + X11 TWEAKS | |
| # ============================================================================= | |
| section "5. KDE Plasma Wayland optimization" | |
| sudo apt install -y \ | |
| plasma-workspace-wayland \ | |
| kwin-wayland-backend-drm \ | |
| xwayland \ | |
| qt6-wayland \ | |
| libqt6waylandclient6 | |
| # KDE env vars for Wayland | |
| KENV="$HOME/.config/plasma-workspace/env/wayland.sh" | |
| mkdir -p "$(dirname $KENV)" | |
| cat > "$KENV" <<'EOF' | |
| export QT_QPA_PLATFORM=wayland | |
| export GDK_BACKEND=wayland | |
| export CLUTTER_BACKEND=wayland | |
| export SDL_VIDEODRIVER=wayland | |
| export MOZ_ENABLE_WAYLAND=1 | |
| export ELECTRON_OZONE_PLATFORM_HINT=auto | |
| EOF | |
| chmod +x "$KENV" | |
| # KDE performance: disable compositing animations on battery | |
| kwriteconfig5 --file kwinrc --group Compositing --key AnimationSpeed 2 | |
| kwriteconfig5 --file kwinrc --group Compositing --key Enabled true | |
| # ============================================================================= | |
| # 6. LAMP STACK — Apache + MariaDB + PHP 8.3 (native, no Docker) | |
| # ============================================================================= | |
| section "6. LAMP stack" | |
| # --- Apache 2.4 --- | |
| sudo apt install -y apache2 | |
| sudo systemctl enable apache2 | |
| # Enable useful modules | |
| for mod in rewrite headers deflate expires ssl http2 proxy_fcgi; do | |
| sudo a2enmod $mod | |
| done | |
| # vhost.d drop-in directory (prototype.in style) | |
| sudo mkdir -p /etc/apache2/vhost.d | |
| sudo tee /etc/apache2/conf-available/vhost-dropin.conf > /dev/null <<'EOF' | |
| IncludeOptional /etc/apache2/vhost.d/*.conf | |
| EOF | |
| sudo a2enconf vhost-dropin | |
| # Apache MPM event tuned for 16GB / N150 | |
| sudo tee /etc/apache2/conf-available/mpm-n150.conf > /dev/null <<'EOF' | |
| <IfModule mpm_event_module> | |
| StartServers 2 | |
| MinSpareThreads 25 | |
| MaxSpareThreads 75 | |
| ThreadLimit 64 | |
| ThreadsPerChild 25 | |
| MaxRequestWorkers 100 | |
| MaxConnectionsPerChild 1000 | |
| </IfModule> | |
| EOF | |
| sudo a2enconf mpm-n150 | |
| sudo a2enmod mpm_event 2>/dev/null || true | |
| # --- MariaDB --- | |
| sudo apt install -y mariadb-server mariadb-client | |
| sudo systemctl enable mariadb | |
| sudo mysql_secure_installation <<'MYSQL' || true | |
| y | |
| n | |
| y | |
| y | |
| y | |
| MYSQL | |
| # InnoDB tuning for 16GB RAM | |
| sudo tee /etc/mysql/mariadb.conf.d/99-n150.cnf > /dev/null <<'EOF' | |
| [mysqld] | |
| innodb_buffer_pool_size = 2G | |
| innodb_buffer_pool_instances = 2 | |
| innodb_log_file_size = 256M | |
| innodb_flush_log_at_trx_commit = 2 | |
| innodb_flush_method = O_DIRECT | |
| query_cache_type = 0 | |
| tmp_table_size = 64M | |
| max_heap_table_size = 64M | |
| max_connections = 100 | |
| thread_cache_size = 8 | |
| slow_query_log = 1 | |
| slow_query_log_file = /var/log/mysql/slow.log | |
| long_query_time = 1 | |
| EOF | |
| sudo systemctl restart mariadb | |
| # --- PHP 8.3 + PHP-FPM --- | |
| sudo add-apt-repository -y ppa:ondrej/php | |
| sudo apt update | |
| sudo apt install -y \ | |
| php8.3 php8.3-fpm php8.3-cli \ | |
| php8.3-mysql php8.3-xml php8.3-curl php8.3-mbstring \ | |
| php8.3-zip php8.3-gd php8.3-intl php8.3-bcmath \ | |
| php8.3-soap php8.3-redis php8.3-xdebug php8.3-opcache \ | |
| php8.3-imagick php8.3-sqlite3 \ | |
| composer | |
| # PHP-FPM pool tuning for N150 (4 cores, 6W TDP — be conservative) | |
| PHP_POOL=/etc/php/8.3/fpm/pool.d/www.conf | |
| sudo sed -i 's/^pm = .*/pm = dynamic/' $PHP_POOL | |
| sudo sed -i 's/^pm.max_children = .*/pm.max_children = 20/' $PHP_POOL | |
| sudo sed -i 's/^pm.start_servers = .*/pm.start_servers = 4/' $PHP_POOL | |
| sudo sed -i 's/^pm.min_spare_servers = .*/pm.min_spare_servers = 2/' $PHP_POOL | |
| sudo sed -i 's/^pm.max_spare_servers = .*/pm.max_spare_servers = 8/' $PHP_POOL | |
| # OPcache for dev | |
| sudo tee /etc/php/8.3/mods-available/opcache-dev.ini > /dev/null <<'EOF' | |
| opcache.enable=1 | |
| opcache.memory_consumption=256 | |
| opcache.interned_strings_buffer=16 | |
| opcache.max_accelerated_files=20000 | |
| opcache.revalidate_freq=1 | |
| opcache.validate_timestamps=1 | |
| opcache.jit=1255 | |
| opcache.jit_buffer_size=128M | |
| EOF | |
| sudo phpenmod opcache-dev | |
| # Xdebug 3 config | |
| sudo tee /etc/php/8.3/mods-available/xdebug.ini > /dev/null <<'EOF' | |
| zend_extension=xdebug.so | |
| xdebug.mode=debug,coverage | |
| xdebug.client_host=127.0.0.1 | |
| xdebug.client_port=9003 | |
| xdebug.idekey=PHPSTORM | |
| xdebug.discover_client_host=0 | |
| xdebug.start_with_request=yes | |
| EOF | |
| sudo systemctl enable php8.3-fpm | |
| sudo systemctl restart php8.3-fpm | |
| # Wire Apache → PHP-FPM | |
| sudo tee /etc/apache2/conf-available/php83-fpm.conf > /dev/null <<'EOF' | |
| <FilesMatch \.php$> | |
| SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost" | |
| </FilesMatch> | |
| EOF | |
| sudo a2enconf php83-fpm | |
| sudo systemctl restart apache2 | |
| # ============================================================================= | |
| # 7. NODE / BUN | |
| # ============================================================================= | |
| section "7. Node.js LTS + Bun" | |
| # Node via nvm (user-space) | |
| curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash | |
| export NVM_DIR="$HOME/.nvm" | |
| # shellcheck source=/dev/null | |
| [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" | |
| nvm install --lts | |
| nvm use --lts | |
| nvm alias default node | |
| # Bun | |
| curl -fsSL https://bun.sh/install | bash | |
| # Global npm tools | |
| npm install -g \ | |
| pm2 \ | |
| @anthropic-ai/sdk \ | |
| typescript \ | |
| tsx \ | |
| prettier | |
| # ============================================================================= | |
| # 8. GIT + SSH AGENT | |
| # ============================================================================= | |
| section "8. Git + SSH" | |
| sudo apt install -y git openssh-server openssh-client | |
| sudo systemctl enable ssh | |
| git config --global core.autocrlf input | |
| git config --global pull.rebase true | |
| git config --global init.defaultBranch main | |
| # SSH agent autostart via KDE | |
| mkdir -p "$HOME/.config/autostart-scripts" | |
| tee "$HOME/.config/autostart-scripts/ssh-agent.sh" > /dev/null <<'EOF' | |
| #!/bin/bash | |
| [ -z "$SSH_AUTH_SOCK" ] && eval "$(ssh-agent -s)" && ssh-add | |
| EOF | |
| chmod +x "$HOME/.config/autostart-scripts/ssh-agent.sh" | |
| # SSH hardening | |
| sudo tee /etc/ssh/sshd_config.d/99-hardened.conf > /dev/null <<'EOF' | |
| PasswordAuthentication yes | |
| PubkeyAuthentication yes | |
| PermitRootLogin no | |
| MaxAuthTries 3 | |
| ClientAliveInterval 120 | |
| ClientAliveCountMax 2 | |
| EOF | |
| sudo systemctl restart ssh | |
| # ============================================================================= | |
| # 9. NETWORK — WiFi 6 + RJ45 OPTIMIZATION | |
| # ============================================================================= | |
| section "9. Network" | |
| sudo apt install -y net-tools nmap iperf3 ethtool | |
| # WiFi power save OFF (N150 iwlwifi) | |
| sudo tee /etc/NetworkManager/conf.d/wifi-powersave-off.conf > /dev/null <<'EOF' | |
| [connection] | |
| wifi.powersave = 2 | |
| EOF | |
| # iwlwifi options — disable 11n/buggy firmware quirks if needed | |
| sudo tee /etc/modprobe.d/iwlwifi.conf > /dev/null <<'EOF' | |
| options iwlwifi power_save=0 | |
| options iwlwifi uapsd_disable=1 | |
| EOF | |
| sudo nmcli general reload | |
| # ============================================================================= | |
| # 10. DOCKER (optional secondary — native stack primary) | |
| # ============================================================================= | |
| section "10. Docker (secondary)" | |
| curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ | |
| sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg | |
| echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker.gpg] \ | |
| https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \ | |
| sudo tee /etc/apt/sources.list.d/docker.list | |
| sudo apt update | |
| sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin | |
| sudo usermod -aG docker "$USER" | |
| sudo systemctl enable docker | |
| # ============================================================================= | |
| # 11. DEV TOOLS | |
| # ============================================================================= | |
| section "11. Dev tools" | |
| # phpMyAdmin | |
| sudo apt install -y phpmyadmin 2>/dev/null || true | |
| # Redis | |
| sudo apt install -y redis-server | |
| sudo systemctl enable redis-server | |
| # Mailpit (local SMTP trap, replaces MailHog) | |
| curl -fsSL https://raw.githubusercontent.com/axllent/mailpit/develop/install.sh | bash || true | |
| # Adminer (lightweight phpMyAdmin alt) | |
| sudo mkdir -p /var/www/html/adminer | |
| sudo wget -qO /var/www/html/adminer/index.php \ | |
| https://www.adminer.org/latest.php || true | |
| # Symfony CLI | |
| curl -1sLf 'https://dl.cloudsmith.io/public/symfony/stable/setup.deb.sh' | sudo -E bash | |
| sudo apt install -y symfony-cli || true | |
| # ============================================================================= | |
| # 12. ZSH + OH-MY-ZSH | |
| # ============================================================================= | |
| section "12. ZSH" | |
| if [ ! -d "$HOME/.oh-my-zsh" ]; then | |
| RUNZSH=no CHSH=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" | |
| fi | |
| # Plugins | |
| ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}" | |
| [ -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ] || \ | |
| git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions" | |
| [ -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ] || \ | |
| git clone https://github.com/zsh-users/zsh-syntax-highlighting "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" | |
| sed -i 's/plugins=(git)/plugins=(git composer symfony2 docker npm zsh-autosuggestions zsh-syntax-highlighting)/' "$HOME/.zshrc" | |
| # Aliases | |
| cat >> "$HOME/.zshrc" <<'ALIASES' | |
| # prototype.in aliases | |
| alias art='php artisan' | |
| alias sf='symfony console' | |
| alias comp='composer' | |
| alias phpu='./vendor/bin/phpunit' | |
| alias phpstan='./vendor/bin/phpstan' | |
| alias fpm='sudo systemctl restart php8.3-fpm && sudo systemctl restart apache2' | |
| alias slog='sudo tail -f /var/log/apache2/error.log' | |
| alias mlog='sudo tail -f /var/log/mysql/error.log' | |
| alias dlog='sudo journalctl -u docker -f' | |
| alias ports='ss -tulnp' | |
| alias htop='btop' | |
| ALIASES | |
| chsh -s "$(which zsh)" "$USER" | |
| # ============================================================================= | |
| # 13. FLATPAK + APP ESSENTIALS | |
| # ============================================================================= | |
| section "13. Apps" | |
| sudo apt install -y flatpak | |
| flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | |
| # PHPStorm (JetBrains Toolbox is the recommended install path) | |
| info "JetBrains Toolbox — install manually from https://www.jetbrains.com/toolbox-app/" | |
| info "Or via Flatpak:" | |
| info " flatpak install flathub com.jetbrains.PhpStorm" | |
| # Firefox Wayland-native | |
| sudo snap remove firefox 2>/dev/null || true | |
| flatpak install -y flathub org.mozilla.firefox || true | |
| # ============================================================================= | |
| # 14. SWAP / ZRAM (N150 thrash guard) | |
| # ============================================================================= | |
| section "14. ZRAM (swap compression)" | |
| sudo apt install -y zram-config || sudo apt install -y zram-tools | |
| sudo tee /etc/default/zramswap > /dev/null <<'EOF' | |
| ALGO=zstd | |
| PERCENT=25 | |
| EOF | |
| sudo systemctl restart zramswap 2>/dev/null || sudo systemctl restart zram-config 2>/dev/null || true | |
| # Swappiness — lower for SSD/ZRAM combo | |
| echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf | |
| sudo sysctl -p /etc/sysctl.d/99-swappiness.conf | |
| # ============================================================================= | |
| # 15. FIREWALL | |
| # ============================================================================= | |
| section "15. UFW" | |
| sudo apt install -y ufw | |
| sudo ufw default deny incoming | |
| sudo ufw default allow outgoing | |
| sudo ufw allow ssh | |
| sudo ufw allow 80/tcp | |
| sudo ufw allow 443/tcp | |
| sudo ufw allow 8025/tcp # Mailpit | |
| sudo ufw --force enable | |
| # ============================================================================= | |
| # DONE | |
| # ============================================================================= | |
| section "✅ Done!" | |
| info "Log: $LOGFILE" | |
| info "" | |
| info "Next steps:" | |
| info " 1. Reboot → Wayland session" | |
| info " 2. sudo tlp-stat -b (check battery thresholds)" | |
| info " 3. vainfo (verify VA-API / Intel UHD)" | |
| info " 4. Install PHPStorm via JetBrains Toolbox" | |
| info " 5. Add vhost configs to /etc/apache2/vhost.d/" | |
| info " 6. Clone github.com/pbrilius/orm → composer install" | |
| info "" | |
| warn "Docker group active after next login (newgrp docker)" | |
| warn "Xdebug enabled by default — disable for prod: phpdismod xdebug" | |
| neofetch |
Comments are disabled for this gist.