Add arch_install.sh
This commit is contained in:
parent
d914d2b2f4
commit
8cda037dc8
|
|
@ -0,0 +1,355 @@
|
|||
#!/usr/bin/env bash
|
||||
# Nextcloud + Apache + PHP-FPM on Arch Linux
|
||||
# Production-oriented, reverse-proxy aware
|
||||
#
|
||||
# What this does:
|
||||
# - Installs Apache, MariaDB, Redis, PHP-FPM and needed PHP extensions
|
||||
# - Downloads official Nextcloud release tarball
|
||||
# - Configures Apache -> PHP-FPM via mod_proxy_fcgi
|
||||
# - Configures MariaDB database/user
|
||||
# - Configures Redis over unix socket for locking/cache
|
||||
# - Installs Nextcloud non-interactively
|
||||
# - Sets trusted proxy / HTTPS overwrite options
|
||||
# - Adds cron job for background jobs
|
||||
#
|
||||
# Assumptions:
|
||||
# - Arch server with systemd
|
||||
# - You want Apache listening on :80 and TLS terminated upstream
|
||||
# - Apache runs as user/group "http" on Arch
|
||||
#
|
||||
# Run as root.
|
||||
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# ====== EDIT ME ======
|
||||
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"
|
||||
|
||||
# If behind Cloudflare Tunnel or another local reverse proxy:
|
||||
TRUST_LOCAL_PROXY="true"
|
||||
REAL_IP_HEADER="CF-Connecting-IP" # or X-Forwarded-For if not Cloudflare
|
||||
|
||||
# Download URL: pin a version for production stability
|
||||
# Check https://download.nextcloud.com/server/releases/
|
||||
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"
|
||||
|
||||
# ====== Sanity checks ======
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "Run this script as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for v in DOMAIN NC_DIR NC_DATA_DIR DB_NAME DB_USER DB_PASS ADMIN_USER ADMIN_PASS NC_VERSION; do
|
||||
if [[ -z "${!v}" ]]; then
|
||||
echo "Variable $v is empty. Edit the script first."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# ====== Packages ======
|
||||
pacman -Syu --noconfirm
|
||||
|
||||
pacman -S --needed --noconfirm \
|
||||
apache mariadb redis cronie \
|
||||
php php-fpm php-gd php-intl php-sodium php-zip php-apcu php-redis php-imagick \
|
||||
curl wget tar bzip2 unzip sudo
|
||||
|
||||
# ====== Directories ======
|
||||
install -d -m 0755 /srv/http
|
||||
install -d -m 0750 "${NC_DATA_DIR}"
|
||||
|
||||
# ====== MariaDB ======
|
||||
if [[ ! -d /var/lib/mysql/mysql ]]; then
|
||||
mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
|
||||
fi
|
||||
|
||||
systemctl enable --now mariadb
|
||||
|
||||
# Headless mysql_secure_installation-ish cleanup
|
||||
mysql <<'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
|
||||
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 ======
|
||||
# Enable required/recommended extensions in /etc/php/php.ini
|
||||
PHP_INI="/etc/php/php.ini"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# Core modules shipped as split packages / shared modules on Arch
|
||||
for ext in gd intl mysqli pdo_mysql sodium zip; do
|
||||
enable_php_ext "$ext"
|
||||
done
|
||||
|
||||
# Recommended php.ini tuning for Nextcloud
|
||||
sed -ri 's/^;?\s*memory_limit\s*=.*/memory_limit = 512M/' "$PHP_INI"
|
||||
sed -ri 's/^;?\s*upload_max_filesize\s*=.*/upload_max_filesize = 1024M/' "$PHP_INI"
|
||||
sed -ri 's/^;?\s*post_max_size\s*=.*/post_max_size = 1024M/' "$PHP_INI"
|
||||
sed -ri 's/^;?\s*max_execution_time\s*=.*/max_execution_time = 360/' "$PHP_INI"
|
||||
sed -ri 's/^;?\s*output_buffering\s*=.*/output_buffering = Off/' "$PHP_INI"
|
||||
sed -ri 's/^;?\s*date\.timezone\s*=.*/date.timezone = UTC/' "$PHP_INI"
|
||||
|
||||
# OPcache tuning
|
||||
if grep -Eq '^\s*;?\s*opcache.enable\s*=' "$PHP_INI"; then
|
||||
sed -ri 's/^;?\s*opcache.enable\s*=.*/opcache.enable=1/' "$PHP_INI"
|
||||
else
|
||||
printf "\nopcache.enable=1\n" >> "$PHP_INI"
|
||||
fi
|
||||
|
||||
if grep -Eq '^\s*;?\s*opcache.enable_cli\s*=' "$PHP_INI"; then
|
||||
sed -ri 's/^;?\s*opcache.enable_cli\s*=.*/opcache.enable_cli=0/' "$PHP_INI"
|
||||
else
|
||||
printf "opcache.enable_cli=0\n" >> "$PHP_INI"
|
||||
fi
|
||||
|
||||
if grep -Eq '^\s*;?\s*opcache.interned_strings_buffer\s*=' "$PHP_INI"; then
|
||||
sed -ri 's/^;?\s*opcache.interned_strings_buffer\s*=.*/opcache.interned_strings_buffer=16/' "$PHP_INI"
|
||||
else
|
||||
printf "opcache.interned_strings_buffer=16\n" >> "$PHP_INI"
|
||||
fi
|
||||
|
||||
if grep -Eq '^\s*;?\s*opcache.max_accelerated_files\s*=' "$PHP_INI"; then
|
||||
sed -ri 's/^;?\s*opcache.max_accelerated_files\s*=.*/opcache.max_accelerated_files=10000/' "$PHP_INI"
|
||||
else
|
||||
printf "opcache.max_accelerated_files=10000\n" >> "$PHP_INI"
|
||||
fi
|
||||
|
||||
if grep -Eq '^\s*;?\s*opcache.memory_consumption\s*=' "$PHP_INI"; then
|
||||
sed -ri 's/^;?\s*opcache.memory_consumption\s*=.*/opcache.memory_consumption=256/' "$PHP_INI"
|
||||
else
|
||||
printf "opcache.memory_consumption=256\n" >> "$PHP_INI"
|
||||
fi
|
||||
|
||||
if grep -Eq '^\s*;?\s*opcache.save_comments\s*=' "$PHP_INI"; then
|
||||
sed -ri 's/^;?\s*opcache.save_comments\s*=.*/opcache.save_comments=1/' "$PHP_INI"
|
||||
else
|
||||
printf "opcache.save_comments=1\n" >> "$PHP_INI"
|
||||
fi
|
||||
|
||||
# php-fpm: use unix socket and Apache-compatible user/group
|
||||
PHP_FPM_WWW_CONF="/etc/php/php-fpm.d/www.conf"
|
||||
sed -ri 's|^user\s*=.*|user = http|' "$PHP_FPM_WWW_CONF"
|
||||
sed -ri 's|^group\s*=.*|group = http|' "$PHP_FPM_WWW_CONF"
|
||||
sed -ri 's|^listen\s*=.*|listen = /run/php-fpm/php-fpm.sock|' "$PHP_FPM_WWW_CONF"
|
||||
sed -ri 's|^;?listen.owner\s*=.*|listen.owner = http|' "$PHP_FPM_WWW_CONF"
|
||||
sed -ri 's|^;?listen.group\s*=.*|listen.group = http|' "$PHP_FPM_WWW_CONF"
|
||||
sed -ri 's|^;?listen.mode\s*=.*|listen.mode = 0660|' "$PHP_FPM_WWW_CONF"
|
||||
sed -ri 's|^;?env\[HOSTNAME\].*|env[HOSTNAME] = $HOSTNAME|' "$PHP_FPM_WWW_CONF" || true
|
||||
sed -ri 's|^;?env\[PATH\].*|env[PATH] = /usr/local/bin:/usr/bin:/bin|' "$PHP_FPM_WWW_CONF" || true
|
||||
sed -ri 's|^;?env\[TMP\].*|env[TMP] = /tmp|' "$PHP_FPM_WWW_CONF" || true
|
||||
sed -ri 's|^;?env\[TMPDIR\].*|env[TMPDIR] = /tmp|' "$PHP_FPM_WWW_CONF" || true
|
||||
sed -ri 's|^;?env\[TEMP\].*|env[TEMP] = /tmp|' "$PHP_FPM_WWW_CONF" || true
|
||||
|
||||
systemctl enable --now php-fpm
|
||||
systemctl restart php-fpm
|
||||
|
||||
# ====== Redis ======
|
||||
REDIS_CONF="/etc/redis/redis.conf"
|
||||
|
||||
sed -ri 's|^port .*|port 0|' "$REDIS_CONF"
|
||||
if grep -Eq '^\s*unixsocket\s+' "$REDIS_CONF"; then
|
||||
sed -ri 's|^unixsocket\s+.*|unixsocket /run/redis/redis.sock|' "$REDIS_CONF"
|
||||
else
|
||||
printf "\nunixsocket /run/redis/redis.sock\n" >> "$REDIS_CONF"
|
||||
fi
|
||||
|
||||
if grep -Eq '^\s*unixsocketperm\s+' "$REDIS_CONF"; then
|
||||
sed -ri 's|^unixsocketperm\s+.*|unixsocketperm 770|' "$REDIS_CONF"
|
||||
else
|
||||
printf "unixsocketperm 770\n" >> "$REDIS_CONF"
|
||||
fi
|
||||
|
||||
install -d -m 0755 /run/redis
|
||||
usermod -aG redis http || true
|
||||
|
||||
systemctl enable --now redis
|
||||
systemctl restart redis
|
||||
|
||||
# ====== Apache ======
|
||||
HTTPD_CONF="/etc/httpd/conf/httpd.conf"
|
||||
|
||||
# Enable required modules if commented
|
||||
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 ssl_module modules/mod_ssl.so)|\1|' "$HTTPD_CONF" || true
|
||||
sed -ri 's|^#(LoadModule socache_shmcb_module modules/mod_socache_shmcb.so)|\1|' "$HTTPD_CONF" || true
|
||||
|
||||
# ServerName to silence warning
|
||||
if ! grep -Eq '^\s*ServerName\s+' "$HTTPD_CONF"; then
|
||||
printf "\nServerName %s\n" "$DOMAIN" >> "$HTTPD_CONF"
|
||||
fi
|
||||
|
||||
# Include extra vhosts dir
|
||||
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"
|
||||
fi
|
||||
|
||||
# RemoteIP config for local tunnel/proxy
|
||||
cat > /etc/httpd/conf/extra/remoteip-nextcloud.conf <<EOF
|
||||
RemoteIPHeader ${REAL_IP_HEADER}
|
||||
RemoteIPTrustedProxy 127.0.0.1
|
||||
RemoteIPTrustedProxy ::1
|
||||
EOF
|
||||
|
||||
# Nextcloud vhost
|
||||
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>
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
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-XSS-Protection "1; mode=block"
|
||||
</IfModule>
|
||||
</Directory>
|
||||
|
||||
LimitRequestBody 0
|
||||
SetEnv HOME ${NC_DIR}
|
||||
SetEnv HTTP_HOME ${NC_DIR}
|
||||
|
||||
<FilesMatch "\.php$">
|
||||
SetHandler "proxy:unix:/run/php-fpm/php-fpm.sock|fcgi://localhost/"
|
||||
</FilesMatch>
|
||||
|
||||
ErrorLog "/var/log/httpd/nextcloud_error.log"
|
||||
CustomLog "/var/log/httpd/nextcloud_access.log" combined
|
||||
</VirtualHost>
|
||||
EOF
|
||||
|
||||
systemctl enable --now httpd
|
||||
httpd -t
|
||||
systemctl reload httpd
|
||||
|
||||
# ====== Download Nextcloud (official upstream tarball) ======
|
||||
TMPDIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMPDIR"' EXIT
|
||||
|
||||
cd "$TMPDIR"
|
||||
curl -fsSLo nextcloud.tar.bz2 "${NC_TARBALL_URL}"
|
||||
curl -fsSLo nextcloud.tar.bz2.sha512 "${NC_SHA512_URL}"
|
||||
|
||||
# Verify sha512
|
||||
sha512sum -c nextcloud.tar.bz2.sha512
|
||||
|
||||
tar -xjf nextcloud.tar.bz2
|
||||
|
||||
# Deploy
|
||||
rm -rf "${NC_DIR}"
|
||||
mv nextcloud "${NC_DIR}"
|
||||
|
||||
# Ownership & permissions
|
||||
chown -R http:http "${NC_DIR}" "${NC_DATA_DIR}"
|
||||
find "${NC_DIR}" -type d -exec chmod 0750 {} \;
|
||||
find "${NC_DIR}" -type f -exec chmod 0640 {} \;
|
||||
chmod 0750 "${NC_DATA_DIR}"
|
||||
|
||||
# Required writable app dirs
|
||||
install -d -o http -g http -m 0750 "${NC_DIR}/data"
|
||||
install -d -o http -g http -m 0750 "${NC_DIR}/config"
|
||||
install -d -o http -g http -m 0750 "${NC_DIR}/apps"
|
||||
|
||||
# ====== Install Nextcloud ======
|
||||
sudo -u http php "${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}"
|
||||
|
||||
# ====== Reverse proxy / HTTPS awareness ======
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set overwrite.cli.url --value="https://${DOMAIN}"
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set overwriteprotocol --value="https"
|
||||
|
||||
if [[ "${TRUST_LOCAL_PROXY}" == "true" ]]; then
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set trusted_proxies 0 --value="127.0.0.1"
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set trusted_proxies 1 --value="::1"
|
||||
|
||||
if [[ "${REAL_IP_HEADER}" == "CF-Connecting-IP" ]]; then
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set forwarded_for_headers 0 --value="HTTP_CF_CONNECTING_IP"
|
||||
else
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set forwarded_for_headers 0 --value="HTTP_X_FORWARDED_FOR"
|
||||
fi
|
||||
fi
|
||||
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set trusted_domains 1 --value="${DOMAIN}"
|
||||
|
||||
# ====== Memory cache / locking ======
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set memcache.local --value='\OC\Memcache\APCu'
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set memcache.locking --value='\OC\Memcache\Redis'
|
||||
sudo -u http php "${NC_DIR}/occ" config:system:set redis --type=json --value='{"host":"\/run\/redis\/redis.sock","port":0,"timeout":1.5}'
|
||||
|
||||
# ====== Background jobs (recommended) ======
|
||||
systemctl enable --now cronie
|
||||
|
||||
cat > /etc/cron.d/nextcloud <<EOF
|
||||
*/5 * * * * http php -f ${NC_DIR}/cron.php
|
||||
EOF
|
||||
chmod 0644 /etc/cron.d/nextcloud
|
||||
systemctl restart cronie
|
||||
|
||||
# ====== Final maintenance/settings ======
|
||||
sudo -u http php "${NC_DIR}/occ" maintenance:update:htaccess || true
|
||||
|
||||
echo "================================================================="
|
||||
echo " Nextcloud installed"
|
||||
echo " URL: https://${DOMAIN}"
|
||||
echo " Admin user: ${ADMIN_USER}"
|
||||
echo " Admin pass: ${ADMIN_PASS}"
|
||||
echo " Web root: ${NC_DIR}"
|
||||
echo " Data dir: ${NC_DATA_DIR}"
|
||||
echo "-----------------------------------------------------------------"
|
||||
echo " Services:"
|
||||
echo " - httpd"
|
||||
echo " - php-fpm"
|
||||
echo " - mariadb"
|
||||
echo " - redis"
|
||||
echo " - cronie"
|
||||
echo "================================================================="
|
||||
Loading…
Reference in New Issue