剪藏#IT老菜鸟#剪藏
Seafile 私有云盘 + Cloudflare 内网穿透
2026 年 5 月 23 日 约 1 分钟


🚀公众号后台复【布道者】查看最新AI技术学习路线🚀
Seafile 私有云盘 + Cloudflare 内网穿透
基于 Docker Compose,一键部署 Seafile 私有云。
版本: 2026.03.29




快速开始
1. 环境检查
JAVASCRIPT
docker --version
docker compose version2. 配置修改
编辑 config/.env,设置:
-
PUBLIC_DOMAIN- 你的域名 -
SEAFILE_ADMIN_EMAIL- 管理员邮箱 -
SEAFILE_ADMIN_PASSWORD- 管理员密码 -
MYSQL_ROOT_PASSWORD- 数据库 root 密码 -
MYSQL_PASSWORD- 数据库用户密码
密码生成工具:
JAVASCRIPT
generate_password() { tr -dc 'A-Za-z0-9' </dev/urandom | head -c 16; }
echo "密码: $(generate_password)"3. 一键部署
JAVASCRIPT
chmod +x deploy.sh
./deploy.sh访问:http://IP:10080
架构
JAVASCRIPT
┌─────────┐ ┌──────────┐ ┌────────────┐
│ Caddy │────▶│ Seafile │────▶│ MariaDB │
│ :10080 │ │ :80 │ │ :3306 │
└─────────┘ └──────────┘ └────────────┘
└────────────┐
▼
┌──────────┐
│Memcached │
│ :11211 │
└──────────┘流量路径
JAVASCRIPT
用户 → Cloudflare HTTPS → cloudflared → Caddy:10080 → seafile-app:80
↓
容器内 Nginx
/ \
Gunicorn Fileserver
:8000 :8082目录结构
JAVASCRIPT
seafile-deploy/
├── deploy.sh # 主部署脚本
├── config/ # 配置文件
│ ├── .env# 环境变量
│ ├── docker-compose.yml # 服务配置
│ └── Caddyfile # 反向代理
├── scripts/ # 辅助脚本
│ └── config_seafile.sh # 应用配置
└── data/ # 数据存储
├── seafile/ # 应用数据
├── mariadb/ # 数据库
└── caddy/ # Caddy 数据和日志服务管理
JAVASCRIPT
docker compose -p seafile -f config/docker-compose.yml up -d # 启动
docker compose -p seafile -f config/docker-compose.yml down # 停止
docker compose -p seafile -f config/docker-compose.yml restart # 重启
docker compose -p seafile -f config/docker-compose.yml logs -f # 日志数据备份
JAVASCRIPT
# 备份
docker compose -p seafile -f config/docker-compose.yml down
tar -czvf seafile-backup-$(date +%Y%m%d).tar.gz data/
docker compose -p seafile -f config/docker-compose.yml up -d
# 恢复
docker compose -p seafile -f config/docker-compose.yml down
rm -rf data/
tar -xzf seafile-backup-20240101.tar.gz
docker compose -p seafile -f config/docker-compose.yml up -d配置说明
环境变量 (.env)
-
服务器:
SERVER_IP,HTTP_PORT -
管理员:
SEAFILE_ADMIN_EMAIL,SEAFILE_ADMIN_PASSWORD -
数据库:
MYSQL_PASSWORD,MYSQL_ROOT_PASSWORD -
时区:
TZ
Docker Compose (docker-compose.yml)
-
服务:MariaDB、Memcached、Seafile、Caddy
-
数据:本地目录挂载
-
资源:树莓派优化配置
-
健康:服务状态检查
💡 缓存建议:Seafile 镜像默认使用 Memcached,零配置即可工作。如使用 Redis 需要额外配置
seahub_settings.py,复杂度较高,建议保持默认的 Memcached。
重要说明
本部署使用 Cloudflare Tunnel (cloudflared) 暴露服务,HTTPS 由 Cloudflare 处理,Caddy 只接收 HTTP 请求。
无需修改 Caddyfile 配置,当前的 HTTP 配置已经正确工作。
极简主义 · UNIX哲学 · 一键部署
目录结构
JAVASCRIPT
pi@pi: /DATA/AppData/seafile $ tree -L 2
├── config
│ ├── Caddyfile
│ └── docker-compose.yml
├── data
│ ├── caddy
│ ├── mariadb
│ └── seafile
├── deploy.sh
├── README.md
└── scripts
└── config_seafile.sh
7 directories, 5 files
pi@pi: /DATA/AppData/seafile $ config/.env
JAVASCRIPT
# Seafile 极简部署配置
# 版本: 2026.03.27
# 遵循UNIX哲学:Just Enough
# ------------------------------
# 基础配置(必须)
# ------------------------------
PUBLIC_DOMAIN="seafile.example.com"# ✅ 取消注释,统一域名
SERVER_IP="192.168.1.10"
HTTP_PORT="10082"
SEAFILE_ADMIN_EMAIL="admin@seafile.local"
SEAFILE_ADMIN_PASSWORD="8tL1YAJS1j3fJ9iJ"
# ------------------------------
# 数据库配置(必须)
# ------------------------------
MYSQL_PASSWORD="TuYgDlXtCM87SwUd"
MYSQL_ROOT_PASSWORD="bVoPKKGjZA6g9RRR"
# ------------------------------
# 时区配置(必须)
# ------------------------------
TZ="Asia/Shanghai"
# ------------------------------
# 信任域配置(自动生成)
# ------------------------------
TRUSTED_DOMAINS="127.0.0.1,localhost,${SERVER_IP},${PUBLIC_DOMAIN}"# ✅ 用变量
SEAFILE_TRUSTED_DOMAINS="${TRUSTED_DOMAINS}"
# ------------------------------
# 性能优化配置
# ------------------------------
MAX_UPLOAD_SIZE="10737418240"# 10GB
MEMORY_LIMIT="1G"config/Caddyfile
JAVASCRIPT
# Seafile 极简部署配置
# 版本: 2026.03.27
# 遵循UNIX哲学:Just Enough
:80 {
request_body {
max_size 10GB
}
reverse_proxy seafile-app:80 {
transport http {
keepalive 300s
read_timeout 3600s
write_timeout 3600s
dial_timeout 10s
}
}
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
X-XSS-Protection "1; mode=block"
X-Robots-Tag "none"
Strict-Transport-Security "max-age=31536000; includeSubDomains"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
encode gzip zstd
log {
level INFO
output file /var/log/caddy/access.log {
roll_size 10MB
roll_keep 5
roll_keep_for 720h
}
}
}config/docker-compose.yml
JAVASCRIPT
# Seafile 极简部署配置
# 版本: 2026.03.27
# 遵循UNIX哲学:Just Enough
# 环境变量配置
x-seafile-env: &seafile-env
DB_HOST: mariadb
DB_ROOT_PASSWD: ${MYSQL_ROOT_PASSWORD}
DB_NAME: seafile
DB_USER: seafile
DB_PASSWD: ${MYSQL_PASSWORD}
SEAFILE_ADMIN_EMAIL: ${SEAFILE_ADMIN_EMAIL}
SEAFILE_ADMIN_PASSWORD: ${SEAFILE_ADMIN_PASSWORD}
SEAFILE_SERVER_HOSTNAME: ${PUBLIC_DOMAIN}# ✅ 关键:改成域名,不要IP+端口
SEAFILE_TIME_ZONE: ${TZ}
SEAFILE_SERVER_LETSENCRYPT: "false"
SEAFILE_SERVER_PROTOCOL: "http"# ✅ 容器内使用HTTP,外部由代理处理HTTPS
SEAFILE_SERVICE_URL: "http://${PUBLIC_DOMAIN}"# ✅ 内部通信使用HTTP
SEAFILE_FILE_SERVER_ROOT: "http://${PUBLIC_DOMAIN}/seafhttp"# ✅ 内部文件服务使用HTTP
# 目录挂载配置
volumes:
seafile_data:
driver: local
driver_opts:
type: none
o: bind
device: ../data/seafile
mariadb_data:
driver: local
driver_opts:
type: none
o: bind
device: ../data/mariadb
caddy_data:
driver: local
driver_opts:
type: none
o: bind
device: ../data/caddy
caddy_config:
driver: local
driver_opts:
type: none
o: bind
device: ../data/caddy/config
caddy_log:
driver: local
driver_opts:
type: none
o: bind
device: ../data/caddy/log
# 网络配置
networks:
default:
driver: bridge
ipam:
config:
- subnet: 172.32.0.0/16
# 服务配置
services:
# 数据库服务
mariadb:
image: m.daocloud.io/docker.io/library/mariadb:latest
container_name: seafile-db
restart: always
volumes: [mariadb_data:/var/lib/mysql]
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: seafile
MYSQL_USER: seafile
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
TZ: ${TZ}
command: >
--transaction-isolation=READ-COMMITTED
--binlog-format=ROW
--innodb_buffer_pool_size=256M
--innodb_log_file_size=64M
--max_connections=100
--skip-name-resolve
networks: [default]
healthcheck:
test: ["CMD", "mariadb-admin", "piJAVASCRIPT
ng", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 60s
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '1.0'
memory: 1G
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
# Memcached 缓存服务
memcached:
image: m.daocloud.io/docker.io/library/memcached:alpine
container_name: seafile-cache
restart: always
command: memcached -m 256
networks: [default]
healthcheck:
test: ["CMD", "echo", "flush_all", "|", "nc", "localhost", "11211"]
interval: 10s
timeout: 5s
retries: 3
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "2"
# Seafile 应用服务
seafile:
image: m.daocloud.io/docker.io/seafileltd/seafile-mc:latest
container_name: seafile-app
restart: always
dns:
- 223.5.5.5 # 阿里云DNS(国内首选,解析速度快、稳定)
- 114.114.114.114 # 备用DNS,避免单DNS故障
- 8.8.8.8 # 谷歌DNS(备用)
volumes:
- seafile_data:/shared
- type: tmpfs
target: /tmp
tmpfs:
size: 256M
environment:
<<: *seafile-env
MAX_UPLOAD_SIZE: ${MAX_UPLOAD_SIZE}
MEMORY_LIMIT: ${MEMORY_LIMIT}
networks: [default]
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 180s
deploy:
resources:
limits:
cpus: '1.0'
memory: ${MEMORY_LIMIT}
reservations:
cpus: '0.5'
memory: 512M
logging:
driver: "json-file"
options:
max-size: "20m"
max-file: "5"
depends_on:
mariadb: {conditiJAVASCRIPT
on: service_healthy}
memcached: {condition: service_healthy}
# Caddy 反向代理服务
caddy:
image: m.daocloud.io/docker.io/library/caddy:alpine
container_name: seafile-proxy
restart: always
ports: ["${HTTP_PORT}:80"]
dns:
- 223.5.5.5 # 阿里云DNS(国内首选,解析速度快、稳定)
- 114.114.114.114 # 备用DNS,避免单DNS故障
- 8.8.8.8 # 谷歌DNS(备用)
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
- caddy_log:/var/log/caddy
networks: [default]
environment:
- SERVER_IP=${SERVER_IP}
- HTTP_PORT=${HTTP_PORT}
- CADDY_ADMIN=0.0.0.0:2019
- TZ=${TZ}
command: sh -c "caddy run --config /etc/caddy/Caddyfile --adapter caddyfile"
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:2019/config || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
depends_on:
seafile: {condition: service_healthy}scripts/config_seafile.sh
JAVASCRIPT
# Seafile 极简部署配置
# 版本: 2026.03.27
# 遵循UNIX哲学:Just Enough
#!/bin/bash
set -euo pipefail
# 路径定义
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CONFIG_DIR="$PROJECT_DIR/config"
# 检查环境文件
[[ -f "$CONFIG_DIR/.env" ]] || { echo "错误: 缺少 $CONFIG_DIR/.env" >&2; exit 1; }
# 加载环境变量
set -a
source "$CONFIG_DIR/.env"
set +a
# Docker Compose 命令
DOCKER_COMPOSE_CMD=$(command -v docker-compose || echo "docker compose")
# 在 Seafile 容器内执行命令
seafile_exec() {
$DOCKER_COMPOSE_CMD -p seafile -f "$CONFIG_DIR/docker-compose.yml" exec -T seafile bash -c "$1"
}
# 安全添加配置(覆盖已存在的配置)
add_config() {
local conf="$1"
local value="$2"
local key="${value%%=*}"
key="${key%"${key##*[![:space:]]}"}"
seafile_exec "touch ${conf}"
if grep -qE "^${key}[[:space:]]*=" ${conf} 2>/dev/null; then
seafile_exec "sed -i \"s#^${key}[[:space:]]*=.*#${value}#\" ${conf}"
else
seafile_exec "echo '${value}' >> ${conf}"
fi
}
# 检查服务是否就绪
check_seafile_ready() {
echo "→ 检查 Seafile 服务状态"
local attempts=0
local max_attempts=10
while [ $attempts -lt $max_attempts ]; do
if seafile_exec "curl -s -L http://localhost >/dev/null 2>&1"; then
echo "✅ 服务正常"
return 0
fi
attempts=$((attempts + 1))
echo "⏳ 等待服务启动... (尝试 $attempts/$max_attempts)"
sleep 5
done
echo "❌ 服务异常" >&2
return 1
}
# 配置 Gunicorn
configure_gunicorn() {
echo "→ 配置 Gunicorn 监听"
seafile_exec "sed -i 's/bind = \"127.0.0.1:8000\"/bind = \"0.0.0.0:8000\"/' /opt/seafile/conf/gunicorn.conf.py"
echo "✅ 完成"
}
# 配置 Seahub(从 .env 读取域名,无硬编码)
configure_seahub() {
echo "→ 配置 seahub_settings.py"
local conf="/opt/seafile/conf/seahub_settings.py"
add_config "$conf" 'MAX_UPLOAD_SIZE = "10737418240"'
add_config "$conf" 'TIME_ZONE = "Asia/Shanghai"'
add_config "$conf" 'CSRF_TRUSTED_ORIGINS = ["https://seafile.example.com", "http://192.168.1.10:10082", "http://localhost", "JAVASCRIPT
http://127.0.0.1"]'
add_config "$conf" 'ALLOWED_HOSTS = ["*"]'
# 动态协议配置,支持HTTP和HTTPS
add_config "$conf" 'SERVICE_URL = "https://seafile.example.com"'
add_config "$conf" 'FILE_SERVER_ROOT = "https://seafile.example.com/seafhttp"'
# 代理 HTTPS 关键配置
add_config "$conf" 'USE_X_FORWARDED_HOST = True'
add_config "$conf" 'SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")'
# 信任代理配置(允许 Caddy/Cloudflared 作为代理)
add_config "$conf" 'TRUSTED_PROXIES = ["172.32.0.0/16", "127.0.0.1"]'
# Cookie 安全配置(内部是 HTTP,反向代理已传递 X-Forwarded-Proto)
add_config "$conf" 'CSRF_COOKIE_SECURE = False'
add_config "$conf" 'SESSION_COOKIE_SECURE = False'
add_config "$conf" 'CSRF_COOKIE_SAMESITE = "Lax"'
add_config "$conf" 'SESSION_COOKIE_SAMESITE = "Lax"'
echo "✅ 完成"
}
# 配置文件服务器(从 .env 读取域名)
configure_fileserver() {
echo "→ 配置 seafile.conf 文件服务"
local conf="/opt/seafile/conf/seafile.conf"
seafile_exec "touch '$conf'"
seafile_exec "grep -q '\[fileserver\]' '$conf' || echo -e '\n[fileserver]' >> '$conf'"
seafile_exec "sed -i '/^\[fileserver\]/,/^$/ s/^host =.*/host = 0.0.0.0/' '$conf'"
seafile_exec "sed -i '/^\[fileserver\]/,/^$/ s/^port =.*/port = 8082/' '$conf'"
seafile_exec "sed -i '/^\[fileserver\]/,/^$/ s/^web_root =.*/web_root = \/seafhttp/' '$conf'"
echo "✅ 完成"
}
# 主流程
main() {
echo "🚀 开始配置 Seafile..."
echo "=================================="
check_seafile_ready || { echo "❌ 配置失败:服务未就绪" >&2; exit 1; }
configure_gunicorn || { echo "❌ 配置失败:Gunicorn 配置错误" >&2; exit 1; }
configure_seahub || { echo "❌ 配置失败:Seahub 配置错误" >&2; exit 1; }
configure_fileserver || { echo "❌ 配置失败:文件服务器配置错误" >&2; exit 1; }
echo -e "\n✅ Seafile 配置已完成"
}
maindeploy.sh
JAVASCRIPT
# Seafile 极简部署配置
# 版本: 2026.03.27
# 遵循UNIX哲学:Just Enough
#!/bin/bash
set -euo pipefail
# 目录定义
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="$PROJECT_DIR/config"
SCRIPTS_DIR="$PROJECT_DIR/scripts"
# 检查环境文件
if [ ! -f "$CONFIG_DIR/.env" ]; then
echo "错误: 环境配置文件 $CONFIG_DIR/.env 不存在" >&2
exit 1
fi
# 安全加载环境变量
set -a
source "$CONFIG_DIR/.env"
set +a
# 确定 Docker Compose 命令
DOCKER_COMPOSE_CMD=$(command -v docker-compose || echo "docker compose")
# 创建数据目录并设置权限
create_data_dir() {
echo "→ 创建数据目录"
# 清理旧数据(防止权限问题)
if [ -d "./data" ] && [ "$(ls -A ./data 2>/dev/null)" ]; then
echo "⚠️ 清理旧数据目录..."
rm -rf ./data/*
fi
local dirs=(
"./data/seafile"
"./data/mariadb"
"./data/caddy/data"
"./data/caddy/config"
"./data/caddy/log"
)
for dir in "${dirs[@]}"; do
mkdir -p "$dir"
chmod -R 755 "$dir"
done
echo "✅ 数据目录创建完成"
}
# 启动服务
start_services() {
echo "→ 启动 Docker 服务"
$DOCKER_COMPOSE_CMD -p seafile -f "$CONFIG_DIR/docker-compose.yml" up -d --wait || exit 1
}
# 验证部署
verify_deployment() {
echo "→ 验证服务可用性"
# 检查内网地址(确保容器正常)
if curl -s -m 5 "http://${SERVER_IP}:${HTTP_PORT}" >/dev/null 2>&1; then
echo "✅ 部署成功!"
else
echo "❌ 部署失败,请检查容器日志" >&2
exit 1
fi
}
# 主流程
main() {
echo "============================================="
echo " Seafile 极简部署 (最终完美版)"
echo "============================================="
# 按顺序执行部署
create_data_dir || exit 1
start_services || exit 1
# 等待初始化(必须)
echo -e "\n→ 等待 Seafile 初始化完成(60秒)..."
sleep 60
# 执行自动配置(关键)
echo -e "\n→ 执行最终配置(域名/HTTPS/内网IP修复)..."
bash "$SCRIPTS_DIR/config_seafile.sh" || exit 1
# 重启使配置全部生效
echo -e "\n→ 重启服务以应用配置..."
$DOCKER_COMPOSE_CMD -p seafile -f "$CONFIG_DIR/docker-compose.yml" restart
# 验证
verify_deployment || exit 1
# 输出信息(显示外网域名 + 内网地址)JAVASCRIPT
echo -e "\n============================================="
echo " 🎉 Seafile 部署完成!"
echo -e " 🌍 外网访问: \033[32mhttps://${PUBLIC_DOMAIN}\033[0m"
echo -e " 🏠 内网访问: \033[32mhttp://${SERVER_IP}:${HTTP_PORT}\033[0m"
echo -e " 📧 管理员邮箱: \033[32m${SEAFILE_ADMIN_EMAIL}\033[0m"
echo -e " 🔑 管理员密码: \033[32m${SEAFILE_ADMIN_PASSWORD}\033[0m"
echo "============================================="
}
# 执行主流程
main