Update arch_install.sh

This commit is contained in:
RomanNum3ral 2026-03-19 12:20:32 +00:00
parent 3e65763673
commit ea41767d53
1 changed files with 87 additions and 143 deletions

View File

@ -1,11 +1,11 @@
#!/usr/bin/env bash
# Nextcloud + Apache + PHP 8.3 (php-legacy) + MariaDB + Valkey/Redis-compatible cache on Arch Linux
# Nextcloud + Apache + PHP 8.3 (php-legacy) + MariaDB + Redis on Arch Linux
# Production-oriented, reverse-proxy aware
#
# Run as root:
# sudo ./arch_install.sh
set -Eeuo pipefail
set -euo pipefail
IFS=$'\n\t'
# =========================
@ -23,41 +23,29 @@ DB_PASS="changeMe"
ADMIN_USER="admin"
ADMIN_PASS="changeMe"
# If you're behind Cloudflare Tunnel or another reverse proxy:
TRUST_LOCAL_PROXY="true"
REAL_IP_HEADER="CF-Connecting-IP" # use X-Forwarded-For if not Cloudflare
# Pin a specific release for production stability
NC_VERSION="33.0.0"
NC_TARBALL_URL="https://download.nextcloud.com/server/releases/nextcloud-${NC_VERSION}.tar.bz2"
NC_SHA512_URL="https://download.nextcloud.com/server/releases/nextcloud-${NC_VERSION}.tar.bz2.sha512"
# PHP legacy paths/services on Arch
PHP_BIN="/usr/bin/php-legacy"
PHP_INI="/etc/php-legacy/php.ini"
PHP_CONF_DIR="/etc/php-legacy/conf.d"
PHP_FPM_WWW_CONF="/etc/php-legacy/php-fpm.d/www.conf"
PHP_FPM_SERVICE="php-fpm-legacy"
# Valkey provides redis on current Arch
REDIS_SERVICE="valkey"
REDIS_CONF="/etc/valkey/valkey.conf"
REDIS_SOCK="/run/valkey/valkey.sock"
REDIS_SOCK="/run/redis/redis.sock"
# =========================
# HELPER FUNCTIONS
# =========================
log() {
printf '\n==== %s ====\n' "$1"
}
die() {
printf '\nERROR: %s\n' "$1" >&2
exit 1
}
require_root() {
[[ $EUID -eq 0 ]] || die "Run this script as root."
if [[ $EUID -ne 0 ]]; then
echo "Run this script as root."
exit 1
fi
}
check_vars() {
@ -68,14 +56,21 @@ check_vars() {
NC_VERSION NC_TARBALL_URL NC_SHA512_URL
)
for v in "${vars[@]}"; do
[[ -n "${!v}" ]] || die "Variable $v is empty. Edit the script first."
if [[ -z "${!v}" ]]; then
echo "Variable $v is empty. Edit the script first."
exit 1
fi
done
}
backup_file() {
local file="$1"
[[ -f "$file" ]] || return 0
cp -a "$file" "${file}.bak.$(date +%Y%m%d-%H%M%S)"
enable_php_ext() {
local ext="$1"
if ! grep -Eq "^[[:space:]]*extension=${ext}\.so" "$PHP_INI"; then
sed -i "/^;extension=${ext}\.so/s/^;//" "$PHP_INI" || true
if ! grep -Eq "^[[:space:]]*extension=${ext}\.so" "$PHP_INI"; then
printf "\nextension=%s.so\n" "$ext" >> "$PHP_INI"
fi
fi
}
set_ini_value() {
@ -98,21 +93,23 @@ set_fpm_value() {
fi
}
write_conf_file() {
local file="$1"
shift
install -d -m 0755 "$PHP_CONF_DIR"
printf '%s\n' "$@" > "$file"
detect_redis_conf() {
if [[ -f /etc/redis/redis.conf ]]; then
echo "/etc/redis/redis.conf"
elif [[ -f /etc/redis.conf ]]; then
echo "/etc/redis.conf"
else
echo ""
fi
}
verify_php_module() {
local module="$1"
"$PHP_BIN" -m 2>/dev/null | grep -qx "$module"
require_cmd() {
command -v "$1" >/dev/null 2>&1 || {
echo "Required command not found: $1"
exit 1
}
}
# =========================
# PRECHECKS
# =========================
require_root
check_vars
@ -120,22 +117,20 @@ log "Updating system and installing packages"
pacman -Syu --noconfirm
pacman -S --needed --noconfirm \
apache mariadb valkey cronie \
apache mariadb redis cronie \
php-legacy php-legacy-fpm php-legacy-gd php-legacy-intl php-legacy-sodium \
php-legacy-apcu php-legacy-igbinary php-legacy-redis php-legacy-imagick \
php-legacy-mysqli php-legacy-pdo php-legacy-zip \
php-legacy-apcu php-legacy-redis php-legacy-imagick \
curl wget tar bzip2 unzip sudo
# =========================
# DIRECTORIES
# =========================
require_cmd mariadb
require_cmd httpd
require_cmd redis-server
require_cmd "${PHP_BIN}"
log "Creating base directories"
install -d -m 0755 /srv/http
install -d -m 0750 "${NC_DATA_DIR}"
# =========================
# MARIADB
# =========================
log "Initializing and configuring MariaDB"
if [[ ! -d /var/lib/mysql/mysql ]]; then
mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
@ -143,14 +138,14 @@ fi
systemctl enable --now mariadb
mysql <<'SQL'
mariadb <<'SQL'
DELETE FROM mysql.user WHERE User='';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db LIKE 'test\_%';
FLUSH PRIVILEGES;
SQL
mysql <<SQL
mariadb <<SQL
CREATE DATABASE IF NOT EXISTS \`${DB_NAME}\`
CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS '${DB_USER}'@'localhost' IDENTIFIED BY '${DB_PASS}';
@ -158,44 +153,23 @@ GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL
# =========================
# PHP
# =========================
log "Configuring PHP 8.3 legacy stack"
for ext in gd intl mysqli pdo_mysql sodium zip apcu redis imagick; do
enable_php_ext "$ext"
done
backup_file "$PHP_INI"
# Ensure extension dir is correct for php-legacy
sed -ri 's|^[;[:space:]]*extension_dir[[:space:]]*=.*|extension_dir = "/usr/lib/php-legacy/modules/"|' "$PHP_INI"
# Remove any manual redis/igbinary/apcu extension lines from php.ini
sed -i \
-e '/^[[:space:]]*extension[[:space:]]*=[[:space:]]*"\{0,1\}igbinary\(.*\)\{0,1\}"\{0,1\}[[:space:]]*$/d' \
-e '/^[[:space:]]*extension[[:space:]]*=[[:space:]]*"\{0,1\}redis\(.*\)\{0,1\}"\{0,1\}[[:space:]]*$/d' \
-e '/^[[:space:]]*extension[[:space:]]*=[[:space:]]*"\{0,1\}apcu\(.*\)\{0,1\}"\{0,1\}[[:space:]]*$/d' \
"$PHP_INI"
# Write active extension files. igbinary must load before redis.
write_conf_file "${PHP_CONF_DIR}/apcu.ini" \
"extension=apcu"
write_conf_file "${PHP_CONF_DIR}/igbinary.ini" \
"extension=igbinary"
write_conf_file "${PHP_CONF_DIR}/redis.ini" \
"extension=redis"
# Nextcloud-oriented php.ini tuning
set_ini_value "memory_limit" "512M"
set_ini_value "upload_max_filesize" "1024M"
set_ini_value "post_max_size" "1024M"
set_ini_value "max_execution_time" "360"
set_ini_value "max_input_time" "360"
set_ini_value "output_buffering" "Off"
set_ini_value "date.timezone" "\"UTC\""
set_ini_value "date.timezone" "UTC"
# OPcache
set_ini_value "zend_extension" "opcache"
# opcache
if ! grep -Eq '^[[:space:]]*zend_extension[[:space:]]*=.*opcache' "$PHP_INI"; then
printf "\nzend_extension=opcache\n" >> "$PHP_INI"
fi
set_ini_value "opcache.enable" "1"
set_ini_value "opcache.enable_cli" "0"
set_ini_value "opcache.interned_strings_buffer" "16"
@ -204,7 +178,6 @@ set_ini_value "opcache.memory_consumption" "256"
set_ini_value "opcache.save_comments" "1"
set_ini_value "opcache.revalidate_freq" "60"
# PHP-FPM pool config for Apache's http user
set_fpm_value "user" "http"
set_fpm_value "group" "http"
set_fpm_value "listen" "/run/php-fpm-legacy/php-fpm.sock"
@ -218,63 +191,57 @@ set_fpm_value "pm.min_spare_servers" "4"
set_fpm_value "pm.max_spare_servers" "16"
systemctl enable --now "${PHP_FPM_SERVICE}"
log "Verifying PHP modules before install"
verify_php_module "igbinary" || die "PHP igbinary module is not loaded."
verify_php_module "redis" || die "PHP redis module is not loaded."
verify_php_module "apcu" || die "PHP apcu module is not loaded."
systemctl restart "${PHP_FPM_SERVICE}"
# =========================
# VALKEY / REDIS-COMPAT
# =========================
log "Configuring Valkey (Redis-compatible cache)"
backup_file "$REDIS_CONF"
# Listen only on localhost TCP for safety and compatibility
if grep -Eq '^[#[:space:]]*bind[[:space:]]+' "$REDIS_CONF"; then
sed -ri 's|^[#[:space:]]*bind[[:space:]]+.*|bind 127.0.0.1 ::1|' "$REDIS_CONF"
else
printf '\nbind 127.0.0.1 ::1\n' >> "$REDIS_CONF"
log "Configuring Redis"
REDIS_CONF="$(detect_redis_conf)"
if [[ -z "${REDIS_CONF}" ]]; then
echo "Could not find Redis config file."
echo "Looked for /etc/redis/redis.conf and /etc/redis.conf"
exit 1
fi
if grep -Eq '^[#[:space:]]*port[[:space:]]+' "$REDIS_CONF"; then
sed -ri 's|^[#[:space:]]*port[[:space:]]+.*|port 6379|' "$REDIS_CONF"
echo "Using Redis config: ${REDIS_CONF}"
sed -ri 's|^port .*|port 0|' "${REDIS_CONF}"
if grep -Eq '^[[:space:]]*unixsocket[[:space:]]+' "${REDIS_CONF}"; then
sed -ri "s|^[[:space:]]*unixsocket[[:space:]]+.*|unixsocket ${REDIS_SOCK}|" "${REDIS_CONF}"
else
printf '\nport 6379\n' >> "$REDIS_CONF"
printf "\nunixsocket %s\n" "${REDIS_SOCK}" >> "${REDIS_CONF}"
fi
# Disable socket use to avoid path/group drift between redis/valkey packaging changes
sed -i '/^[#[:space:]]*unixsocket[[:space:]]\+/d' "$REDIS_CONF"
sed -i '/^[#[:space:]]*unixsocketperm[[:space:]]\+/d' "$REDIS_CONF"
if grep -Eq '^[[:space:]]*unixsocketperm[[:space:]]+' "${REDIS_CONF}"; then
sed -ri 's|^[[:space:]]*unixsocketperm[[:space:]]+.*|unixsocketperm 770|' "${REDIS_CONF}"
else
printf "unixsocketperm 770\n" >> "${REDIS_CONF}"
fi
systemctl enable --now "${REDIS_SERVICE}"
systemctl restart "${REDIS_SERVICE}"
usermod -aG redis http || true
systemctl enable --now redis
systemctl restart redis
# =========================
# APACHE
# =========================
log "Configuring Apache"
HTTPD_CONF="/etc/httpd/conf/httpd.conf"
sed -ri 's|^#(LoadModule proxy_module modules/mod_proxy.so)|\1|' "$HTTPD_CONF"
sed -ri 's|^#(LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so)|\1|' "$HTTPD_CONF"
sed -ri 's|^#(LoadModule rewrite_module modules/mod_rewrite.so)|\1|' "$HTTPD_CONF"
sed -ri 's|^#(LoadModule headers_module modules/mod_headers.so)|\1|' "$HTTPD_CONF"
sed -ri 's|^#(LoadModule remoteip_module modules/mod_remoteip.so)|\1|' "$HTTPD_CONF" || true
sed -ri 's|^#(LoadModule env_module modules/mod_env.so)|\1|' "$HTTPD_CONF" || true
sed -ri 's|^#(LoadModule mime_module modules/mod_mime.so)|\1|' "$HTTPD_CONF" || true
sed -ri 's|^#(LoadModule setenvif_module modules/mod_setenvif.so)|\1|' "$HTTPD_CONF" || true
sed -ri 's|^#(LoadModule proxy_module modules/mod_proxy.so)|\1|' "${HTTPD_CONF}"
sed -ri 's|^#(LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so)|\1|' "${HTTPD_CONF}"
sed -ri 's|^#(LoadModule rewrite_module modules/mod_rewrite.so)|\1|' "${HTTPD_CONF}"
sed -ri 's|^#(LoadModule headers_module modules/mod_headers.so)|\1|' "${HTTPD_CONF}"
sed -ri 's|^#(LoadModule remoteip_module modules/mod_remoteip.so)|\1|' "${HTTPD_CONF}" || true
sed -ri 's|^#(LoadModule env_module modules/mod_env.so)|\1|' "${HTTPD_CONF}" || true
sed -ri 's|^#(LoadModule mime_module modules/mod_mime.so)|\1|' "${HTTPD_CONF}" || true
sed -ri 's|^#(LoadModule dir_module modules/mod_dir.so)|\1|' "${HTTPD_CONF}" || true
sed -ri 's|^#(LoadModule setenvif_module modules/mod_setenvif.so)|\1|' "${HTTPD_CONF}" || true
if ! grep -Eq '^[[:space:]]*ServerName[[:space:]]+' "$HTTPD_CONF"; then
printf "\nServerName %s\n" "$DOMAIN" >> "$HTTPD_CONF"
if ! grep -Eq '^[[:space:]]*ServerName[[:space:]]+' "${HTTPD_CONF}"; then
printf "\nServerName %s\n" "${DOMAIN}" >> "${HTTPD_CONF}"
fi
install -d -m 0755 /etc/httpd/conf/extra
if ! grep -Fq "IncludeOptional conf/extra/*.conf" "$HTTPD_CONF"; then
printf "\nIncludeOptional conf/extra/*.conf\n" >> "$HTTPD_CONF"
if ! grep -Fq "IncludeOptional conf/extra/*.conf" "${HTTPD_CONF}"; then
printf "\nIncludeOptional conf/extra/*.conf\n" >> "${HTTPD_CONF}"
fi
cat > /etc/httpd/conf/extra/remoteip-nextcloud.conf <<EOF
@ -301,13 +268,11 @@ cat > /etc/httpd/conf/extra/nextcloud.conf <<EOF
Header always set Referrer-Policy "no-referrer"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Robots-Tag "noindex, nofollow"
Header always set X-Permitted-Cross-Domain-Policies "none"
Header always set X-Download-Options "noopen"
Header always set X-XSS-Protection "1; mode=block"
</IfModule>
</Directory>
DirectoryIndex index.php index.html
LimitRequestBody 0
SetEnv HOME ${NC_DIR}
SetEnv HTTP_HOME ${NC_DIR}
@ -325,9 +290,6 @@ httpd -t
systemctl enable --now httpd
systemctl reload httpd
# =========================
# DOWNLOAD NEXTCLOUD
# =========================
log "Downloading official Nextcloud release"
TMPDIR="$(mktemp -d)"
trap 'rm -rf "$TMPDIR"' EXIT
@ -335,9 +297,7 @@ trap 'rm -rf "$TMPDIR"' EXIT
cd "$TMPDIR"
curl -fsSLo nextcloud.tar.bz2 "${NC_TARBALL_URL}"
curl -fsSLo nextcloud.tar.bz2.sha512 "${NC_SHA512_URL}"
sha512sum -c nextcloud.tar.bz2.sha512
tar -xjf nextcloud.tar.bz2
log "Deploying Nextcloud"
@ -352,9 +312,6 @@ chmod 0750 "${NC_DATA_DIR}"
install -d -o http -g http -m 0750 "${NC_DIR}/config"
install -d -o http -g http -m 0750 "${NC_DIR}/apps"
# =========================
# INSTALL NEXTCLOUD
# =========================
log "Running Nextcloud installer"
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" maintenance:install \
--database "mysql" \
@ -365,9 +322,6 @@ sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" maintenance:install \
--admin-pass "${ADMIN_PASS}" \
--data-dir "${NC_DATA_DIR}"
# =========================
# REVERSE PROXY / HTTPS
# =========================
log "Applying reverse-proxy and HTTPS settings"
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set overwrite.cli.url --value="https://${DOMAIN}"
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set overwriteprotocol --value="https"
@ -385,19 +339,11 @@ fi
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set trusted_domains 1 --value="${DOMAIN}"
# =========================
# CACHE / LOCKING
# =========================
log "Configuring APCu and Redis"
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set memcache.local --value='\OC\Memcache\APCu'
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set memcache.locking --value='\OC\Memcache\Redis'
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set redis host --value="127.0.0.1"
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set redis port --type=integer --value=6379
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set redis timeout --type=float --value=1.5
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set redis --type=json --value="{\"host\":\"${REDIS_SOCK}\",\"port\":0,\"timeout\":1.5}"
# =========================
# CRON
# =========================
log "Configuring cron background jobs"
systemctl enable --now cronie
@ -408,9 +354,6 @@ EOF
chmod 0644 /etc/cron.d/nextcloud
systemctl restart cronie
# =========================
# FINALIZE
# =========================
log "Finalizing"
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" maintenance:update:htaccess || true
@ -424,11 +367,12 @@ echo " Web root: ${NC_DIR}"
echo " Data dir: ${NC_DATA_DIR}"
echo " PHP: ${PHP_BIN}"
echo " FPM svc: ${PHP_FPM_SERVICE}"
echo " Redis conf: ${REDIS_CONF}"
echo "-----------------------------------------------------------------"
echo " Services enabled:"
echo " - httpd"
echo " - ${PHP_FPM_SERVICE}"
echo " - mariadb"
echo " - ${REDIS_SERVICE}"
echo " - redis"
echo " - cronie"
echo "================================================================="