盤(pán):從LNMP部署到安全加固實(shí)戰(zhàn))
最近有個(gè)朋友問(wèn)我百度網(wǎng)盤(pán)限速嚴(yán)重服務(wù)器上又存著不少代碼和設(shè)計(jì)稿有沒(méi)有省心點(diǎn)的方案我第一反應(yīng)就是自建一個(gè)網(wǎng)盤(pán)用開(kāi)源項(xiàng)目把存儲(chǔ)掌握在自己手里。這個(gè)場(chǎng)景最適合的其實(shí)是 OwnCloud——它部署不復(fù)雜對(duì)硬件要求也不高生態(tài)和文檔都比較成熟。這篇我就完整過(guò)一遍用 OwnCloud 搭建個(gè)人網(wǎng)盤(pán)的流程從環(huán)境準(zhǔn)備、LNMP 部署、OwnCloud 初始化到安全加固和排坑全部按實(shí)際操作的順序來(lái)寫(xiě)新手可以直接照著抄作業(yè)。先說(shuō)清楚這套方案能解決什么問(wèn)題一是擺脫第三方網(wǎng)盤(pán)的限速和容量限制容量取決于你服務(wù)器硬盤(pán)大小二是數(shù)據(jù)完全自主管理不經(jīng)過(guò)別人的服務(wù)器三是支持 Web 訪問(wèn)、桌面客戶端、手機(jī) App 多端同步完全滿足個(gè)人文件和團(tuán)隊(duì)小規(guī)模共享的需求。適合的對(duì)象是有一點(diǎn) Linux 基礎(chǔ)的用戶哪怕你只熟悉基礎(chǔ)命令只要按著步驟一步步來(lái)也能把服務(wù)跑起來(lái)。1. 選型思路與部署環(huán)境準(zhǔn)備1.1 為什么選 OwnCloud 而不是其他方案市面上的開(kāi)源私有網(wǎng)盤(pán)方案不少常見(jiàn)的有 OwnCloud、Nextcloud、Seafile、Pydio 等。Nextcloud 是從 OwnCloud 分叉出去的功能更豐富、社區(qū)更活躍但功能多也意味著體積更大、更新更頻繁對(duì)低配服務(wù)器不算友好。Seafile 性能很強(qiáng)適合文件量特別大的場(chǎng)景但它的存儲(chǔ)方式不是直接可見(jiàn)的文件結(jié)構(gòu)數(shù)據(jù)層做了分塊處理出問(wèn)題之后恢復(fù)的復(fù)雜度高一些。OwnCloud 的優(yōu)勢(shì)在于“輕”和“穩(wěn)”核心功能聚焦在文件同步、分享、版本管理、在線預(yù)覽這些網(wǎng)盤(pán)剛需上PHP 部署模式簡(jiǎn)單數(shù)據(jù)庫(kù)可以用 MySQL 也可以用 SQLite對(duì)單核 512MB 內(nèi)存的小機(jī)器也能跑得動(dòng)。如果你只是想要一個(gè)穩(wěn)定、省心、數(shù)據(jù)全在自己手里的網(wǎng)盤(pán)不去折騰過(guò)多擴(kuò)展功能OwnCloud 是一個(gè)非常成熟的選擇。我實(shí)際部署下來(lái)2 核 2G 的云主機(jī)帶 20 個(gè)用戶同步完全沒(méi)有壓力。這里要提醒一句選型不要去追“誰(shuí)功能多”而是看你的實(shí)際使用規(guī)模。個(gè)人用或者小團(tuán)隊(duì)內(nèi)部用穩(wěn)定性和維護(hù)成本往往比功能數(shù)量更重要。1.2 服務(wù)器與系統(tǒng)基礎(chǔ)準(zhǔn)備部署 OwnCloud 推薦用 Linux 系統(tǒng)我用的是 Debian 系的發(fā)行版Ubuntu 和 Debian 的包管理方式和文檔資源最多遇到問(wèn)題最容易搜到解決方案。CentOS 也不是不行但配置路徑和命令會(huì)有差異不建議新手一上來(lái)用。服務(wù)器配置方面最低 1 核 1G 內(nèi)存就可以跑起來(lái)但如果你打算開(kāi)多人使用、或者經(jīng)常傳大文件建議至少 2 核 2G 內(nèi)存磁盤(pán)單獨(dú)掛載數(shù)據(jù)盤(pán)系統(tǒng)盤(pán)和數(shù)據(jù)盤(pán)分離否則將來(lái)系統(tǒng)重裝的時(shí)候數(shù)據(jù)備份會(huì)非常麻煩。我這里用模擬項(xiàng)目 X 的服務(wù)器做演示系統(tǒng)是 Ubuntu 22.04IP 用阿里云、騰訊云、AWS 這類(lèi)云廠商的公網(wǎng) IP數(shù)據(jù)盤(pán)單獨(dú)掛在 /data 下。操作系統(tǒng)裝好之后先做兩件事更新軟件源設(shè)置好主機(jī)名。更新軟件源的命令很簡(jiǎn)單但容易被忽略新裝的系統(tǒng)源緩存往往是空的不更新會(huì)導(dǎo)致后面安裝包失敗。sudo apt update sudo apt upgrade -y然后確認(rèn)你當(dāng)前的 PHP 版本。OwnCloud 10.x 系列要求 PHP 7.x 以上我推薦使用 PHP 7.4 版本官方兼容性列表里這個(gè)版本驗(yàn)證得最充分性能和穩(wěn)定性也比較均衡。Ubuntu 22.04 系統(tǒng)源默認(rèn)是 PHP 8.1直接裝也能用但如果想省心一點(diǎn)可以通過(guò)第三方源安裝 PHP 7.4。1.3 軟件架構(gòu)LNMP 組合的取舍OwnCloud 本質(zhì)是 PHP 程序需要一個(gè) Web 服務(wù)器和數(shù)據(jù)庫(kù)來(lái)跑。常見(jiàn)的組合是 LAMPApache MySQL PHP和 LNMPNginx MySQL PHP兩者都能用。我個(gè)人的習(xí)慣是 LNMP原因很實(shí)在Nginx 對(duì)靜態(tài)文件的處理效率高占用內(nèi)存比 Apache 低得多尤其在小內(nèi)存服務(wù)器上這個(gè)差距非常明顯。OwnCloud 的網(wǎng)頁(yè)端有大量靜態(tài)資源圖片、CSS、JSNginx 處理這些文件的并發(fā)能力比 Apache 好。Apache 的優(yōu)勢(shì)是很多程序的偽靜態(tài)規(guī)則可以直接用 .htaccessOwnCloud 官方也提供了 Apache 的配置模板。但 Nginx 配置其實(shí)更清晰規(guī)則寫(xiě)明確以后不容易出現(xiàn)權(quán)限繞過(guò)的問(wèn)題。這個(gè)方案里我用的是 Nginx 1.24 PHP-FPM 7.4 MySQL 8.0。數(shù)據(jù)庫(kù)方面測(cè)試環(huán)境或者文件量不大的個(gè)人用可以選擇 SQLite零配置文件型數(shù)據(jù)庫(kù)省掉維護(hù) MySQL 的麻煩。但我強(qiáng)烈建議正式環(huán)境用 MySQL原因有兩個(gè)一是并發(fā)性能好很多多終端同步同時(shí)操作時(shí) SQLite 會(huì)有鎖庫(kù)問(wèn)題二是 OwnCloud 的日志、文件緩存、分享記錄這些數(shù)據(jù)以后會(huì)越攢越多MySQL 管理工具多備份和遷移都方便。2. LNMP 基礎(chǔ)環(huán)境搭建2.1 Nginx 安裝與基礎(chǔ)配置安裝 Nginx 很直接Ubuntu 源里就有。sudo apt install nginx -y裝完先別急著配置站點(diǎn)先確認(rèn) Nginx 服務(wù)已經(jīng)啟動(dòng)。sudo systemctl start nginx sudo systemctl enable nginx然后在瀏覽器訪問(wèn)服務(wù)器 IP看到 Nginx 默認(rèn)歡迎頁(yè)就說(shuō)明第一步?jīng)]問(wèn)題。這一步我建議一定做很多新手后面配置了一堆東西發(fā)現(xiàn)訪問(wèn)不了根本不知道是 Nginx 沒(méi)啟動(dòng)還是防火墻的問(wèn)題。先確認(rèn)基礎(chǔ)層正常再一層層往上搭排查會(huì)輕松很多。Nginx 默認(rèn)的站點(diǎn)配置文件在 /etc/nginx/sites-available/我們需要新建一個(gè) OwnCloud 專用的配置文件后續(xù)會(huì)給具體的配置內(nèi)容?,F(xiàn)在先確認(rèn)安裝的 Nginx 版本nginx -v2.2 PHP 與擴(kuò)展組件安裝PHP-FPM 是 OwnCloud 運(yùn)行的核心只裝 PHP 本體不夠OwnCloud 依賴很多 PHP 擴(kuò)展任何一個(gè)缺失都可能導(dǎo)致安裝失敗或者預(yù)覽功能異常。我在第一次部署時(shí)就漏裝了 php-zip導(dǎo)致 OwnCloud 后臺(tái)無(wú)法解壓上傳的壓縮包排查了很久才發(fā)現(xiàn)是擴(kuò)展問(wèn)題。Ubuntu apt 源下安裝 PHP 7.4 需要先添加軟件源。這里我用 Sury 源這是社區(qū)維護(hù)最及時(shí)的 PHP 源sudo apt install software-properties-common sudo add-apt-repository ppa:ondrej/php sudo apt update然后安裝 PHP 7.4 和全部需要的擴(kuò)展sudo apt install -y php7.4-fpm php7.4-mysql php7.4-gd php7.4-zip php7.4-xml php7.4-mbstring php7.4-curl php7.4-intl php7.4-bcmath php7.4-gmp php7.4-imagick php7.4-apcu php7.4-redis這里逐個(gè)說(shuō)下每個(gè)擴(kuò)展的作用方便你知道哪些是必需的php-mysql 是連數(shù)據(jù)庫(kù)用的不裝 OwnCloud 連數(shù)據(jù)庫(kù)那步直接失敗php-gd 和 php-imagick 負(fù)責(zé)圖片縮略圖生成不裝的話圖片文件不會(huì)顯示預(yù)覽縮略圖php-zip 負(fù)責(zé)壓縮包在線解壓php-xml 和 php-mbstring 是 PHP 框架運(yùn)行的基礎(chǔ)依賴php-curl 處理外部 URL 請(qǐng)求php-intl 提供國(guó)際化支持避免后臺(tái)界面出現(xiàn)亂碼php-bcmath 和 php-gmp 是 OwnCloud 某些安全功能會(huì)用到的數(shù)學(xué)計(jì)算庫(kù)。安裝完成后啟動(dòng) PHP-FPMsudo systemctl start php7.4-fpm sudo systemctl enable php7.4-fpm確認(rèn) PHP-FPM 正常運(yùn)行systemctl status php7.4-fpm2.3 MySQL 數(shù)據(jù)庫(kù)與專門(mén)賬號(hào)創(chuàng)建MySQL 8.0 需要單獨(dú)安裝這里用最簡(jiǎn)單的 apt 方式sudo apt install mysql-server -y安裝完成后初始化安全設(shè)置sudo mysql_secure_installation這個(gè)命令會(huì)讓你設(shè)置 root 密碼以及是否移除匿名用戶等選項(xiàng)建議都選是。生產(chǎn)環(huán)境一定要有一個(gè)強(qiáng)密碼數(shù)據(jù)庫(kù)里存的是整個(gè)網(wǎng)盤(pán)的文件索引和用戶信息一旦泄露后果比較嚴(yán)重。接下來(lái)是創(chuàng)建 OwnCloud 專用的數(shù)據(jù)庫(kù)和用戶。為什么要單獨(dú)建一個(gè)賬號(hào)而不是直接用 root原因很簡(jiǎn)單OwnCloud 如果出現(xiàn) SQL 注入漏洞攻擊者拿到的只是這個(gè)專用賬號(hào)的權(quán)限可以最大程度控制損失。這是我在所有 Web 應(yīng)用部署中堅(jiān)持的一條原則應(yīng)用賬號(hào)權(quán)限最小化。登錄 MySQLsudo mysql -u root -p進(jìn)入 MySQL 命令行后執(zhí)行CREATE DATABASE owncloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER owncloudlocalhost IDENTIFIED BY YouShouldUseAStrongPassword; GRANT ALL PRIVILEGES ON owncloud.* TO owncloudlocalhost; FLUSH PRIVILEGES; EXIT;數(shù)據(jù)庫(kù)名和用戶名按你的喜好來(lái)不一定要 owncloud。密碼這里我建議直接用隨機(jī)生成的強(qiáng)密碼可以用密碼管理器生成不要用生日、名字這類(lèi)容易被猜到的。值得注意的是 utf8mb4 字符集的選擇。后面數(shù)據(jù)量大了以后文件系統(tǒng)里可能出現(xiàn)各種字符的文件名包括 emoji 字符utf8mb4 才能完整支持。如果用了老的 utf8某些文件名會(huì)變成亂碼數(shù)據(jù)庫(kù)層面很難修復(fù)。3. OwnCloud 源碼部署與目錄規(guī)劃3.1 下載 OwnCloud 源碼包OwnCloud 源碼包可以直接從官網(wǎng)下載頁(yè)面拿地址。這里要強(qiáng)調(diào)一點(diǎn)永遠(yuǎn)不要用 apt 源里的舊版本 OwnCloud因?yàn)榘姹咎峡赡芤呀?jīng)有已知安全漏洞。直接從官網(wǎng)下載最新穩(wěn)定版二進(jìn)制簽名校驗(yàn)也更可靠。下載和解壓命令cd /var/www sudo wget https://download.owncloud.com/download/community/production/web/owncloud-latest.tar.bz2 sudo tar -xjf owncloud-latest.tar.bz2命令里下載地址是官網(wǎng)的社區(qū)版發(fā)布路徑。解壓完成后 /var/www/owncloud 就是 web 根目錄。源碼包下載解壓后建議順便做一次 SHA256 完整性校驗(yàn)官網(wǎng)提供了對(duì)應(yīng)的校驗(yàn)值和簽名文件不要偷懶跳過(guò)。網(wǎng)上拉取的安裝包如果被篡改過(guò)后面整個(gè)系統(tǒng)都不安全這一步雖然麻煩但成本遠(yuǎn)低于事后補(bǔ)救。3.2 目錄規(guī)劃與 data 目錄外移這個(gè)是我覺(jué)得整個(gè)部署過(guò)程中最重要的一步不要用默認(rèn)的 data 目錄位置也就是 /var/www/owncloud/data。默認(rèn)位置有幾個(gè)隱患一是如果 Web 服務(wù)器只有 root 用戶能訪問(wèn)后續(xù) PHP-FPM 寫(xiě)不進(jìn)去服務(wù)起不來(lái)二是 data 目錄放在 Web 根目錄下面萬(wàn)一 Nginx 配置錯(cuò)誤可能把用戶的文件直接暴露在瀏覽器上等于裸奔三是系統(tǒng)盤(pán)一旦滿了會(huì)影響整個(gè)服務(wù)器的運(yùn)行而單獨(dú)掛載的數(shù)據(jù)盤(pán)可以避免這種連鎖反應(yīng)。正確的做法是把 data 目錄放到一個(gè)獨(dú)立的、Web 不可達(dá)的位置。我的服務(wù)器數(shù)據(jù)盤(pán)掛在 /data 下所以我把數(shù)據(jù)目錄放在 /data/owncloud-datasudo mkdir -p /data/owncloud-data注意data 目錄掛載點(diǎn)不要放在 Web 目錄下面。OwnCloud 在初始化的時(shí)候會(huì)要求你輸入數(shù)據(jù)目錄的絕對(duì)路徑到時(shí)候填 /data/owncloud-data 即可。這個(gè)路徑目前還是空目錄權(quán)限先設(shè)置好等初始化的時(shí)候 OwnCloud 會(huì)往里面寫(xiě)入一些緩存和日志文件。3.3 PHP-FPM 用戶與目錄權(quán)限精細(xì)控制權(quán)限這塊是整個(gè) LNMP 架構(gòu)里最容易踩坑的環(huán)節(jié)。常見(jiàn)做法是 chmod 777但在生產(chǎn)環(huán)境這是比較大的安全隱患。任何用戶都能寫(xiě)意味著如果 Web 程序被攻破攻擊者可以在你的 Web 根目錄里寫(xiě)入任意文件進(jìn)一步拿到服務(wù)器權(quán)限。正確的思路是讓 PHP-FPM 的運(yùn)行用戶和 Nginx 的運(yùn)行用戶保持一致然后把這個(gè)用戶作為 OwnCloud 目錄的擁有者。Ubuntu 下 Nginx 默認(rèn)用戶是 www-dataPHP-FPM 默認(rèn)用戶也是 www-data所以直接給 www-data 授權(quán)即可sudo chown -R www-data:www-data /var/www/owncloud sudo chmod -R 750 /var/www/owncloud sudo chown -R www-data:www-data /data/owncloud-data sudo chmod -R 750 /data/owncloud-data這里 chmod 750 的意思擁有者 www-data 有讀寫(xiě)執(zhí)行權(quán)限所屬組有讀寫(xiě)執(zhí)行權(quán)限其他用戶無(wú)任何權(quán)限。既能保證 PHP-FPM 正常寫(xiě)緩存、寫(xiě)日志又防止其他系統(tǒng)用戶亂動(dòng) web 目錄。config 目錄和 config.php 文件建議單獨(dú)收緊權(quán)限sudo chmod 640 /var/www/owncloud/config/config.php保存敏感數(shù)據(jù)庫(kù)密碼的配置文件權(quán)限盡量收緊到只能 www-data 讀取寫(xiě)即可。3.4 Nginx 站點(diǎn)配置與請(qǐng)求路由編輯 /etc/nginx/sites-available/owncloud 配置文件內(nèi)容需要正確處理 PHP 請(qǐng)求和靜態(tài)資源server { listen 80; server_name your-domain.com; # 使用 HTTPS 后這部分會(huì)改成 443 并加 SSL 證書(shū)配置 root /var/www/owncloud; index index.php; client_max_body_size 1024M; client_body_timeout 300s; # 上傳請(qǐng)求的臨時(shí)目錄也可以單獨(dú)指定可選 location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ \.(?:ico|css|js|gif|jpe?g|png)$ { expires 1d; add_header Cache-Control public, immutable; } # 關(guān)鍵拒絕直接訪問(wèn) data 目錄下的文件 location ~ ^/data/ { deny all; } }這里面幾個(gè)關(guān)鍵點(diǎn)client_max_body_size 控制上傳文件大小上限。 默認(rèn)是 1M如果你不修改超過(guò) 1M 的文件傳到一半就會(huì)被 Nginx 拒絕報(bào) 413 錯(cuò)誤。個(gè)人用設(shè)成 1024M 甚至更大都沒(méi)問(wèn)題但要注意和 PHP 側(cè)的 upload_max_filesize 配合。try_files 規(guī)則確保了前端路由正常工作。OwnCloud 的部分頁(yè)面通過(guò) index.php 重寫(xiě)實(shí)現(xiàn)了友好的 URL沒(méi)有這條規(guī)則訪問(wèn)某些鏈接會(huì)直接 404。deny all 是對(duì) data 目錄的兜底保護(hù)。即使數(shù)據(jù)目錄不小心被放在了 Web 根目錄下這條規(guī)則也能阻止外部訪問(wèn)。創(chuàng)建完軟鏈接啟用站點(diǎn)配置同時(shí)禁用默認(rèn)站點(diǎn)避免沖突sudo ln -s /etc/nginx/sites-available/owncloud /etc/nginx/sites-enabled/ sudo rm /etc/nginx/sites-enabled/default sudo nginx -t sudo systemctl reload nginxnginx -t 是檢查配置語(yǔ)法如果輸出 syntax is ok 說(shuō)明配置沒(méi)問(wèn)題。這里我建議一定執(zhí)行一下配置語(yǔ)法錯(cuò)誤時(shí) restart 服務(wù)會(huì)直接失敗而這里能提前發(fā)現(xiàn)。4. Web 端初始化與關(guān)鍵參數(shù)配置4.1 瀏覽器安裝向?qū)Р僮魅鞒蘊(yùn)ginx 和 PHP 環(huán)境都就緒后在瀏覽器里輸入你的域名或服務(wù)器 IP就能進(jìn)入 OwnCloud 安裝界面。這個(gè)過(guò)程雖然簡(jiǎn)單但有幾個(gè)細(xì)節(jié)容易遺漏。安裝向?qū)枰来翁顚?xiě)管理員賬號(hào)和密碼。 管理員是整站權(quán)限最高的人建議用單獨(dú)的郵箱前綴不用 admin 這種默認(rèn)名稱。數(shù)據(jù)目錄路徑。 這里就填寫(xiě)之前準(zhǔn)備的 /data/owncloud-data不要用默認(rèn)路徑。數(shù)據(jù)庫(kù)配置。 數(shù)據(jù)庫(kù)類(lèi)型選 MySQL/MariaDB數(shù)據(jù)庫(kù)主機(jī)填 localhost用戶名填 owncloud密碼填之前設(shè)置的強(qiáng)密碼數(shù)據(jù)庫(kù)名填 owncloud。填寫(xiě)完成后點(diǎn)擊安裝完成按鈕OwnCloud 會(huì)自動(dòng)建表并初始化。過(guò)程大概十幾秒到一分鐘取決于服務(wù)器性能。如果中途報(bào)錯(cuò)通常和 PHP 擴(kuò)展缺失或者目錄權(quán)限有關(guān)下一步就去解決這個(gè)問(wèn)題。安裝完成后推薦先在后臺(tái)“設(shè)置”里面把默認(rèn)的推薦應(yīng)用裝上。OwnCloud 的默認(rèn)應(yīng)用列表里有文檔、日歷、聯(lián)系人等模塊按自己的需求啟用即可不需要的都關(guān)掉保持后臺(tái)干凈也減少攻擊面。4.2 安裝報(bào)錯(cuò)快速判斷思路安裝頁(yè)面如果遲遲不出現(xiàn)或者點(diǎn)擊安裝后報(bào)錯(cuò)需要快速定位是哪一環(huán)出了問(wèn)題。我常用的排查順序是先看 Nginx 和 PHP-FPM 狀態(tài)是否正常systemctl status nginx systemctl status php7.4-fpm再看 PHP 擴(kuò)展是否齊全。判斷方法是先臨時(shí)創(chuàng)建一個(gè)探針文件在 /var/www/owncloud 下創(chuàng)建 info.php內(nèi)容為 phpinfo();然后在瀏覽器訪問(wèn) http://你的服務(wù)器IP/info.php查看 phpinfo 頁(yè)面里是否列出了所有需要的擴(kuò)展。確認(rèn)之后立刻刪除這個(gè)探針文件因?yàn)?phpinfo 會(huì)暴露服務(wù)器細(xì)節(jié)數(shù)據(jù)。最后看日志PHP-FPM 的日志在 /var/log/php7.4-fpm.logNginx 錯(cuò)誤日志在 /var/log/nginx/error.log。絕大部分問(wèn)題的根因都在這兩個(gè)日志里比在網(wǎng)上搜報(bào)錯(cuò)得快得多。4.3 config.php 核心參數(shù)逐項(xiàng)說(shuō)明安裝完成后OwnCloud 的配置文件在 /var/www/owncloud/config/config.php該文件會(huì)自動(dòng)保存安裝時(shí)填寫(xiě)的所有信息。后續(xù)想修改域名、數(shù)據(jù)庫(kù)配置、調(diào)整一些高級(jí)功能都是通過(guò)編輯這個(gè)文件來(lái)操作。一個(gè)典型的 config.php 需要確認(rèn)以下字段?php $CONFIG array ( instanceid 自動(dòng)生成的ID, passwordsalt 自動(dòng)生成的鹽值, trusted_domains array ( 0 localhost, 1 your-domain.com, ), datadirectory /data/owncloud-data, dbtype mysql, version 10.x.x.x, overwrite.cli.url https://your-domain.com, htaccess.RewriteBase /, default_phone_region CN, memcache.local \OC\Memcache\APCu, logfile /data/owncloud-data/owncloud.log, loglevel 2, mail_smtpmode smtp, );trusted_domains 是域名白名單這個(gè)參數(shù)非常有用。 如果配置里沒(méi)加自己的域名那么通過(guò)這個(gè)域名訪問(wèn) OwnCloud 會(huì)直接報(bào)錯(cuò) “Access through untrusted domain”。這也是很多人裝完以后用 IP 能訪問(wèn)、用域名訪問(wèn)卻被拒絕的原因。添加域名時(shí)需要把域名寫(xiě)進(jìn)數(shù)組有幾個(gè)加幾個(gè)。overwrite.cli.url 的作用是讓后臺(tái)某些功能在 CLI 模式下生成正確的 URL比如郵件通知鏈接、分享鏈接。不填的話可能鏈接生成的域名是 localhost導(dǎo)致分享鏈接無(wú)效。default_phone_region 是設(shè)置默認(rèn)電話區(qū)號(hào)主要影響兩步驗(yàn)證功能。memcache.local 配置的是本地緩存驅(qū)動(dòng)加了 APCu 這行之后頁(yè)面加載速度會(huì)明顯提升。這個(gè)后面性能優(yōu)化部分會(huì)詳細(xì)講。4.4 上傳大小限制與 PHP 參數(shù)協(xié)調(diào)前面 Nginx 配了 client_max_body_size 1024M但 PHP 這邊默認(rèn)的上傳限制只有 2M如果不改超過(guò) 2M 的文件依然會(huì)失敗而且報(bào)錯(cuò)信息在 Web 端還看不明顯只會(huì)顯示“上傳失敗”或者網(wǎng)絡(luò)錯(cuò)誤。修改 PHP 上傳配置sudo vim /etc/php/7.4/fpm/php.ini找到并修改以下幾個(gè)參數(shù)memory_limit 512M upload_max_filesize 1000M post_max_size 1100M max_execution_time 3600 max_input_time 3600解釋一下這幾個(gè)參數(shù)的關(guān)系。post_max_size 必須大于 upload_max_filesize因?yàn)樯蟼鞯奈募前谝粋€(gè) POST 請(qǐng)求里的除了文件本身還有表單的其他字段。max_execution_time 影響的是大文件上傳時(shí) PHP 腳本的處理時(shí)間上限上傳速度慢的情況下腳本執(zhí)行時(shí)間可能超過(guò)默認(rèn)的 30 秒導(dǎo)致上傳中斷。修改完 php.ini 后必須重啟 PHP-FPM 才會(huì)生效sudo systemctl restart php7.4-fpm這里我踩過(guò)一次坑改了 php.ini 之后忘了重啟 PHP-FPM測(cè)試上傳一個(gè) 100MB 的文件還是失敗浪費(fèi)了大量時(shí)間排查 Nginx 配置和網(wǎng)絡(luò)最后才發(fā)現(xiàn)只是沒(méi)有重啟。養(yǎng)成修改配置后立刻重啟相關(guān)服務(wù)的習(xí)慣能省很多時(shí)間。5. 安全加固與性能優(yōu)化5.1 HTTPS 強(qiáng)制啟用自建網(wǎng)盤(pán)一定不要只用 HTTP 裸奔。傳文件的過(guò)程如果被中間人截獲賬號(hào)密碼和文件內(nèi)容都會(huì)泄露。啟用 TLS 最方便的方式是使用 Lets Encrypt 簽發(fā)免費(fèi)證書(shū)用一個(gè)名為 Certbot 的工具就能自動(dòng)完成申請(qǐng)和配置。安裝 Certbotsudo apt install certbot python3-certbot-nginx -y然后執(zhí)行申請(qǐng)命令注意預(yù)先將域名解析到這個(gè)服務(wù)器 IPsudo certbot --nginx -d your-domain.comCertbot 會(huì)自動(dòng)修改 Nginx 配置把 80 端口重定向到 443并配置證書(shū)。申請(qǐng)完成后證書(shū)的有效期是 90 天Certbot 會(huì)自動(dòng)續(xù)期不用你手動(dòng)管。但要注意申請(qǐng)過(guò)程需要域名能正常解析到你當(dāng)前服務(wù)器否則驗(yàn)證會(huì)失敗。啟用 HTTPS 之后順手再改一下 config.php把 overwrite.cli.url 改成 https 開(kāi)頭否則部分鏈接會(huì)繼續(xù)生成 http 地址。另外后臺(tái)如果開(kāi)了“分享到外部”的功能外面的用戶打開(kāi)分享鏈接時(shí)也會(huì)提示不安全這個(gè)細(xì)節(jié)容易被忽視。5.2 目錄權(quán)限巡檢與敏感文件保護(hù)權(quán)限問(wèn)題不僅要在部署時(shí)做平時(shí)也要定期檢查。我習(xí)慣每三個(gè)月跑一次權(quán)限巡檢腳本檢查關(guān)鍵目錄的屬主和權(quán)限是否被改過(guò)因?yàn)橛行┎寮蛘呤謩?dòng)操作會(huì)不小心把目錄權(quán)限改掉導(dǎo)致安全風(fēng)險(xiǎn)。重點(diǎn)檢查的對(duì)象/var/www/owncloud/config/config.php權(quán)限應(yīng)保持 640 或更嚴(yán)格屬主 www-data。/data/owncloud-data權(quán)限 750其他用戶不可讀。/var/www/owncloud/.htaccess 存在且內(nèi)容正常包含對(duì) data 目錄的保護(hù)規(guī)則。如果你用 Nginx.htaccess 并不會(huì)生效但 OwnCloud 后臺(tái)的安全檢測(cè)頁(yè)面會(huì)檢查它是否存在。它的存在相當(dāng)于一重額外保險(xiǎn)如果哪天你從 Nginx 切回 Apache它仍然能擋住數(shù)據(jù)目錄。也可以通過(guò) OwnCloud 后臺(tái)的“安全與設(shè)置警告”頁(yè)面直接檢查配置情況。進(jìn)入管理設(shè)置右上角管理員頭像菜單中的“設(shè)置”頁(yè)面上方會(huì)列出所有安全相關(guān)的警告包括目錄權(quán)限、數(shù)據(jù)目錄位置、HTTPS 狀態(tài)、內(nèi)存緩存等。這是官方提供的體檢指標(biāo)應(yīng)該養(yǎng)成定期查看的習(xí)慣。5.3 緩存配置與性能提升默認(rèn)情況下 OwnCloud 沒(méi)有啟用任何內(nèi)存緩存這意味著 PHP 每處理一個(gè)請(qǐng)求都要重新編譯一遍部分模板和配置信息頁(yè)面打開(kāi)速度和請(qǐng)求響應(yīng)速度都比較慢。安裝擴(kuò)展時(shí)已經(jīng)裝了 APCu 和 Redis現(xiàn)在只需要在 config.php 里啟用它們。APCu 作為本地緩存LOCALmemcache.local \OC\Memcache\APCu,如果用戶量較大、有多臺(tái)服務(wù)器或者頻繁使用文件鎖可以加 Redis 作為分布式緩存memcache.distributed \OC\Memcache\Redis, redis array ( host localhost, port 6379, ),個(gè)人使用場(chǎng)景下APCu 的成本最低效果也最明顯。我自己的服務(wù)器啟用 APCu 后后臺(tái)頁(yè)面加載時(shí)間從 1.5 秒降到了 0.3 秒左右體感非常明顯。需要注意的是安裝新的緩存配置后要來(lái)后臺(tái)看一下安全設(shè)置警告是否消失。有些場(chǎng)景下 APCu 和 Redis 的 PHP 擴(kuò)展版本不匹配會(huì)導(dǎo)致報(bào)錯(cuò)啟用后反而白屏這也需要檢查一下 PHP-FPM 的日志。5.4 后臺(tái)任務(wù)定時(shí)執(zhí)行配置OwnCloud 有一些后臺(tái)任務(wù)需要定期運(yùn)行比如清理過(guò)期文件版本、清理回收站、發(fā)送定時(shí)通知等。默認(rèn)情況下這些任務(wù)是在用戶每次訪問(wèn)網(wǎng)頁(yè)時(shí)隨機(jī)觸發(fā)執(zhí)行的也就是 AJAX 模式。這個(gè)模式實(shí)現(xiàn)起來(lái)最簡(jiǎn)單但隨著任務(wù)變多、用戶在線的頻率不一致會(huì)出現(xiàn)在線用戶離開(kāi)后任務(wù)長(zhǎng)時(shí)間不執(zhí)行的狀況。更可靠的方式是配置 Cron 定時(shí)任務(wù)。先在 OwnCloud 后臺(tái)“設(shè)置”中把后臺(tái)任務(wù)模式切換為 Cron然后在系統(tǒng) crontab 中添加定期執(zhí)行命令sudo crontab -u www-data -e添加一行*/5 * * * * php -f /var/www/owncloud/cron.php每 5 分鐘執(zhí)行一次 cron.php這樣文件過(guò)期清理、應(yīng)用更新檢查等任務(wù)都能按時(shí)運(yùn)行不再依賴用戶在線。這里有個(gè)細(xì)節(jié)使用 crontab -u www-data 而不是直接用 root 的 crontab是為了保證 cron 任務(wù)是以 www-data 用戶身份運(yùn)行和 PHP-FPM 保持一致避免因?yàn)闄?quán)限不一致導(dǎo)致某些任務(wù)寫(xiě)文件失敗。6. 常見(jiàn)問(wèn)題與排坑實(shí)錄6.1 安裝頁(yè)面無(wú)限回跳或請(qǐng)求 404癥狀訪問(wèn)安裝地址后能打開(kāi)第一頁(yè)但點(diǎn)擊安裝或者繼續(xù)后就跳回原來(lái)的頁(yè)面或者干脆 404。原因通常是兩種。一是 PHP 擴(kuò)展缺失比如 xml、mbstring 缺失時(shí)OwnCloud 會(huì)在初始化階段因?yàn)槟硞€(gè)函數(shù)不存在而終止頁(yè)面表現(xiàn)為跳回安裝。二是不小心把 site 配置里的 root 指向了錯(cuò)誤目錄。排查方法先看 PHP-FPM 錯(cuò)誤日志再執(zhí)行 php -m 列出當(dāng)前所有已加載擴(kuò)展和官方要求對(duì)比缺什么補(bǔ)什么。配置 root 目錄時(shí)需要確認(rèn)解壓出來(lái)的源碼包確實(shí)在對(duì)應(yīng)的路徑下。6.2 上傳大文件反復(fù)失敗小文件正常很多人在部署完成后發(fā)現(xiàn)上傳幾張圖片沒(méi)問(wèn)題但傳一個(gè) 2GB 的視頻文件就報(bào)錯(cuò)。這個(gè)問(wèn)題幾乎都是三個(gè)地方?jīng)]配齊導(dǎo)致的三個(gè)條件都滿足才能成功傳輸大文件。Nginx 的 client_max_body_size 是否已經(jīng)設(shè)為足夠大的值。PHP 的 upload_max_filesize 是否已經(jīng)調(diào)整。PHP 的 post_max_size 是否大于 upload_max_filesize。修改完三個(gè)參數(shù)并重啟 Nginx 和 PHP-FPM 之后再做測(cè)試。如果還失敗檢查磁盤(pán)可用空間上傳過(guò)程中文件會(huì)寫(xiě)入臨時(shí)目錄如果臨時(shí)目錄所在磁盤(pán)被寫(xiě)滿也會(huì)失敗。我自己常用一個(gè)測(cè)試方法先傳一個(gè)略大于上限的文件看報(bào)錯(cuò)信息是來(lái)自 Nginx 還是來(lái)自 PHP 還是來(lái)自應(yīng)用層。Nginx 報(bào) 413 錯(cuò)誤、PHP 報(bào) 502 或者超時(shí)、應(yīng)用層提示上傳失敗這三類(lèi)報(bào)錯(cuò)對(duì)應(yīng)完全不同的排查方向。把大文件拆成不同大小分別測(cè)試能很快定位卡點(diǎn)。6.3 502 Bad Gateway 錯(cuò)誤Nginx 返回 502 說(shuō)明 Nginx 無(wú)法和 PHP-FPM 通信原因一般有三個(gè)PHP-FPM 進(jìn)程崩潰或未啟動(dòng)。PHP-FPM 監(jiān)聽(tīng)地址和 Nginx 配置不一致。PHP-FPM 某個(gè) worker 執(zhí)行超時(shí)被終止。排查第一步查看 PHP-FPM 狀態(tài)sudo systemctl status php7.4-fpm如果狀態(tài)正常檢查 PHP-FPM 配置中的監(jiān)聽(tīng)方式。默認(rèn)是 unix socket 還是 TCP需要在 Nginx 配置里保持一致。Ubuntu 的 PHP-FPM 默認(rèn)是以 socket 方式監(jiān)聽(tīng)路徑在 /run/php/php7.4-fpm.sock如果 Nginx 里寫(xiě)的是 9000 端口就會(huì)連接不上出現(xiàn) 502。如果是偶發(fā)性的 502更多和 PHP 的 max_execution_time、memory_limit 有關(guān)。大文件預(yù)覽或者生成縮略圖時(shí)PHP 處理時(shí)間過(guò)長(zhǎng)被干掉也會(huì)表現(xiàn)為 502。日志里會(huì)記錄具體是哪個(gè)請(qǐng)求觸發(fā)的超時(shí)按日志信息針對(duì)性調(diào)參即可。6.4 客戶端同步時(shí)反復(fù)提示連接不上安裝完 OwnCloud 后用桌面客戶端登錄時(shí)提示無(wú)法連接到服務(wù)器但瀏覽器訪問(wèn)卻正常。這種情況最常見(jiàn)的根因是令牌認(rèn)證Token-based auth配置問(wèn)題或者客戶端地址填錯(cuò)。服務(wù)器地址要填完整的 HTTPS 地址和路徑比如 https://your-domain.com/owncloud不要只填域名。如果服務(wù)器開(kāi)了強(qiáng)制 HTTPS但客戶端填了 http 地址也會(huì)連接不上。還有一個(gè)比較隱蔽的原因服務(wù)器啟用了兩步驗(yàn)證但客戶端沒(méi)有輸入驗(yàn)證碼。打開(kāi)兩步驗(yàn)證后客戶端登錄時(shí)需要額外生成一個(gè)應(yīng)用專用密碼直接在客戶端里輸入賬號(hào)密碼是過(guò)不去的。在后臺(tái)“個(gè)人信息”里生成應(yīng)用密碼填給客戶端即可。6.5 同步文件數(shù)量和磁盤(pán)空間的關(guān)系最后補(bǔ)充一個(gè)容易忽視的細(xì)節(jié)OwnCloud 默認(rèn)啟用了文件版本控制功能每次文件修改都會(huì)保留上一個(gè)版本。如果一個(gè)文件被頻繁修改且文件體量很大版本記錄會(huì)一直占著磁盤(pán)空間。個(gè)人使用建議在后臺(tái)設(shè)置里把保留的版本數(shù)調(diào)小比如保留 3 個(gè)版本即可否則時(shí)間久了你可能驚訝地發(fā)現(xiàn)磁盤(pán)空間被版本記錄占滿了。后臺(tái)管理設(shè)置里的“文件版本控制”區(qū)域可以配置保留策略把“保留多少版本”設(shè)置為 3把“保留多少天”設(shè)置為 30能有效控制空間占用。這個(gè)設(shè)置我是在數(shù)據(jù)盤(pán)告警時(shí)才發(fā)現(xiàn)的當(dāng)時(shí)有 20GB 的磁盤(pán)空間被版本記錄占掉清理之后立刻釋放了空間。6.6 域名變更后如何平滑遷移如果以后換域名或者換服務(wù)器OwnCloud 遷移主要涉及幾個(gè)部分配置文件中的 trusted_domains、overwrite.cli.url 需要更新數(shù)據(jù)目錄整體復(fù)制到新服務(wù)器數(shù)據(jù)庫(kù) dump 后導(dǎo)入新庫(kù)。遷移時(shí)服務(wù)可以先停一停避免數(shù)據(jù)不一致。數(shù)據(jù)庫(kù)遷移命令mysqldump -u owncloud -p owncloud owncloud-backup.sql scp owncloud-backup.sql usernew-server:/data/到新服務(wù)器導(dǎo)入mysql -u owncloud -p owncloud owncloud-backup.sql數(shù)據(jù)目錄如果有 rsync建議用 rsync 同步而不是 scp因?yàn)?rsync 支持?jǐn)帱c(diǎn)續(xù)傳大目錄傳輸更可靠rsync -avz /data/owncloud-data/ usernew-server:/data/owncloud-data/遷移完成后修改 config.php 里的地址相關(guān)配置再刷新客戶端即可。根據(jù)我個(gè)人實(shí)際體驗(yàn)OwnCloud 自建網(wǎng)盤(pán)最花時(shí)間的并不是安裝過(guò)程而是后續(xù)的配置調(diào)優(yōu)和排坑。裝的次數(shù)多了以后你會(huì)慢慢形成自己的檢查清單安裝完成先看后臺(tái)安全告警再傳幾個(gè)不同大小的文件測(cè)試上傳鏈路最后再配置客戶端。這套流程下來(lái)基本不會(huì)再出問(wèn)題。目前這個(gè)方案我在個(gè)人服務(wù)器上跑了快兩年除了偶爾磁盤(pán)告警和系統(tǒng)更新之外幾乎沒(méi)有需要額外費(fèi)心的地方希望這篇記錄能幫你少走一些彎路。