前陣子為了使用 WebDav 功能來備份書籤 (Floccus),一開始想手動設定 HTTPD 的 WebDav 功能,無奈怎麼弄都怪怪的,而且還要安全認證,所以就打算用 NextCloud 所提供的 WebDav 功能。除此之外,NextCloud 本身提供的安全性也更高一些,可以啟動二階段認證、掛載外部儲存空間等,省掉很多自行維護的人力。
在開始之前,你的網域託管在 Route 53:如果你的網域是在 CloudFlare 之類的東西的話,只要把 acme.sh
內的 --dns dns_aws
改成 --dns dns_cf
就可以了,也請記得加上 CloudFlare 的相關 Key,在 acme.sh
的 Github 有所有支援的 DNS Provider 的設定:How to use DNS API。
目前有以下功能:
- 申請、自動 renew Let’s Encrypt 憑證。
- 安裝所有 NextCloud 的必要 PHP 模組
- 建立資料庫、權限、密碼
- 執行
mysql_secure_installation
、更改 DBroot
密碼 - 依據官方文件調整 HTTPD 參數:
- 關閉檔案清單:
Options -Indexes
。 - 啟用
rewrite
:AllowOverride All
。 - 設定
Strict-Transport-Security
。 - 設定 NextCloud 的 Maintenance Window 時段。
- 關閉檔案清單:
在開始執行之前,有幾個參數需要手動調整:
DOMAIN
:要申請 SSL 憑證的域名。MAIL
:註冊 Let’s Encrypt 的信箱。AWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEY
:有 Route 53 的權限的 IAM User 的 AKSK,請參考:How to use Amazon Route53 API。ROOT_DB_PASSWORD
:資料庫root
密碼。NC_DB_NAME
:NextCloud 的資料庫名稱。NC_DB_USER
:資料庫使用者名稱。NC_DB_PASSWORD
:資料庫使用者的密碼。NC_MAINTENANCE_WINDOW=16
:NextCloud 的維護時段 (UTC+0)。PHP_MEMORY_LIMIT
:PHP 記憶體大小。PHP_POST_MAX_SIZE
:PHP 接受 POST 大小。PHP_UPLOAD_MAX_FILESIZE
:PHP 接受的檔案大小。
Userdata
#!/bin/sh
set -x
export DOMAIN=""
export MAIL=""
export AWS_ACCESS_KEY_ID=""
export AWS_SECRET_ACCESS_KEY=""
export ROOT_DB_PASSWORD=""
export NC_DB_NAME="nextcloud"
export NC_DB_USER="nc_user"
export NC_DB_PASSWORD=""
export NC_MAINTENANCE_WINDOW=16
export PHP_MEMORY_LIMIT="1G"
export PHP_POST_MAX_SIZE="10G"
export PHP_UPLOAD_MAX_FILESIZE="10G"
########
export HOME=/root
max_attempts=5
attempt_num=1
success=false
while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do
echo "Trying dnf install"
dnf install cronie httpd mod_ssl socat mariadb105-server unzip php8.3-fpm php8.3-pdo php8.3-mysqlnd php8.3-xml php8.3-mbstring php8.3-gd php8.3-zip php8.3-opcache php8.3-modphp php8.3-process php8.3-bcmath php8.3-gmp php8.3-intl php8.3-sodium -y
if [ $? -eq 0 ]; then
echo "dnf install succeeded"
success=true
else
echo "Attempt $attempt_num failed. Sleeping for 3 seconds and trying again..."
sleep 3
((attempt_num++))
fi
done
systemctl start httpd
systemctl enable httpd
systemctl start mariadb
systemctl enable mariadb
curl https://get.acme.sh | sh -s email=$MAIL
/root/.acme.sh/acme.sh --issue --force\
--dns dns_aws \
-d $DOMAIN \
--cert-file /etc/pki/tls/certs/$DOMAIN.cert.pem \
--key-file /etc/pki/tls/private/$DOMAIN.key.pem \
--fullchain-file /etc/pki/tls/certs/$DOMAIN.fullchain.pem \
--reloadcmd "systemctl reload httpd" --apache
# Replace the default SSL credential files.
sed -i 's/SSLCertificateFile\ \/etc\/pki\/tls\/certs\/localhost.crt/SSLCertificateFile\ \/etc\/pki\/tls\/certs\/'$DOMAIN'.cert.pem/g' /etc/httpd/conf.d/ssl.conf
sed -i 's/SSLCertificateKeyFile\ \/etc\/pki\/tls\/private\/localhost.key/SSLCertificateKeyFile\ \/etc\/pki\/tls\/private\/'$DOMAIN'.key.pem/g' /etc/httpd/conf.d/ssl.conf
sed -i 's/#SSLCertificateChainFile\ \/etc\/pki\/tls\/certs\/server-chain.crt/SSLCertificateChainFile\ \/etc\/pki\/tls\/certs\/'$DOMAIN'.fullchain.pem/g' /etc/httpd/conf.d/ssl.conf
sed -i 's/Options\ Indexes\ FollowSymLinks/Options\ -Indexes\ +FollowSymLinks/g' /etc/httpd/conf/httpd.conf
sed -i 's/AllowOverride\ None/AllowOverride\ All/g' /etc/httpd/conf/httpd.conf
# Update the php limits.
echo "php_value[memory_limit] = $PHP_MEMORY_LIMIT" >> /etc/php-fpm.d/www.conf
echo "php_value[post_max_size] = $PHP_POST_MAX_SIZE" >> /etc/php-fpm.d/www.conf
echo "php_value[upload_max_filesize] = $PHP_UPLOAD_MAX_FILESIZE" >> /etc/php-fpm.d/www.conf
# Set Strict-Transport-Security header
sed -i 's/<\/VirtualHost>/\ \ \ \ \<IfModule\ mod_headers.c\>\n\ \ \ \ \ \ \ \ Header\ always\ set\ Strict-Transport-Security\ \"max-age\=15552000\;\ includeSubDomains\"\n\ \ \ \ \<\/IfModule\>\n<\/VirtualHost>/g' /etc/httpd/conf.d/ssl.conf
# Update the opcache configuation.
sed -i "s/;opcache.interned_strings_buffer=8/opcache.interned_strings_buffer=64/g" /etc/php.d/10-opcache.ini
systemctl reload httpd
systemctl restart php-fpm
curl -O --output-dir /var/www/ https://download.nextcloud.com/server/releases/latest.zip
unzip /var/www/latest.zip -d /var/www/
rm -rf /var/www/html/
mv /var/www/nextcloud /var/www/html
chown -R apache:apache /var/www/html
### mysql_secure_installation
mysql -e "UPDATE mysql.user SET Password=PASSWORD('$ROOT_DB_PASSWORD') WHERE User='root';"
mysql -e "DELETE FROM mysql.user WHERE User='';"
mysql -e "DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');"
mysql -e "DROP DATABASE IF EXISTS test;"
mysql -e "DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';"
mysql -e "FLUSH PRIVILEGES;"
### Create a database for NextCloud
mysql -e "CREATE USER '$NC_DB_USER'@'localhost' IDENTIFIED BY '$NC_DB_PASSWORD';"
mysql -e "CREATE DATABASE IF NOT EXISTS $NC_DB_NAME CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
mysql -e "GRANT ALL PRIVILEGES on $NC_DB_NAME.* to '$NC_DB_USER'@'localhost';"
### Set root password form empty.
mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$ROOT_DB_PASSWORD';"
### First access to generate config.php from config.sample.php
curl localhost >> /dev/null
sed -i "s/);/ 'maintenance_window_start' => $NC_MAINTENANCE_WINDOW,\n);/g" /var/www/html/config/config.php
已知問題
- Amazon Linux 2023 沒有
php-imagick
可用。
其他建議
- 可依據需求連線 ElastiCache (Memcached、Reds) 快取(成本很高)。
- 使用 S3 作為外部儲存空間 (External Storages),因為 S3 會依據檔案用量收費,但 EBS 會以硬碟的檔案大小來收費。使用 S3 還可以直接從 AWS Conosle 存取當案。