-
-
Notifications
You must be signed in to change notification settings - Fork 2k
-
Hello everyone
On the community website, there are only two options available for Nextcloud:
1- Nextcloud VM (Turnkey)
2- Nextcloudpi LXC
Due to my limited knowledge of implementing the scripts you have here, I would like to contribute my small contribution with a bash script for those interested in having Nextcloud installed natively on Debian and configured for a minimum of security.
I'm also leaving it in case anyone in the community understands more than I do about implementing it and incorporating it into the other scripts.
#!/bin/bash
# ALL-IN-ONE script to install Nextcloud on Debian LXC (Proxmox) for PRODUCTION v2
# - Asks for Nextcloud Admin username/password and domain.
# - WITHOUT firewall rule for SSH (assumes access only via Proxmox console).
# Installs: Apache, MariaDB, PHP (generic modules), Redis, APCu.
# Configures: Nextcloud, Apache VirtualHost (HTTP for reverse proxy), Firewall (ufw),
# Basic MariaDB hardening, Nextcloud Cron Task.
# Generates: Secure passwords for NC DB User, MariaDB Root.
# DOES NOT include: Local SSL configuration (uses Cloudflare), Backups (uses Proxmox Backup).
# --- Security and Robustness Options ---
set -e # Exit immediately if a command fails
set -o pipefail # Consider failures in pipelines
# set -u # Treat undefined variables as an error
# --- Configuration Variables (DB Passwords are generated) ---
DB_NAME="nextcloud_db"
DB_USER="nextcloud_user"
DB_PASSWORD=$(openssl rand -base64 15) # Nextcloud DB Password (Generated)
DB_ROOT_PASSWORD=$(openssl rand -base64 15) # MariaDB Root Password (Generated)
# Paths and Webserver
NC_PARENT_PATH="/var/www/html"
NC_DIR_NAME="nextcloud"
NC_PATH="${NC_PARENT_PATH}/${NC_DIR_NAME}"
WEB_USER="www-data"
WEB_GROUP="www-data"
# Mail Configuration (Optional - adjust or use environment variables)
MAIL_FROM_ADDRESS="no-reply"
MAIL_DOMAIN="" # Will be set with the Nextcloud domain if left empty
# --- Essential Dependency Check ---
#echo "--- Checking basic dependencies ---"
#for cmd in wget unzip openssl mysql apache2ctl php redis-server ufw; do
# if ! command -v $cmd &> /dev/null; then
# echo "Error: Essential command '$cmd' not found. Install the corresponding package." >&2
# exit 1
# fi
#done
# --- Initial Check ---
if [ "$(id -u)" -ne 0 ]; then
echo "Error: This script must be run as root." >&2
exit 1
fi
# --- Get User Data ---
# Domain
while [ -z "$NEXTCLOUD_DOMAIN" ]; do
read -p "Enter the EXACT domain to access Nextcloud (e.g., cloud.your-domain.com): " NEXTCLOUD_DOMAIN
if [ -z "$NEXTCLOUD_DOMAIN" ]; then
echo "Error: The domain cannot be empty."
fi
done
if [ -z "$MAIL_DOMAIN" ]; then
MAIL_DOMAIN="$NEXTCLOUD_DOMAIN"
fi
# Nextcloud Admin User
while [ -z "$ADMIN_USER" ]; do
read -p "Enter the username for the Nextcloud Administrator: " ADMIN_USER
if [ -z "$ADMIN_USER" ]; then
echo "Error: The username cannot be empty."
fi
done
# Nextcloud Admin Password (with confirmation)
while true; do
read -sp "Enter the password for user '${ADMIN_USER}': " ADMIN_PASS
echo # New line after hidden prompt
if [ -z "$ADMIN_PASS" ]; then
echo "Error: The password cannot be empty."
continue
fi
read -sp "Confirm the password: " ADMIN_PASS_CONFIRM
echo # New line
if [ "$ADMIN_PASS" = "$ADMIN_PASS_CONFIRM" ]; then
break
else
echo "Error: Passwords do not match. Try again."
fi
done
# --- Show Generated Passwords (Important for the user to see them NOW) ---
echo "------------------------------------------------------------------------"
echo "Confirmed Configuration and Generated Passwords:"
echo " - Nextcloud Domain : ${NEXTCLOUD_DOMAIN}"
echo " - Nextcloud Admin User : ${ADMIN_USER} (Password ${ADMIN_PASS})"
echo "IMPORTANT! Save these DB passwords in a safe place NOW:"
echo " - Nextcloud DB User : ${DB_USER}"
echo " - Nextcloud DB Password : ${DB_PASSWORD}"
echo " - MariaDB Root Password : ${DB_ROOT_PASSWORD}"
echo "------------------------------------------------------------------------"
read -p "Passwords shown. Press [Enter] to continue or Ctrl+C to cancel..."
# --- Helper Functions ---
wait_for_apt_lock() {
# Waits for apt/dpkg locks to be released.
while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || fuser /var/cache/apt/archives/lock >/dev/null 2>&1; do
echo "Waiting for apt/dpkg lock to be released..."
sleep 5
done
}
detect_php_version() {
# Detects the installed PHP version and sets paths.
PHP_VERSION=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
PHP_INI_PATH="/etc/php/${PHP_VERSION}/apache2/php.ini"
PHP_CLI_INI_PATH="/etc/php/${PHP_VERSION}/cli/php.ini"
echo "--- Detected PHP version: ${PHP_VERSION} ---"
if [ ! -f "$PHP_INI_PATH" ]; then
echo "Warning: Could not find php.ini for Apache at the expected path (${PHP_INI_PATH}). Searching..."
PHP_INI_PATH=$(find /etc/php/ -name php.ini | grep apache2 | head -n 1)
if [ -z "$PHP_INI_PATH" ]; then echo "Error: Unable to locate php.ini for Apache." >&2; fi
fi
if [ ! -f "$PHP_CLI_INI_PATH" ]; then
echo "Warning: Could not find php.ini for CLI at the expected path (${PHP_CLI_INI_PATH}). Searching..."
PHP_CLI_INI_PATH=$(find /etc/php/ -name php.ini | grep cli | head -n 1)
if [ -z "$PHP_CLI_INI_PATH" ]; then echo "Warning: Unable to locate php.ini for CLI."; fi
fi
}
# --- Start of Installation ---
echo "--- Starting FULL Nextcloud installation for production ---"
export DEBIAN_FRONTEND=noninteractive
# 1. Update system and install dependencies (including ufw)
echo "--- [1/12] Updating packages and installing dependencies ---"
wait_for_apt_lock
apt update
wait_for_apt_lock
apt install -y apache2 mariadb-server libapache2-mod-php \
php-gd php-mysql php-curl php-mbstring php-intl php-imagick php-xml \
php-zip php-bcmath php-gmp php-apcu php-redis redis-server \
wget unzip sudo imagemagick librsvg2-bin ffmpeg php-bz2 php-ldap \
ufw # Ensure ufw is installed
echo "--- Dependencies installed successfully ---"
# 2. Detect PHP version
detect_php_version
# 3. Configure and Harden MariaDB (Basic)
echo "--- [2/12] Configuring and Hardening MariaDB (Basic) ---"
systemctl start mariadb
systemctl enable mariadb
echo "Setting MariaDB root password..."
mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASSWORD}'; FLUSH PRIVILEGES;"
echo "MariaDB root password set."
echo "Removing anonymous users and test DB..."
mysql -u root -p"${DB_ROOT_PASSWORD}" -e "DELETE FROM mysql.user WHERE User=''; \
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); \
DROP DATABASE IF EXISTS test; \
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; \
FLUSH PRIVILEGES;"
echo "Anonymous users and test DB removed."
echo "Creating database and user for Nextcloud..."
mysql -u root -p"${DB_ROOT_PASSWORD}" <<MYSQL_SCRIPT
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_PASSWORD}';
GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost';
FLUSH PRIVILEGES;
MYSQL_SCRIPT
echo "--- Nextcloud database and user created ---"
echo "--- BASIC MariaDB hardening completed. REVIEW MANUALLY with 'sudo mysql_secure_installation' if you want more security. ---"
# 4. Configure PHP
echo "--- [3/12] Adjusting PHP configuration ---"
# (PHP adjustment code unchanged... uses detected $PHP_INI_PATH and $PHP_CLI_INI_PATH)
if [ -n "$PHP_INI_PATH" ] && [ -f "$PHP_INI_PATH" ]; then
echo "Adjusting ${PHP_INI_PATH}..."
sed -i "s/memory_limit = .*/memory_limit = 1024M/" $PHP_INI_PATH
sed -i "s/upload_max_filesize = .*/upload_max_filesize = 1024M/" $PHP_INI_PATH
sed -i "s/post_max_size = .*/post_max_size = 1024M/" $PHP_INI_PATH
sed -i "s/max_execution_time = .*/max_execution_time = 360/" $PHP_INI_PATH
sed -i "s/max_input_time = .*/max_input_time = 360/" $PHP_INI_PATH
sed -i "s/;date.timezone =.*/date.timezone = UTC/" $PHP_INI_PATH
sed -i "s/;opcache.enable=.*/opcache.enable=1/" $PHP_INI_PATH
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" $PHP_INI_PATH
sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=32/" $PHP_INI_PATH
sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=10000/" $PHP_INI_PATH
sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=128/" $PHP_INI_PATH
sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" $PHP_INI_PATH
sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=1/" $PHP_INI_PATH
else
echo "Warning: Could not adjust PHP configuration for Apache (${PHP_INI_PATH}). Review manually."
fi
if [ -n "$PHP_CLI_INI_PATH" ] && [ -f "$PHP_CLI_INI_PATH" ]; then
echo "Adjusting ${PHP_CLI_INI_PATH}..."
sed -i "s/memory_limit = .*/memory_limit = 1024M/" $PHP_CLI_INI_PATH
sed -i "s/;date.timezone =.*/date.timezone = UTC/" $PHP_CLI_INI_PATH
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" $PHP_CLI_INI_PATH # Enable opcache for CLI
else
echo "Warning: Could not adjust PHP configuration for CLI (${PHP_CLI_INI_PATH}). Review manually."
fi
systemctl restart apache2
echo "--- PHP configuration adjusted ---"
# 5. Configure Apache
echo "--- [4/12] Configuring Apache ---"
# (Apache VirtualHost configuration code unchanged...)
cat <<EOF > /etc/apache2/sites-available/${NEXTCLOUD_DOMAIN}.conf
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName ${NEXTCLOUD_DOMAIN}
DocumentRoot ${NC_PATH}
Alias / "/${NC_PATH}/"
<Directory ${NC_PATH}>
Options +FollowSymlinks
AllowOverride All
Require all granted
<IfModule mod_dav.c>
Dav off
</IfModule>
SetEnv HOME ${NC_PATH}
SetEnv HTTP_HOME ${NC_PATH}
</Directory>
ErrorLog \${APACHE_LOG_DIR}/error_${NEXTCLOUD_DOMAIN}.log
CustomLog \${APACHE_LOG_DIR}/access_${NEXTCLOUD_DOMAIN}.log combined
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" env=HTTPS
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-SSL "on"
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} DavClnt
RewriteRule ^$ /remote.php/webdav/ [L,R=302]
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
RewriteRule ^remote/(.*) /remote.php [L]
RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.*
RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L]
</IfModule>
<IfModule mod_env.c>
SetEnv MOD_X_ACCEL_REDIRECT_ENABLED off
</IfModule>
</VirtualHost>
EOF
a2enmod rewrite headers env dir mime expires remoteip socache_shmcb ssl
a2ensite ${NEXTCLOUD_DOMAIN}.conf
a2dissite 000-default.conf
systemctl restart apache2
echo "--- Apache configured and restarted ---"
# 6. Download Nextcloud
echo "--- [5/12] Downloading the latest stable version of Nextcloud ---"
# (Download code unchanged...)
LATEST_NC_ZIP_URL="https://download.nextcloud.com/server/releases/latest.zip"
wget --progress=bar:force ${LATEST_NC_ZIP_URL} -O /tmp/nextcloud.zip
echo "--- Download completed ---"
# 7. Extract and move Nextcloud
echo "--- [6/12] Extracting Nextcloud files ---"
# (Extraction code unchanged...)
mkdir -p ${NC_PARENT_PATH}
unzip -q /tmp/nextcloud.zip -d ${NC_PARENT_PATH}/
rm /tmp/nextcloud.zip
if [ ! -d "${NC_PATH}" ]; then echo "Error: Directory ${NC_PATH} was not created after extraction." >&2; exit 1; fi
echo "--- Files extracted to ${NC_PATH} ---"
# 8. Set permissions
echo "--- [7/12] Setting correct permissions for Nextcloud ---"
# (Permissions code unchanged...)
mkdir -p ${NC_PATH}/data
chown -R ${WEB_USER}:${WEB_GROUP} ${NC_PATH}/
find ${NC_PATH}/ -type d -exec chmod 750 {} \;
find ${NC_PATH}/ -type f -exec chmod 640 {} \;
chown -R ${WEB_USER}:${WEB_GROUP} ${NC_PATH}/config ${NC_PATH}/data ${NC_PATH}/apps
chmod 750 ${NC_PATH}/config ${NC_PATH}/data ${NC_PATH}/apps
echo "--- Permissions set ---"
# 9. Run Nextcloud installation via occ (Uses the entered $ADMIN_USER and $ADMIN_PASS variables)
echo "--- [8/12] Running the Nextcloud command-line installer (occ) ---"
cd ${NC_PATH}
sudo -u ${WEB_USER} php occ maintenance:install \
--database "mysql" \
--database-name "${DB_NAME}" \
--database-user "${DB_USER}" \
--database-pass "${DB_PASSWORD}" \
--admin-user "${ADMIN_USER}" \
--admin-pass "${ADMIN_PASS}" \
--data-dir "${NC_PATH}/data"
# Configure trusted domains and reverse proxy
sudo -u ${WEB_USER} php occ config:system:set trusted_domains 0 --value="${NEXTCLOUD_DOMAIN}"
sudo -u ${WEB_USER} php occ config:system:set overwrite.cli.url --value="http://${NEXTCLOUD_DOMAIN}"
sudo -u ${WEB_USER} php occ config:system:set overwriteprotocol --value='https'
# Configure Redis and APCu cache
sudo -u ${WEB_USER} php occ config:system:set memcache.local --value '\OC\Memcache\APCu'
sudo -u ${WEB_USER} php occ config:system:set memcache.distributed --value '\OC\Memcache\Redis'
sudo -u ${WEB_USER} php occ config:system:set memcache.locking --value '\OC\Memcache\Redis'
sudo -u ${WEB_USER} php occ config:system:set redis host --value 'localhost'
sudo -u ${WEB_USER} php occ config:system:set redis port --value 6379
# Optimize database
sudo -u ${WEB_USER} php occ db:add-missing-indices
echo "--- Installation with 'occ' completed ---"
# 10. Optimize and configure Nextcloud (General)
echo "--- [9/12] Applying additional configurations and optimizations ---"
# (occ optimization code unchanged...)
sudo -u ${WEB_USER} php occ config:system:set mail_smtpmode --value 'sendmail'
sudo -u ${WEB_USER} php occ config:system:set mail_sendmailmode --value 'smtp'
sudo -u ${WEB_USER} php occ config:system:set mail_from_address --value "${MAIL_FROM_ADDRESS}"
sudo -u ${WEB_USER} php occ config:system:set mail_domain --value "${MAIL_DOMAIN}"
sudo -u ${WEB_USER} php occ config:system:set default_phone_region --value='ES' # Keep 'ES' or change to desired region code
sudo -u ${WEB_USER} php occ config:system:set maintenance_window_start --value="1"
# Final repair
sudo -u ${WEB_USER} php occ maintenance:repair --include-expensive
echo "--- Additional configuration applied ---"
# 11. Configure Firewall (ufw) - WITHOUT SSH RULE
echo "--- [10/12] Configuring the Firewall (ufw) ---"
ufw default deny incoming
ufw default allow outgoing
# echo "Allowing SSH on port ${SSH_PORT}/tcp..." # RULE REMOVED
# ufw allow ${SSH_PORT}/tcp # RULE REMOVED
echo "Allowing HTTP (Port 80/tcp) for Cloudflare..."
ufw allow 80/tcp
echo "Enabling UFW..."
yes | ufw enable || echo "ufw enable failed, it might already be active or require interaction. Enable manually with 'sudo ufw enable'"
echo "Current firewall status:"
ufw status verbose
echo "--- Firewall configured (WITHOUT SSH access allowed by UFW) ---"
# 12. Configure Nextcloud Cron Task
echo "--- [11/12] Configuring the Nextcloud Cron task ---"
# (Cron configuration code unchanged...)
CRON_FILE="/etc/cron.d/nextcloud"
CRON_JOB="*/5 * * * * ${WEB_USER} /usr/bin/php -f ${NC_PATH}/cron.php"
echo "${CRON_JOB}" > "${CRON_FILE}"
chown root:root "${CRON_FILE}"
chmod 644 "${CRON_FILE}"
systemctl restart cron
echo "--- Cron task configured in ${CRON_FILE} ---"
# 13. Final cleanup and message
echo "--- [12/12] Final Cleanup and Message ---"
systemctl restart apache2
echo "========================================================================"
echo " Basic Nextcloud installation and configuration for production completed! "
echo "========================================================================"
echo ""
echo " Web Access (make sure Cloudflare points to the IP of this LXC):"
echo " https://${NEXTCLOUD_DOMAIN}"
echo ""
echo " Nextcloud Administrator Credentials:"
echo " User: ${ADMIN_USER}"
echo " Password: ${ADMIN_PASS}"
echo ""
echo " !!! SAVE THESE DATABASE CREDENTIALS IN A VERY SAFE PLACE !!!"
echo " Nextcloud DB User : ${DB_USER}"
echo " Nextcloud DB Password : ${DB_PASSWORD}"
echo ""
echo " MariaDB Root User : root@localhost"
echo " MariaDB Root Password : ${DB_ROOT_PASSWORD}"
echo ""
echo " RECOMMENDED next steps:"
echo " 1. Check the Firewall status: sudo ufw status verbose (Confirm there is NO rule for SSH)"
echo " 2. Check the 'Administration -> Overview' section in Nextcloud for potential warnings."
echo " 3. Consider running 'sudo mysql_secure_installation' for more thorough MariaDB hardening."
echo " 4. Configure 'trusted_proxies' in Nextcloud with Cloudflare's IP ranges if you need to see the real IP of visitors."
echo " 5. Verify that the Cron task is working (check in 'Overview' that it says 'Run with Cron')."
echo " 6. Implement monitoring for the server and services."
echo " 7. Remember that Proxmox Backup Server handles backups of the entire container."
echo "========================================================================"
exit 0
Greetings to everyone, and thanks for the great work.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 1 -
❤️ 2
Replies: 1 comment 1 reply
-
Hello everyone
On the community website, there are only two options available for Nextcloud: 1- Nextcloud VM (Turnkey) 2- Nextcloudpi LXC
Due to my limited knowledge of implementing the scripts you have here, I would like to contribute my small contribution with a bash script for those interested in having Nextcloud installed natively on Debian and configured for a minimum of security. I'm also leaving it in case anyone in the community understands more than I do about implementing it and incorporating it into the other scripts.
#!/bin/bash # ALL-IN-ONE script to install Nextcloud on Debian LXC (Proxmox) for PRODUCTION v2 # - Asks for Nextcloud Admin username/password and domain. # - WITHOUT firewall rule for SSH (assumes access only via Proxmox console). # Installs: Apache, MariaDB, PHP (generic modules), Redis, APCu. # Configures: Nextcloud, Apache VirtualHost (HTTP for reverse proxy), Firewall (ufw), # Basic MariaDB hardening, Nextcloud Cron Task. # Generates: Secure passwords for NC DB User, MariaDB Root. # DOES NOT include: Local SSL configuration (uses Cloudflare), Backups (uses Proxmox Backup). # --- Security and Robustness Options --- set -e # Exit immediately if a command fails set -o pipefail # Consider failures in pipelines # set -u # Treat undefined variables as an error # --- Configuration Variables (DB Passwords are generated) --- DB_NAME="nextcloud_db" DB_USER="nextcloud_user" DB_PASSWORD=$(openssl rand -base64 15) # Nextcloud DB Password (Generated) DB_ROOT_PASSWORD=$(openssl rand -base64 15) # MariaDB Root Password (Generated) # Paths and Webserver NC_PARENT_PATH="/var/www/html" NC_DIR_NAME="nextcloud" NC_PATH="${NC_PARENT_PATH}/${NC_DIR_NAME}" WEB_USER="www-data" WEB_GROUP="www-data" # Mail Configuration (Optional - adjust or use environment variables) MAIL_FROM_ADDRESS="no-reply" MAIL_DOMAIN="" # Will be set with the Nextcloud domain if left empty # --- Essential Dependency Check --- #echo "--- Checking basic dependencies ---" #for cmd in wget unzip openssl mysql apache2ctl php redis-server ufw; do # if ! command -v $cmd &> /dev/null; then # echo "Error: Essential command '$cmd' not found. Install the corresponding package." >&2 # exit 1 # fi #done # --- Initial Check --- if [ "$(id -u)" -ne 0 ]; then echo "Error: This script must be run as root." >&2 exit 1 fi # --- Get User Data --- # Domain while [ -z "$NEXTCLOUD_DOMAIN" ]; do read -p "Enter the EXACT domain to access Nextcloud (e.g., cloud.your-domain.com): " NEXTCLOUD_DOMAIN if [ -z "$NEXTCLOUD_DOMAIN" ]; then echo "Error: The domain cannot be empty." fi done if [ -z "$MAIL_DOMAIN" ]; then MAIL_DOMAIN="$NEXTCLOUD_DOMAIN" fi # Nextcloud Admin User while [ -z "$ADMIN_USER" ]; do read -p "Enter the username for the Nextcloud Administrator: " ADMIN_USER if [ -z "$ADMIN_USER" ]; then echo "Error: The username cannot be empty." fi done # Nextcloud Admin Password (with confirmation) while true; do read -sp "Enter the password for user '${ADMIN_USER}': " ADMIN_PASS echo # New line after hidden prompt if [ -z "$ADMIN_PASS" ]; then echo "Error: The password cannot be empty." continue fi read -sp "Confirm the password: " ADMIN_PASS_CONFIRM echo # New line if [ "$ADMIN_PASS" = "$ADMIN_PASS_CONFIRM" ]; then break else echo "Error: Passwords do not match. Try again." fi done # --- Show Generated Passwords (Important for the user to see them NOW) --- echo "------------------------------------------------------------------------" echo "Confirmed Configuration and Generated Passwords:" echo " - Nextcloud Domain : ${NEXTCLOUD_DOMAIN}" echo " - Nextcloud Admin User : ${ADMIN_USER} (Password ${ADMIN_PASS})" echo "IMPORTANT! Save these DB passwords in a safe place NOW:" echo " - Nextcloud DB User : ${DB_USER}" echo " - Nextcloud DB Password : ${DB_PASSWORD}" echo " - MariaDB Root Password : ${DB_ROOT_PASSWORD}" echo "------------------------------------------------------------------------" read -p "Passwords shown. Press [Enter] to continue or Ctrl+C to cancel..." # --- Helper Functions --- wait_for_apt_lock() { # Waits for apt/dpkg locks to be released. while fuser /var/lib/dpkg/lock >/dev/null 2>&1 || fuser /var/lib/apt/lists/lock >/dev/null 2>&1 || fuser /var/cache/apt/archives/lock >/dev/null 2>&1; do echo "Waiting for apt/dpkg lock to be released..." sleep 5 done } detect_php_version() { # Detects the installed PHP version and sets paths. PHP_VERSION=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;') PHP_INI_PATH="/etc/php/${PHP_VERSION}/apache2/php.ini" PHP_CLI_INI_PATH="/etc/php/${PHP_VERSION}/cli/php.ini" echo "--- Detected PHP version: ${PHP_VERSION} ---" if [ ! -f "$PHP_INI_PATH" ]; then echo "Warning: Could not find php.ini for Apache at the expected path (${PHP_INI_PATH}). Searching..." PHP_INI_PATH=$(find /etc/php/ -name php.ini | grep apache2 | head -n 1) if [ -z "$PHP_INI_PATH" ]; then echo "Error: Unable to locate php.ini for Apache." >&2; fi fi if [ ! -f "$PHP_CLI_INI_PATH" ]; then echo "Warning: Could not find php.ini for CLI at the expected path (${PHP_CLI_INI_PATH}). Searching..." PHP_CLI_INI_PATH=$(find /etc/php/ -name php.ini | grep cli | head -n 1) if [ -z "$PHP_CLI_INI_PATH" ]; then echo "Warning: Unable to locate php.ini for CLI."; fi fi } # --- Start of Installation --- echo "--- Starting FULL Nextcloud installation for production ---" export DEBIAN_FRONTEND=noninteractive # 1. Update system and install dependencies (including ufw) echo "--- [1/12] Updating packages and installing dependencies ---" wait_for_apt_lock apt update wait_for_apt_lock apt install -y apache2 mariadb-server libapache2-mod-php \ php-gd php-mysql php-curl php-mbstring php-intl php-imagick php-xml \ php-zip php-bcmath php-gmp php-apcu php-redis redis-server \ wget unzip sudo imagemagick librsvg2-bin ffmpeg php-bz2 php-ldap \ ufw # Ensure ufw is installed echo "--- Dependencies installed successfully ---" # 2. Detect PHP version detect_php_version # 3. Configure and Harden MariaDB (Basic) echo "--- [2/12] Configuring and Hardening MariaDB (Basic) ---" systemctl start mariadb systemctl enable mariadb echo "Setting MariaDB root password..." mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '${DB_ROOT_PASSWORD}'; FLUSH PRIVILEGES;" echo "MariaDB root password set." echo "Removing anonymous users and test DB..." mysql -u root -p"${DB_ROOT_PASSWORD}" -e "DELETE FROM mysql.user WHERE User=''; \ DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); \ DROP DATABASE IF EXISTS test; \ DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'; \ FLUSH PRIVILEGES;" echo "Anonymous users and test DB removed." echo "Creating database and user for Nextcloud..." mysql -u root -p"${DB_ROOT_PASSWORD}" <<MYSQL_SCRIPT 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_PASSWORD}'; GRANT ALL PRIVILEGES ON ${DB_NAME}.* TO '${DB_USER}'@'localhost'; FLUSH PRIVILEGES; MYSQL_SCRIPT echo "--- Nextcloud database and user created ---" echo "--- BASIC MariaDB hardening completed. REVIEW MANUALLY with 'sudo mysql_secure_installation' if you want more security. ---" # 4. Configure PHP echo "--- [3/12] Adjusting PHP configuration ---" # (PHP adjustment code unchanged... uses detected $PHP_INI_PATH and $PHP_CLI_INI_PATH) if [ -n "$PHP_INI_PATH" ] && [ -f "$PHP_INI_PATH" ]; then echo "Adjusting ${PHP_INI_PATH}..." sed -i "s/memory_limit = .*/memory_limit = 1024M/" $PHP_INI_PATH sed -i "s/upload_max_filesize = .*/upload_max_filesize = 1024M/" $PHP_INI_PATH sed -i "s/post_max_size = .*/post_max_size = 1024M/" $PHP_INI_PATH sed -i "s/max_execution_time = .*/max_execution_time = 360/" $PHP_INI_PATH sed -i "s/max_input_time = .*/max_input_time = 360/" $PHP_INI_PATH sed -i "s/;date.timezone =.*/date.timezone = UTC/" $PHP_INI_PATH sed -i "s/;opcache.enable=.*/opcache.enable=1/" $PHP_INI_PATH sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" $PHP_INI_PATH sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=32/" $PHP_INI_PATH sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=10000/" $PHP_INI_PATH sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=128/" $PHP_INI_PATH sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" $PHP_INI_PATH sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=1/" $PHP_INI_PATH else echo "Warning: Could not adjust PHP configuration for Apache (${PHP_INI_PATH}). Review manually." fi if [ -n "$PHP_CLI_INI_PATH" ] && [ -f "$PHP_CLI_INI_PATH" ]; then echo "Adjusting ${PHP_CLI_INI_PATH}..." sed -i "s/memory_limit = .*/memory_limit = 1024M/" $PHP_CLI_INI_PATH sed -i "s/;date.timezone =.*/date.timezone = UTC/" $PHP_CLI_INI_PATH sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" $PHP_CLI_INI_PATH # Enable opcache for CLI else echo "Warning: Could not adjust PHP configuration for CLI (${PHP_CLI_INI_PATH}). Review manually." fi systemctl restart apache2 echo "--- PHP configuration adjusted ---" # 5. Configure Apache echo "--- [4/12] Configuring Apache ---" # (Apache VirtualHost configuration code unchanged...) cat <<EOF > /etc/apache2/sites-available/${NEXTCLOUD_DOMAIN}.conf <VirtualHost *:80> ServerAdmin webmaster@localhost ServerName ${NEXTCLOUD_DOMAIN} DocumentRoot ${NC_PATH} Alias / "/${NC_PATH}/" <Directory ${NC_PATH}> Options +FollowSymlinks AllowOverride All Require all granted <IfModule mod_dav.c> Dav off </IfModule> SetEnv HOME ${NC_PATH} SetEnv HTTP_HOME ${NC_PATH} </Directory> ErrorLog \${APACHE_LOG_DIR}/error_${NEXTCLOUD_DOMAIN}.log CustomLog \${APACHE_LOG_DIR}/access_${NEXTCLOUD_DOMAIN}.log combined <IfModule mod_headers.c> Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" env=HTTPS RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-SSL "on" </IfModule> <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{HTTP_USER_AGENT} DavClnt RewriteRule ^$ /remote.php/webdav/ [L,R=302] RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L] RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L] RewriteRule ^remote/(.*) /remote.php [L] RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L] RewriteCond %{REQUEST_URI} !^/\.well-known/(acme-challenge|pki-validation)/.* RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L] </IfModule> <IfModule mod_env.c> SetEnv MOD_X_ACCEL_REDIRECT_ENABLED off </IfModule> </VirtualHost> EOF a2enmod rewrite headers env dir mime expires remoteip socache_shmcb ssl a2ensite ${NEXTCLOUD_DOMAIN}.conf a2dissite 000-default.conf systemctl restart apache2 echo "--- Apache configured and restarted ---" # 6. Download Nextcloud echo "--- [5/12] Downloading the latest stable version of Nextcloud ---" # (Download code unchanged...) LATEST_NC_ZIP_URL="https://download.nextcloud.com/server/releases/latest.zip" wget --progress=bar:force ${LATEST_NC_ZIP_URL} -O /tmp/nextcloud.zip echo "--- Download completed ---" # 7. Extract and move Nextcloud echo "--- [6/12] Extracting Nextcloud files ---" # (Extraction code unchanged...) mkdir -p ${NC_PARENT_PATH} unzip -q /tmp/nextcloud.zip -d ${NC_PARENT_PATH}/ rm /tmp/nextcloud.zip if [ ! -d "${NC_PATH}" ]; then echo "Error: Directory ${NC_PATH} was not created after extraction." >&2; exit 1; fi echo "--- Files extracted to ${NC_PATH} ---" # 8. Set permissions echo "--- [7/12] Setting correct permissions for Nextcloud ---" # (Permissions code unchanged...) mkdir -p ${NC_PATH}/data chown -R ${WEB_USER}:${WEB_GROUP} ${NC_PATH}/ find ${NC_PATH}/ -type d -exec chmod 750 {} \; find ${NC_PATH}/ -type f -exec chmod 640 {} \; chown -R ${WEB_USER}:${WEB_GROUP} ${NC_PATH}/config ${NC_PATH}/data ${NC_PATH}/apps chmod 750 ${NC_PATH}/config ${NC_PATH}/data ${NC_PATH}/apps echo "--- Permissions set ---" # 9. Run Nextcloud installation via occ (Uses the entered $ADMIN_USER and $ADMIN_PASS variables) echo "--- [8/12] Running the Nextcloud command-line installer (occ) ---" cd ${NC_PATH} sudo -u ${WEB_USER} php occ maintenance:install \ --database "mysql" \ --database-name "${DB_NAME}" \ --database-user "${DB_USER}" \ --database-pass "${DB_PASSWORD}" \ --admin-user "${ADMIN_USER}" \ --admin-pass "${ADMIN_PASS}" \ --data-dir "${NC_PATH}/data" # Configure trusted domains and reverse proxy sudo -u ${WEB_USER} php occ config:system:set trusted_domains 0 --value="${NEXTCLOUD_DOMAIN}" sudo -u ${WEB_USER} php occ config:system:set overwrite.cli.url --value="http://${NEXTCLOUD_DOMAIN}" sudo -u ${WEB_USER} php occ config:system:set overwriteprotocol --value='https' # Configure Redis and APCu cache sudo -u ${WEB_USER} php occ config:system:set memcache.local --value '\OC\Memcache\APCu' sudo -u ${WEB_USER} php occ config:system:set memcache.distributed --value '\OC\Memcache\Redis' sudo -u ${WEB_USER} php occ config:system:set memcache.locking --value '\OC\Memcache\Redis' sudo -u ${WEB_USER} php occ config:system:set redis host --value 'localhost' sudo -u ${WEB_USER} php occ config:system:set redis port --value 6379 # Optimize database sudo -u ${WEB_USER} php occ db:add-missing-indices echo "--- Installation with 'occ' completed ---" # 10. Optimize and configure Nextcloud (General) echo "--- [9/12] Applying additional configurations and optimizations ---" # (occ optimization code unchanged...) sudo -u ${WEB_USER} php occ config:system:set mail_smtpmode --value 'sendmail' sudo -u ${WEB_USER} php occ config:system:set mail_sendmailmode --value 'smtp' sudo -u ${WEB_USER} php occ config:system:set mail_from_address --value "${MAIL_FROM_ADDRESS}" sudo -u ${WEB_USER} php occ config:system:set mail_domain --value "${MAIL_DOMAIN}" sudo -u ${WEB_USER} php occ config:system:set default_phone_region --value='ES' # Keep 'ES' or change to desired region code sudo -u ${WEB_USER} php occ config:system:set maintenance_window_start --value="1" # Final repair sudo -u ${WEB_USER} php occ maintenance:repair --include-expensive echo "--- Additional configuration applied ---" # 11. Configure Firewall (ufw) - WITHOUT SSH RULE echo "--- [10/12] Configuring the Firewall (ufw) ---" ufw default deny incoming ufw default allow outgoing # echo "Allowing SSH on port ${SSH_PORT}/tcp..." # RULE REMOVED # ufw allow ${SSH_PORT}/tcp # RULE REMOVED echo "Allowing HTTP (Port 80/tcp) for Cloudflare..." ufw allow 80/tcp echo "Enabling UFW..." yes | ufw enable || echo "ufw enable failed, it might already be active or require interaction. Enable manually with 'sudo ufw enable'" echo "Current firewall status:" ufw status verbose echo "--- Firewall configured (WITHOUT SSH access allowed by UFW) ---" # 12. Configure Nextcloud Cron Task echo "--- [11/12] Configuring the Nextcloud Cron task ---" # (Cron configuration code unchanged...) CRON_FILE="/etc/cron.d/nextcloud" CRON_JOB="*/5 * * * * ${WEB_USER} /usr/bin/php -f ${NC_PATH}/cron.php" echo "${CRON_JOB}" > "${CRON_FILE}" chown root:root "${CRON_FILE}" chmod 644 "${CRON_FILE}" systemctl restart cron echo "--- Cron task configured in ${CRON_FILE} ---" # 13. Final cleanup and message echo "--- [12/12] Final Cleanup and Message ---" systemctl restart apache2 echo "========================================================================" echo " Basic Nextcloud installation and configuration for production completed! " echo "========================================================================" echo "" echo " Web Access (make sure Cloudflare points to the IP of this LXC):" echo " https://${NEXTCLOUD_DOMAIN}" echo "" echo " Nextcloud Administrator Credentials:" echo " User: ${ADMIN_USER}" echo " Password: ${ADMIN_PASS}" echo "" echo " !!! SAVE THESE DATABASE CREDENTIALS IN A VERY SAFE PLACE !!!" echo " Nextcloud DB User : ${DB_USER}" echo " Nextcloud DB Password : ${DB_PASSWORD}" echo "" echo " MariaDB Root User : root@localhost" echo " MariaDB Root Password : ${DB_ROOT_PASSWORD}" echo "" echo " RECOMMENDED next steps:" echo " 1. Check the Firewall status: sudo ufw status verbose (Confirm there is NO rule for SSH)" echo " 2. Check the 'Administration -> Overview' section in Nextcloud for potential warnings." echo " 3. Consider running 'sudo mysql_secure_installation' for more thorough MariaDB hardening." echo " 4. Configure 'trusted_proxies' in Nextcloud with Cloudflare's IP ranges if you need to see the real IP of visitors." echo " 5. Verify that the Cron task is working (check in 'Overview' that it says 'Run with Cron')." echo " 6. Implement monitoring for the server and services." echo " 7. Remember that Proxmox Backup Server handles backups of the entire container." echo "========================================================================" exit 0Greetings to everyone, and thanks for the great work.
Thanks @kiwinh0, this is the only lxc I have outside of the community scripts, I'll try it as soon as possible.
Beta Was this translation helpful? Give feedback.
All reactions
-
❤️ 1
-
THX 🤗
Beta Was this translation helpful? Give feedback.