#!/usr/bin/env bash # Nextcloud + Apache + PHP 8.3-FPM on Ubuntu 24.04 # - Applies requested php.ini edits # - Apache with proxy_fcgi (no mod_php) # - Downloads Nextcloud to /var/www/nextcloud # - MariaDB DB + user # - Redis for file locking (optional but recommended) set -euo pipefail IFS=$'\n\t' export DEBIAN_FRONTEND=noninteractive # ====== EDIT ME ====== DOMAIN="cloud.example.com" NC_DIR="/var/www/nextcloud" NC_DATA_DIR="/var/ncdata" DB_NAME="nextcloud" DB_USER="nextclouduser" DB_PASS="ChangeMe_DB_Secret!" ADMIN_USER="ncadmin" ADMIN_PASS="ChangeMe_Admin_Secret!" PHP_VER="8.3" PHP_FPM_SOCK="/run/php/php${PHP_VER}-fpm.sock" # ====== Base packages ====== apt-get update apt-get -y upgrade apt-get install -y software-properties-common apt-transport-https ca-certificates \ lsb-release unzip wget curl gnupg2 tar sudo # ====== MariaDB ====== apt-get install -y mariadb-server mariadb-client systemctl enable --now mariadb # Headless mysql_secure_installation equivalent mysql --protocol=socket <<'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 --protocol=socket </dev/null 2>&1 || true a2enmod mpm_event >/dev/null 2>&1 || true # Nextcloud vhost cat >/etc/apache2/sites-available/nextcloud.conf < ServerName ${DOMAIN} DocumentRoot ${NC_DIR} Require all granted AllowOverride All Options FollowSymLinks MultiViews Dav off # Large uploads LimitRequestBody 0 SetEnv HOME ${NC_DIR} SetEnv HTTP_HOME ${NC_DIR} # Security headers (tune later, add HSTS after TLS) 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" # PHP-FPM socket SetHandler "proxy:unix:${PHP_FPM_SOCK}|fcgi://localhost/" ErrorLog \${APACHE_LOG_DIR}/nextcloud_error.log CustomLog \${APACHE_LOG_DIR}/nextcloud_access.log combined EOF a2ensite nextcloud.conf a2dissite 000-default.conf >/dev/null 2>&1 || true systemctl enable --now apache2 apache2ctl configtest systemctl reload apache2 # ====== Download Nextcloud (latest) ====== mkdir -p /tmp/nc cd /tmp/nc wget -q https://download.nextcloud.com/server/releases/latest.zip unzip -q -o latest.zip # Deploy to /var/www/nextcloud rm -rf "${NC_DIR}" mv nextcloud "${NC_DIR}" # Ownership & permissions install -d -m 0750 "${NC_DATA_DIR}" chown -R www-data:www-data "${NC_DIR}" "${NC_DATA_DIR}" chmod -R 750 "${NC_DIR}" # ====== Bootstrap Nextcloud (non-interactive) ====== sudo -u www-data 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}" # Trusted domain + base URL (HTTP for now—add TLS later) sudo -u www-data php "${NC_DIR}/occ" config:system:set trusted_domains 1 --value="${DOMAIN}" sudo -u www-data php "${NC_DIR}/occ" config:system:set overwrite.cli.url --value="http://${DOMAIN}" # Caching: APCu local + Redis locking (unix socket) sudo -u www-data php "${NC_DIR}/occ" config:system:set memcache.local --value='\OC\Memcache\APCu' sudo -u www-data php "${NC_DIR}/occ" config:system:set memcache.locking --value='\OC\Memcache\Redis' sudo -u www-data php "${NC_DIR}/occ" config:system:set redis --type=json --value='{"host":"\/var\/run\/redis\/redis-server.sock","port":0,"timeout":1.5}' # ====== Cron every 5 minutes ====== cat >/etc/cron.d/nextcloud < Overview, run security & setup warnings." echo " 3) Consider MariaDB tuning (innodb_buffer_pool_size etc.)" echo "================================================================="