seafile 13.0 专业版使用 nginx 部署并启用 onlyoffice

不想使用官方caddy部署的可以参考一下,使用seasearch搜索引擎,全新部署和升级都可以使用。

准备工作:
1.为个人网站申请SSL证书并保存为 .crt 和 .key 两个文件。
2.修改 .env 文件,启动参数中的配置根据个人网站实际情况进行修改,默认seafile使用8443端口。
3.修改 nginx.conf 文件,2个server中的8443端口(4处)和3个server中的证书名称(6处),以及业务主站点server_name字段中的seafile.com域名。
4.删除官网下载的yml文件中所有 labels: caddy 字段。

wget -O .env https://manual.seafile.com/13.0/repo/docker/pro/env
wget https://manual.seafile.com/13.0/repo/docker/pro/seafile-server.yml
wget https://manual.seafile.com/13.0/repo/docker/seadoc.yml
wget https://manual.seafile.com/13.0/repo/docker/pro/seasearch.yml
wget -O notification-server.yml https://manual.seafile.com/13.0/repo/docker/notification-server.yml

部署工作(替换为自己的证书名称):
mkdir -p /opt/nginx/conf
cp nginx.conf /opt/nginx/conf
mkdir -p /opt/nginx/certs
cp seafile.com.crt /opt/nginx/certs
cp seafile.com.key /opt/nginx/certs
chmod 400 /opt/nginx/certs/seafile.com.key


docker compose pull
docker compose up -d
docker compose stop

#######################################################################

编辑 /opt/seafile-pe/seafile-data/seafile/conf/seafevents.conf 文件,添加以下内容

# 获取 seasearch_token:echo -n '登录邮箱:密码' | base64
[SEASEARCH]
enabled = true
seasearch_url = http://seasearch:4080
seasearch_token = 填入根据邮箱和密码算出的seasearch_token
interval = 10m
index_office_pdf = false

[INDEX FILES]
enabled = false   # 禁用 Elasticsearch 搜索,默认为 true,使用 Seasearch 时必须设置为 false
index_office_pdf = false

#######################################################################

配置onlyoffice:
编辑 /opt/seafile-pe/seafile-data/seafile/conf/seahub_settings.py 文件
添加以下内容,域名:端口 和 Onlyoffice JWT 密钥 根据实际情况修改

ENABLE_ONLYOFFICE = True
VERIFY_ONLYOFFICE_CERTIFICATE = False
ONLYOFFICE_FORCE_SAVE = True
ONLYOFFICE_APIJS_URL = 'https://网站域名:8443/onlyofficeds/web-apps/apps/api/documents/api.js'
ONLYOFFICE_JWT_SECRET = '填入.env文件中设置的JWT_PRIVATE_KEY'

#######################################################################

.env文件替换

######################################
#                    Docker compose 配置                   #
######################################
COMPOSE_FILE='nginx.yml,seafile-server.yml,seadoc.yml,seasearch.yml,notification-server.yml,onlyoffice.yml'
COMPOSE_PATH_SEPARATOR=','

# Images
NGINX_IMAGE=library/nginx:stable-alpine
SEAFILE_IMAGE=seafileltd/seafile-pro-mc:13.0-latest
SEAFILE_DB_IMAGE=library/mariadb:10.11
SEAFILE_REDIS_IMAGE=library/redis:8.8
SEADOC_IMAGE=seafileltd/sdoc-server:2.0-latest
SEASEARCH_IMAGE=seafileltd/seasearch:1.0-latest
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:13.0-latest
ONLYOFFICE_IMAGE=onlyoffice/documentserver:10.0.0.1

# Local storage path
NGINX_VOLUME=/opt/nginx
BASIC_STORAGE_PATH=/opt/seafile-13
SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-pe
SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db
SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data
SS_DATA_PATH=$BASIC_STORAGE_PATH/seasearch-data
NOTIFICATION_VOLUME=$BASIC_STORAGE_PATH/notification
ONLYOFFICE_VOLUME=/opt/onlyoffice

######################################
#        启动参数,只需要配置这部分内容即可          #
######################################

SEAFILE_SERVER_PROTOCOL=https             #是否使用https协议
SEAFILE_SERVER_DOMAIN=seafile.com       #seafile网站域名
SEAFILE_SERVER_PORT=8443                   #seafile网站使用的端口
JWT_PRIVATE_KEY=密钥                          #JWT 私钥,长度不少于 32 个字符的随机字符串。可以使用下列命令生成 JWT 私钥:pwgen -s 40 1
DATABASE_PASSWORD=密码                  #seafile数据库用户的密码
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=admin@seafile.com     #seafile服务的账号
INIT_SEAFILE_ADMIN_PASSWORD=password             #seafile服务的密码

######################################
#                              扩展配置                             #
######################################

# Seafile service
SEAFILE_SERVER_HOSTNAME=$SEAFILE_SERVER_DOMAIN:$SEAFILE_SERVER_PORT
SEAFILE_SERVICE_URL=$SEAFILE_SERVER_PROTOCOL://$SEAFILE_SERVER_HOSTNAME

# Time zone 
TIME_ZONE=Asia/Shanghai

# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=$DATABASE_PASSWORD

# Database
SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_PORT=3306
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=$DATABASE_PASSWORD
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=$DATABASE_PASSWORD

# Storage type
SEAF_SERVER_STORAGE_TYPE=disk
SS_STORAGE_TYPE=disk

# Cache
CACHE_PROVIDER=redis

# Onlyoffice
ONLYOFFICE_JWT_SECRET=$JWT_PRIVATE_KEY

# SeaDoc
ENABLE_SEADOC=true
SEADOC_SERVER_URL=$SEAFILE_SERVICE_URL/sdoc-server

# Notification
ENABLE_NOTIFICATION_SERVER=true
NOTIFICATION_SERVER_URL=$SEAFILE_SERVICE_URL/notification

# SeaSearch
SS_MAX_OBJ_CACHE_SIZE=10GB
SS_LOG_TO_STDOUT=false
SS_LOG_OUTPUT=true
SS_LOG_LEVEL=info

# SeaSearch admin user
INIT_SS_ADMIN_USER=$INIT_SEAFILE_ADMIN_EMAIL
INIT_SS_ADMIN_PASSWORD=$INIT_SEAFILE_ADMIN_PASSWORD

# NO root user
NON_ROOT=false


nginx.yml

