seafile12 社区版 容器运行,内网自建证书 nginx https反代 不使用caddy,添加seadoc和onlyoffice插件

  • seafile 12 社区版

  • ubuntu22.04

  • 内网IP:192.168.3.50

  • 自建证书:seafile.example.com

  • 不使用官方 Caddy 代理

  • 安装 Seadoc、Onlyoffice 插件

  • 使用宿主机的 Mysql8 与 nginx

注:因为服务器已经装好了Mysql8 与 nginx已经占用了80和443端口,
所以没使用官网的 Mariadb 和 Caddy

seafile相关配置文件


.env

COMPOSE_FILE='seafile-server.yml,seadoc.yml,onlyoffice.yml'
COMPOSE_PATH_SEPARATOR=','

## Images
#SEAFILE_DB_IMAGE=mariadb:10.11
#SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.9-alpine
SEAFILE_IMAGE=seafileltd/seafile-mc:12.0-latest
SEAFILE_MEMCACHED_IMAGE=memcached:1.6.29
SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:12.0-latest
ONLYOFFICE_IMAGE=onlyoffice/documentserver:latest


## Storage
#SEAFILE_MYSQL_VOLUME=/data/apps/seafile-all/seafile-mysql/db
#SEAFILE_CADDY_VOLUME=/data/apps/seafile-all/seafile-caddy
SEAFILE_VOLUME=/data/apps/seafile-all/seafile-data
SEADOC_VOLUME=/data/apps/seafile-all/seadoc-data
NOTIFICATION_SERVER_VOLUME=/data/apps/seafile-all/notification-data
ONLYOFFICE_VOLUME=/data/apps/seafile-all/onlyoffice


## Startup
SEAFILE_SERVER_PROTOCOL=https
SEAFILE_SERVER_HOSTNAME=seafile.example.com
TIME_ZONE=Asia/Shanghai
JWT_PRIVATE_KEY=exnB1uEoWnhBu3cXq7n50k7CR4hYag456TfK7rTp

## Database
SEAFILE_MYSQL_DB_HOST=192.168.3.50
SEAFILE_MYSQL_DB_PORT=3306
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=jj2022Msql@!0688
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=jjseafile!22!
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db
INIT_SEAFILE_ADMIN_EMAIL=admin
INIT_SEAFILE_ADMIN_PASSWORD=seafile@jj.game

ENABLE_SEADOC=true
SEADOC_SERVER_URL=https://seafile.mingzhougame.com/sdoc-server


#onlyoffice
ONLYOFFICE_PORT=6233
ONLYOFFICE_JWT_SECRET=exnB1uEoWnhBu3cXq7n50k7CR4hYag456TfK7rTp


seafile-server.yml

services:
  memcached:
    image: ${SEAFILE_MEMCACHED_IMAGE:-memcached:1.6.29}
    container_name: seafile-memcached
    restart: unless-stopped
    entrypoint: memcached -m 256
    networks:
      - seafile-net

  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:12.0-latest}
    container_name: seafile
    restart: unless-stopped
    extra_hosts:
      - "seafile.example.com:192.168.3.50"
    ports:
      - "8000:8000"
      - "8082:8082"
      - "8080:8080"
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
      #- ${SEAFILE_VOLUME:-/opt/seafile-data}/seahub:/opt/seafile/seafile-server-latest/seahub
    environment:
      - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - DB_ROOT_PASSWD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - 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:-Asia/Shanghai}
      - 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_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_SEADOC=${ENABLE_SEADOC:-true}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
    depends_on:
      memcached:
        condition: service_started
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

seadoc.yml

services:
  seadoc:
    image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest}
    container_name: seadoc
    restart: unless-stopped
    volumes:
      - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared
    extra_hosts:
      - "seafile.example.com:192.168.3.50"
    ports:
      - "8888: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=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Asia/Shanghai}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - NON_ROOT=${NON_ROOT:-false}
      - SEAHUB_SERVICE_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

onlyoffice.yml

