从seafile 12版本开始官方推荐使用caddy,个人还是习惯使用nginx,如果有相同需求可以参考本贴。
准备工作:
1.为个人网站申请SSL证书并保存为 .crt 和 .key 两个文件
2.修改 .env 文件,启动参数中的配置根据个人网站实际情况进行修改
3.修改 seafile.nginx.conf 文件,两个server中的8443端口(4处)和证书名称(4处),以及server_name字段中的seafile.com域名
部署网站:
mkdir -p /opt/seafile-pe/seafile-nginx
cp seafile.nginx.conf /opt/seafile-pe/seafile-nginx
mkdir -p /opt/seafile-pe/seafile-certs
cp seafile.com.crt /opt/seafile-pe/seafile-certs
cp seafile.com.key /opt/seafile-pe/seafile-certs
chmod 400 /opt/seafile-pe/seafile-certs/seafile.com.key
mkdir -p /opt/seafile-pe/seafile-elasticsearch/data
chmod 777 -R /opt/seafile-pe/seafile-elasticsearch/data
docker compose pull
docker compose up -d
docker logs seafile -f
配置onlyoffice:
编辑 /opt/seafile-pe/seafile-data/seafile/conf/seahub_settings.py 文件
在末尾添加以下内容,域名:端口 和 Onlyoffice JWT 密钥 根据实际情况修改,重启生效
ENABLE_ONLYOFFICE = True
VERIFY_ONLYOFFICE_CERTIFICATE = True
ONLYOFFICE_APIJS_URL = ‘https://域名:端口/web-apps/apps/api/documents/api.js’
ONLYOFFICE_JWT_SECRET = ‘Onlyoffice JWT 密钥’
ONLYOFFICE_FILE_EXTENSION = (‘doc’, ‘docx’, ‘ppt’, ‘pptx’, ‘xls’, ‘xlsx’, ‘odt’, ‘fodt’, ‘odp’, ‘fodp’, ‘ods’, ‘fods’, ‘csv’, ‘ppsx’, ‘pps’)
ONLYOFFICE_EDIT_FILE_EXTENSION = (‘doc’, ‘docx’, ‘ppt’, ‘pptx’, ‘xls’, ‘xlsx’, ‘odt’, ‘fodt’, ‘odp’, ‘fodp’, ‘ods’, ‘fods’, ‘csv’, ‘ppsx’, ‘pps’)
OFFICE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024
#######################################################################
以下7个文件直接复制保存即可,或者自己对照修改官方下载的文件
.env
######################################
# Docker compose 配置 #
######################################
COMPOSE_FILE='seafile-server.yml,seadoc.yml,elasticsearch.yml,notification-server.yml,onlyoffice.yml'
COMPOSE_PATH_SEPARATOR=','
### Images
SEAFILE_IMAGE=seafileltd/seafile-pro-mc:13.0-latest
SEAFILE_DB_IMAGE=library/mariadb:10.11
SEAFILE_REDIS_IMAGE=library/redis:latest
SEADOC_IMAGE=seafileltd/sdoc-server:2.0-latest
SEAFILE_ELASTICSEARCH_IMAGE=library/elasticsearch:8.19.9
ONLYOFFICE_IMAGE=onlyoffice/documentserver:latest
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:13.0-latest
### Local storage path
BASIC_STORAGE_PATH=/opt/seafile-pe
SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-data
SEAFILE_CERTS=$BASIC_STORAGE_PATH/seafile-certs
SEAFILE_NGINX=$BASIC_STORAGE_PATH/seafile-nginx
SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db
SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data
SS_DATA_PATH=$BASIC_STORAGE_PATH/seasearch-data
SEAFILE_ELASTICSEARCH_VOLUME=$BASIC_STORAGE_PATH/seafile-elasticsearch/data
ONLYOFFICE_VOLUME=$BASIC_STORAGE_PATH/onlyoffice
######################################
# 启动参数 #
######################################
SEAFILE_SERVER_PORT=8443 #Seafile网站使用的端口
SEAFILE_SERVER_PROTOCOL=https
SEAFILE_SERVER_HOSTNAME=seafile.com #Seafile网站使用的域名
TIME_ZONE=Asia/Shanghai
JWT_PRIVATE_KEY=Seafile JWT 密钥 #Seafile需要一个长度不小于32个字符的随机字符串
SEAFILE_CERTS_CRT=seafile.com.crt #Seafile网站SSL证书的crt文件
SEAFILE_CERTS_KEY=seafile.com.key #Seafile网站SSL证书的key文件
### Seafile admin user
INIT_SEAFILE_ADMIN_EMAIL=登录邮箱 #Seafile网站的登录账号
INIT_SEAFILE_ADMIN_PASSWORD=自定义密码 #Seafile网站的登录密码
## Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=自定义密码 #Redis 服务密码
### Database
SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_PORT=3306
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=自定义密码 #MySQL seafile用户的密码
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db
### Database root password, Used to create Seafile users
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=自定义密码 #MySQL root用户的密码
### Onlyoffice
ONLYOFFICE_PORT=6233
ONLYOFFICE_JWT_SECRET=Onlyoffice JWT 密钥 #OnlyOffice的 JWT 验证会被强制启用
######################################
# 扩展配置 #
######################################
## Cache
CACHE_PROVIDER=redis
## Seafile service URL
SEAFILE_SERVICE_URL=$SEAFILE_SERVER_PROTOCOL://$SEAFILE_SERVER_HOSTNAME:$SEAFILE_SERVER_PORT
ONLYOFFICE_SERVICE_URL=$SEAFILE_SERVER_PROTOCOL://$SEAFILE_SERVER_HOSTNAME:$ONLYOFFICE_PORT
## SeaDoc service
ENABLE_SEADOC=true
## Notification
ENABLE_NOTIFICATION_SERVER=true
NOTIFICATION_SERVER_URL=http://notification-server:8083
INNER_NOTIFICATION_SERVER_URL=$NOTIFICATION_SERVER_URL
## Metadata server
MD_FILE_COUNT_LIMIT=100000
MD_MAX_CACHE_SIZE=1GB
## SeaSearch admin user
INIT_SS_ADMIN_USER=$INIT_SEAFILE_ADMIN_EMAIL
INIT_SS_ADMIN_PASSWORD=$INIT_SEAFILE_ADMIN_PASSWORD
## Storage type
SEAF_SERVER_STORAGE_TYPE=disk
MD_STORAGE_TYPE=$SEAF_SERVER_STORAGE_TYPE
SS_STORAGE_TYPE=$SEAF_SERVER_STORAGE_TYPE
## Local cache
SS_MAX_OBJ_CACHE_SIZE=10GB
## Log
SS_LOG_TO_STDOUT=false
SS_LOG_OUTPUT=true
SS_LOG_LEVEL=info
SEAFILE_LOG_TO_STDOUT=false
SEATABLE_LOG_TO_STDOUT=false
## NO root user
NON_ROOT=false
seafile.nginx.conf
# -*- mode: nginx -*-
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
server_tokens off;
}
server {
listen 443 ssl default_server;
listen 8443 ssl default_server;
listen [::]:443 ssl default_server;
listen [::]:8443 ssl default_server;
http2 on;
server_name _;
error_page 497 =301 https://$host:$server_port$request_uri;
return 444;
server_tokens off;
ssl_certificate /opt/seafile-certs/seafile.com.crt;
ssl_certificate_key /opt/seafile-certs/seafile.com.key;
}
server {
listen 443 ssl;
listen 8443 ssl;
listen [::]:443 ssl;
listen [::]:8443 ssl;
http2 on;
server_name seafile.com localhost 127.0.0.1 [::1];
error_page 497 =301 https://$host:$server_port$request_uri;
server_tokens off;
ssl_certificate /opt/seafile-certs/seafile.com.crt;
ssl_certificate_key /opt/seafile-certs/seafile.com.key;
ssl_session_timeout 30m;
ssl_session_cache shared:SSL:5m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
proxy_set_header X-Forwarded-For $remote_addr;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
location / {
proxy_pass http://127.0.0.1:8000/;
proxy_read_timeout 1200s;
proxy_set_header Host $http_host;
proxy_set_header Forwarded "for=$remote_addr;proto=$scheme";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Connection "";
proxy_http_version 1.1;
client_max_body_size 0;
access_log /var/log/nginx/seahub.access.log seafileformat;
error_log /var/log/nginx/seahub.error.log;
}
location /seafhttp {
rewrite ^/seafhttp(.*)$ $1 break;
proxy_pass http://127.0.0.1:8082;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 0;
proxy_connect_timeout 36000s;
proxy_read_timeout 36000s;
proxy_request_buffering off;
access_log /var/log/nginx/seafhttp.access.log seafileformat;
error_log /var/log/nginx/seafhttp.error.log;
}
location /notification/ping {
proxy_pass http://notification-server:8083/ping;
access_log /var/log/nginx/notification.access.log seafileformat;
error_log /var/log/nginx/notification.error.log;
}
location /notification {
proxy_pass http://notification-server:8083/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
access_log /var/log/nginx/notification.access.log seafileformat;
error_log /var/log/nginx/notification.error.log;
}
location /seafdav {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1200s;
client_max_body_size 0;
access_log /var/log/nginx/seafdav.access.log seafileformat;
error_log /var/log/nginx/seafdav.error.log;
}
location /media {
root /opt/seafile/seafile-server-latest/seahub;
}
location /sdoc-server/ {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Allow-Headers "deviceType,token, authorization, content-type";
return 204;
}
proxy_pass http://seadoc:80/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100m;
access_log /var/log/nginx/seadoc.access.log seafileformat;
error_log /var/log/nginx/seadoc.error.log;
}
location /socket.io {
proxy_pass http://seadoc:80;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_redirect off;
proxy_buffers 8 32k;
proxy_buffer_size 64k;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
}
location = /favicon.ico {
log_not_found off;
access_log off;
}
}
elasticsearch.yml
services:
elasticsearch:
image: ${SEAFILE_ELASTICSEARCH_IMAGE:-elasticsearch:8.15.0}
container_name: seafile-elasticsearch
restart: unless-stopped
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms2g -Xmx2g"
- "xpack.security.enabled=false"
ulimits:
memlock:
soft: -1
hard: -1
mem_limit: 4g
volumes:
- "${SEAFILE_ELASTICSEARCH_VOLUME:-/opt/seafile-elasticsearch/data}:/usr/share/elasticsearch/data"
networks:
- seafile-net
networks:
seafile-net:
name: seafile-net
notification-server.yml
services:
notification-server:
image: ${NOTIFICATION_SERVER_IMAGE:-seafileltd/notification-server:13.0-latest}
container_name: notification-server
restart: unless-stopped
volumes:
- ${SEAFILE_VOLUME:-/opt/seafile-data}/seafile/logs:/shared/seafile/logs
ports:
- 8083:8083
environment:
- SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
- SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
- SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
- SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
- SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
- SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
- NOTIFICATION_SERVER_LOG_LEVEL=${NOTIFICATION_SERVER_LOG_LEVEL:-info}
depends_on:
db:
condition: service_healthy
networks:
- seafile-net
networks:
seafile-net:
name: seafile-net
onlyoffice.yml
services:
onlyoffice:
image: ${ONLYOFFICE_IMAGE:-onlyoffice/documentserver:8.3.3}
container_name: onlyoffice
restart: unless-stopped
ports:
- ${ONLYOFFICE_PORT:-6233}:443
volumes:
- ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/logs:/var/log/onlyoffice
- ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/data:/var/www/onlyoffice/Data
- ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/lib:/var/lib/onlyoffice
- ${ONLYOFFICE_VOLUME:-/opt/onlyoffice}/db:/var/lib/postgresql
- ${SEAFILE_CERTS:-/opt/seafile-pe/seafile-certs}:/var/www/onlyoffice/certs
environment:
- TIME_ZONE=Asia/Shanghai
- JWT_ENABLED=true
- JWT_SECRET=${ONLYOFFICE_JWT_SECRET:?Variable is not set or empty}
- SSL_CERTIFICATE_PATH=/var/www/onlyoffice/certs/$SEAFILE_CERTS_CRT
- SSL_KEY_PATH=/var/www/onlyoffice/certs/$SEAFILE_CERTS_KEY
healthcheck:
test: ["CMD-SHELL", "curl -f $ONLYOFFICE_SERVICE_URL/welcome/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
- seafile-net
networks:
seafile-net:
name: seafile-net
seadoc.yml
services:
seadoc:
image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:2.0-latest}
container_name: seadoc
restart: unless-stopped
volumes:
- ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared
# ports:
# - 80:80
environment:
- DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
- DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
- DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
- DB_NAME=${SEADOC_MYSQL_DB_NAME:-${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}}
- TIME_ZONE=${TIME_ZONE:-Etc/UTC}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- NON_ROOT=${NON_ROOT:-false}
- SEAHUB_SERVICE_URL=${SEAFILE_SERVICE_URL:-http://seafile}
depends_on:
db:
condition: service_healthy
networks:
- seafile-net
networks:
seafile-net:
name: seafile-net
seafile-server.yml
services:
db:
image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
container_name: seafile-mysql
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
- MYSQL_LOG_CONSOLE=true
- MARIADB_AUTO_UPGRADE=1
volumes:
- "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
networks:
- seafile-net
healthcheck:
test:
[
"CMD",
"/usr/local/bin/healthcheck.sh",
"--connect",
"--mariadbupgrade",
"--innodb_initialized",
]
interval: 20s
start_period: 30s
timeout: 5s
retries: 10
redis:
image: ${SEAFILE_REDIS_IMAGE:-redis}
container_name: seafile-redis
restart: unless-stopped
command:
- /bin/sh
- -c
- redis-server --requirepass "$$REDIS_PASSWORD"
environment:
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
networks:
- seafile-net
seafile:
image: ${SEAFILE_IMAGE:-seafileltd/seafile-pro-mc:13.0-latest}
container_name: seafile
restart: unless-stopped
ports:
- 80:80
- 443:443
- ${SEAFILE_SERVER_PORT:-8443}:${SEAFILE_SERVER_PORT:-8443}
volumes:
- ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
- ${SEAFILE_CERTS:-/opt/seafile-certs}:/opt/seafile-certs:ro
- ${SEAFILE_NGINX:-/opt/seafile-nginx}:/etc/nginx/sites-enabled:ro
environment:
- INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
- SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
- SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
- SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
- SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
- SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
- SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
- SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
- TIME_ZONE=${TIME_ZONE:-Etc/UTC}
- INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
- INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
- SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}:${SEAFILE_SERVER_PORT:?Variable is not set or empty}
- SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
- SITE_ROOT=${SITE_ROOT:-/}
- NON_ROOT=${NON_ROOT:-false}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
- ENABLE_GO_FILESERVER=${ENABLE_GO_FILESERVER:-true}
- ENABLE_SEADOC=${ENABLE_SEADOC:-true}
- SEADOC_SERVER_URL=$SEAFILE_SERVICE_URL/sdoc-server
- CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
- REDIS_HOST=${REDIS_HOST:-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_PASSWORD=${REDIS_PASSWORD:-}
- MEMCACHED_HOST=${MEMCACHED_HOST:-memcached}
- MEMCACHED_PORT=${MEMCACHED_PORT:-11211}
- SEAF_SERVER_STORAGE_TYPE=${SEAF_SERVER_STORAGE_TYPE:-}
- ENABLE_NOTIFICATION_SERVER=${ENABLE_NOTIFICATION_SERVER:-false}
- INNER_NOTIFICATION_SERVER_URL=${INNER_NOTIFICATION_SERVER_URL:-http://notification-server:8083}
- NOTIFICATION_SERVER_URL=${NOTIFICATION_SERVER_URL:-$SEAFILE_SERVICE_URL/notification}
- ENABLE_SEAFILE_AI=${ENABLE_SEAFILE_AI:-false}
- SEAFILE_AI_SERVER_URL=${SEAFILE_AI_SERVER_URL:-http://seafile-ai:8888}
- SEAFILE_AI_SECRET_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- MD_FILE_COUNT_LIMIT=${MD_FILE_COUNT_LIMIT:-100000}
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
seadoc:
condition: service_started
notification-server:
condition: service_started
networks:
- seafile-net
networks:
seafile-net:
name: seafile-net