该篇是 https://wiki.waringid.me/x/JwC2Aw 的延续。之前的内容都是在旧版本数据的基础上升级更新而来。
前几天在 QQ 群里的讨论中远程了一位使用自建证书的环境才发现 12 版本的配置和 seadoc 的内容有了变化(例如新版本的 seadoc 本地挂载的目录中只有 logs 这个内容,以往其它的目录都没有了;另外配置本地 SSL 证书存在无法正常打开 seadoc 文档的情况)
本例不启用 caddy.yml 组件,直接使用内置的 nginx 组件。 |
前置要求
cd /data/seafile wget -O .env https://manual.seafile.com/12.0/repo/docker/ce/env wget https://manual.seafile.com/12.0/repo/docker/seadoc.yml wget https://manual.seafile.com/12.0/repo/docker/ce/seafile-server.yml wget https://manual.seafile.com/12.0/repo/docker/caddy.yml |
COMPOSE_FILE='seafile-server.yml,seadoc.yml' COMPOSE_PATH_SEPARATOR=',' SEAFILE_IMAGE=seafileltd/seafile-mc:12.0-latest SEAFILE_DB_IMAGE=mariadb:10.11 SEAFILE_MEMCACHED_IMAGE=memcached:1.6.29 SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.9-alpine SEAFILE_VOLUME=/data/seafile/seafile-data SEAFILE_MYSQL_VOLUME=/data/seafile/seafile-mysql/db SEAFILE_CADDY_VOLUME=/data/seafile/seafile-caddy SEAFILE_MYSQL_DB_HOST=db INIT_SEAFILE_MYSQL_ROOT_PASSWORD=www.waringid.com SEAFILE_MYSQL_DB_USER=seafile SEAFILE_MYSQL_DB_PASSWORD=www.waringid.com TIME_ZONE=Asia/Shanghai JWT_PRIVATE_KEY=iQbv/xGIWph09Bi2n2NMQOOp4cKKLupafk8XuTNe6YPLoOOKtGh92W0TcB9dpR2P SEAFILE_SERVER_HOSTNAME=seafile.waringid.local SEAFILE_SERVER_PROTOCOL=https INIT_SEAFILE_ADMIN_EMAIL=admin@waringid.local INIT_SEAFILE_ADMIN_PASSWORD=www.waringid.com SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest SEADOC_VOLUME=/data/seafile/seadoc-data ENABLE_SEADOC=true SEADOC_SERVER_URL=https://seafile.waringid.local/sdoc-server NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:12.0-latest NOTIFICATION_SERVER_VOLUME=/data/seafile/notification-data |
services: db: image: ${SEAFILE_DB_IMAGE:-mariadb:10.11} container_name: seafile-mysql 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 memcached: image: ${SEAFILE_MEMCACHED_IMAGE:-memcached:1.6.29} container_name: seafile-memcached entrypoint: memcached -m 256 networks: - seafile-net seafile: image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:12.0-latest} container_name: seafile ports: - "80:80" - "443:443" volumes: - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared 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:-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_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 #labels: # caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty} # caddy.reverse_proxy: "{{upstreams 80}}" depends_on: db: condition: service_healthy memcached: condition: service_started networks: - seafile-net networks: seafile-net: name: seafile-net |
services: seadoc: image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest} container_name: seadoc 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:-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_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty} #labels: # caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty} # caddy.@ws.0_header: "Connection *Upgrade*" # caddy.@ws.1_header: "Upgrade websocket" # caddy.0_reverse_proxy: "@ws {{upstreams 80}}" # caddy.1_handle_path: "/socket.io/*" # caddy.1_handle_path.0_rewrite: "* /socket.io{uri}" # caddy.1_handle_path.1_reverse_proxy: "{{upstreams 80}}" # caddy.2_handle_path: "/sdoc-server/*" # caddy.2_handle_path.0_rewrite: "* {uri}" # caddy.2_handle_path.1_reverse_proxy: "{{upstreams 80}}" depends_on: db: condition: service_healthy networks: - seafile-net networks: seafile-net: name: seafile-net |
docker compose -f /data/seafile/.env up -d mkdir /data/seafile/seafile-data/nginx/ssl cp ssl.crt ssl.key /data/seafile/seafile-data/nginx/ssl/ |
完成服务启动后,系统可以通过 http 的方式访问,但是无法通过 https 访问。原因是取消了 caddy.yml 配置,无法正常生成 SSL 证书和对应的配置文件。需要配置 SSL 证书和 Nginx 访问。
按上述配置复制对应的 SSL 证书到指定的位置。然后按以下的配置修改 Nginx 配置文件(/data/seafile/seafile-data/nginx/conf/seafile.nginx.conf)
# -*- mode: nginx -*- # Auto generated at 04/16/2025 14:18:39 server { listen 80; server_name seafile.waringid.local; location / { rewrite ^ https://$host$request_uri? permanent; } } server { listen 443 ssl; ssl_certificate /shared/nginx/ssl/ssl.crt; ssl_certificate_key /shared/nginx/ssl/ssl.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; 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 /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_read_timeout 36000s; access_log /var/log/nginx/seafhttp.access.log seafileformat; error_log /var/log/nginx/seafhttp.error.log; } location /notification/ping { proxy_pass http://127.0.0.1:8083/ping; access_log /var/log/nginx/notification.access.log seafileformat; error_log /var/log/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 /var/log/nginx/notification.access.log seafileformat; error_log /var/log/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 /var/log/nginx/seafdav.access.log seafileformat; error_log /var/log/nginx/seafdav.error.log; } location /:dir_browser { # Logo of WebDAV proxy_pass http://127.0.0.1:8080/:dir_browser; } 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 /media { root /opt/seafile/seafile-server-latest/seahub; } } |
SECRET_KEY = "s-g22nrldjimu!a9h4h)keb*1*lsu*rhbw#r&1w=qvi#&f)_-t" CSRF_TRUSTED_ORIGINS = ['https://seafile.waringid.local','http://seafile.waringid.local'] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'seahub_db', 'USER': 'seafile', 'PASSWORD': 'www.waringid.com', 'HOST': 'db', 'PORT': '3306', 'OPTIONS': {'charset': 'utf8mb4'}, } } CACHES = { 'default': { 'BACKEND': 'django_pylibmc.memcached.PyLibMCCache', 'LOCATION': 'memcached:11211', }, 'locmem': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', }, } COMPRESS_CACHE_BACKEND = 'locmem' TIME_ZONE = 'Asia/Shanghai' |
重启服务后即可实现 SSL 的内部访问模式。需要注意的是 seadoc 文件在 https 自签名证书(非公网证书)的配置下无法正常打开和编辑。
docker compose -f /data/seafile/.env restart |
配置步骤和前面的类似,取消了 caddy 的配置同时增加了 nginx 和证书配置以及 onlyoffice 的内容
mkdir -p /opt/seafile-pe/seafile-elasticsearch/data chmod 777 -R /opt/seafile-pe/seafile-elasticsearch/data mkdir -p /opt/seafile-pe/seafile-data/certs cp seafile.example.com.crt /opt/seafile-pe/seafile-data/certs/ cp seafile.example.com.key /opt/seafile-pe/seafile-data/certs/ chmod 400 /opt/seafile-pe/seafile-data/certs/seafile.example.com.key mkdir -p /opt/seafile-pe/onlyoffice/data/certs cp seafile.example.com.crt /opt/seafile-pe/onlyoffice/data/certs/onlyoffice.crt cp seafile.example.com.key /opt/seafile-pe/onlyoffice/data/certs/onlyoffice.key chmod 400 /opt/seafile-pe/onlyoffice/data/certs/onlyoffice.key |
新内容部署需要调整以下内容
注释或删除 seafile-server.yml 和 seadoc.yml 文件中的 caddy 字段所有内容 .env 文件 BASIC_STORAGE_PATH= Startup parameters 段落下的自定义部分 seafile-server.yml 文件 seafile: ports: - "8443:8443" seafile.nginx.conf 文件 listen 8443 ssl listen [::]:8443 ssl ssl_certificate /shared/certs/seafile.example.com.crt; ssl_certificate_key /shared/certs/seafile.example.com.key; server_name seafile.example.com localhost 127.0.0.1 192.168.3.5 [::1]; 添加 Seadoc 反向代理 location /sdoc-server/ { } 和 location /socket.io { } seahub_settings.py 文件 ONLYOFFICE_APIJS_URL = ONLYOFFICE_JWT_SECRET = |
############################################ # Docker compose configurations # ############################################ COMPOSE_FILE='seafile-server.yml,seadoc.yml,onlyoffice.yml' COMPOSE_PATH_SEPARATOR=',' ## Images SEAFILE_IMAGE=seafileltd/seafile-pro-mc:12.0-latest SEAFILE_DB_IMAGE=mariadb:10.11.11 SEAFILE_MEMCACHED_IMAGE=memcached:1.6.38 SEAFILE_ELASTICSEARCH_IMAGE=elasticsearch:8.18.0 SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:12.0-latest SEASEARCH_IMAGE=seafileltd/seasearch:latest ONLYOFFICE_IMAGE=onlyoffice/documentserver:latest ## Persistent Storage BASIC_STORAGE_PATH=/opt/seafile-pe #此处自定义Seafile的安装目录 SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-data SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db SEAFILE_ELASTICSEARCH_VOLUME=$BASIC_STORAGE_PATH/seafile-elasticsearch/data NOTIFICATION_SERVER_VOLUME=$BASIC_STORAGE_PATH/notification-data SS_DATA_PATH=$BASIC_STORAGE_PATH/seasearch-data SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data ONLYOFFICE_VOLUME=$BASIC_STORAGE_PATH/onlyoffice ############################################ # Startup parameters # ############################################ SEAFILE_SERVER_PORT=8443 #此处设置Seafile服务的访问端口 SEAFILE_SERVER_PROTOCOL=https #此处设置是否开启https SEAFILE_SERVER_HOSTNAME=seafile.example.com:$SEAFILE_SERVER_PORT #此处设置Seafile服务的域名或IP地址 TIME_ZONE=Asia/Shanghai #此处设置时区 JWT_PRIVATE_KEY=密码 #此处设置JWT密码,不少于32位 ## Database SEAFILE_MYSQL_DB_HOST=db SEAFILE_MYSQL_DB_USER=seafile SEAFILE_MYSQL_DB_PASSWORD=密码 #此处设置数据库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=密码 #此处设置数据库root用户密码 ## Seafile admin user INIT_SEAFILE_ADMIN_EMAIL=seafile@example.com #此处设置Seafile网站的登录邮箱账号 INIT_SEAFILE_ADMIN_PASSWORD=密码 #此处设置Seafile网站的账号登录密码 ## Seadoc ENABLE_SEADOC=true ## OnlyOffice ONLYOFFICE_PORT=6233 #此处设置onlyoffice的映射端口 ONLYOFFICE_JWT_SECRET=密码 #此处密码应与前边的JWT密码相同 ############################################ # Additional configurations for extensions # ############################################ ### Storage type SS_STORAGE_TYPE=disk # options: disk (local disk), s3 ### Local storage mode SS_MAX_OBJ_CACHE_SIZE=10GB ### Log SS_LOG_TO_STDOUT=false SS_LOG_OUTPUT=true SS_LOG_LEVEL=info ### S3 mode SS_S3_USE_V4_SIGNATURE=false SS_S3_ACCESS_ID=<your access id> SS_S3_ACCESS_SECRET=<your access secret> SS_S3_ENDPOINT=s3.us-east-1.amazonaws.com SS_S3_BUCKET=<your bucket name> SS_S3_USE_HTTPS=true SS_S3_PATH_STYLE_REQUEST=true SS_S3_AWS_REGION=us-east-1 SS_S3_SSE_C_KEY=<your SSE-C key> ### SeaSearch admin user INIT_SS_ADMIN_USER=$INIT_SEAFILE_ADMIN_EMAIL INIT_SS_ADMIN_PASSWORD=$INIT_SEAFILE_ADMIN_PASSWORD |
services: db: image: ${SEAFILE_DB_IMAGE:-mariadb:10.11.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 memcached: image: ${SEAFILE_MEMCACHED_IMAGE:-memcached:1.6.38} container_name: seafile-memcached restart: unless-stopped entrypoint: memcached -m 256 networks: - seafile-net elasticsearch: image: ${SEAFILE_ELASTICSEARCH_IMAGE:-elasticsearch:8.18.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 seafile: image: ${SEAFILE_IMAGE:-seafileltd/seafile-pro-mc:12.0-latest} container_name: seafile restart: unless-stopped ports: - "80:80" - "443:443" - "8443:8443" # 此处配置Seafile服务的访问端口 volumes: - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared 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 - INIT_S3_STORAGE_BACKEND_CONFIG=${INIT_S3_STORAGE_BACKEND_CONFIG:-false} - INIT_S3_COMMIT_BUCKET=${INIT_S3_COMMIT_BUCKET:-} - INIT_S3_FS_BUCKET=${INIT_S3_FS_BUCKET:-} - INIT_S3_BLOCK_BUCKET=${INIT_S3_BLOCK_BUCKET:-} - INIT_S3_KEY_ID=${INIT_S3_KEY_ID:-} - INIT_S3_SECRET_KEY=${INIT_S3_SECRET_KEY:-} - INIT_S3_USE_V4_SIGNATURE=${INIT_S3_USE_V4_SIGNATURE:-true} - INIT_S3_AWS_REGION=${INIT_S3_AWS_REGION:-us-east-1} - INIT_S3_HOST=${INIT_S3_HOST:-us-east-1} - INIT_S3_USE_HTTPS=${INIT_S3_USE_HTTPS:-true} depends_on: db: condition: service_healthy memcached: condition: service_started elasticsearch: condition: service_started networks: - seafile-net networks: seafile-net: name: seafile-net |
services: seadoc: image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.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:-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} depends_on: db: condition: service_healthy networks: - seafile-net networks: seafile-net: name: seafile-net |
services: onlyoffice: image: ${ONLYOFFICE_IMAGE:-onlyoffice/documentserver:latest} container_name: onlyoffice restart: unless-stopped 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} 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 networks: - seafile-net networks: seafile-net: name: seafile-net |
# -*- 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 /shared/certs/seafile.example.com.crt; ssl_certificate_key /shared/certs/seafile.example.com.key; } server { listen 443 ssl; listen 8443 ssl; listen [::]:443 ssl; listen [::]:8443 ssl; http2 on; server_name seafile.example.com localhost 127.0.0.1 192.168.3.5 [::1]; error_page 497 =301 https://$host:$server_port$request_uri; server_tokens off; ssl_certificate /shared/certs/seafile.example.com.crt; ssl_certificate_key /shared/certs/seafile.example.com.key; ssl_session_timeout 5m; 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://127.0.0.1:8083/ping; access_log /var/log/nginx/notification.access.log seafileformat; error_log /var/log/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 /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; } } |
先拉取镜像并启动,然后修改启动后生成的配置文件,最后重启完成整体的安装配置
docker compose pull docker compose up -d |
修改 seahub_settings.py 配置文件
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 = ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'odt', 'fodt', 'odp', 'fodp', 'ods', 'fods', 'csv', 'ppsx', 'pps') ONLYOFFICE_JWT_SECRET = 'env文件中配置的JWT密码' |
最后完成重启
docker compose down docker compose up -d |
适用于家用宽带有固定 IP 地址但无法使用 80 和 443 这些端口的场景
内网宿主机地址 192.168.1.11 ,完成部署后确保该地址在内网能正常访问
# 下载配置文件 wget -c https://manual.seafile.com/12.0/docker/ce/env -O .env wget -c https://manual.seafile.com/12.0/docker/caddy.yml -O caddy.yml wget -c https://manual.seafile.com/12.0/docker/ce/seafile-server.yml -O seafile-server.yml wget -c https://manual.seafile.com/12.0/docker/seadoc.yml -O seadoc.yml # 设置变量 SEAFILE_SERVER_HOSTNAME=192.168.1.11 TIME_ZONE='Asia/Shanghai' SEAFILE_MYSQL_ROOT_PASSWORD=$(cat /dev/urandom |tr -dc [:alnum:] |head -c 16) SEAFILE_MYSQL_DB_PASSWORD=$(cat /dev/urandom |tr -dc [:alnum:] |head -c 16) JWT_PRIVATE_KEY=$(cat /dev/urandom |tr -dc [:alnum:] |head -c 32) SEAFILE_ADMIN_PASSWORD=$(cat /dev/urandom |tr -dc [:alnum:] |head -c 12) # 编辑.env文件 sed -e "s/\(COMPOSE_FILE='seafile-server.yml,caddy.yml\)\S\+/\1,seadoc.yml'/g" \ -e "s/\(ENABLE_SEADOC=\)\S\+/\1true/g" \ -e "s/seafile.example.com/${SEAFILE_SERVER_HOSTNAME}/g" \ -e "s/\(INIT_SEAFILE_MYSQL_ROOT_PASSWORD=\)\S\+/\1${SEAFILE_MYSQL_ROOT_PASSWORD}/g" \ -e "s/\(SEAFILE_MYSQL_DB_PASSWORD=\)\S\+/\1${SEAFILE_MYSQL_DB_PASSWORD}/g" \ -e "s,\(TIME_ZONE=\)\S\+,\1${TIME_ZONE},g" \ -e "s/\(JWT_PRIVATE_KEY=\)\S*/\1${JWT_PRIVATE_KEY}/g" \ -e "s/\(INIT_SEAFILE_ADMIN_PASSWORD=\)\S\+/\1${SEAFILE_ADMIN_PASSWORD}/g" \ -i .env # 启动Seafile docker compose up -d # 查看Seafile启动日志 docker compose logs -f |
待 Seafile 启动使用浏览器访问 “http://192.168.1.11”,登录测试编辑 seadoc 文件和知识库文件正常,表示部署成功。
另外,为方便后面调试,建议开启 Caddy 的 debug 日志,并将配置目录外置:创建外置配置目录“mkdir -p /opt/seafile-caddy/config”,然后,编辑 caddy.yml 文件:
...... labels: caddy.debug: volumes: - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}/config:/config/caddy ...... |
重启后生效。后面调试,在需要查看 Caddy 配置时,执行“cat /opt/seafile-caddy/config/Caddyfile.autosave”
如果你的公网IP在配置端口映射时,可以设置内外的端口号不同,否则该步骤可以忽略
1、编辑 .env
SEAFILE_SERVER_HOSTNAME=192.168.1.11:51480 SEADOC_SERVER_URL=http://192.168.1.11:51480/sdoc-server |
2、修改 caddy.yml
ports: - 51480:80 |
3、修改 seafile-server.yml 和 seadoc.yml
labels: #caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty} caddy: http://192.168.1.11 |
这里必须要改,因为“.env”配置的“SEAFILE_SERVER_HOSTNAME”值带有端口号,不被Caddy接受。 |
4、重启应用
docker compose down docker compose up -d docker compose logs -f |
启动后使用浏览器访问“http://192.168.1.11:51480”,登录测试编辑 seadoc 文件和知识库文件正常,表示成功。
配置公网IP(1.2.3.4)的端口映射,将 51480 端口指向内网 IP(192.168.1.111)的 80端口(未做步骤4.2)或51480端口(已做步骤4.2)。另外,配置启用公网 IP 后,从本地内网也必须用公网 IP 端口访问 Seafile,因此公网映射要支持本地自反访问。
1、编辑 .env
SEAFILE_SERVER_HOSTNAME=1.2.3.4:51480 SEADOC_SERVER_URL=http://1.2.3.4:51480/sdoc-server |
2、修改 seafile-server.yml 和 seadoc.yml
labels: #caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty} caddy: http://1.2.3.4 |
3、重启应用
docker compose down docker compose up -d docker compose logs -f |
启动后使用浏览器访问“http://1.2.3.4:51480”,登录测试编辑 seadoc 文件和知识库文件正常,表示成功。
注意:自签发证书的使用者可选名称必须包括 seafile-caddy 的容器 IP,否则不被 caddy 接受,导致启用 HTTPS 后服务不可访问。 |
制作证书前,执行“docker inspect seafile-caddy |grep '"IPAddress"'”,输出结果本人是:
$ docker inspect seafile-caddy |grep '"IPAddress"' "IPAddress": "", "IPAddress": "172.18.0.2", |
这表示部署的 seafile-caddy 可能会使用的IP是:172.18.0.2 至 172.18.0.6。
使用证书工具自签发服务端证书,证书使用者可选名称要包括的IP地址为:192.168.1.11,1.2.3.4,172.18.0.2,172.18.0.3,172.18.0.4,172.18.0.5,172.18.0.6。使用证书制作工具制作出服务端证书,后面启用 HTTPS需要使用根证书、服务端证书公钥和服务端证书私钥。
未做步骤4.2的,需要配置公网IP(1.2.3.4)的端口映射,将 51480 端口指向内网IP(192.168.1.111)的 443 端口。做了步骤4.2的下面会配置将 51480 端口换到 Caddy 的 443 端口。
1、编辑 .env
SEAFILE_SERVER_PROTOCOL=https SEADOC_SERVER_URL=https://1.2.3.4:51480/sdoc-server |
2、编辑 /data/opt/seafile-data/seafile/conf/seahub_settings.py
FILE_SERVER_ROOT = 'https://1.2.3.4:51480/seafhttp' CSRF_TRUSTED_ORIGINS = [ 'https://1.2.3.4' ] |
3、编辑 caddy.yml(注:未做步骤4.2的不用修改端口;做了步骤4.2点需要修改端口):
ports: #- 51480:80 - 51480:443 labels: caddy.auto_https: "disable_certs" |
4、复制证书到 Caddy 目录
mkdir -p /opt/seafile-caddy/certificates/local/1.2.3.4/ cp root.crt /opt/seafile-caddy/certificates/local/1.2.3.4/ cp server.crt /opt/seafile-caddy/certificates/local/1.2.3.4/ cp server.key /opt/seafile-caddy/certificates/local/1.2.3.4/ |
5、复制证书到Seafile目录:
cp root.crt /opt/seafile-data/ |
6、编辑 seafile-server.yml
...... command: /bin/bash -c "cat /shared/root.crt >>/opt/seafile/seafile-server-*/seahub/thirdpart/certifi/cacert.pem; /sbin/my_init -- /scripts/enterpoint.sh" ...... labels: caddy: https://1.2.3.4 caddy.tls: /data/caddy/certificates/local/1.2.3.4/server.crt /data/caddy/certificates/local/1.2.3.4/server.key caddy.tls.ca_root: /data/caddy/certificates/local/1.2.3.4/root.crt ...... |
7、复制证书到 Seadoc 目录
cp root.crt /opt/seadoc-data/ |
8、编辑 seadoc.yml
...... environment: - NODE_EXTRA_CA_CERTS=/shared/root.crt ...... labels: caddy: https://1.2.3.4 ...... |
9、重新启动 Seafile:
docker compose down docker compose up -d docker compose logs -f |
启动后使用浏览器访问“https://1.2.3.4:51480 ”,登录测试编辑 seadoc 文件和知识库文件正常,表示成功。