services:
  onlyoffice:
    image: ${ONLYOFFICE_IMAGE:-onlyoffice/documentserver:latest}
    restart: unless-stopped
    container_name: seafile-onlyoffice
    extra_hosts:
      - "seafile.example.com:192.168.3.50"
    ports:
      - ${ONLYOFFICE_PORT:-6233}:443
    environment:
      #- DB_TYPE=${DB_TYPE:-mariadb}
      #- DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      #- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      #- DB_PWD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - TIME_ZONE=${TIME_ZONE:-Asia/Shanghai}
      - JWT_ENABLED=true
      - JWT_SECRET=${ONLYOFFICE_JWT_SECRET:?Variable is not set or empty}
    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
    networks:
      - seafile-net

networks:
  seafile-net:
    name: seafile-net

开始初始化-初始化后还需要修改映射出来的相关配置文件

docker compose pull      #拉取或更新镜像
docker compose up -d

----------------------------------------------------------------------------------

#onlyoffice相关操作
## 编辑 seahub_settings.py 添加xim以下内容(域名和JWT如有修改请同步)
vim /data/apps/seafile-all/seafile-data/seafile/conf/seahub_settings.py

CSRF_TRUSTED_ORIGINS = ['https://seafile.example.com']
ENABLE_ONLYOFFICE = True
ONLYOFFICE_APIJS_URL = 'https://seafile.example.com:6233/web-apps/apps/api/documents/api.js'
ONLYOFFICE_FILE_EXTENSION = ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'odt', 'fodt', 'odp', 'fodp', 'ods', 'fods', 'csv', 'ppsx', 'pps')
ONLYOFFICE_EDIT_FILE_EXTENSION = ('docx', 'pptx', 'xlsx')
ONLYOFFICE_JWT_SECRET = 'exnB1uEoWnhBu3cXq7n50k7CR4hYag456TfK7rTp'

##复制自己的ssl证书到onlyoffice目录,必须重命名为onlyoffice.crt和onlyoffice.key
mkdir /data/apps/seafile-all/onlyoffice/data/certs
cp 证书.crt /data/apps/seafile-all/onlyoffice/data/certs/onlyoffice.crt
cp 证书.key /data/apps/seafile-all/onlyoffice/data/certs/onlyoffice.key
chmod 400 /data/apps/seafile-all/onlyoffice/data/certs/onlyoffice.key

----------------------------------------------------------------------------------

#seafile相关操作(因为使用宿主机进行代理,需将media映射出来,否定登录成功后默认头像会404,这个很明显能看出来)
## custom和 avatars 是软连接,直接拷贝 避免映射出宿主机失效
docker exec -it seafile bash
cp -r /opt/seafile/seafile-server-latest/seahub /shared/
rm -rf /shared/seahub/media/custom
rm -rf /shared/seahub/media/avatars
cp -r /opt/seafile/seafile-server-latest/seahub/media/custom /shared/seahub/media/
cp -r /opt/seafile/seafile-server-latest/seahub/media/avatars /shared/seahub/media/

##退出容器,将seafile的volumes第二条注释去掉
exit
vim /data/apps/seafile-all/seafile/seafile-server.yml
- ${SEAFILE_VOLUME:-/opt/seafile-data}/seahub:/opt/seafile/seafile-server-latest/seahub

----------------------------------------------------------------------------------

docker compose stop
docker compose up -d
docker exec seafile-onlyoffice supervisorctl start ds:example


宿主机nginx配置文件

#去到主配置文件 include 目录下
vim seafile.example.com.conf

log_format seafileformat '$http_x_forwarded_for $remote_addr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_response_time';
log_format sdoc-serverformat '[$time_iso8601] $http_x_forwarded_for $remote_addr "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_response_time';

