Created
September 2, 2025 15:12
-
-
Save eusonlito/4e547c1616b9982e55fbf7fa76112e47 to your computer and use it in GitHub Desktop.
Setup script (Ubuntu 22.04 + Apache + PHP 8.4 + MySQL)
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 -Eeuo pipefail | |
### CONFIG ################################################################# | |
PHP_VERSION="8.4" | |
SYSTEM_LOCALE="en_US.UTF-8" # final user is English-speaking | |
TIMEZONE="${TIMEZONE:-UTC}" # override by exporting TIMEZONE before running | |
USE_PHP_FPM="1" # 1 = Apache + PHP-FPM (recommended), 0 = mod_php | |
MYSQL_APT_DEB="mysql-apt-config_0.8.34-1_all.deb" # latest as of 2025-09-02 | |
########################################################################### | |
echo "==> Checking for root privileges..." | |
if [ "$EUID" -ne 0 ]; then | |
echo "This script must be run as root." | |
exit 1 | |
fi | |
trap 'echo "[ERROR] Failed at line $LINENO"; exit 1' ERR | |
export DEBIAN_FRONTEND=noninteractive | |
export NEEDRESTART_MODE=a # auto-restart services when safe | |
echo "==> Refreshing APT & installing base tools..." | |
apt-get update -o Dpkg::Use-Pty=0 | |
apt-get install -y -o Dpkg::Use-Pty=0 \ | |
software-properties-common ca-certificates lsb-release apt-transport-https \ | |
locales tzdata curl wget gnupg debconf-utils | |
echo "==> Configuring locale and timezone..." | |
if ! grep -q "^${SYSTEM_LOCALE}" /etc/locale.gen; then | |
echo "${SYSTEM_LOCALE} UTF-8" >> /etc/locale.gen | |
fi | |
locale-gen "${SYSTEM_LOCALE}" | |
update-locale LANG="${SYSTEM_LOCALE}" LC_ALL="${SYSTEM_LOCALE}" | |
if [ -n "${TIMEZONE}" ]; then | |
timedatectl set-timezone "${TIMEZONE}" || true | |
fi | |
echo "==> Adding Ondřej Surý PPAs (Apache & PHP)..." | |
add-apt-repository -y ppa:ondrej/apache2 | |
add-apt-repository -y ppa:ondrej/php | |
apt-get update -o Dpkg::Use-Pty=0 | |
apt-get -y -o Dpkg::Use-Pty=0 full-upgrade | |
############################################################################ | |
# Oracle MySQL APT repo (fixed version, no parsing) # | |
############################################################################ | |
echo "==> Adding Oracle MySQL APT repo (non-interactive, fixed version)..." | |
wget -qO /tmp/mysql-apt-config.deb "https://dev.mysql.com/get/${MYSQL_APT_DEB}" | |
# Preseed to select the LTS server line when available (avoids TUI) | |
echo "mysql-apt-config mysql-apt-config/select-server select mysql-8.4-lts" | debconf-set-selections || true | |
echo "mysql-apt-config mysql-apt-config/enable-repo select Enabled" | debconf-set-selections || true | |
dpkg -i /tmp/mysql-apt-config.deb || apt-get -f install -y -o Dpkg::Use-Pty=0 | |
apt-get update -o Dpkg::Use-Pty=0 | |
############################################################################ | |
# Apache + PHP # | |
############################################################################ | |
echo "==> Installing Apache and PHP ${PHP_VERSION}..." | |
if [ "${USE_PHP_FPM}" = "1" ]; then | |
apt-get install -y -o Dpkg::Use-Pty=0 \ | |
apache2 \ | |
"php${PHP_VERSION}-fpm" "php${PHP_VERSION}-cli" "php${PHP_VERSION}-common" \ | |
"php${PHP_VERSION}-opcache" "php${PHP_VERSION}-readline" | |
else | |
apt-get install -y -o Dpkg::Use-Pty=0 \ | |
apache2 \ | |
"libapache2-mod-php${PHP_VERSION}" "php${PHP_VERSION}-cli" "php${PHP_VERSION}-common" \ | |
"php${PHP_VERSION}-opcache" "php${PHP_VERSION}-readline" | |
fi | |
echo "==> Installing PHP extensions (full set from your original script)..." | |
apt-get install -y -o Dpkg::Use-Pty=0 \ | |
"php${PHP_VERSION}" \ | |
"php${PHP_VERSION}-bcmath" \ | |
"php${PHP_VERSION}-bz2" \ | |
"php${PHP_VERSION}-cli" \ | |
"php${PHP_VERSION}-common" \ | |
"php${PHP_VERSION}-curl" \ | |
"php${PHP_VERSION}-gd" \ | |
"php${PHP_VERSION}-fpm" \ | |
"php${PHP_VERSION}-imagick" \ | |
"php${PHP_VERSION}-intl" \ | |
"php${PHP_VERSION}-memcached" \ | |
"php${PHP_VERSION}-mbstring" \ | |
"php${PHP_VERSION}-mysql" \ | |
"php${PHP_VERSION}-opcache" \ | |
"php${PHP_VERSION}-pgsql" \ | |
"php${PHP_VERSION}-readline" \ | |
"php${PHP_VERSION}-redis" \ | |
"php${PHP_VERSION}-tidy" \ | |
"php${PHP_VERSION}-xml" \ | |
"php${PHP_VERSION}-soap" \ | |
"php${PHP_VERSION}-xsl" \ | |
"php${PHP_VERSION}-zip" \ | |
php-apcu \ | |
php-imagick \ | |
php-memcached \ | |
php-redis \ | |
memcached \ | |
redis-server | |
echo "==> Enabling PHP modules when present..." | |
if [ -f "/etc/php/${PHP_VERSION}/mods-available/sockets.ini" ]; then | |
phpenmod -v "${PHP_VERSION}" sockets | |
fi | |
if [ -f "/etc/php/${PHP_VERSION}/mods-available/apcu.ini" ]; then | |
phpenmod -v "${PHP_VERSION}" apcu | |
fi | |
if [ -f "/etc/php/${PHP_VERSION}/mods-available/redis.ini" ]; then | |
phpenmod -v "${PHP_VERSION}" redis | |
fi | |
echo "==> Apache hardening and modules..." | |
if [ -f /etc/apache2/conf-enabled/security.conf ]; then | |
SEC="/etc/apache2/conf-enabled/security.conf" | |
else | |
if [ -f /etc/apache2/conf.d/security ]; then | |
SEC="/etc/apache2/conf.d/security" | |
else | |
SEC="" | |
fi | |
fi | |
if [ -n "${SEC}" ]; then | |
sed -i -E \ | |
-e 's/^\s*#?\s*ServerTokens\s+.*/ServerTokens Prod/' \ | |
-e 's/^\s*#?\s*ServerSignature\s+.*/ServerSignature Off/' \ | |
-e 's/^\s*#?\s*TraceEnable\s+.*/TraceEnable Off/' \ | |
"${SEC}" | |
fi | |
a2enmod deflate expires filter headers include proxy_fcgi rewrite setenvif socache_shmcb ssl | |
if [ "${USE_PHP_FPM}" = "1" ]; then | |
if a2query -m mpm_prefork >/dev/null 2>&1; then | |
a2dismod mpm_prefork | |
fi | |
a2enmod mpm_event | |
a2enconf "php${PHP_VERSION}-fpm" | |
else | |
if a2query -m mpm_event >/dev/null 2>&1; then | |
a2dismod mpm_event | |
fi | |
a2enmod "php${PHP_VERSION}" mpm_prefork | |
fi | |
echo "==> Applying PHP tuned settings (mods-available/99-custom.ini)..." | |
CUSTOM_MOD="/etc/php/${PHP_VERSION}/mods-available/99-custom.ini" | |
cat > "${CUSTOM_MOD}" <<EOF | |
; Custom PHP settings | |
expose_php = Off | |
max_execution_time = 180 | |
max_input_time = 240 | |
memory_limit = 512M | |
upload_max_filesize = 200M | |
post_max_size = 2G | |
max_input_vars = 10000 | |
date.timezone = ${TIMEZONE} | |
opcache.enable=1 | |
opcache.memory_consumption=128 | |
opcache.interned_strings_buffer=16 | |
opcache.max_accelerated_files=10000 | |
opcache.validate_timestamps=0 | |
EOF | |
phpenmod -v "${PHP_VERSION}" -s ALL 99-custom | |
############################################################################ | |
# MySQL server # | |
############################################################################ | |
echo "==> Installing MySQL Server..." | |
apt-get install -y -o Dpkg::Use-Pty=0 mysql-server | |
echo "==> Securing MySQL root account..." | |
MYSQL_ROOT_PASSWORD="$(openssl rand -base64 24 | tr -d '\n' | cut -c1-32)" | |
mysql --protocol=socket -uroot <<SQL || true | |
ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY '${MYSQL_ROOT_PASSWORD}'; | |
FLUSH PRIVILEGES; | |
SQL | |
cat > /root/.my.cnf <<EOF | |
[client] | |
user=root | |
password=${MYSQL_ROOT_PASSWORD} | |
EOF | |
chmod 600 /root/.my.cnf | |
############################################################################ | |
# Final checks and restarts # | |
############################################################################ | |
echo "==> Verifying key directories..." | |
if [ ! -d /etc/apache2 ]; then | |
echo "Apache installation missing." | |
exit 1 | |
fi | |
if [ ! -d "/etc/php/${PHP_VERSION}" ]; then | |
echo "PHP ${PHP_VERSION} installation missing." | |
exit 1 | |
fi | |
if [ ! -d /etc/mysql ]; then | |
echo "MySQL installation missing." | |
exit 1 | |
fi | |
echo "==> Enabling & restarting services..." | |
systemctl enable --now apache2 | |
if [ "${USE_PHP_FPM}" = "1" ]; then | |
systemctl enable --now "php${PHP_VERSION}-fpm" | |
fi | |
systemctl restart apache2 | |
echo | |
echo "Finished." | |
echo "MySQL root password saved at /root/.my.cnf (chmod 600)." | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment