之前经常用各家的网盘,有时候临时存文件,但是不想带u盘;有时候给人家分享文件,看着进度条一点点挪动发不出来,忍无可忍,无需再忍,我们自己部署一个。
1、前置准备
域名一个(可以自己创建二级域名,然后解析到服务器),云服务器一台(也可以考虑家里云,但是要自己查询相关注意事项,以免被判成在跑PCDN),域名证书(我们使用caddy,所以下载pem/key格式,即nginx通用格式即可)(二级域名请单独给它申请证书)。
创建我们放nextcloud的目录:
mkdir /home/naseele/nextcloud我们的项目基本路径大致如下(这里看看就行了,不用急着创建,需要手动创建的后面会提):
nextcloud
├── docker-compose.yml # 核心编排文件
├── Caddyfile # caddy反向代理配置
├── nextcloud_certs/ # 存放 SSL 证书 (.pem, .key)
├── html/ # Nextcloud 数据 (自动生成)
│ ├── config/config.php # (后续修改) 核心配置
│ └── .user.ini # (后续新建) PHP 优化配置
└── db/ # 数据库文件 (自动生成)2、挂载硬盘
我给nextcloud单独添加了一块小硬盘,如果你没有单独挂载硬盘的需求,请跳过本节,直接看第三章。
另外如果你用的是云服务器,我更推荐你去看你的服务器提供商的增挂硬盘教程,因为不同的服务商增加硬盘的预处理不同。这里仅展示雨云的作为参考。
2.1 查询硬盘情况
本节我们使用两个指令(lsblk和fdisk)确定新硬盘的情况。
首先查看硬盘和分区结构
sudo lsblk我们能看到类似:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 30G 0 disk
├─sda1 8:1 0 1M 0 part
└─sda2 8:2 0 30G 0 part /
sdb 8:16 0 30G 0 disk
sr0 11:0 1 1024M 0 rom参数解释:sda (30G disk): 这是我的第一块硬盘。
├─sda1: 一个极小的分区(1M),通常是引导分区。└─sda2: 主分区(30G)。- 注意看
MOUNTPOINTS这一列,sda2对应的是/。这意味着它是系统盘(根目录),你的系统在这上面。最好不要动它。
sdb (30G disk): 这是我的第二块硬盘。
- 有用信息 3:
MOUNTPOINTS这一列是空的(下面没有├─sdb1这种分支)。也就是说,这块盘存在,但系统还没开始用它。这就是我们要操作的目标。
sr0: 这是虚拟光驱(CD-ROM),通常是云服务商挂载系统镜像用的,直接忽略。
查看硬盘分区表、
sudo fdisk -l我们能看到类似:
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: CB7D37F2-E81E-412D-9A53-58CFF4AE9DC5
Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 62914526 62910431 30G Linux filesystem
Disk /dev/sdb: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
输出分三段,第二段详细列出了 sda 被切成了两块(sda1 和 sda2),并且明确标记了 sda2 是 "Linux filesystem",即我们的系统。这是先前就在使用的盘,不要动他,第三段是我们新加的盘,Disk /dev/sdb: 30 GiB 确认了它的容量大小。它没有任何 "Device ... Start ... End" 的列表,说明这是一块完全纯净的“白板”硬盘,里面连分区表都没有,更别提文件系统了。
综上,我们的新硬盘sdb的大小为30gb,没有分区信息,也没有挂载(MOUNTPOINTS 为空)。
2.2 硬盘初始化与挂载
因为硬盘没有分区信息,我们不能直接挂载,需要先格式化
1. 格式化硬盘
我们将 /dev/sdb 格式化为 ext4 文件系统:
sudo mkfs.ext4 /dev/sdb2. 创建挂载点
创建我们想要挂载的那个目录:
mkdir -p /home/naseele/nextcloud3. 获取硬盘 UUID
为了防止重启后盘符变化(比如 sdb 变成 sdc),我们需要用 UUID 挂载。输入:
sudo blkid /dev/sdb复制输出结果中 UUID="xxxx-xxxx..." 引号里的那串字符。
4. 配置开机自动挂载
编辑 /etc/fstab 文件:
sudo nano /etc/fstab在文件末尾添加一行(请把 你的UUID 替换为刚才复制的字符):
UUID=你的UUID /home/naseele/nextcloud ext4 defaults 0 0按 Ctrl+O 保存,Enter 确认,Ctrl+X 退出。(nano的快捷键是这个,使用其他文本编辑器的请自行百度)
最后我们的fstab文件的内容类似这样:
UUID="7378aa-c12a-6c8d-xt89-ad57so69yhb3" /home/naseele/nextcloud ext4 defaults 0 05. 挂载并修复权限
现在立刻挂载,并把所有权交给我的宿主机用户 naseele
sudo mount -a
sudo chown -R naseele:naseele /home/naseele/nextcloud2.3 创建必要目录
在 /home/naseele/nextcloud 下创建结构:
mkdir -p html db caddy_data caddy_config nextcloud_certs3、创建配置文件
3.1 容器编排
现在来为我们的 Nextcloud 创建 docker-compose.yml
进入目录:
cd /home/naseele/nextcloud新建 docker-compose.yml:
nano docker-compose.ymlservices:
# === 1. 数据库服务 ===
nextcloud-db:
image: mariadb:10.6
container_name: nextcloud_db
restart: always
# === 给它 最多 1 分钟的优雅退出的时间 ===
stop_grace_period: 1m
# 数据库性能优化参数
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
volumes:
- ./db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=你的Root密码
- MYSQL_PASSWORD=你的数据库密码
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- TZ=Asia/Shanghai
# === 2. 缓存服务 (带密码) ===
redis:
image: redis:alpine
container_name: nextcloud_redis
restart: always
# 启用密码保护
command: redis-server --requirepass 你的Redis强密码
environment:
- TZ=Asia/Shanghai
# === 3. Nextcloud 应用服务 ===
nextcloud-app:
image: nextcloud:latest
container_name: nextcloud_app
restart: always
depends_on:
- nextcloud-db
- redis
environment:
- MYSQL_PASSWORD=你的数据库密码
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_HOST=nextcloud-db
# 域名信任
- NEXTCLOUD_TRUSTED_DOMAINS=你的nextcloud域名
- PHP_MEMORY_LIMIT=4G
# Redis 连接配置
- REDIS_HOST=redis
- REDIS_HOST_PASSWORD=你的Redis强密码
- TZ=Asia/Shanghai
# === 禁用 IPv6 配置 ===
sysctls:
- net.ipv6.conf.all.disable_ipv6=1
- net.ipv6.conf.default.disable_ipv6=1
# 国内环境 DNS 优化 (解决无法连接应用商店/更新)
dns:
- 223.5.5.5
- 114.114.114.114
volumes:
- ./html:/var/www/html
# === 4. Caddy 反向代理 (整合进来了) ===
caddy:
image: caddy:latest
container_name: caddy
restart: always
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./caddy_data:/data
- ./caddy_config:/config
# 挂载证书目录
- ./nextcloud_certs:/etc/caddy/certs
environment:
- TZ=Asia/Shanghai
depends_on:
- nextcloud-app请自行替换第12、13、24、37、45行的密码(填你自己编的密码就行,但是最好复杂一些,这个密码平时我们不用手动输入,不用担心记不住),并确保13行与37行的MYSQL_PASSWORD内容一致、24与45行的redis密码内容一致。
目录结构说明: 部署并启动后,你的 /home/naseele/nextcloud 下会自动生成两个文件夹(如果已经创建了也不影响):
./db: 存放数据库文件(占用新硬盘空间)。./html: 存放 Nextcloud 程序和所有用户上传的照片/文件(占用新硬盘空间)。 这样就完美实现了数据隔离。
3.2 反向代理配置
在/home/naseele/nextcloud下:
touch Caddyfile修改Caddyfile:
# 全局配置:关闭 OCSP Stapling (解决国内启动卡顿/超时)
{
ocsp_stapling off
}
你的域名 {
encode gzip
# 1. 完善的服务发现 (适配 iOS/macOS 客户端)
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
redir /.well-known/webfinger /index.php/.well-known/webfinger 301
redir /.well-known/nodeinfo /index.php/.well-known/nodeinfo 301
# 2. 安全与 HSTS
header {
Strict-Transport-Security "max-age=15552000; includeSubDomains"
}
# 3. 反向代理核心配置
reverse_proxy nextcloud_app:80 {
# 头部透传 (修复登录循环、生成正确链接)
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-Port {server_port}
# 大文件上传超时优化 (防止 502 错误)
transport http {
response_header_timeout 7200s
}
}
# SSL 证书 (容器内路径)
tls /etc/caddy/certs/nextcloud.pem /etc/caddy/certs/nextcloud.key
}这里我们关闭了OCSP功能,因为它会拖慢caddy的启动速度,详情请参阅这篇文章。
3.3 上传域名证书
请将证书上传至 /home/naseele/nextcloud/nextcloud_certs下,并确保它们的名字与Caddyfile中的文件名称一致。我们Caddyfile中这一行
tls /etc/caddy/certs/nextcloud.pem /etc/caddy/certs/nextcloud.key规定了两个文件的名字和路径,请自行适配。
3.4 启动容器
docker compose up -d4、配置优化
4.1 PHP 运行限制优化 (.user.ini)
路径: /home/naseele/nextcloud/html/.user.ini (需手动创建或修改),如果无修改权限请加sudo,修改后记得确定文件所有者还是www-data。
目标:允许 100G 大文件上传,防止超时。
upload_max_filesize=100G
post_max_size=100G
memory_limit=1024M
max_input_time=7200
max_execution_time=7200
output_buffering=04.2 Nextcloud 核心配置 (config.php)
路径: /home/naseele/nextcloud/html/config/config.php
目标:开启 APCu/Redis 缓存、修复网络连接、本地化。
<?php
$CONFIG = array (
// ... 其他自动生成的配置 ...
// === 1. HTTPS 强制修正 ===
'overwriteprotocol' => 'https',
'overwrite.cli.url' => 'https://你的域名',
// === 2. 信任代理 (Docker网段) ===
'trusted_proxies' => ['172.16.0.0/12', '192.168.0.0/16', '10.0.0.0/8'],
// === 3. 缓存策略 (APCu + Redis)(应该已经带了,不要重复添加) ===
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
// === 4. 网络连接修复 (国内环境)(可选) ===
'has_internet_connection' => true,
'connectivity_request_domains' => ['www.baidu.com', 'www.qq.com'],
'connectivity_request_url' => 'https://www.baidu.com',
// === 5. 本地化与维护 ===
'default_phone_region' => 'CN',
'maintenance_window_start' => 2, // 对应北京时间 02:00 (因容器已设TZ)
// === 6. 临时目录指向挂载盘 ===
'tempdirectory' => '/var/www/html/data/tmp',
);
5. 性能与功能调优命令
本节命令均在 /home/naseele/nextcloud 目录下执行。
5.1 设置分块上传大小
如果上行带宽比较小,设置 20MB 分块以保证稳定性。
docker exec -u 33 -it nextcloud_app php occ config:system:set files.chunked_upload.max_size --value 20971520 --type int5.2 预览图尺寸限制
如果你安装了Preview Generator插件,请看看本节。
默认情况下,当你打开手机相册或网页看图时,Nextcloud 是“实时”生成缩略图的。如果你存了几千张照片,滑动的时候 CPU 会瞬间飙升,界面卡顿,图片一片黑,加载半天才出来。
Preview Generator 插件会在后台利用 Cron 任务,提前把你所有照片的缩略图生成好。等你打开相册时,直接从硬盘读取。但是我们也要考虑硬盘占用的问题。
安装好先别急着执行php occ preview:generate-all,先做一些调优,防止我们的存储空间被占满。
设置预览图的最大宽高(推荐设为 1024 或 2048),防止生成过大缩略图占满硬盘。
docker exec -u 33 -it nextcloud_app php occ config:system:set preview_max_x --value 2048 --type int
docker exec -u 33 -it nextcloud_app php occ config:system:set preview_max_y --value 2048 --type int限制系统级最大预览图
# 限制系统级最大预览图 (2048px)
docker exec -u 33 -it nextcloud_app php occ config:system:set preview_max_x --value 2048 --type int
docker exec -u 33 -it nextcloud_app php occ config:system:set preview_max_y --value 2048 --type int启用 jpeg 压缩 (默认就是开的,确认一下)
docker exec -u 33 -it nextcloud_app php occ config:system:set preview_max_scale_factor --value 1 --type int指定只生成哪几种预览 (可选,高级优化)
这个在启用插件后去 管理设置-回忆 修改
还可以将预览 JPEG 质量设置为 60,以更低的质量预览,节省更多空间。
docker exec -u 33 -it nextcloud_app php occ config:system:set jpeg_quality --value="60" --type=integer
docker exec -u 33 -it nextcloud_app php occ config:app:set preview jpeg_quality --value="60" --type=integer我想重置/重新生成所有预览。
如果你以前已经生成了一堆巨大的缩略图,或者你发现 appdata_xxxx/preview 文件夹太大了,想反悔,可以随时清空所有缩略图重新来: (注意:这会让看图暂时变卡,直到新图生成完毕)(以下部分参考官方仓库)
请在服务器上运行
docker exec -u 33 -it nextcloud_app php occ preview:cleanup更多信息请参阅文档。
警告:此方法未经官方支持,但已有多位用户证实有效。请自行承担风险。务必保留备份。
- 删除文件夹
your-nextcloud-data-directory/appdata_*/preview - 可选:更改参数
preview_max_x和(例如,更改为preview_max_y) ,并根据 README更改应用程序参数、和(或者更好的是,分别更改为较低的值,例如,和)。config.php512previewgeneratorheightSizessquareSizeswidthSizes512256512 - 运行
occ files:scan-app-data(这将重置数据库中生成的预览) - 运行
occ preview:generate-all [user-id](如果您已完成步骤 2,则此操作将运行得非常快)
配置完成,开始生成缩略图(初次可以用一下这个,之后建议配置定时任务,详见6.自动化维护):
docker exec -u 33 -it nextcloud_app php occ preview:generate-all如果你的服务器CPU核数较多,可以换用这个生成缩略图:
# 这里的 4 代表 4 个并行进程,根据你 CPU 核心数调整,太高会卡
docker exec -u 33 -it nextcloud_app php occ preview:generate-all --workers=4注:如果报错OCP\Files\GenericFileException怎么办?
请在宿主机执行:
# 强制把 html 目录及其下所有文件的归属权交给 www-data (ID 33)
sudo chown -R 33:33 /home/naseele/nextcloud/html清理可能损坏的缓存
因为刚才生成失败,可能留下了一些半成品的锁或者空文件夹,建议先清理一下应用数据缓存:
docker exec -u 33 -it nextcloud_app php occ files:scan-app-data给命令“开挂”
我们不依赖配置文件的限制,直接在命令行里强制给 PHP 无限内存和无限执行时间。
请运行这条“满血版”命令(注意加了 -d 参数):
docker exec -u 33 -it nextcloud_app php -d memory_limit=-1 -d max_execution_time=0 occ preview:generate-all -vvmemory_limit=-1:内存无上限(只要物理内存够)。max_execution_time=0:永不超时。-vv:开启详细日志,这样如果还报错,我们能看到具体是哪一张图片导致的。
如果用这个“满血版”命令可行,请使用ctrl + c打断生成,然后用这个命令来。建议跑到后台运行,使用screen或者byobu保证后台常驻。多线程请用这个满血版命令:
docker exec -u 33 -it nextcloud_app php -d memory_limit=-1 -d max_execution_time=0 occ preview:generate-all --workers=4 -vv多线程用户如果发现加上 --workers=4 后又开始报 GenericFileException 或者数据库锁死(因为 4 个进程同时抢着写数据库),请降低并发数。
把 --workers=4 改成 --workers=2 试试。有时候“慢即是快”,2 个稳定的线程比 4 个总是报错的线程要快得多。
5.3 其他插件安装(可选)
Memories: 替代原生相册,体验极佳。如果要使用这个和Preview Generator配合,需要额外执行:
docker exec -u 33 -it nextcloud_app php occ config:app:set --value="256" previewgenerator coverWidthHeightSizes关于memories的调优我单独写了一篇文章,如有需要请参考这篇文章。
6. 自动化维护 (Crontab)
先到nextcloud网页端后台,管理设置-基本设置,将后台任务Cron模式,然后手动执行
docker exec -u 33 nextcloud_app php cron.php 在宿主机执行
crontab -e如果你安装了5.2所说的插件Preview Generator,请写入这个配置:
# ==================================================
# Nextcloud 自动化任务 (服务器时间: UTC)
# ==================================================
# 1. 核心后台任务 (Cron.php)
# 频率:每 5 分钟一次
# 优化:使用 [ -n ... ] 严格判断容器是否存活,防止容器关闭时报错刷屏
*/5 * * * * [ -n "$(docker ps -q -f name=nextcloud_app)" ] && docker exec -u 33 nextcloud_app php cron.php > /dev/null 2>> /home/naseele/nextcloud_cron_errors.log
# 2. 缩略图预生成 (Preview Generator)
# 目标:北京时间凌晨 04:00 -> 对应 UTC 时间 20:00
# 优化:设为 20:02 执行,故意错开核心任务 (20:00 那次),避免 CPU 撞车
*/20 * * * * [ -n "$(docker ps -q -f name=nextcloud_app)" ] && docker exec -u 33 nextcloud_app php occ preview:pre-generate > /dev/null 2>> /home/naseele/nextcloud_preview_errors.log如果没有安装那个插件,我们只用考虑nextcloud本身的定时任务就行,请写入这个配置:
# 1. 核心后台任务 (Cron.php)
# 频率:每 5 分钟一次
# 优化:使用 [ -n ... ] 严格判断容器是否存活,防止容器关闭时报错刷屏
*/5 * * * * [ -n "$(docker ps -q -f name=nextcloud_app)" ] && docker exec -u 33 nextcloud_app php cron.php > /dev/null 2>> /home/naseele/nextcloud_cron_errors.log7. 排除文件夹
nextcloud自带的照片文件夹以及我们安装的memories都会进行全盘扫描和图片聚合,但是有些图片我们不想让他聚合,怎么办?方法很简单,在我们想屏蔽的目录创建一个文件,命名为.nomedia,就可以了。创建之后它默认隐藏(nextcloud默认不显示.开头的文件),但是我们试着往这个文件夹上传叫.nomedia的文件的时候,会提示已经有一个叫这个名字的文件了。
注意,一旦我们在这个文件夹放了这个文件,此文件夹及其子文件夹的所有媒体文件都会被排除。
如果你不想在网页端这边创建,可以在电脑创建然后上传(用windows的务必先打开显示文件后缀再创建);或者用指令直接在服务器后台生成这个文件(记得替换路径中的用户名 Naseele 和目标文件夹路径):
docker exec -u 33 nextcloud_app touch "/var/www/html/data/Naseele/files/你的/文件夹/路径/.nomedia"如果你没有装memories,到此应该没什么问题了,装memories的朋友可能发现图片还在展示,因为memories弄的索引还在,我们手动刷新一下:
docker exec -u 33 -it nextcloud_app php occ memories:index这样就大功告成了,被屏蔽文件依然安全地保存在硬盘里,我们可以通过“文件”列表找到并下载它们,只是不再在“照片”(或记忆)里单独展示。
如果你发现虽然照片没了,但之前生成的缩略图好像还在占空间,可以跑一次清理(非必须):
docker exec -u 33 -it nextcloud_app php occ files:scan-app-data

Comments NOTHING