server {
    listen 80;
    listen 443 ssl;
    server_name seafile.example.com;
    ssl_certificate /data/mon/seafile.example.com.crt;
    ssl_certificate_key /data/mon/seafile.example.com.key;

    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_read_timeout 310s;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection "";
        proxy_http_version 1.1;

        add_header Access-Control-Allow-Origin *;
        client_max_body_size 0;
        access_log      /data/logs/nginx/seahub.access.log seafileformat;
        error_log       /data/logs/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_read_timeout  36000s;

        access_log      /data/logs/nginx/seafhttp.access.log seafileformat;
        error_log       /data/logs/nginx/seafhttp.error.log;
    }

    location /notification/ping {
        proxy_pass http://127.0.0.1:8083/ping;
        access_log      /data/logs/nginx/notification.access.log seafileformat;
        error_log       /data/logs/nginx/notification.error.log;
    }

    location /notification {
        proxy_pass http://127.0.0.1:8083/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        access_log      /data/logs/nginx/notification.access.log seafileformat;
        error_log       /data/logs/nginx/notification.error.log;
    }

    location /seafdav {
        rewrite ^/seafdav$ /seafdav/ permanent;
    }

    location /seafdav/ {
        proxy_pass         http://127.0.0.1:8080/seafdav/;
        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_read_timeout  1200s;
        client_max_body_size 0;

        access_log      /data/logs/nginx/seafdav.access.log seafileformat;
        error_log       /data/logs/nginx/seafdav.error.log;
    }

    location /:dir_browser {
        # Logo of WebDAV
        proxy_pass         http://127.0.0.1:8080/:dir_browser;
    }

    location /media {
        #root /opt/seafile/seafile-server-latest/seahub;
        # 注意这里的root是seafile映射出来的路径
        root /data/apps/seafile-all/seafile-data/seahub;
        access_log      /data/logs/nginx/media.access.log seafileformat;
        error_log       /data/logs/nginx/media.error.log;
    }

    location /sdoc-server/ {
        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;
        }
        rewrite ^/sdoc-server(.*)$ $1 break;
        proxy_pass         http://127.0.0.1:8888;
        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      /data/logs/nginx/nginx-sdoc-server.access.log sdoc-serverformat;
        error_log       /data/logs/nginx/nginx-sdoc-server.error.log;
    }

    location /socket.io {
	#rewrite ^/socket.io(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8888;
        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;
    
        access_log      /data/logs/nginx/nginx-socket-io.access.log sdoc-serverformat;
        error_log       /data/logs/nginx/nginx-socket-io.error.log;
    }

}
宿主机增加hosts解析
echo "192.168.3.50 seafile.example.com" >> /etc/hosts
测试配置文件是否存在异常(log目录不存在的话会报异常)
nginx -t
没异常则重载配置
nginx -s reload

windows也增加hosts解析
C:\Windows\System32\drivers\etc\hosts
192.168.3.50 seafile.example.com

至此局域网内访问的话直接浏览器输入域名即可正常访问啦


遇到的问题 与 补充说明

  1. Mysql8 身份认证失败
#因为 mysql8 创建的用户默认是 caching_sha2_password 的验证方式,需要执行以下命令修改
#docker logs seafile 出现错误:Error happened during creating seafile admin,执行以下指令
mysql -u root -p
select user,host from mysql.user;
ALTER USER ‘seafile’@‘%’ IDENTIFIED BY ‘jjseafile!22!’ PASSWORD EXPIRE NEVER;
ALTER USER ‘seafile’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘jjseafile!22!’;
FLUSH PRIVILEGES;
ALTER USER ‘seafile’@‘%’ IDENTIFIED BY ‘jjseafile!22!’;
exit;
  1. seadoc 和 onlyoffice 无法加载文件
#主要原有还是容器中网络问题、配错路径也有可能
extra_hosts:
  - "seafile.example.com:192.168.3.50"
该参数既是给容器增加hosts解析
  1. https 账号认证后显示CSRF失败
#增加一行内容
vim /data/apps/seafile-all/seafile-data/seafile/conf/seahub_settings.py
CSRF_TRUSTED_ORIGINS = ['https://seafile.example.com']

有公网域名或者内网有DNS解析劫持的。那么所有的hosts其实都是可以忽略的

先支持一下,那为什么我自签名证书,外网访问的时候seadoc文件显示加载文档失败呢

1、进入到seadoc容器中,wget以下seahub地址,然后看index文件中的内容是否是正常的登录界面的内容。大概率是容器中的网络问题,导致直接访问到公网的域名去了。
解决办法就是容器中加hosts解析,为seafile、seadoc、宿主机都在/etc/hosts增加一行(onlyoffice也是一样的)
192.168.3.50 seafile.example.com

持久化操作例如:
extra_hosts:
- “seafile.example.com:192.168.3.50”