La Suite Drive是法国政府主导的又一个开源网盘程序。特点如下:
- 🔐 将您的文件安全地存储在集中位置
- 🌐 通过我们的网页界面,随时随地访问您的文件
- 🔍 强大的搜索功能,可快速查找文件和文件夹
- 📂 文件结构清晰有序,导航和筛选功能直观易用
- 🤝 与团队成员共享文件和文件夹
- 👥 精细化的访问控制,确保您的信息安全,且只与授权人员共享
- 🏢 创建工作区以组织团队协作和管理共享资源
- 🚀
易于安装、可扩展且安全的文件存储解决方案
为什么把易于安装给划掉?因为这个项目我认为就目前而言是非常难以安装的,官方没有提供生产部署的文档,且部署步骤太多太杂了。。我认为这与官方的宣传不符,所以给划掉了= =
这里我为了尝鲜体验一番,记录一下用docker compose部署的方式。如果后续官方写了部署文档,请以官方的文档为准。这个项目目前应该还是Beta状态,如果官方后续对项目做了比较大的改动,不保证这篇文章的部署方法一直有效。
准备工作:
1.一台Debian服务器,内存不低于4GB,放行80、443、9199、9299、9980端口。
2.添加域名A记录解析,本文示例域名:drive.example.com、onlyoffice.example.com、collabora.example.com。
3.部署RustFS对象存储服务,或Garage S3对象存储服务。推荐RustFS,因为Drive的文档编辑功能需要S3支持“版本控制”的功能,Garage S3缺少这个功能将导致文档无法保存。本文S3示例域名:rustfs.example.com
4.部署VoidAuth OIDC身份验证服务。本文示例域名:voidauth.example.com
在VoidAuth创建OIDC APP:
设置Redirect URLs:
https://drive.example.com/api/v1.0/callback/
设置PostLogout URL:
https://drive.example.com/api/v1.0/logout-callback/
在RustFS控制台创建存储桶,并启用版本控制:
做好上面的准备工作后,现在可以正式部署Drive了,在服务器内安装Docker:
apt -y update apt -y install curl curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
新建compose文件:
mkdir -p /opt/drive && cd /opt/drive && nano docker-compose.yml
写入如下内容,需要修改的地方写了注释:
x-common-env: &common-env
BACKEND_HOST: backend
FRONTEND_HOST: frontend
# Django
DJANGO_ALLOWED_HOSTS: "*"
DJANGO_SECRET_KEY: 7cafccee9288097a2b3eb64305b0d07bff6682bc50a2b3f99a9696ef2e000fab # 使用openssl rand -hex 32生成
DJANGO_SETTINGS_MODULE: drive.settings
DJANGO_CONFIGURATION: Production
# Logging
LOGGING_LEVEL_HANDLERS_CONSOLE: ERROR
LOGGING_LEVEL_LOGGERS_ROOT: INFO
LOGGING_LEVEL_LOGGERS_APP: INFO
# Python
PYTHONPATH: /app
# Mail
DJANGO_EMAIL_HOST: mail.example.com
DJANGO_EMAIL_HOST_USER: smtp
DJANGO_EMAIL_HOST_PASSWORD: smtppassword
DJANGO_EMAIL_PORT: 587
DJANGO_EMAIL_FROM: smtp@example.com
DJANGO_EMAIL_USE_TLS: true
DJANGO_EMAIL_BRAND_NAME: "La Suite Numérique"
DJANGO_EMAIL_LOGO_IMG: "https://drive.example.com/assets/logo-suite-numerique.png"
# Media S3
STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage
AWS_S3_ACCESS_KEY_ID: imlala
AWS_S3_SECRET_ACCESS_KEY: s3secretaccesskey
AWS_S3_REGION_NAME: auto
AWS_STORAGE_BUCKET_NAME: drive-media-storage
AWS_S3_SIGNATURE_VERSION: s3v4
AWS_S3_ENDPOINT_URL: https://rustfs.example.com
MEDIA_BASE_URL: https://drive.example.com
# OIDC
OIDC_OP_JWKS_ENDPOINT: https://voidauth.example.com/oidc/jwks
OIDC_OP_AUTHORIZATION_ENDPOINT: https://voidauth.example.com/oidc/auth
OIDC_OP_TOKEN_ENDPOINT: https://voidauth.example.com/oidc/token
OIDC_OP_USER_ENDPOINT: https://voidauth.example.com/oidc/me
OIDC_OP_LOGOUT_ENDPOINT: https://voidauth.example.com/oidc/session/end
OIDC_RP_CLIENT_ID: pcl1xbprEdcbi0xQ
OIDC_RP_CLIENT_SECRET: youroidcsecret
OIDC_RP_SIGN_ALGO: RS256
OIDC_RP_SCOPES: "openid email"
LOGIN_REDIRECT_URL: https://drive.example.com
LOGIN_REDIRECT_URL_FAILURE: https://drive.example.com
LOGOUT_REDIRECT_URL: https://drive.example.com
OIDC_REDIRECT_ALLOWED_HOSTS: '["https://drive.example.com"]'
# WOPI
WOPI_CLIENTS: "collabora,onlyoffice"
WOPI_COLLABORA_DISCOVERY_URL: https://collabora.example.com/hosting/discovery
WOPI_ONLYOFFICE_DISCOVERY_URL: https://onlyoffice.example.com/hosting/discovery
WOPI_SRC_BASE_URL: https://drive.example.com
x-postgres-env: &postgres-env
# Postgresql db container configuration
POSTGRES_DB: drive
POSTGRES_USER: drive
POSTGRES_PASSWORD: 023917148a35e7c9a62964caabe0334c # 设置数据库密码
# App database configuration
DB_HOST: postgresql
DB_NAME: drive
DB_USER: drive
DB_PASSWORD: 023917148a35e7c9a62964caabe0334c # 设置数据库密码
DB_PORT: 5432
services:
postgresql:
image: postgres:16
restart: unless-stopped
environment:
<<: *postgres-env
volumes:
- ./data/databases/backend:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 1s
timeout: 2s
retries: 300
redis:
image: redis:5
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 5s
retries: 5
start_period: 10s
backend:
image: lasuite/drive-backend:main
restart: unless-stopped
user: "${DOCKER_USER:-1000}"
depends_on:
postgresql:
condition: service_healthy
restart: true
redis:
condition: service_healthy
environment:
<<: [*common-env, *postgres-env]
frontend:
image: lasuite/drive-frontend:main
user: "${DOCKER_USER:-1000}"
restart: unless-stopped
depends_on:
- backend
environment:
<<: [*common-env]
ports:
- 127.0.0.1:9199:8083
volumes:
- ./default.conf.template:/etc/nginx/templates/docs.conf.template
entrypoint:
- /docker-entrypoint.sh
command: ["nginx", "-g", "daemon off;"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080"]
interval: 15s
timeout: 30s
retries: 20
start_period: 10s
celery:
image: lasuite/drive-backend:main
user: ${DOCKER_USER:-1000}
restart: unless-stopped
environment:
<<: [*common-env, *postgres-env]
command: [ "celery", "-A", "drive.celery_app", "worker", "-l", "INFO" ]
onlyoffice-docs:
image: onlyoffice/documentserver:latest
container_name: onlyoffice-docs
restart: unless-stopped
environment:
- WOPI_ENABLED=true
- JWT_ENABLED=true
- JWT_SECRET=be1b32d03c4397d2cabffa3acef7450b # 设置JWT密钥
ports:
- "127.0.0.1:9299:80"
volumes:
- ./onlyoffice/logs:/var/log/onlyoffice
- ./onlyoffice/data:/var/www/onlyoffice/Data
- ./onlyoffice/lib:/var/lib/onlyoffice
- ./onlyoffice/db:/var/lib/postgresql
collabora:
image: collabora/code:latest
container_name: collabora-code
restart: unless-stopped
ports:
- "127.0.0.1:9980:9980"
environment:
- server_name=collabora.example.com
- username=admin
- password=97bfec0e41e788611c636024fa5bd4bb # 设置collabora管理员密码
- extra_params=--o:ssl.enable=false --o:ssl.termination=true
注意事项:
如果你只想使用一个办公套件,例如onlyoffice,那么请修改如下变量:
WOPI_CLIENTS: "onlyoffice" #WOPI_COLLABORA_DISCOVERY_URL: https://collabora.example.com/hosting/discovery #注释掉这个变量
Drive的WOPI在默认情况下会使用onlyoffice,如果你不需要collabora code可以不部署,并且onlyoffice的使用体验比collabora code好的多。
新建前端容器需要用到的NGINX配置文件:
nano default.conf.template
写入如下内容:
upstream docs_backend {
server ${BACKEND_HOST}:8000 fail_timeout=0;
}
upstream docs_frontend {
server ${FRONTEND_HOST}:3000 fail_timeout=0;
}
server {
listen 8083;
server_name localhost;
charset utf-8;
# increase max upload size
client_max_body_size 5120m;
server_tokens off;
proxy_ssl_server_name on;
location @proxy_to_docs_backend {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://docs_backend;
}
location @proxy_to_docs_frontend {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
proxy_pass http://docs_frontend;
}
location / {
try_files $uri @proxy_to_docs_frontend;
}
location /api {
try_files $uri @proxy_to_docs_backend;
}
location /admin {
try_files $uri @proxy_to_docs_backend;
}
location /media/ {
# Auth request configuration
auth_request /media-auth;
auth_request_set $authHeader $upstream_http_authorization;
auth_request_set $authDate $upstream_http_x_amz_date;
auth_request_set $authContentSha256 $upstream_http_x_amz_content_sha256;
# Pass specific headers from the auth response
proxy_set_header Authorization $authHeader;
proxy_set_header X-Amz-Date $authDate;
proxy_set_header X-Amz-Content-SHA256 $authContentSha256;
proxy_pass https://rustfs.example.com/drive-media-storage/;
proxy_set_header Host rustfs.example.com;
proxy_ssl_name rustfs.example.com;
}
# Proxy auth for media-preview
location /media/preview/ {
# Auth request configuration
auth_request /media-auth;
auth_request_set $authHeader $upstream_http_authorization;
auth_request_set $authDate $upstream_http_x_amz_date;
auth_request_set $authContentSha256 $upstream_http_x_amz_content_sha256;
# Pass specific headers from the auth response
proxy_set_header Authorization $authHeader;
proxy_set_header X-Amz-Date $authDate;
proxy_set_header X-Amz-Content-SHA256 $authContentSha256;
proxy_pass https://rustfs.example.com/drive-media-storage/;
proxy_set_header Host rustfs.example.com;
proxy_ssl_name rustfs.example.com;
}
location /media-auth {
proxy_pass http://docs_backend/api/v1.0/items/media-auth/;
proxy_set_header X-Forwarded-Proto https;
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-Original-URL $request_uri;
# Prevent the body from being passed
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-Method $request_method;
}
}
注意将location /media/和location /media/preview/内的域名改为自己的S3域名:
proxy_pass https://rustfs.example.com/drive-media-storage/; proxy_set_header Host rustfs.example.com; proxy_ssl_name rustfs.example.com;
启动全部容器:
docker compose up -d
运行数据库迁移、创建Django管理员账号:
docker compose run --rm backend python manage.py migrate docker compose run --rm backend python manage.py createsuperuser --email imlala@lala.im --password youradminpassword
运行如下命令启用WOPI客户端:
docker compose run --rm backend python manage.py trigger_wopi_configuration
这应该是一个BUG,按道理来说celery会自动执行,但是不知道为什么没生效。如果不执行这个命令将无法使用文档编辑功能。
配置Ferron反向代理:
nano /etc/ferron.kdl
写入如下内容:
drive.example.com {
proxy "http://127.0.0.1:9199/"
proxy_request_header_replace "Host" "{header:Host}"
}
onlyoffice.example.com {
proxy "http://127.0.0.1:9299/"
proxy_request_header_replace "Host" "{header:Host}"
}
collabora.example.com {
proxy "http://127.0.0.1:9980/"
proxy_request_header_replace "Host" "{header:Host}"
disable_url_sanitizer #true
}
重载Ferron:
systemctl reload ferron
如遇到Ferron反向代理导致上传速度慢,可以参考这篇文章解决。
所有服务将在以下URL提供访问:
https://drive.example.com https://onlyoffice.example.com/admin https://collabora.example.com/browser/dist/admin/admin.html
效果:
总结一下部署过程中遇到的问题。
1.由于官方的环境变量配置文件不完整,导致部署非常困难,甚至有些变量还要翻源码才能知道是什么作用= =
2.前端容器必须配置入口点启动脚本,否则无法使用挂载的自定义NGINX配置文件。
3.官方提供的NGINX配置文件缺少对/media/preview/的路由,导致上传的文件无法预览。
4.Ferron反向代理collabora code遇到WebSocket连接失败。原因是Ferron默认会过滤URL防止路径遍历等安全漏洞,collabora code的WebSocket连接URL里面包含https://被Ferron过滤成https:/了,导致后端报错Bad URL。解决办法是关闭Ferron的URL过滤:disable_url_sanitizer #true
5.S3实现不支持版本控制,导致文档无法保存,这个之前已经提过了。
6.S3跨域问题,因为Drive是直接操作S3,没有经过后端,所以S3这边要设置跨域规则。
7.目前需要手动执行python manage.py trigger_wopi_configuration来集成onlyoffice等办公套件,这是一个BUG:见此issue
总之就是这个项目完成度还是非常高的,基本功能都有了,要我说就是还差个文件缩略图和密码分享的功能。但是有一说一部署确实太多坑了,建议再观望一下= =
荒岛
























