261 lines
7.8 KiB
Bash
261 lines
7.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Nextcloud + Apache + PHP 8.3 (php-legacy) + MariaDB + Valkey on Arch Linux
|
|
# Optimized version with PHP extension loading fixes
|
|
|
|
set -euo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
# =========================
|
|
# EDIT THESE VARIABLES
|
|
# =========================
|
|
DOMAIN="domain.com"
|
|
|
|
NC_DIR="/srv/http/nextcloud"
|
|
NC_DATA_DIR="/srv/nextcloud-data"
|
|
|
|
DB_NAME="nextcloud"
|
|
DB_USER="nextcloud"
|
|
DB_PASS="changeMe"
|
|
|
|
ADMIN_USER="admin"
|
|
ADMIN_PASS="changeMe"
|
|
|
|
TRUST_LOCAL_PROXY="true"
|
|
REAL_IP_HEADER="CF-Connecting-IP"
|
|
|
|
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_BIN="/usr/bin/php-legacy"
|
|
PHP_INI="/etc/php-legacy/php.ini"
|
|
PHP_FPM_WWW_CONF="/etc/php-legacy/php-fpm.d/www.conf"
|
|
PHP_FPM_SERVICE="php-fpm-legacy"
|
|
|
|
KV_SOCK="/run/valkey/valkey.sock"
|
|
|
|
# =========================
|
|
# HELPERS
|
|
# =========================
|
|
log() {
|
|
printf '\n==== %s ====\n' "$1"
|
|
}
|
|
|
|
require_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "Run this script as root."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
check_vars() {
|
|
local vars=(DOMAIN NC_DIR NC_DATA_DIR DB_NAME DB_USER DB_PASS ADMIN_USER ADMIN_PASS)
|
|
for v in "${vars[@]}"; do
|
|
if [[ -z "${!v}" ]]; then
|
|
echo "Variable $v is empty. Edit the script first."
|
|
exit 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
set_ini_value() {
|
|
local key="$1"
|
|
local value="$2"
|
|
if grep -Eq "^[;[:space:]]*${key}[[:space:]]*=" "$PHP_INI"; then
|
|
sed -ri "s|^[;[:space:]]*${key}[[:space:]]*=.*|${key} = ${value}|" "$PHP_INI"
|
|
else
|
|
printf "\n%s = %s\n" "$key" "$value" >> "$PHP_INI"
|
|
fi
|
|
}
|
|
|
|
set_fpm_value() {
|
|
local key="$1"
|
|
local value="$2"
|
|
if grep -Eq "^[;[:space:]]*${key}[[:space:]]*=" "$PHP_FPM_WWW_CONF"; then
|
|
sed -ri "s|^[;[:space:]]*${key}[[:space:]]*=.*|${key} = ${value}|" "$PHP_FPM_WWW_CONF"
|
|
else
|
|
printf "\n%s = %s\n" "$key" "$value" >> "$PHP_FPM_WWW_CONF"
|
|
fi
|
|
}
|
|
|
|
detect_kv_conf() {
|
|
for f in /etc/valkey/valkey.conf /etc/redis/redis.conf /etc/redis.conf; do
|
|
[[ -f "$f" ]] && echo "$f" && return
|
|
done
|
|
}
|
|
|
|
detect_kv_service() {
|
|
for s in valkey redis; do
|
|
[[ -f "/usr/lib/systemd/system/${s}.service" ]] && echo "$s" && return
|
|
done
|
|
}
|
|
|
|
require_root
|
|
check_vars
|
|
|
|
# =========================
|
|
# PACKAGES
|
|
# =========================
|
|
log "Updating system and installing packages"
|
|
pacman -Syu --noconfirm
|
|
pacman -S --needed --noconfirm \
|
|
apache mariadb valkey cronie \
|
|
php-legacy php-legacy-fpm php-legacy-gd php-legacy-intl php-legacy-sodium \
|
|
php-legacy-apcu php-legacy-redis php-legacy-imagick php-legacy-igbinary \
|
|
curl wget tar bzip2 unzip sudo
|
|
|
|
KV_CONF="$(detect_kv_conf)"
|
|
KV_SERVICE="$(detect_kv_service)"
|
|
|
|
# =========================
|
|
# DIRECTORIES
|
|
# =========================
|
|
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
|
|
fi
|
|
|
|
systemctl enable --now mariadb
|
|
|
|
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}';
|
|
GRANT ALL PRIVILEGES ON \`${DB_NAME}\`.* TO '${DB_USER}'@'localhost';
|
|
FLUSH PRIVILEGES;
|
|
SQL
|
|
|
|
# =========================
|
|
# PHP CONFIGURATION (FIXED)
|
|
# =========================
|
|
log "Configuring PHP 8.3 legacy stack"
|
|
|
|
# First, remove existing extension lines to avoid duplicates
|
|
for ext in gd intl mysqli pdo_mysql sodium zip apcu redis igbinary imagick; do
|
|
sed -i "/extension=${ext}\.so/d" "$PHP_INI"
|
|
sed -i "/;extension=${ext}\.so/d" "$PHP_INI"
|
|
done
|
|
|
|
# Force correct loading order at the top of php.ini
|
|
# igbinary MUST load before redis to avoid "undefined symbol" errors
|
|
printf "extension=igbinary.so\nextension=redis.so\nextension=imagick.so\nextension=gd.so\nextension=intl.so\nextension=mysqli.so\nextension=pdo_mysql.so\nextension=sodium.so\nextension=zip.so\nextension=apcu.so\n" | cat - "$PHP_INI" > temp && mv temp "$PHP_INI"
|
|
|
|
set_ini_value "memory_limit" "512M"
|
|
set_ini_value "upload_max_filesize" "1024M"
|
|
set_ini_value "post_max_size" "1024M"
|
|
set_ini_value "output_buffering" "Off"
|
|
|
|
# Opcache
|
|
if ! grep -Eq '^[[:space:]]*zend_extension[[:space:]]*=.*opcache' "$PHP_INI"; then
|
|
sed -i "1i zend_extension=opcache" "$PHP_INI"
|
|
fi
|
|
set_ini_value "opcache.enable" "1"
|
|
set_ini_value "opcache.memory_consumption" "256"
|
|
set_ini_value "opcache.save_comments" "1"
|
|
|
|
# PHP-FPM Socket Setup
|
|
set_fpm_value "user" "http"
|
|
set_fpm_value "group" "http"
|
|
set_fpm_value "listen" "/run/php-fpm-legacy/php-fpm.sock"
|
|
set_fpm_value "listen.owner" "http"
|
|
set_fpm_value "listen.group" "http"
|
|
set_fpm_value "listen.mode" "0660"
|
|
|
|
systemctl enable --now "${PHP_FPM_SERVICE}"
|
|
systemctl restart "${PHP_FPM_SERVICE}"
|
|
|
|
# =========================
|
|
# VALKEY
|
|
# =========================
|
|
log "Configuring Valkey/Redis"
|
|
sed -ri 's|^port .*|port 0|' "${KV_CONF}"
|
|
if grep -Eq '^[[:space:]]*unixsocket[[:space:]]+' "${KV_CONF}"; then
|
|
sed -ri "s|^[[:space:]]*unixsocket[[:space:]]+.*|unixsocket ${KV_SOCK}|" "${KV_CONF}"
|
|
else
|
|
printf "\nunixsocket %s\nunixsocketperm 770\n" "${KV_SOCK}" >> "${KV_CONF}"
|
|
fi
|
|
|
|
usermod -aG valkey http 2>/dev/null || true
|
|
usermod -aG redis http 2>/dev/null || true
|
|
systemctl enable --now "${KV_SERVICE}"
|
|
systemctl restart "${KV_SERVICE}"
|
|
|
|
# =========================
|
|
# APACHE CONFIGURATION (FIXED)
|
|
# =========================
|
|
log "Configuring Apache"
|
|
HTTPD_CONF="/etc/httpd/conf/httpd.conf"
|
|
|
|
# Enable required modules
|
|
for mod in proxy proxy_fcgi rewrite headers remoteip env mime dir setenvif dav dav_fs dav_lock; do
|
|
sed -ri "s|^#(LoadModule ${mod}_module)| \1|" "${HTTPD_CONF}"
|
|
done
|
|
|
|
# CLEANUP: Aggressively disable all default extra configs and wildcard includes
|
|
sed -i 's/^[[:space:]]*Include conf\/extra\/httpd-.*\.conf/#&/' "${HTTPD_CONF}"
|
|
sed -i '/IncludeOptional conf\/extra\/\*\.conf/d' "${HTTPD_CONF}"
|
|
|
|
# Add ONLY the specific Nextcloud include
|
|
if ! grep -Fq "Include conf/extra/nextcloud.conf" "${HTTPD_CONF}"; then
|
|
printf "\nInclude conf/extra/nextcloud.conf\n" >> "${HTTPD_CONF}"
|
|
fi
|
|
|
|
cat > /etc/httpd/conf/extra/nextcloud.conf <<EOF
|
|
<VirtualHost *:80>
|
|
ServerName ${DOMAIN}
|
|
DocumentRoot ${NC_DIR}
|
|
|
|
<Directory ${NC_DIR}>
|
|
Require all granted
|
|
AllowOverride All
|
|
Options FollowSymLinks MultiViews
|
|
|
|
<IfModule mod_dav.c>
|
|
Dav off
|
|
</IfModule>
|
|
</Directory>
|
|
|
|
<FilesMatch "\.php$">
|
|
SetHandler "proxy:unix:/run/php-fpm-legacy/php-fpm.sock|fcgi://localhost/"
|
|
</FilesMatch>
|
|
|
|
ErrorLog "/var/log/httpd/nextcloud_error.log"
|
|
</VirtualHost>
|
|
EOF
|
|
|
|
systemctl enable --now httpd
|
|
systemctl restart httpd
|
|
|
|
# =========================
|
|
# DOWNLOAD & INSTALL
|
|
# =========================
|
|
log "Downloading and Deploying Nextcloud"
|
|
TMPDIR="$(mktemp -d)"
|
|
cd "$TMPDIR"
|
|
curl -fsSLo nextcloud.tar.bz2 "${NC_TARBALL_URL}"
|
|
tar -xjf nextcloud.tar.bz2
|
|
rm -rf "${NC_DIR}"
|
|
mv nextcloud "${NC_DIR}"
|
|
chown -R http:http "${NC_DIR}" "${NC_DATA_DIR}"
|
|
|
|
log "Running Nextcloud installer"
|
|
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" maintenance:install \
|
|
--database "mysql" --database-name "${DB_NAME}" \
|
|
--database-user "${DB_USER}" --database-pass "${DB_PASS}" \
|
|
--admin-user "${ADMIN_USER}" --admin-pass "${ADMIN_PASS}" \
|
|
--data-dir "${NC_DATA_DIR}"
|
|
|
|
# Apply System Configs
|
|
sudo -u http "${PHP_BIN}" "${NC_DIR}/occ" config:system:set trusted_domains 1 --value="${DOMAIN}"
|
|
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 --type=json --value="{\"host\":\"${KV_SOCK}\",\"port\":0,\"timeout\":1.5}"
|
|
|
|
log "Installation Complete!"
|
|
log "Please edit trusted domains at: /srv/http/nextcloud/config/config.php" |