diff --git a/arch_install.sh b/arch_install.sh index 1678421..e09cf3f 100644 --- a/arch_install.sh +++ b/arch_install.sh @@ -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 <> "$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 < /etc/httpd/conf/extra/nextcloud.conf < + 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 "=================================================================" \ No newline at end of file