services:
  nginx:
    image: ${NGINX_IMAGE:-library/nginx:stable-alpine}
    container_name: nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "${SEAFILE_SERVER_PORT:-8443}:${SEAFILE_SERVER_PORT:-8443}"
    volumes:
      # 主配置文件
      - $NGINX_VOLUME/conf/nginx.conf:/etc/nginx/nginx.conf:ro
      # 站点配置目录
      # - $NGINX_VOLUME/conf.d:/etc/nginx/conf.d:ro
      # 证书目录
      - $NGINX_VOLUME/certs:/etc/nginx/certs:ro
      # 日志目录
      - $NGINX_VOLUME/logs:/var/log/nginx
      # 网站根目录
      # - $NGINX_VOLUME/html:/usr/share/nginx/html:ro
    environment:
      - TZ=${TIME_ZONE:-Asia/Shanghai}
    healthcheck:
      test: ["CMD-SHELL", "netstat -tulpn | grep -q ':80 ' || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    depends_on:
      seafile:
        condition: service_healthy
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

nginx.conf

user  nginx;
worker_processes  auto;
worker_rlimit_nofile 65535;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  4096;
    use epoll;
    multi_accept on;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
    client_max_body_size  0;

    gzip  on;
    gzip_vary on;
    gzip_min_length 1k;
    gzip_comp_level 2;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    map $http_x_forwarded_proto $the_scheme {
            default $http_x_forwarded_proto;
            "" $scheme;
        }

    map $http_x_forwarded_host $the_host {
            default $http_x_forwarded_host;
            "" $http_host;
        }

    map $http_upgrade $proxy_connection {
            default upgrade;
            "" close;
        }

    # include /etc/nginx/conf.d/*.conf;

    # --------------------------
    # 80端口:统一跳转至8443端口HTTPS
    # --------------------------
    server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_tokens off;
        server_name _;

        return 301 https://$host:8443$request_uri;
    }

    # --------------------------
    # 443端口:统一跳转至8443端口HTTPS
    # --------------------------
    server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        http2 on;
        server_tokens off;
        server_name _;

        ssl_certificate     /etc/nginx/certs/seafile.com.crt;
        ssl_certificate_key /etc/nginx/certs/seafile.com.key;

        error_page 497 =301 https://$host:8443$request_uri;
        return 301 https://$host:8443$request_uri;
    }

    # --------------------------
    # 默认站点:拦截非法域名
    # --------------------------
    server {
        listen 8443 ssl default_server;
        listen [::]:8443 ssl default_server;
        http2 on;
        server_tokens off;
        server_name _;

        ssl_certificate     /etc/nginx/certs/seafile.com.crt;
        ssl_certificate_key /etc/nginx/certs/seafile.com.key;

        error_page 497 =301 https://$host:$server_port$request_uri;
        if ($scheme = https) {
            return 444;
        }
    }

    # --------------------------
    # 8443端口业务主站点
    # --------------------------
    server {
        listen 8443 ssl;
        listen [::]:8443 ssl;
        http2 on;
        server_tokens off;
        server_name www.seafile.com localhost 127.0.0.1 [::1];

        # SSL 证书配置
        ssl_certificate     /etc/nginx/certs/seafile.com.crt;
        ssl_certificate_key /etc/nginx/certs/seafile.com.key;

        # HTTP 自动跳转
        error_page 497 =301 https://$host:$server_port$request_uri;

        # SSL 性能优化
        ssl_session_timeout 30m;
        ssl_session_cache   shared:SSL:10m;
        ssl_session_tickets off;

        # SSL 安全配置
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-A128-GCM-SHA256:ECDHE-RSA-A128-GCM-SHA256:ECDHE-ECDSA-A256-GCM-SHA384:ECDHE-RSA-A256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-A128-GCM-SHA256:DHE-RSA-A256-GCM-SHA384;
        ssl_prefer_server_ciphers on;

        # 安全响应头
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-Content-Type-Options nosniff always;
        add_header X-Frame-Options SAMEORIGIN always;
        add_header X-XSS-Protection "1; mode=block" always;

        # 全局反向代理头
        proxy_set_header Host $http_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-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Port $server_port;

        # ----- 反向代理业务 -----
        # Seafile:全量转发到 Seafile 容器 80 端口(官方内置 Nginx)
        location / {
            proxy_pass http://seafile;
            proxy_http_version 1.1;
            proxy_set_header Host $http_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-Proto $scheme;
            proxy_set_header Connection "";
            proxy_read_timeout 36000s;
            proxy_buffering off;
            proxy_request_buffering off;
            client_max_body_size 0;
        }

        # SeaDoc:全量转发到 SeaDoc 容器 80 端口
        location /sdoc-server/ {
            proxy_pass http://seadoc/;
            proxy_redirect off;
            proxy_set_header Host $http_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;
            client_max_body_size 100m;
        }

        location /socket.io {
            proxy_pass http://seadoc;
            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;
        }

        # Notification:通知服务
        location /notification/ping {
            proxy_pass http://notification-server:8083/ping;
            access_log /var/log/nginx/notification.access.log;
            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;
            error_log /var/log/nginx/notification.error.log;
        }

        location /onlyofficeds/ {
            # THIS ONE IS IMPORTANT ! - Trailing slash !
            proxy_pass http://onlyoffice/;
            proxy_http_version 1.1;
            client_max_body_size 100M; # Limit Document size to 100MB
            proxy_read_timeout 3600s;
            proxy_connect_timeout 3600s;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $proxy_connection;
            # THIS ONE IS IMPORTANT ! - Subfolder and NO trailing slash !
            proxy_set_header X-Forwarded-Host $the_host/onlyofficeds;
            proxy_set_header X-Forwarded-Proto $the_scheme;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }

        # 关闭浏览器自动请求网站图标文件的日志记录
        location = /favicon.ico {
            log_not_found off;
            access_log off;
        }
    }
}

onlyoffice.yml

services:

  onlyoffice:
    image: ${ONLYOFFICE_IMAGE:-onlyoffice/documentserver:10.0}
    container_name: onlyoffice
    restart: unless-stopped
    stdin_open: true
    stop_grace_period: 10s
    # ports:
      # - 6233:80
    entrypoint: ["/bin/bash", "-c"]
    command:
      - |
        rm -f /var/run/supervisor.sock /var/run/supervisord.pid
        exec /app/ds/run-document-server.sh
    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
      - /etc/localtime:/etc/localtime:ro
    environment:
      - JWT_ENABLED=true
      - JWT_SECRET=${ONLYOFFICE_JWT_SECRET:?Variable is not set or empty}
    healthcheck:
      test: ["CMD-SHELL", "supervisorctl status ds:docservice ds:converter | grep -c RUNNING | grep -q 2"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 60s
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net