From 65cfb1e8207504d8ca7f1438d23e9efe3c1dc6d2 Mon Sep 17 00:00:00 2001 From: skywalker Date: Mon, 23 Sep 2024 16:48:28 +0800 Subject: [PATCH 01/22] Seafile Setup with Docker (v12.0) --- .../deploy_seafile_with_docker_v12.0.md | 176 +++++++++++ .../docker-compose/ce/12.0/seafile-server.yml | 2 + .../pro/12.0/seafile-server.yml | 2 + .../deploy_seafile_pro_with_docker_v12.0.md | 285 ++++++++++++++++++ mkdocs.yml | 3 + 5 files changed, 468 insertions(+) create mode 100644 manual/docker/deploy_seafile_with_docker_v12.0.md create mode 100644 manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md diff --git a/manual/docker/deploy_seafile_with_docker_v12.0.md b/manual/docker/deploy_seafile_with_docker_v12.0.md new file mode 100644 index 000000000..0fa49ff73 --- /dev/null +++ b/manual/docker/deploy_seafile_with_docker_v12.0.md @@ -0,0 +1,176 @@ +# Deploy Seafile with Docker (v12.0) + +## Getting started + +The following assumptions and conventions are used in the rest of this document: + +- `/opt/seafile-data` is the directory of Seafile. If you decide to put Seafile in a different directory — which you can — adjust all paths accordingly. +- Seafile uses two [Docker volumes](https://docs.docker.com/storage/volumes/) for persisting data generated in its database and Seafile Docker container. The volumes' [host paths](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes) are `/opt/seafile-mysql` and `/opt/seafile-data`, respectively. It is not recommended to change these paths. If you do, account for it when following these instructions. +- All configuration and log files for Seafile and the webserver Nginx are stored in the volume of the Seafile container. + +### Install docker + +Use the [official installation guide for your OS to install Docker](https://docs.docker.com/engine/install/). + +### Download and modify `.env` + +From Seafile Docker 12.0, we recommend that you use `.env`, `seafile-server.yml` and `caddy.yml` files for configuration. + +**NOTE:** Different versions of Seafile have different compose files. + +```bash +mkdir /opt/seafile +cd /opt/seafile + +# Seafile CE 12.0 +wget -O .env https://manual.seafile.com/docker/docker-compose/ce/12.0/env +wget https://manual.seafile.com/docker/docker-compose/ce/12.0/seafile-server.yml +wget https://manual.seafile.com/docker/docker-compose/ce/12.0/caddy.yml + +nano .env +``` + +The following fields merit particular attention: + +* The volume directory of Seafile data (SEAFILE_VOLUMES) +* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUMES) +* The volume directory of Caddy data (SEAFILE_CADDY_VOLUMES) +* The root password of MySQL (SEAFILE_MYSQL_ROOT_PASSWORD) +* The user password of MySQL (SEAFILE_MYSQL_DB_PASSWORD) +* JWT (JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1`) +* Seafile server hostname (SEAFILE_SERVER_HOSTNAME) +* Seafile server protocol (SEAFILE_SERVER_PROTOCOL, use http or https) +* Time zone (TIME_ZONE) +* Admin username (SEAFILE_ADMIN_EMAIL) +* Admin password (SEAFILE_ADMIN_PASSWORD) + +NOTE: SSL is now handled by the caddy server. + +### Start Seafile server + +Start Seafile server with the following command + +```bash +# if `.env` file is in current directory: +docker compose up -d + +# if `.env` file is elsewhere: +docker compose -f /path/to/.env up -d +``` + +Wait for a few minutes for the first time initialization, then visit `http://seafile.example.com` to open Seafile Web UI. + +## Seafile directory structure + +### `/opt/seafile-data` + +Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various log files and upload directory outside. This allows you to rebuild containers easily without losing important information. + +* /opt/seafile-data/seafile: This is the directory for seafile server configuration and data. + * /opt/seafile-data/seafile/logs: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `/opt/seafile-data/seafile/logs/seafile.log`. +* /opt/seafile-data/logs: This is the directory for operating system and Nginx logs. + * /opt/seafile-data/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `/opt/seafile-data/logs/var-log/nginx/`. + +### Find logs + +To monitor container logs (from outside of the container), please use the following commands: + +```bash +# if the `.env` file is in current directory: +docker compose logs --follow +# if the `.env` file is elsewhere: +docker compose -f /path/to/.env logs --follow + +# you can also specify container name: +docker compose logs seafile --follow +# or, if the `.env` file is elsewhere: +docker compose -f /path/to/.env logs seafile --follow +``` + +The Seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafile-data/logs/seafile` in the server that run the docker. + +The system logs are under `/shared/logs/var-log`, or `/opt/seafile-data/logs/var-log` in the server that run the docker. + +To monitor all Seafile logs simultaneously (from outside of the container), run + +```bash +sudo tail -f $(find /opt/seafile-data/ -type f -name *.log 2>/dev/null) +``` + +## More configuration options + +### Use an existing mysql-server + +If you want to use an existing mysql-server, you can modify the `.env` as follows + +```env +SEAFILE_MYSQL_DB_HOST=192.168.0.2 +SEAFILE_MYSQL_DB_PORT=3306 +SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD +SEAFILE_MYSQL_DB_PASSWORD=PASSWORD +``` + +NOTE: `SEAFILE_MYSQL_ROOT_PASSWORD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (SEAFILE_MYSQL_DB_PASSWORD). You can remove the `SEAFILE_MYSQL_ROOT_PASSWORD`. + +### Modify Seafile server configurations + +The config files are under `/opt/seafile-data/seafile/conf`. You can modify the configurations according to [Seafile manual](https://manual.seafile.com/) + +After modification, you need to restart the container: + +```bash +docker compose restart +``` + +### Add a new admin + +Ensure the container is running, then enter this command: + +```bash +docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh +``` + +Enter the username and password according to the prompts. You now have a new admin account. + +### Run Seafile as non root user inside docker + +You can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) + +First add the `NON_ROOT=true` to the `.env`. + +```env +NON_ROOT=true +``` + +Then modify `/opt/seafile-data/seafile/` permissions. + +```bash +chmod -R a+rwx /opt/seafile-data/seafile/ +``` + +Then destroy the containers and run them again: + +```bash +docker compose down +docker compose up -d +``` + +Now you can run Seafile as `seafile` user. (**NOTE:** Later, when doing maintenance, other scripts in docker are also required to be run as `seafile` user, e.g. `su seafile -c ./seaf-gc.sh`) + +## Backup and recovery + +Follow the instructions in [Backup and restore for Seafile Docker](../maintain/backup_recovery.md) + +## Garbage collection + +When files are deleted, the blocks comprising those files are not immediately removed as there may be other files that reference those blocks (due to the magic of deduplication). To remove them, Seafile requires a ['garbage collection'](../maintain/seafile_gc.md) process to be run, which detects which blocks no longer used and purges them. (**NOTE:** for technical reasons, the GC process does not guarantee that _every single_ orphan block will be deleted.) + +The required scripts can be found in the `/scripts` folder of the docker container. To perform garbage collection, simply run `docker exec seafile /scripts/gc.sh`. For the community edition, this process will stop the seafile server, but it is a relatively quick process and the seafile server will start automatically once the process has finished. The Professional supports an online garbage collection. + +## FAQ + +### You can run docker commands like `docker exec` to find errors + +```bash +docker exec -it seafile /bin/bash +``` diff --git a/manual/docker/docker-compose/ce/12.0/seafile-server.yml b/manual/docker/docker-compose/ce/12.0/seafile-server.yml index fcb7eec10..ed027159b 100644 --- a/manual/docker/docker-compose/ce/12.0/seafile-server.yml +++ b/manual/docker/docker-compose/ce/12.0/seafile-server.yml @@ -27,6 +27,7 @@ services: - ${SEAFILE_VOLUMES:-/opt/seafile-data}:/shared environment: - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db} + - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306} - DB_ROOT_PASSWD=${SEAFILE_MYSQL_ROOT_PASSWORD:?Variable is not set or empty} - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty} - TIME_ZONE=${TIME_ZONE:-Etc/UTC} @@ -35,6 +36,7 @@ services: - 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} - ENABLE_SEADOC=${ENABLE_SEADOC:-false} - SEADOC_SERVER_URL=${SEADOC_SERVER_URL:-http://example.example.com/sdoc-server} diff --git a/manual/docker/docker-compose/pro/12.0/seafile-server.yml b/manual/docker/docker-compose/pro/12.0/seafile-server.yml index 4d9f5a286..d90bb5ce7 100644 --- a/manual/docker/docker-compose/pro/12.0/seafile-server.yml +++ b/manual/docker/docker-compose/pro/12.0/seafile-server.yml @@ -45,6 +45,7 @@ services: - ${SEAFILE_VOLUMES:-/opt/seafile-data}:/shared environment: - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db} + - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306} - DB_ROOT_PASSWD=${SEAFILE_MYSQL_ROOT_PASSWORD:?Variable is not set or empty} - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty} - TIME_ZONE=${TIME_ZONE:-Etc/UTC} @@ -53,6 +54,7 @@ services: - 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} - ENABLE_SEADOC=${ENABLE_SEADOC:-false} - SEADOC_SERVER_URL=${SEADOC_SERVER_URL:-http://example.example.com/sdoc-server} diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md new file mode 100644 index 000000000..55796d1ab --- /dev/null +++ b/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md @@ -0,0 +1,285 @@ +# Installation of Seafile Server Professional Edition with Docker (v12.0) + +This manual explains how to deploy and run Seafile Server Professional Edition (Seafile PE) on a Linux server using Docker and Docker Compose. The deployment has been tested for Debian/Ubuntu and CentOS, but Seafile PE should also work on other Linux distributions. + +## Requirements + +Seafile PE requires a minimum of 2 cores and 2GB RAM. If Elasticsearch is installed on the same server, the minimum requirements are 4 cores and 4 GB RAM, and make sure the [mmapfs counts](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-store.html#mmapfs) do not cause excptions like out of memory, which can be increased by following command (see for futher details): + +```shell +sysctl -w vm.max_map_count=262144 #run as root +``` + +or modify **/etc/sysctl.conf** and reboot to set this value permanently: + +```shell +nano /etc/sysctl.conf + +# modify vm.max_map_count +vm.max_map_count=262144 +``` + +Seafile PE can be used without a paid license with up to three users. Licenses for more user can be purchased in the [Seafile Customer Center](https://customer.seafile.com) or contact Seafile Sales at sales@seafile.com. + +## Setup + +The following assumptions and conventions are used in the rest of this document: + +- `/opt/seafile-data` is the directory of Seafile. If you decide to put Seafile in a different directory - which you can - adjust all paths accordingly. +- Seafile uses two [Docker volumes](https://docs.docker.com/storage/volumes/) for persisting data generated in its database and Seafile Docker container. The volumes' [host paths](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes) are /opt/seafile-mysql and /opt/seafile-data, respectively. It is not recommended to change these paths. If you do, account for it when following these instructions. +- All configuration and log files for Seafile and the webserver Nginx are stored in the volume of the Seafile container. + +### Installing Docker + +Use the [official installation guide for your OS to install Docker](https://docs.docker.com/engine/install/). + +### Downloading the Seafile Image + +Log into Seafile's private repository and pull the Seafile image: + +```bash +docker login docker.seadrive.org +docker pull docker.seadrive.org/seafileltd/seafile-pro-mc:12.0-latest +``` + +When prompted, enter the username and password of the private repository. They are available on the download page in the [Customer Center](https://customer.seafile.com/downloads). + +NOTE: Older Seafile PE versions are also available in the repository (back to Seafile 7.0). To pull an older version, replace '12.0-latest' tag by the desired version. + +### Downloading and Modifying `.env` + +From Seafile Docker 12.0, we recommend that you use `.env`, `seafile-server.yml` and `caddy.yml` files for configuration. + +NOTE: Different versions of Seafile have different compose files. + +```bash +mkdir /opt/seafile +cd /opt/seafile + +# Seafile PE 12.0 +wget -O .env https://manual.seafile.com/docker/docker-compose/pro/12.0/env +wget https://manual.seafile.com/docker/docker-compose/pro/12.0/seafile-server.yml +wget https://manual.seafile.com/docker/docker-compose/pro/12.0/caddy.yml + +nano .env +``` + +The following fields merit particular attention: + +* The volume directory of Seafile data (SEAFILE_VOLUMES) +* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUMES) +* The volume directory of Caddy data (SEAFILE_CADDY_VOLUMES) +* The volume directory of Elasticsearch data (SEAFILE_ELASTICSEARCH_VOLUMES) +* The root password of MySQL (SEAFILE_MYSQL_ROOT_PASSWORD) +* The user password of MySQL (SEAFILE_MYSQL_DB_PASSWORD) +* JWT (JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1`) +* Seafile server hostname (SEAFILE_SERVER_HOSTNAME) +* Seafile server protocol (SEAFILE_SERVER_PROTOCOL, use http or https) +* Time zone (TIME_ZONE) +* Admin username (SEAFILE_ADMIN_EMAIL) +* Admin password (SEAFILE_ADMIN_PASSWORD) + +NOTE: SSL is now handled by the caddy server. + +To conclude, set the directory permissions of the Elasticsearch volumne: + +```bash +mkdir -p /opt/seafile-elasticsearch/data +chmod 777 -R /opt/seafile-elasticsearch/data +``` + +### Starting the Docker Containers + +Run docker compose in detached mode: + +```bash +docker compose up -d +``` + +NOTE: You must run the above command in the directory with the `.env`. + +Wait a few moment for the database to initialize. You can now access Seafile at the host name specified in the Compose file. (A 502 Bad Gateway error means that the system has not yet completed the initialization.) + +### Find logs + +To view Seafile docker logs, please use the following command + +```shell +docker compose logs -f +``` + +The Seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafile-data/logs/seafile` in the server that run the docker. + +The system logs are under `/shared/logs/var-log`, or `/opt/seafile-data/logs/var-log` in the server that run the docker. + +### Activating the Seafile License + +If you have a `seafile-license.txt` license file, simply put it in the volume of the Seafile container. The volumne's default path in the Compose file is `/opt/seafile-data`. If you have modified the path, save the license file under your custom path. + +Then restart Seafile: + +```bash +docker compose down + +docker compose up -d +``` + +## Seafile directory structure + +### `/opt/seafile-data` + +Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various log files and upload directory outside. This allows you to rebuild containers easily without losing important information. + +* /opt/seafile-data/seafile: This is the directory for seafile server configuration 、logs and data. + * /opt/seafile-data/seafile/logs: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `/opt/seafile-data/seafile/logs/seafile.log`. +* /opt/seafile-data/logs: This is the directory for operating system and Nginx logs. + * /opt/seafile-data/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `/opt/seafile-data/logs/var-log/nginx/`. + +### Reviewing the Deployment + +The command `docker container list` should list the containers specified in the `.env`. + +The directory layout of the Seafile container's volume should look as follows: + +```bash +$ tree /opt/seafile-data -L 2 +/opt/seafile-data +├── logs +│   └── var-log +├── nginx +│   └── conf +└── seafile +    ├── ccnet +    ├── conf +    ├── logs +    ├── pro-data +    ├── seafile-data +    └── seahub-data +``` + +All Seafile config files are stored in `/opt/seafile-data/seafile/conf`. The nginx config file is in `/opt/seafile-data/nginx/conf`. + +Any modification of a configuration file requires a restart of Seafile to take effect: + +```bash +docker compose restart +``` + +All Seafile log files are stored in `/opt/seafile-data/seafile/logs` whereas all other log files are in `/opt/seafile-data/logs/var-log`. + +## Use an existing mysql-server + +If you want to use an existing mysql-server, you can modify the `.env` as follows + +```env +SEAFILE_MYSQL_DB_HOST=192.168.0.2 +SEAFILE_MYSQL_DB_PORT=3306 +SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD +SEAFILE_MYSQL_DB_PASSWORD=PASSWORD +``` + +NOTE: `SEAFILE_MYSQL_ROOT_PASSWORD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (SEAFILE_MYSQL_DB_PASSWORD). You can remove the `SEAFILE_MYSQL_ROOT_PASSWORD`. + +## Run Seafile as non root user inside docker + +You can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) + +First add the `NON_ROOT=true` to the `.env`. + +```env +NON_ROOT=true +``` + +Then modify `/opt/seafile-data/seafile/` permissions. + +```bash +chmod -R a+rwx /opt/seafile-data/seafile/ +``` + +Then destroy the containers and run them again: + +```bash +docker compose down +docker compose up -d +``` + +Now you can run Seafile as `seafile` user. (**NOTE:** Later, when doing maintenance, other scripts in docker are also required to be run as `seafile` user, e.g. `su seafile -c ./seaf-gc.sh`) + +## Backup and Recovery + +Follow the instructions in [Backup and restore for Seafile Docker](../../maintain/backup_recovery.md) + +## Garbage Collection + +When files are deleted, the blocks comprising those files are not immediately removed as there may be other files that reference those blocks (due to the magic of deduplication). To remove them, Seafile requires a ['garbage collection'](https://manual.seafile.com/maintain/seafile_gc/) process to be run, which detects which blocks no longer used and purges them. (NOTE: for technical reasons, the GC process does not guarantee that _every single_ orphan block will be deleted.) + +The required scripts can be found in the `/scripts` folder of the docker container. To perform garbage collection, simply run `docker exec seafile /scripts/gc.sh`. For the community edition, this process will stop the seafile server, but it is a relatively quick process and the seafile server will start automatically once the process has finished. The Professional supports an online garbage collection. + +## OnlyOffice with Docker + +You need to manually add the OnlyOffice config to `.env` + +* [OnlyOffice with Docker](deploy_onlyoffice_with_docker.md) + +## Clamav with Docker + +You need to manually add the Clamav config to `.env` + +* [Deploy Clamav with Docker](../../deploy_pro/deploy_clamav_with_seafile.md) + +## Other functions + +### LDAP/AD Integration for Pro + +* [Configure LDAP in Seafile Pro](../../deploy_pro/using_ldap_pro.md) +* [Syncing Groups from LDAP/AD](../../deploy_pro/ldap_group_sync.md) +* [Syncing Roles from LDAP/AD](../../deploy_pro/ldap_role_sync.md) + +### S3/OpenSwift/Ceph Storage Backends + +* [Setup Seafile Professional Server With Amazon S3](../../deploy_pro/setup_with_amazon_s3.md) +* [Setup Seafile Professional Server With OpenStack Swift](../../deploy_pro/setup_with_swift.md) +* [Setup Seafile Professional Server With Ceph](../../deploy_pro/setup_with_ceph.md) +* [Data migration between different backends](../../deploy_pro/migrate.md) +* [Using multiple storage backends](../../deploy_pro/multiple_storage_backends.md) + +### Online File Preview and Editing + +* [Enable Office/PDF Documents Online Preview](../../deploy_pro/office_documents_preview.md) +* [Integrating with Office Online Server](../../deploy_pro/office_web_app.md) + +### Advanced User Management + +* [Multi-Institutions Support](../../deploy_pro/multi_institutions.md) +* [Roles and Permissions](../../deploy_pro/roles_permissions.md) + +### Advanced Authentication + +* [Two-factor Authentication](../../deploy_pro/two_factor_authentication.md) +* [ADFS or SAML 2.0](../../deploy_pro/adfs.md) +* [CAS](../../deploy_pro/cas.md) + +### Admin Tools + +* [Import Directory to Seafile](../../deploy_pro/seaf_import.md) + + +## FAQ + +Q: I forgot the Seafile admin email address/password, how do I create a new admin account? + +A: You can create a new admin account by running + +```bash +docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh +``` + +The Seafile service must be up when running the superuser command. + +Q: If, for whatever reason, the installation fails, how do I to start from a clean slate again? + +A: Remove the directories /opt/seafile, /opt/seafile-data, /opt/seafile-elasticsearch, /opt/seafile-mysql and /opt/seafile-caddy and start again. + +Q: Something goes wrong during the start of the containers. How can I find out more? + +A: You can view the docker logs using this command: `docker compose logs -f`. diff --git a/mkdocs.yml b/mkdocs.yml index 6f1c6c596..8720a38fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -81,6 +81,9 @@ nav: - Migration from Seafile Community: docker/pro-edition/migrate_ce_to_pro_with_docker.md - Migrate from non-docker deployment: docker/non_docker_to_docker.md - Seafile Docker autostart: docker/seafile_docker_autostart.md + - Seafile Setup with Docker (v12.0): + - Seafile Community Installation (v12.0): docker/deploy_seafile_with_docker_v12.0.md + - Seafile Professional Installation (v12.0): docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md - Advanced Setup Options: - LDAP/AD Integration: - LDAP Integration: deploy/using_ldap.md From 22c83a39f13337e06e474f3ce68d0bb4cf99c496 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Tue, 24 Sep 2024 21:59:14 +0800 Subject: [PATCH 02/22] opt: some santences in 12.0 --- .../deploy_seafile_with_docker_v12.0.md | 22 ++++++++--------- .../deploy_seafile_pro_with_docker_v12.0.md | 24 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/manual/docker/deploy_seafile_with_docker_v12.0.md b/manual/docker/deploy_seafile_with_docker_v12.0.md index 0fa49ff73..889cb1dc2 100644 --- a/manual/docker/deploy_seafile_with_docker_v12.0.md +++ b/manual/docker/deploy_seafile_with_docker_v12.0.md @@ -32,17 +32,17 @@ nano .env The following fields merit particular attention: -* The volume directory of Seafile data (SEAFILE_VOLUMES) -* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUMES) -* The volume directory of Caddy data (SEAFILE_CADDY_VOLUMES) -* The root password of MySQL (SEAFILE_MYSQL_ROOT_PASSWORD) -* The user password of MySQL (SEAFILE_MYSQL_DB_PASSWORD) -* JWT (JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1`) -* Seafile server hostname (SEAFILE_SERVER_HOSTNAME) -* Seafile server protocol (SEAFILE_SERVER_PROTOCOL, use http or https) -* Time zone (TIME_ZONE) -* Admin username (SEAFILE_ADMIN_EMAIL) -* Admin password (SEAFILE_ADMIN_PASSWORD) +- `SEAFILE_VOLUMES`: The volume directory of Seafile data +- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data +- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data +- `SEAFILE_MYSQL_ROOT_PASSWORD`: The user `root` password of MySQL +- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL +- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` +- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain +- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) +- `TIME_ZONE`: Time zone (default UTC) +- `SEAFILE_ADMIN_EMAIL`: Admin username +- `SEAFILE_ADMIN_PASSWORD`: Admin password NOTE: SSL is now handled by the caddy server. diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md index 55796d1ab..5c45b66b4 100644 --- a/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md +++ b/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md @@ -66,18 +66,18 @@ nano .env The following fields merit particular attention: -* The volume directory of Seafile data (SEAFILE_VOLUMES) -* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUMES) -* The volume directory of Caddy data (SEAFILE_CADDY_VOLUMES) -* The volume directory of Elasticsearch data (SEAFILE_ELASTICSEARCH_VOLUMES) -* The root password of MySQL (SEAFILE_MYSQL_ROOT_PASSWORD) -* The user password of MySQL (SEAFILE_MYSQL_DB_PASSWORD) -* JWT (JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1`) -* Seafile server hostname (SEAFILE_SERVER_HOSTNAME) -* Seafile server protocol (SEAFILE_SERVER_PROTOCOL, use http or https) -* Time zone (TIME_ZONE) -* Admin username (SEAFILE_ADMIN_EMAIL) -* Admin password (SEAFILE_ADMIN_PASSWORD) +- `SEAFILE_VOLUMES`: The volume directory of Seafile data +- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data +- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data +- `SEAFILE_ELASTICSEARCH_VOLUMES`: The volume directory of Elasticsearch data +- `SEAFILE_MYSQL_ROOT_PASSWORD`: The `root` password of MySQL +- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL +- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` +- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain +- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) +- `TIME_ZONE`: Time zone (default UTC) +- `SEAFILE_ADMIN_EMAIL`: Admin username +- `SEAFILE_ADMIN_PASSWORD`: Admin password NOTE: SSL is now handled by the caddy server. From 3f5d0b5b0c8136dbbb5639b4e93cd2760c0477f0 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 12:26:54 +0800 Subject: [PATCH 03/22] feat: 12.0 support version control --- manual/docker/deploy_seafile_with_docker.md | 211 +++---------- .../deploy_seafile_with_docker_v12.0.md | 176 ----------- .../deploy_seafile_pro_with_docker.md | 239 ++++----------- .../deploy_seafile_pro_with_docker_v12.0.md | 285 ------------------ mkdocs.yml | 6 +- 5 files changed, 99 insertions(+), 818 deletions(-) delete mode 100644 manual/docker/deploy_seafile_with_docker_v12.0.md delete mode 100644 manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md diff --git a/manual/docker/deploy_seafile_with_docker.md b/manual/docker/deploy_seafile_with_docker.md index c7f141b31..5ca698266 100644 --- a/manual/docker/deploy_seafile_with_docker.md +++ b/manual/docker/deploy_seafile_with_docker.md @@ -12,9 +12,9 @@ The following assumptions and conventions are used in the rest of this document: Use the [official installation guide for your OS to install Docker](https://docs.docker.com/engine/install/). -### Download and modify `docker-compose.yml` +### Download and modify `.env` -Download the `docker-compose.yml` sample file into Seafile's directory and modify the Compose file to fit your environment and settings. +From Seafile Docker 12.0, we recommend that you use `.env`, `seafile-server.yml` and `caddy.yml` files for configuration. **NOTE:** Different versions of Seafile have different compose files. @@ -22,31 +22,40 @@ Download the `docker-compose.yml` sample file into Seafile's directory and modif mkdir /opt/seafile cd /opt/seafile -# Seafile CE 10.0 -wget -O "docker-compose.yml" "https://manual.seafile.com/docker/docker-compose/ce/10.0/docker-compose.yml" +# Seafile CE 12.0 +wget -O .env https://manual.seafile.com/docker/docker-compose/ce/12.0/env +wget https://manual.seafile.com/docker/docker-compose/ce/12.0/seafile-server.yml +wget https://manual.seafile.com/docker/docker-compose/ce/12.0/caddy.yml -# Seafile CE 11.0 -wget -O "docker-compose.yml" "https://manual.seafile.com/docker/docker-compose/ce/11.0/docker-compose.yml" - -nano docker-compose.yml +nano .env ``` The following fields merit particular attention: -* The password of MySQL root (`MYSQL_ROOT_PASSWORD` and `DB_ROOT_PASSWD`) -* The volume directory of MySQL data (volumes) -* The volume directory of Seafile data (volumes). +- `SEAFILE_VOLUMES`: The volume directory of Seafile data +- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data +- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data +- `SEAFILE_MYSQL_ROOT_PASSWORD`: The user `root` password of MySQL +- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL +- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` +- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain +- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) +- `TIME_ZONE`: Time zone (default UTC) +- `SEAFILE_ADMIN_EMAIL`: Admin username +- `SEAFILE_ADMIN_PASSWORD`: Admin password + +NOTE: SSL is now handled by the caddy server. ### Start Seafile server Start Seafile server with the following command ```bash -# if `docker-compose.yml` file is in current directory: -docker-compose up -d +# if `.env` file is in current directory: +docker compose up -d -# if `docker-compose.yml` file is elsewhere: -docker-compose -f /path/to/docker-compose.yml up -d +# if `.env` file is elsewhere: +docker compose -f /path/to/.env up -d ``` Wait for a few minutes for the first time initialization, then visit `http://seafile.example.com` to open Seafile Web UI. @@ -61,22 +70,21 @@ Placeholder spot for shared volumes. You may elect to store certain persistent i * /opt/seafile-data/seafile/logs: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `/opt/seafile-data/seafile/logs/seafile.log`. * /opt/seafile-data/logs: This is the directory for operating system and Nginx logs. * /opt/seafile-data/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `/opt/seafile-data/logs/var-log/nginx/`. -* /opt/seafile-data/ssl: This is directory for certificate, which does not exist by default. ### Find logs To monitor container logs (from outside of the container), please use the following commands: ```bash -# if the `docker-compose.yml` file is in current directory: +# if the `.env` file is in current directory: docker compose logs --follow -# if the `docker-compose.yml` file is elsewhere: -docker compose -f /path/to/docker-compose.yml logs --follow +# if the `.env` file is elsewhere: +docker compose -f /path/to/.env logs --follow # you can also specify container name: docker compose logs seafile --follow -# or, if the `docker-compose.yml` file is elsewhere: -docker compose -f /path/to/docker-compose.yml logs seafile --follow +# or, if the `.env` file is elsewhere: +docker compose -f /path/to/.env logs seafile --follow ``` The Seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafile-data/logs/seafile` in the server that run the docker. @@ -84,121 +92,25 @@ The Seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafil The system logs are under `/shared/logs/var-log`, or `/opt/seafile-data/logs/var-log` in the server that run the docker. To monitor all Seafile logs simultaneously (from outside of the container), run + ```bash sudo tail -f $(find /opt/seafile-data/ -type f -name *.log 2>/dev/null) ``` ## More configuration options -### Custom admin username and password - -The default admin account is `me@example.com` and the password is `asecret`. You can use a different password by setting the container's environment variables in the `docker-compose.yml`: -e.g. - -```yml -seafile: - ... - - environment: - ... - - SEAFILE_ADMIN_EMAIL=me@example.com - - SEAFILE_ADMIN_PASSWORD=a_very_secret_password - ... - -``` - -### Let's Encrypt SSL certificate - -If you set `SEAFILE_SERVER_LETSENCRYPT` to `true`, the container would request a letsencrypt-signed SSL certificate for you automatically. - -e.g. - -```yml -seafile: - ... - ports: - - "80:80" - - "443:443" - ... - environment: - ... - - SEAFILE_SERVER_LETSENCRYPT=true - - SEAFILE_SERVER_HOSTNAME=seafile.example.com - ... - -``` - -Since version 10.0.x, if you want to use a reverse proxy and apply for a certificate outside docker, you can use `FORCE_HTTPS_IN_CONF` to force write `https://` in the configuration file. - -e.g. - -```yml -seafile: - ... - environment: - ... - - SEAFILE_SERVER_LETSENCRYPT=false - - SEAFILE_SERVER_HOSTNAME=seafile.example.com - - FORCE_HTTPS_IN_CONF=true - ... - -``` - -If you want to use your own SSL certificate, you can mount the certificate into the docker container by setting the container's volumes variables in the `docker-compose.yml`. - -⚠️ Assuming your site name is `seafile.example.com`, then your certificate must have the name `seafile.example.com.crt`, and the private key must have the name `seafile.example.com.key` in container. - -e.g. - -```yml -seafile: - ... - ports: - - "80:80" - - "443:443" - ... - volumes: - ... - - /etc/letsencrypt/live/seafile.example.com/fullchain.pem:/shared/ssl/seafile.example.com.crt - - /etc/letsencrypt/live/seafile.example.com/privkey.pem:/shared/ssl/seafile.example.com.key - environment: - ... - - SEAFILE_SERVER_LETSENCRYPT=false - - SEAFILE_SERVER_HOSTNAME=seafile.example.com - - FORCE_HTTPS_IN_CONF=true - ... - ... -``` - ### Use an existing mysql-server -If you want to use an existing mysql-server, you can modify the `docker-compose.yml` as follows - -```yml -services: - #db: - #image: mariadb:10.11 - #... - - seafile: - ... - environment: - ... - - DB_HOST=192.168.0.2 - - DB_PORT=3306 - - DB_ROOT_PASSWD=mysql_root_password - ... - depends_on: - #- db - - memcached +If you want to use an existing mysql-server, you can modify the `.env` as follows + +```env +SEAFILE_MYSQL_DB_HOST=192.168.0.2 +SEAFILE_MYSQL_DB_PORT=3306 +SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD +SEAFILE_MYSQL_DB_PASSWORD=PASSWORD ``` -* The entire db chapter needs to be removed -* The host of MySQL (`DB_HOST`) -* The port of MySQL (`DB_PORT`) -* The password of MySQL root (`DB_ROOT_PASSWD`) -* db in depends_on chapter needs to be removed -* `DB_ROOT_PASSWD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (in `conf/seafile.conf`). You can remove the `DB_ROOT_PASSWD`. +NOTE: `SEAFILE_MYSQL_ROOT_PASSWORD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (SEAFILE_MYSQL_DB_PASSWORD). You can remove the `SEAFILE_MYSQL_ROOT_PASSWORD`. ### Modify Seafile server configurations @@ -222,18 +134,12 @@ Enter the username and password according to the prompts. You now have a new adm ### Run Seafile as non root user inside docker -Since version 10.0, you can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) +You can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) -First add the `NON_ROOT=true` to the `docker-compose.yml`. - -```yml -seafile: - ... - environment: - ... - - NON_ROOT=true - ... +First add the `NON_ROOT=true` to the `.env`. +```env +NON_ROOT=true ``` Then modify `/opt/seafile-data/seafile/` permissions. @@ -242,16 +148,6 @@ Then modify `/opt/seafile-data/seafile/` permissions. chmod -R a+rwx /opt/seafile-data/seafile/ ``` -Note: Before version 11.0.9, you have to create a seafile user on the host, and modify the owner to seafile in `/opt/seafile-data/seafile/`. (**NOTE:** Do not change the `uid` and `gid`.) - -```bash -groupadd --gid 8000 seafile - -useradd --home-dir /home/seafile --create-home --uid 8000 --gid 8000 --shell /bin/sh --skel /dev/null seafile - -chown -R seafile:seafile /opt/seafile-data/seafile/ -``` - Then destroy the containers and run them again: ```bash @@ -271,29 +167,6 @@ When files are deleted, the blocks comprising those files are not immediately re The required scripts can be found in the `/scripts` folder of the docker container. To perform garbage collection, simply run `docker exec seafile /scripts/gc.sh`. For the community edition, this process will stop the seafile server, but it is a relatively quick process and the seafile server will start automatically once the process has finished. The Professional supports an online garbage collection. -## Deploy Seafile docker with custom port - -Assume your custom port is 8001, when it is a new installation, you only need to modify the `docker-compose.yml` and start the Seafile docker. - -```yml - seafile: - ... - ports: - - "8001:80" - environment: - ... - - SEAFILE_SERVER_HOSTNAME=seafile.example.com:8001 - ... - ... -``` - -If you have installed the Seafile docker, besides modifying the `docker-compose.yml`, you also need to modify the already generated configuration file `conf/seahub_settings.py`, then restart Seafile: - -```py -SERVICE_URL = "http://seafile.example.com:8001" -FILE_SERVER_ROOT = "http://seafile.example.com:8001/seafhttp" -``` - ## FAQ ### You can run docker commands like `docker exec` to find errors diff --git a/manual/docker/deploy_seafile_with_docker_v12.0.md b/manual/docker/deploy_seafile_with_docker_v12.0.md deleted file mode 100644 index 889cb1dc2..000000000 --- a/manual/docker/deploy_seafile_with_docker_v12.0.md +++ /dev/null @@ -1,176 +0,0 @@ -# Deploy Seafile with Docker (v12.0) - -## Getting started - -The following assumptions and conventions are used in the rest of this document: - -- `/opt/seafile-data` is the directory of Seafile. If you decide to put Seafile in a different directory — which you can — adjust all paths accordingly. -- Seafile uses two [Docker volumes](https://docs.docker.com/storage/volumes/) for persisting data generated in its database and Seafile Docker container. The volumes' [host paths](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes) are `/opt/seafile-mysql` and `/opt/seafile-data`, respectively. It is not recommended to change these paths. If you do, account for it when following these instructions. -- All configuration and log files for Seafile and the webserver Nginx are stored in the volume of the Seafile container. - -### Install docker - -Use the [official installation guide for your OS to install Docker](https://docs.docker.com/engine/install/). - -### Download and modify `.env` - -From Seafile Docker 12.0, we recommend that you use `.env`, `seafile-server.yml` and `caddy.yml` files for configuration. - -**NOTE:** Different versions of Seafile have different compose files. - -```bash -mkdir /opt/seafile -cd /opt/seafile - -# Seafile CE 12.0 -wget -O .env https://manual.seafile.com/docker/docker-compose/ce/12.0/env -wget https://manual.seafile.com/docker/docker-compose/ce/12.0/seafile-server.yml -wget https://manual.seafile.com/docker/docker-compose/ce/12.0/caddy.yml - -nano .env -``` - -The following fields merit particular attention: - -- `SEAFILE_VOLUMES`: The volume directory of Seafile data -- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data -- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data -- `SEAFILE_MYSQL_ROOT_PASSWORD`: The user `root` password of MySQL -- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL -- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` -- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain -- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) -- `TIME_ZONE`: Time zone (default UTC) -- `SEAFILE_ADMIN_EMAIL`: Admin username -- `SEAFILE_ADMIN_PASSWORD`: Admin password - -NOTE: SSL is now handled by the caddy server. - -### Start Seafile server - -Start Seafile server with the following command - -```bash -# if `.env` file is in current directory: -docker compose up -d - -# if `.env` file is elsewhere: -docker compose -f /path/to/.env up -d -``` - -Wait for a few minutes for the first time initialization, then visit `http://seafile.example.com` to open Seafile Web UI. - -## Seafile directory structure - -### `/opt/seafile-data` - -Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various log files and upload directory outside. This allows you to rebuild containers easily without losing important information. - -* /opt/seafile-data/seafile: This is the directory for seafile server configuration and data. - * /opt/seafile-data/seafile/logs: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `/opt/seafile-data/seafile/logs/seafile.log`. -* /opt/seafile-data/logs: This is the directory for operating system and Nginx logs. - * /opt/seafile-data/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `/opt/seafile-data/logs/var-log/nginx/`. - -### Find logs - -To monitor container logs (from outside of the container), please use the following commands: - -```bash -# if the `.env` file is in current directory: -docker compose logs --follow -# if the `.env` file is elsewhere: -docker compose -f /path/to/.env logs --follow - -# you can also specify container name: -docker compose logs seafile --follow -# or, if the `.env` file is elsewhere: -docker compose -f /path/to/.env logs seafile --follow -``` - -The Seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafile-data/logs/seafile` in the server that run the docker. - -The system logs are under `/shared/logs/var-log`, or `/opt/seafile-data/logs/var-log` in the server that run the docker. - -To monitor all Seafile logs simultaneously (from outside of the container), run - -```bash -sudo tail -f $(find /opt/seafile-data/ -type f -name *.log 2>/dev/null) -``` - -## More configuration options - -### Use an existing mysql-server - -If you want to use an existing mysql-server, you can modify the `.env` as follows - -```env -SEAFILE_MYSQL_DB_HOST=192.168.0.2 -SEAFILE_MYSQL_DB_PORT=3306 -SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD -SEAFILE_MYSQL_DB_PASSWORD=PASSWORD -``` - -NOTE: `SEAFILE_MYSQL_ROOT_PASSWORD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (SEAFILE_MYSQL_DB_PASSWORD). You can remove the `SEAFILE_MYSQL_ROOT_PASSWORD`. - -### Modify Seafile server configurations - -The config files are under `/opt/seafile-data/seafile/conf`. You can modify the configurations according to [Seafile manual](https://manual.seafile.com/) - -After modification, you need to restart the container: - -```bash -docker compose restart -``` - -### Add a new admin - -Ensure the container is running, then enter this command: - -```bash -docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh -``` - -Enter the username and password according to the prompts. You now have a new admin account. - -### Run Seafile as non root user inside docker - -You can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) - -First add the `NON_ROOT=true` to the `.env`. - -```env -NON_ROOT=true -``` - -Then modify `/opt/seafile-data/seafile/` permissions. - -```bash -chmod -R a+rwx /opt/seafile-data/seafile/ -``` - -Then destroy the containers and run them again: - -```bash -docker compose down -docker compose up -d -``` - -Now you can run Seafile as `seafile` user. (**NOTE:** Later, when doing maintenance, other scripts in docker are also required to be run as `seafile` user, e.g. `su seafile -c ./seaf-gc.sh`) - -## Backup and recovery - -Follow the instructions in [Backup and restore for Seafile Docker](../maintain/backup_recovery.md) - -## Garbage collection - -When files are deleted, the blocks comprising those files are not immediately removed as there may be other files that reference those blocks (due to the magic of deduplication). To remove them, Seafile requires a ['garbage collection'](../maintain/seafile_gc.md) process to be run, which detects which blocks no longer used and purges them. (**NOTE:** for technical reasons, the GC process does not guarantee that _every single_ orphan block will be deleted.) - -The required scripts can be found in the `/scripts` folder of the docker container. To perform garbage collection, simply run `docker exec seafile /scripts/gc.sh`. For the community edition, this process will stop the seafile server, but it is a relatively quick process and the seafile server will start automatically once the process has finished. The Professional supports an online garbage collection. - -## FAQ - -### You can run docker commands like `docker exec` to find errors - -```bash -docker exec -it seafile /bin/bash -``` diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md index 356a406c7..a825cc7c2 100644 --- a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md +++ b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md @@ -3,6 +3,7 @@ This manual explains how to deploy and run Seafile Server Professional Edition (Seafile PE) on a Linux server using Docker and Docker Compose. The deployment has been tested for Debian/Ubuntu and CentOS, but Seafile PE should also work on other Linux distributions. ## Requirements + Seafile PE requires a minimum of 2 cores and 2GB RAM. If Elasticsearch is installed on the same server, the minimum requirements are 4 cores and 4 GB RAM, and make sure the [mmapfs counts](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-store.html#mmapfs) do not cause excptions like out of memory, which can be increased by following command (see for futher details): ```shell @@ -36,62 +37,49 @@ Use the [official installation guide for your OS to install Docker](https://docs Log into Seafile's private repository and pull the Seafile image: -``` +```bash docker login docker.seadrive.org -docker pull docker.seadrive.org/seafileltd/seafile-pro-mc:latest +docker pull docker.seadrive.org/seafileltd/seafile-pro-mc:12.0-latest ``` When prompted, enter the username and password of the private repository. They are available on the download page in the [Customer Center](https://customer.seafile.com/downloads). -NOTE: Older Seafile PE versions are also available in the repository (back to Seafile 7.0). To pull an older version, replace 'latest' tag by the desired version. +NOTE: Older Seafile PE versions are also available in the repository (back to Seafile 7.0). To pull an older version, replace '12.0-latest' tag by the desired version. -### Downloading and Modifying docker-compose.yml +### Downloading and Modifying `.env` -Download the docker-compose.yml sample file into Seafile's directory and modify the Compose file to fit your environment and settings. +From Seafile Docker 12.0, we recommend that you use `.env`, `seafile-server.yml` and `caddy.yml` files for configuration. NOTE: Different versions of Seafile have different compose files. -``` +```bash mkdir /opt/seafile cd /opt/seafile -# Seafile PE 7.1 and 8.0 -wget -O "docker-compose.yml" "https://manual.seafile.com/docker/docker-compose/pro/7.1_8.0/docker-compose.yml" - -# Seafile PE 9.0 -wget -O "docker-compose.yml" "https://manual.seafile.com/docker/docker-compose/pro/9.0/docker-compose.yml" - -# Seafile PE 10.0 -wget -O "docker-compose.yml" "https://manual.seafile.com/docker/docker-compose/pro/10.0/docker-compose.yml" - -# Seafile PE 11.0 -wget -O "docker-compose.yml" "https://manual.seafile.com/docker/docker-compose/pro/11.0/docker-compose.yml" +# Seafile PE 12.0 +wget -O .env https://manual.seafile.com/docker/docker-compose/pro/12.0/env +wget https://manual.seafile.com/docker/docker-compose/pro/12.0/seafile-server.yml +wget https://manual.seafile.com/docker/docker-compose/pro/12.0/caddy.yml -nano docker-compose.yml +nano .env ``` The following fields merit particular attention: -* The password of MariaDB root (MYSQL_ROOT_PASSWORD and DB_ROOT_PASSWD) -* The Seafile admin email address (SEAFILE_ADMIN_EMAIL) -* The Seafile admin password (SEAFILE_ADMIN_PASSWORD) -* The listening ports of the container seafile -* The host name (SEAFILE_SERVER_HOSTNAME) -* The use of Let's Encrypt for HTTPS (SEAFILE_SERVER_LETSENCRYPT) - -The new password for MYSQL_ROOT_PASSWORD and DB_ROOT_PASSWD must be identical. - -To enable HTTPS access (which is required for production use) enter the SEAFILE_SERVER_HOSTNAME and uncomment port 443 in the configuration of the container seafile. If you want to use Let's Encrypt to obtain a SSL certificate, set SEAFILE_SERVER_LETSENCRYPT to `true` (and do not comment out port 80 because it is required when requesting a Let's Encrypt certificate). If you want to use your own SSL certificate, leave SEAFILE_SERVER_LETSENCRYPT set to `false` and follow the instructions in section [Configuring a Custom SSL Certificate](https://manual.seafile.com/docker/pro-edition/deploy_seafile_pro_with_docker/#configuring-a-custom-ssl-certificate). - -Additional customizable options in the Compose file are: - -* The volume path for the container db -* The volume path for the container elasticsearch -* The volume path for the container seafile -* The image tag of the Seafile version to install (image) -* The time zone (TIME_ZONE) - -If you have pulled a particular version, modify the image tag accordingly. +- `SEAFILE_VOLUMES`: The volume directory of Seafile data +- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data +- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data +- `SEAFILE_ELASTICSEARCH_VOLUMES`: The volume directory of Elasticsearch data +- `SEAFILE_MYSQL_ROOT_PASSWORD`: The `root` password of MySQL +- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL +- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` +- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain +- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) +- `TIME_ZONE`: Time zone (default UTC) +- `SEAFILE_ADMIN_EMAIL`: Admin username +- `SEAFILE_ADMIN_PASSWORD`: Admin password + +NOTE: SSL is now handled by the caddy server. To conclude, set the directory permissions of the Elasticsearch volumne: @@ -108,7 +96,7 @@ Run docker compose in detached mode: docker compose up -d ``` -NOTE: You must run the above command in the directory with the docker-compose.yml. +NOTE: You must run the above command in the directory with the `.env`. Wait a few moment for the database to initialize. You can now access Seafile at the host name specified in the Compose file. (A 502 Bad Gateway error means that the system has not yet completed the initialization.) @@ -146,167 +134,60 @@ Placeholder spot for shared volumes. You may elect to store certain persistent i * /opt/seafile-data/seafile/logs: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `/opt/seafile-data/seafile/logs/seafile.log`. * /opt/seafile-data/logs: This is the directory for operating system and Nginx logs. * /opt/seafile-data/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `/opt/seafile-data/logs/var-log/nginx/`. -* /opt/seafile-data/ssl: This is directory for certificate, which does not exist by default. ### Reviewing the Deployment -The command `docker container list` should list the four containers specified in the docker-compose.yml. +The command `docker container list` should list the containers specified in the `.env`. The directory layout of the Seafile container's volume should look as follows: -``` +```bash $ tree /opt/seafile-data -L 2 /opt/seafile-data ├── logs │   └── var-log ├── nginx │   └── conf -├── seafile -│   ├── ccnet -│   ├── conf -│   ├── logs -│   ├── pro-data -│   ├── seafile-data -│   └── seahub-data -└── ssl - ├── account.conf - ├── ca - ├── http.header - ├── SEAFILE_SERVER_HOSTNAME - ├── SEAFILE_SERVER_HOSTNAME.crt - └── SEAFILE_SERVER_HOSTNAME.key +└── seafile +    ├── ccnet +    ├── conf +    ├── logs +    ├── pro-data +    ├── seafile-data +    └── seahub-data ``` -NOTE: The directory `ssl` does not exist if Let's Encrypt is not used for HTTPS. SEAFILE_SERVER_HOSTNAME substitutes for the host name used in the docker-compose.yml file. - All Seafile config files are stored in `/opt/seafile-data/seafile/conf`. The nginx config file is in `/opt/seafile-data/nginx/conf`. Any modification of a configuration file requires a restart of Seafile to take effect: -``` +```bash docker compose restart ``` All Seafile log files are stored in `/opt/seafile-data/seafile/logs` whereas all other log files are in `/opt/seafile-data/logs/var-log`. -## Configuring a Custom SSL Certificate - -NOTE: This section is only relevant when you do not want to use a Let's Encrypt certificate, but a certificate of your own. - -Create a folder for the certificate: - -``` -mkdir /opt/seafile-data/ssl -``` - -Save your certificate and private key in this folder. - -Modify the nginx configuration `seafile.nginx.conf` in `/opt/seafile-data/nginx/conf` to look like this: - -``` -server { - listen 80; - server_name example.seafile.com default_server; - - location / { - rewrite ^ https://$host$request_uri? permanent; - } -} -server { - listen 443; - ssl on; - ssl_certificate /shared/ssl/your-ssl-crt.crt; - ssl_certificate_key /shared/ssl/your-ssl-key.key; - ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; - - server_name example.seafile.com; - ... - -``` - -Modify the values for server_name, ssl_certificate, and ssl_certificate_key to correspond to your situation. - -Now reload the nginx configuration: - -``` -docker exec -it seafile /usr/sbin/nginx -s reload -``` - -NOTE: If you got the following error when SEAFILE_SERVER_LETSENCRYPT=true is set: - -```log -subprocess.CalledProcessError: Command '/scripts/ssl.sh /shared/ssl cloud.seafile-demo.de' returned non-zero exit status 128. -``` - -In /scripts/ssl.sh (script in seafile container), `git clone git://` has to be replaced with `git clone https://`. - -Then restart the container: - -```shell -docker compose restart -``` - -Since version 9.0.6, we use acme (not acme-tiny) to get certificate and fix this error. - -Since version 10.0.x, if you want to use a reverse proxy and apply for a certificate outside docker, you can use `FORCE_HTTPS_IN_CONF` to force write `https://` in the configuration file. - -e.g. - -``` -seafile: - ... - environment: - ... - - SEAFILE_SERVER_LETSENCRYPT=false - - SEAFILE_SERVER_HOSTNAME=seafile.example.com - - FORCE_HTTPS_IN_CONF=true - ... - -``` - ## Use an existing mysql-server -If you want to use an existing mysql-server, you can modify the `docker-compose.yml` as follows - -```yml -services: - #db: - #image: mariadb:10.11 - #... - - seafile: - ... - environment: - ... - - DB_HOST=192.168.0.2 - - DB_PORT=3306 - - DB_ROOT_PASSWD=mysql_root_password - ... - depends_on: - #- db - - memcached +If you want to use an existing mysql-server, you can modify the `.env` as follows + +```env +SEAFILE_MYSQL_DB_HOST=192.168.0.2 +SEAFILE_MYSQL_DB_PORT=3306 +SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD +SEAFILE_MYSQL_DB_PASSWORD=PASSWORD ``` -* The entire db chapter needs to be removed -* The host of MySQL (DB_HOST) -* The port of MySQL (DB_PORT) -* The password of MySQL root (DB_ROOT_PASSWD) -* db in depends_on chapter needs to be removed -* When Seafile is installed, the user `seafile` will be used to connect to the mysql-server (in conf/seafile.conf). You can remove the `DB_ROOT_PASSWD`. +NOTE: `SEAFILE_MYSQL_ROOT_PASSWORD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (SEAFILE_MYSQL_DB_PASSWORD). You can remove the `SEAFILE_MYSQL_ROOT_PASSWORD`. ## Run Seafile as non root user inside docker -Since version 10.0, you can use run seafile as non root user in docker. (NOTE: Programs such as my_init, Nginx are still run as root inside docker.) +You can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) -First add the `NON_ROOT=true` to the docker-compose.yml. +First add the `NON_ROOT=true` to the `.env`. -```yml -seafile: - ... - environment: - ... - - NON_ROOT=true - ... +```env +NON_ROOT=true ``` Then modify `/opt/seafile-data/seafile/` permissions. @@ -315,28 +196,19 @@ Then modify `/opt/seafile-data/seafile/` permissions. chmod -R a+rwx /opt/seafile-data/seafile/ ``` -Note: Before version 11.0.7-pro, you have to create a seafile user on the host, and modify the owner to seafile in `/opt/seafile-data/seafile/`. (**NOTE:** Do not change the `uid` and `gid`.) - -```bash -groupadd --gid 8000 seafile - -useradd --home-dir /home/seafile --create-home --uid 8000 --gid 8000 --shell /bin/sh --skel /dev/null seafile - -chown -R seafile:seafile /opt/seafile-data/seafile/ -``` - -Restarting the container run Seafile use seafile user. (NOTE: Later when do maintenance, other scripts in docker also required to run as seafile user, e.g. `su seafile -c ./seaf-gc.sh`) +Then destroy the containers and run them again: ```bash docker compose down docker compose up -d ``` +Now you can run Seafile as `seafile` user. (**NOTE:** Later, when doing maintenance, other scripts in docker are also required to be run as `seafile` user, e.g. `su seafile -c ./seaf-gc.sh`) + ## Backup and Recovery Follow the instructions in [Backup and restore for Seafile Docker](../../maintain/backup_recovery.md) - ## Garbage Collection When files are deleted, the blocks comprising those files are not immediately removed as there may be other files that reference those blocks (due to the magic of deduplication). To remove them, Seafile requires a ['garbage collection'](https://manual.seafile.com/maintain/seafile_gc/) process to be run, which detects which blocks no longer used and purges them. (NOTE: for technical reasons, the GC process does not guarantee that _every single_ orphan block will be deleted.) @@ -345,15 +217,13 @@ The required scripts can be found in the `/scripts` folder of the docker contain ## OnlyOffice with Docker -You need to manually add the OnlyOffice config to docker-compose.yml +You need to manually add the OnlyOffice config to `.env` * [OnlyOffice with Docker](deploy_onlyoffice_with_docker.md) ## Clamav with Docker -Since version 9.0.6, you can deploy Clamav with Docker. - -You need to manually add the Clamav config to docker-compose.yml +You need to manually add the Clamav config to `.env` * [Deploy Clamav with Docker](../../deploy_pro/deploy_clamav_with_seafile.md) @@ -393,7 +263,6 @@ You need to manually add the Clamav config to docker-compose.yml * [Import Directory to Seafile](../../deploy_pro/seaf_import.md) - ## FAQ Q: I forgot the Seafile admin email address/password, how do I create a new admin account? diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md deleted file mode 100644 index 5c45b66b4..000000000 --- a/manual/docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md +++ /dev/null @@ -1,285 +0,0 @@ -# Installation of Seafile Server Professional Edition with Docker (v12.0) - -This manual explains how to deploy and run Seafile Server Professional Edition (Seafile PE) on a Linux server using Docker and Docker Compose. The deployment has been tested for Debian/Ubuntu and CentOS, but Seafile PE should also work on other Linux distributions. - -## Requirements - -Seafile PE requires a minimum of 2 cores and 2GB RAM. If Elasticsearch is installed on the same server, the minimum requirements are 4 cores and 4 GB RAM, and make sure the [mmapfs counts](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-store.html#mmapfs) do not cause excptions like out of memory, which can be increased by following command (see for futher details): - -```shell -sysctl -w vm.max_map_count=262144 #run as root -``` - -or modify **/etc/sysctl.conf** and reboot to set this value permanently: - -```shell -nano /etc/sysctl.conf - -# modify vm.max_map_count -vm.max_map_count=262144 -``` - -Seafile PE can be used without a paid license with up to three users. Licenses for more user can be purchased in the [Seafile Customer Center](https://customer.seafile.com) or contact Seafile Sales at sales@seafile.com. - -## Setup - -The following assumptions and conventions are used in the rest of this document: - -- `/opt/seafile-data` is the directory of Seafile. If you decide to put Seafile in a different directory - which you can - adjust all paths accordingly. -- Seafile uses two [Docker volumes](https://docs.docker.com/storage/volumes/) for persisting data generated in its database and Seafile Docker container. The volumes' [host paths](https://docs.docker.com/compose/compose-file/compose-file-v3/#volumes) are /opt/seafile-mysql and /opt/seafile-data, respectively. It is not recommended to change these paths. If you do, account for it when following these instructions. -- All configuration and log files for Seafile and the webserver Nginx are stored in the volume of the Seafile container. - -### Installing Docker - -Use the [official installation guide for your OS to install Docker](https://docs.docker.com/engine/install/). - -### Downloading the Seafile Image - -Log into Seafile's private repository and pull the Seafile image: - -```bash -docker login docker.seadrive.org -docker pull docker.seadrive.org/seafileltd/seafile-pro-mc:12.0-latest -``` - -When prompted, enter the username and password of the private repository. They are available on the download page in the [Customer Center](https://customer.seafile.com/downloads). - -NOTE: Older Seafile PE versions are also available in the repository (back to Seafile 7.0). To pull an older version, replace '12.0-latest' tag by the desired version. - -### Downloading and Modifying `.env` - -From Seafile Docker 12.0, we recommend that you use `.env`, `seafile-server.yml` and `caddy.yml` files for configuration. - -NOTE: Different versions of Seafile have different compose files. - -```bash -mkdir /opt/seafile -cd /opt/seafile - -# Seafile PE 12.0 -wget -O .env https://manual.seafile.com/docker/docker-compose/pro/12.0/env -wget https://manual.seafile.com/docker/docker-compose/pro/12.0/seafile-server.yml -wget https://manual.seafile.com/docker/docker-compose/pro/12.0/caddy.yml - -nano .env -``` - -The following fields merit particular attention: - -- `SEAFILE_VOLUMES`: The volume directory of Seafile data -- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data -- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data -- `SEAFILE_ELASTICSEARCH_VOLUMES`: The volume directory of Elasticsearch data -- `SEAFILE_MYSQL_ROOT_PASSWORD`: The `root` password of MySQL -- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL -- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` -- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain -- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) -- `TIME_ZONE`: Time zone (default UTC) -- `SEAFILE_ADMIN_EMAIL`: Admin username -- `SEAFILE_ADMIN_PASSWORD`: Admin password - -NOTE: SSL is now handled by the caddy server. - -To conclude, set the directory permissions of the Elasticsearch volumne: - -```bash -mkdir -p /opt/seafile-elasticsearch/data -chmod 777 -R /opt/seafile-elasticsearch/data -``` - -### Starting the Docker Containers - -Run docker compose in detached mode: - -```bash -docker compose up -d -``` - -NOTE: You must run the above command in the directory with the `.env`. - -Wait a few moment for the database to initialize. You can now access Seafile at the host name specified in the Compose file. (A 502 Bad Gateway error means that the system has not yet completed the initialization.) - -### Find logs - -To view Seafile docker logs, please use the following command - -```shell -docker compose logs -f -``` - -The Seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafile-data/logs/seafile` in the server that run the docker. - -The system logs are under `/shared/logs/var-log`, or `/opt/seafile-data/logs/var-log` in the server that run the docker. - -### Activating the Seafile License - -If you have a `seafile-license.txt` license file, simply put it in the volume of the Seafile container. The volumne's default path in the Compose file is `/opt/seafile-data`. If you have modified the path, save the license file under your custom path. - -Then restart Seafile: - -```bash -docker compose down - -docker compose up -d -``` - -## Seafile directory structure - -### `/opt/seafile-data` - -Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various log files and upload directory outside. This allows you to rebuild containers easily without losing important information. - -* /opt/seafile-data/seafile: This is the directory for seafile server configuration 、logs and data. - * /opt/seafile-data/seafile/logs: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `/opt/seafile-data/seafile/logs/seafile.log`. -* /opt/seafile-data/logs: This is the directory for operating system and Nginx logs. - * /opt/seafile-data/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `/opt/seafile-data/logs/var-log/nginx/`. - -### Reviewing the Deployment - -The command `docker container list` should list the containers specified in the `.env`. - -The directory layout of the Seafile container's volume should look as follows: - -```bash -$ tree /opt/seafile-data -L 2 -/opt/seafile-data -├── logs -│   └── var-log -├── nginx -│   └── conf -└── seafile -    ├── ccnet -    ├── conf -    ├── logs -    ├── pro-data -    ├── seafile-data -    └── seahub-data -``` - -All Seafile config files are stored in `/opt/seafile-data/seafile/conf`. The nginx config file is in `/opt/seafile-data/nginx/conf`. - -Any modification of a configuration file requires a restart of Seafile to take effect: - -```bash -docker compose restart -``` - -All Seafile log files are stored in `/opt/seafile-data/seafile/logs` whereas all other log files are in `/opt/seafile-data/logs/var-log`. - -## Use an existing mysql-server - -If you want to use an existing mysql-server, you can modify the `.env` as follows - -```env -SEAFILE_MYSQL_DB_HOST=192.168.0.2 -SEAFILE_MYSQL_DB_PORT=3306 -SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD -SEAFILE_MYSQL_DB_PASSWORD=PASSWORD -``` - -NOTE: `SEAFILE_MYSQL_ROOT_PASSWORD` is needed during installation. Later, after Seafile is installed, the user `seafile` will be used to connect to the mysql-server (SEAFILE_MYSQL_DB_PASSWORD). You can remove the `SEAFILE_MYSQL_ROOT_PASSWORD`. - -## Run Seafile as non root user inside docker - -You can use run seafile as non root user in docker. (**NOTE:** Programs such as `my_init`, Nginx are still run as `root` inside docker.) - -First add the `NON_ROOT=true` to the `.env`. - -```env -NON_ROOT=true -``` - -Then modify `/opt/seafile-data/seafile/` permissions. - -```bash -chmod -R a+rwx /opt/seafile-data/seafile/ -``` - -Then destroy the containers and run them again: - -```bash -docker compose down -docker compose up -d -``` - -Now you can run Seafile as `seafile` user. (**NOTE:** Later, when doing maintenance, other scripts in docker are also required to be run as `seafile` user, e.g. `su seafile -c ./seaf-gc.sh`) - -## Backup and Recovery - -Follow the instructions in [Backup and restore for Seafile Docker](../../maintain/backup_recovery.md) - -## Garbage Collection - -When files are deleted, the blocks comprising those files are not immediately removed as there may be other files that reference those blocks (due to the magic of deduplication). To remove them, Seafile requires a ['garbage collection'](https://manual.seafile.com/maintain/seafile_gc/) process to be run, which detects which blocks no longer used and purges them. (NOTE: for technical reasons, the GC process does not guarantee that _every single_ orphan block will be deleted.) - -The required scripts can be found in the `/scripts` folder of the docker container. To perform garbage collection, simply run `docker exec seafile /scripts/gc.sh`. For the community edition, this process will stop the seafile server, but it is a relatively quick process and the seafile server will start automatically once the process has finished. The Professional supports an online garbage collection. - -## OnlyOffice with Docker - -You need to manually add the OnlyOffice config to `.env` - -* [OnlyOffice with Docker](deploy_onlyoffice_with_docker.md) - -## Clamav with Docker - -You need to manually add the Clamav config to `.env` - -* [Deploy Clamav with Docker](../../deploy_pro/deploy_clamav_with_seafile.md) - -## Other functions - -### LDAP/AD Integration for Pro - -* [Configure LDAP in Seafile Pro](../../deploy_pro/using_ldap_pro.md) -* [Syncing Groups from LDAP/AD](../../deploy_pro/ldap_group_sync.md) -* [Syncing Roles from LDAP/AD](../../deploy_pro/ldap_role_sync.md) - -### S3/OpenSwift/Ceph Storage Backends - -* [Setup Seafile Professional Server With Amazon S3](../../deploy_pro/setup_with_amazon_s3.md) -* [Setup Seafile Professional Server With OpenStack Swift](../../deploy_pro/setup_with_swift.md) -* [Setup Seafile Professional Server With Ceph](../../deploy_pro/setup_with_ceph.md) -* [Data migration between different backends](../../deploy_pro/migrate.md) -* [Using multiple storage backends](../../deploy_pro/multiple_storage_backends.md) - -### Online File Preview and Editing - -* [Enable Office/PDF Documents Online Preview](../../deploy_pro/office_documents_preview.md) -* [Integrating with Office Online Server](../../deploy_pro/office_web_app.md) - -### Advanced User Management - -* [Multi-Institutions Support](../../deploy_pro/multi_institutions.md) -* [Roles and Permissions](../../deploy_pro/roles_permissions.md) - -### Advanced Authentication - -* [Two-factor Authentication](../../deploy_pro/two_factor_authentication.md) -* [ADFS or SAML 2.0](../../deploy_pro/adfs.md) -* [CAS](../../deploy_pro/cas.md) - -### Admin Tools - -* [Import Directory to Seafile](../../deploy_pro/seaf_import.md) - - -## FAQ - -Q: I forgot the Seafile admin email address/password, how do I create a new admin account? - -A: You can create a new admin account by running - -```bash -docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh -``` - -The Seafile service must be up when running the superuser command. - -Q: If, for whatever reason, the installation fails, how do I to start from a clean slate again? - -A: Remove the directories /opt/seafile, /opt/seafile-data, /opt/seafile-elasticsearch, /opt/seafile-mysql and /opt/seafile-caddy and start again. - -Q: Something goes wrong during the start of the containers. How can I find out more? - -A: You can view the docker logs using this command: `docker compose logs -f`. diff --git a/mkdocs.yml b/mkdocs.yml index 8720a38fc..ce892d4d2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -20,12 +20,15 @@ theme: plugins: - search - awesome-pages + - mike # Customization extra: social: - icon: fontawesome/brands/github link: https://github.com/haiwen/seafile-admin-docs/ + version: + provider: mike extra_css: - stylesheets/extra.css @@ -81,9 +84,6 @@ nav: - Migration from Seafile Community: docker/pro-edition/migrate_ce_to_pro_with_docker.md - Migrate from non-docker deployment: docker/non_docker_to_docker.md - Seafile Docker autostart: docker/seafile_docker_autostart.md - - Seafile Setup with Docker (v12.0): - - Seafile Community Installation (v12.0): docker/deploy_seafile_with_docker_v12.0.md - - Seafile Professional Installation (v12.0): docker/pro-edition/deploy_seafile_pro_with_docker_v12.0.md - Advanced Setup Options: - LDAP/AD Integration: - LDAP Integration: deploy/using_ldap.md From 9a81108b3901c3736b77a1abf0ec8f8e7e4f89bd Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 13:43:14 +0800 Subject: [PATCH 04/22] update deploy-12.0.yml --- .github/workflows/deploy.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5b37a1b4c..048e2fccd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -3,16 +3,18 @@ name: Deploy CI on: push: branches: - - master + - 12.0 jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + with: + fetch-depth: 0 - uses: actions/setup-python@v2 with: python-version: 3.x - - run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-material-extensions + - run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-material-extensions mike - run: cd $GITHUB_WORKSPACE - - run: mkdocs gh-deploy --force + - run: mike deploy --push -u 12.0 \ No newline at end of file From 9cb7250a00d21f0d054a5fc3c12796b414f4c124 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 14:57:56 +0800 Subject: [PATCH 05/22] rename deploy.yml --- .github/workflows/{deploy.yml => deploy-12.0.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{deploy.yml => deploy-12.0.yml} (100%) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy-12.0.yml similarity index 100% rename from .github/workflows/deploy.yml rename to .github/workflows/deploy-12.0.yml From 8f56a5a76c62e6b3d786d9bb99c3e181d51ad8d7 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 15:17:33 +0800 Subject: [PATCH 06/22] update deploy --- .github/workflows/deploy-12.0.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy-12.0.yml b/.github/workflows/deploy-12.0.yml index 048e2fccd..b84ec328d 100644 --- a/.github/workflows/deploy-12.0.yml +++ b/.github/workflows/deploy-12.0.yml @@ -16,5 +16,7 @@ jobs: with: python-version: 3.x - run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-material-extensions mike + - run: git config user.name ci-bot + - run: git config user.email ci-bot@seafile.com - run: cd $GITHUB_WORKSPACE - run: mike deploy --push -u 12.0 \ No newline at end of file From 2c5b9155c4727a2b3ef6480ab8b14af1d6ba7eea Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 15:18:50 +0800 Subject: [PATCH 07/22] update deploy --- .github/workflows/deploy-12.0.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-12.0.yml b/.github/workflows/deploy-12.0.yml index b84ec328d..748624a0d 100644 --- a/.github/workflows/deploy-12.0.yml +++ b/.github/workflows/deploy-12.0.yml @@ -1,4 +1,4 @@ -name: Deploy CI +name: Deploy CI - 12.0 on: push: From a552933e16b03eccbffe680cfaf1abb122d4c02d Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 15:24:01 +0800 Subject: [PATCH 08/22] update deploy --- .github/workflows/deploy-12.0.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/deploy-12.0.yml b/.github/workflows/deploy-12.0.yml index 748624a0d..4c34c5210 100644 --- a/.github/workflows/deploy-12.0.yml +++ b/.github/workflows/deploy-12.0.yml @@ -16,7 +16,5 @@ jobs: with: python-version: 3.x - run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-material-extensions mike - - run: git config user.name ci-bot - - run: git config user.email ci-bot@seafile.com - run: cd $GITHUB_WORKSPACE - - run: mike deploy --push -u 12.0 \ No newline at end of file + - run: GIT_COMMITTER_NAME=ci-bot GIT_COMMITTER_EMAIL=ci-bot@seafile.com \ mike deploy --push -u 12.0 \ No newline at end of file From edf6880877b13e4ac449349dceb07e1cbae61a32 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 15:29:42 +0800 Subject: [PATCH 09/22] update deploy.yml --- .github/workflows/deploy-12.0.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-12.0.yml b/.github/workflows/deploy-12.0.yml index 4c34c5210..8bf9bd8ec 100644 --- a/.github/workflows/deploy-12.0.yml +++ b/.github/workflows/deploy-12.0.yml @@ -17,4 +17,5 @@ jobs: python-version: 3.x - run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-material-extensions mike - run: cd $GITHUB_WORKSPACE - - run: GIT_COMMITTER_NAME=ci-bot GIT_COMMITTER_EMAIL=ci-bot@seafile.com \ mike deploy --push -u 12.0 \ No newline at end of file + - run: GIT_COMMITTER_NAME=ci-bot GIT_COMMITTER_EMAIL=ci-bot@seafile.com + - run: mike deploy --push -u 12.0 \ No newline at end of file From 95e62d901c065d7ab5a1195546f7737e31e8e846 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 15:32:55 +0800 Subject: [PATCH 10/22] update deploy.yml --- .github/workflows/deploy-12.0.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-12.0.yml b/.github/workflows/deploy-12.0.yml index 8bf9bd8ec..85def0bed 100644 --- a/.github/workflows/deploy-12.0.yml +++ b/.github/workflows/deploy-12.0.yml @@ -17,5 +17,6 @@ jobs: python-version: 3.x - run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-material-extensions mike - run: cd $GITHUB_WORKSPACE - - run: GIT_COMMITTER_NAME=ci-bot GIT_COMMITTER_EMAIL=ci-bot@seafile.com + - run: git config user.name ci-bot + - run: git config user.email ci-bot@seafile.com - run: mike deploy --push -u 12.0 \ No newline at end of file From 422219601863cb9b80e845a80f257c62bd68f85b Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Fri, 11 Oct 2024 17:28:17 +0800 Subject: [PATCH 11/22] feat: add strucutres of seafile docker and descriptions of caddy --- manual/docker/deploy_seafile_with_docker.md | 41 +++--------------- .../deploy_seafile_pro_with_docker.md | 36 +-------------- manual/docker/seafile_docker_structures.md | 11 +++++ .../images/seafile-12.0-docker-structure.png | Bin 0 -> 104053 bytes mkdocs.yml | 1 + 5 files changed, 20 insertions(+), 69 deletions(-) create mode 100644 manual/docker/seafile_docker_structures.md create mode 100644 manual/images/seafile-12.0-docker-structure.png diff --git a/manual/docker/deploy_seafile_with_docker.md b/manual/docker/deploy_seafile_with_docker.md index 5ca698266..f7915b54e 100644 --- a/manual/docker/deploy_seafile_with_docker.md +++ b/manual/docker/deploy_seafile_with_docker.md @@ -44,7 +44,7 @@ The following fields merit particular attention: - `SEAFILE_ADMIN_EMAIL`: Admin username - `SEAFILE_ADMIN_PASSWORD`: Admin password -NOTE: SSL is now handled by the caddy server. +NOTE: SSL is now handled by the [caddy server](#about-ssl-and-caddy) from 12.0. ### Start Seafile server @@ -175,40 +175,11 @@ The required scripts can be found in the `/scripts` folder of the docker contain docker exec -it seafile /bin/bash ``` -### LetsEncrypt SSL certificate is about to expire +### About SSL and Caddy -If the certificate is not renewed automatically, you can execute the following command to manually renew the certificate. +From Seafile 12.0, the SSL is handled by [***Caddy***](https://caddyserver.com/docs/). Caddy is a modern open source web server that mainly binds external traffic and internal services in [seafile docker](./seafile_docker_structures.md). The default caddy image is [`lucaslorentz/caddy-docker-proxy:2.9`](https://github.com/lucaslorentz/caddy-docker-proxy), which user only needs to correctly configure the following fields in `.env` to automatically complete the acquisition and update of the certificate: -```bash -# /scripts/ssl.sh /shared/ssl/ -/scripts/ssl.sh /shared/ssl/ example.seafile.com -``` - -### Change the environment variable `SEAFILE_SERVER_LETSENCRYPT=false` value to `true` - -1. If you want to change to https after using http, first back up the `seafile.nginx.conf`: - -```bash -mv /opt/seafile-data/nginx/conf/seafile.nginx.conf /opt/seafile-data/nginx/conf/seafile.nginx.conf.bak -# or -mv /opt/seafile-data/nginx/conf/seafile.nginx.conf{,.bak} -``` - -2. Destroy the containers with `docker compose down`. - -3. Edit `docker-compose.yml`: change `SEAFILE_SERVER_LETSENCRYPT=false` value to `true`. - -4. Run `docker compose up -d` again. The new Seafile container will automatically request for an SSL certificate to be generated and installed. - -**Notes:** - -- You need to manually change http to https in other configuration files. - -- `SERVICE_URL` and `FILE_SERVER_ROOT` environment variables in the system admin page also need to be modified. - -- If you have modified the old `seafile.nginx.conf`, now you can modify the new `seafile.nginx.conf` as you want. Then execute the following command: - -```bash -# test the Nginx configuration and, if OK, reload nginx for configuration to take effect: -docker exec seafile nginx -t && docker exec seafile nginx -s reload +```shell +SEAFILE_SERVER_PROTOCOL=https +SEAFILE_SERVER_HOSTNAME=example.com ``` diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md index a825cc7c2..3a6d621f8 100644 --- a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md +++ b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md @@ -79,7 +79,7 @@ The following fields merit particular attention: - `SEAFILE_ADMIN_EMAIL`: Admin username - `SEAFILE_ADMIN_PASSWORD`: Admin password -NOTE: SSL is now handled by the caddy server. +NOTE: SSL is now handled by the [caddy server](../deploy_seafile_with_docker.md#about-ssl-and-caddy) from 12.0. To conclude, set the directory permissions of the Elasticsearch volumne: @@ -269,7 +269,7 @@ Q: I forgot the Seafile admin email address/password, how do I create a new admi A: You can create a new admin account by running -``` +```shell docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh ``` @@ -286,35 +286,3 @@ A: You can view the docker logs using this command: `docker compose logs -f`. Q: I forgot the admin password. How do I create a new admin account? A: Make sure the seafile container is running and enter `docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh`. - -Q: The Let's Encrypt SSL certificate is about to expire, how do I renew it? - -A: The SSL certificate should be renewed automatically 30 days prior to its expiration. If the automatic renewal fails, these commands renew the certificate manually: -``` -docker exec -it seafile /bin/bash -/scripts/ssl.sh /shared/ssl/ SEAFILE_SERVER_HOSTNAME -``` -SEAFILE_SERVER_HOSTNAME is the host name used in the docker-compose.yml. - -Q: **SEAFILE_SERVER_LETSENCRYPT=false change to true.** - -A: If you want to change to https after using http, first backup and move the seafile.nginx.conf. - -```sh -mv /opt/seafile-data/nginx/conf/seafile.nginx.conf /opt/seafile-data/nginx/conf/seafile.nginx.conf.bak -``` - -Starting the new container will automatically apply a certificate. - -```sh -docker compose down -docker compose up -d -``` - -You need to manually change http to https in other configuration files, SERVICE_URL and FILE_SERVER_ROOT in the system admin page also need to be modified. - -If you have modified the old seafile.nginx.conf, now you can modify the new seafile.nginx.conf as you want. Then execute the following command to make the nginx configuration take effect. - -```sh -docker exec seafile nginx -s reload -``` diff --git a/manual/docker/seafile_docker_structures.md b/manual/docker/seafile_docker_structures.md new file mode 100644 index 000000000..d25655929 --- /dev/null +++ b/manual/docker/seafile_docker_structures.md @@ -0,0 +1,11 @@ +# Seafile Docker Structures + +Seafile Docker consists of the following two components: + +- Seafile server: Seafile core services, see [Seafile Components](../overview/components.md) for the details. +- Sdoc server: Seadoc server, provide the online collaborative document editor, see [SeaDoc](../extra_setup/setup_seadoc.md#architecture) for the details. +- Database: Stores data related to seafile services, seadoc services, user information, third-party plug-ins, etc. The default database image is `mariadb:10.11`. +- Memcached: Cache servers are used to store avatars, profiles, etc. +- Caddy: Caddy server enables user to access the seafile service (i.e., Seafile server and Sdoc server) externally and handles `SSL` configuration + +![Seafile Docker Structure](../images/seafile-12.0-docker-structure.png) diff --git a/manual/images/seafile-12.0-docker-structure.png b/manual/images/seafile-12.0-docker-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..690a14cf4d23c45a9e9fd345fa0f848689a54585 GIT binary patch literal 104053 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

=j+y!81)BbV`4U?@K4gKWTadC}+YY@+?jd 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 Q2mhqR<;32c(Y^Km06hcw2LJ#7 literal 0 HcmV?d00001 diff --git a/mkdocs.yml b/mkdocs.yml index ce892d4d2..b638b3137 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,6 +77,7 @@ nav: - Setup Seafile cluster with NFS: deploy_pro/setup_seafile_cluster_with_nfs.md - License: deploy_pro/seafile_professional_sdition_software_license_agreement.md - Seafile Setup with Docker: + - Seafile Docker Structures: docker/seafile_docker_structures.md - Seafile Community Installation: docker/deploy_seafile_with_docker.md - Seafile Professional Installation: docker/pro-edition/deploy_seafile_pro_with_docker.md - Seafile Docker Cluster Deployment: docker/cluster/deploy_seafile_cluster_with_docker.md From dbbe455da051f3a467d62384a980e2e9c61628a7 Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Fri, 11 Oct 2024 21:07:56 +0800 Subject: [PATCH 12/22] Update seafile_docker_structures.md --- manual/docker/seafile_docker_structures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manual/docker/seafile_docker_structures.md b/manual/docker/seafile_docker_structures.md index d25655929..182b7d0b7 100644 --- a/manual/docker/seafile_docker_structures.md +++ b/manual/docker/seafile_docker_structures.md @@ -3,9 +3,9 @@ Seafile Docker consists of the following two components: - Seafile server: Seafile core services, see [Seafile Components](../overview/components.md) for the details. -- Sdoc server: Seadoc server, provide the online collaborative document editor, see [SeaDoc](../extra_setup/setup_seadoc.md#architecture) for the details. -- Database: Stores data related to seafile services, seadoc services, user information, third-party plug-ins, etc. The default database image is `mariadb:10.11`. -- Memcached: Cache servers are used to store avatars, profiles, etc. +- Sdoc server: SeaDoc server, provide a lightweight online collaborative document editor, see [SeaDoc](../extra_setup/setup_seadoc.md#architecture) for the details. +- Database: Stores data related to Seafile and SeaDoc. +- Memcached: Cache server. - Caddy: Caddy server enables user to access the seafile service (i.e., Seafile server and Sdoc server) externally and handles `SSL` configuration ![Seafile Docker Structure](../images/seafile-12.0-docker-structure.png) From f1b27f1fce02f0a8bb143c20708db681f090e936 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Sat, 12 Oct 2024 11:24:25 +0800 Subject: [PATCH 13/22] opt: structures, sentences and variables --- manual/docker/deploy_seafile_with_docker.md | 6 +++--- manual/docker/docker-compose/ce/12.0/caddy.yml | 2 +- manual/docker/docker-compose/ce/12.0/env | 8 ++++---- manual/docker/docker-compose/ce/12.0/seadoc.yml | 2 +- .../docker/docker-compose/ce/12.0/seafile-server.yml | 4 ++-- manual/docker/docker-compose/pro/12.0/caddy.yml | 2 +- manual/docker/docker-compose/pro/12.0/env | 10 +++++----- manual/docker/docker-compose/pro/12.0/seadoc.yml | 2 +- .../docker-compose/pro/12.0/seafile-server.yml | 6 +++--- .../docker/docker-compose/seadoc/1.0/standalone/env | 2 +- .../docker-compose/seadoc/1.0/standalone/seadoc.yml | 2 +- .../pro-edition/deploy_seafile_pro_with_docker.md | 8 ++++---- ...cker_structures.md => seafile_docker_overview.md} | 6 +++--- manual/upgrade/upgrade_docker.md | 12 ++++++------ manual/upgrade/upgrade_notes_for_12.0.x.md | 2 +- mkdocs.yml | 2 +- 16 files changed, 38 insertions(+), 38 deletions(-) rename manual/docker/{seafile_docker_structures.md => seafile_docker_overview.md} (77%) diff --git a/manual/docker/deploy_seafile_with_docker.md b/manual/docker/deploy_seafile_with_docker.md index f7915b54e..bd7dabc85 100644 --- a/manual/docker/deploy_seafile_with_docker.md +++ b/manual/docker/deploy_seafile_with_docker.md @@ -32,9 +32,9 @@ nano .env The following fields merit particular attention: -- `SEAFILE_VOLUMES`: The volume directory of Seafile data -- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data -- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data +- `SEAFILE_VOLUME`: The volume directory of Seafile data, default is `/opt/seafile-data` +- `SEAFILE_MYSQL_VOLUME`: The volume directory of MySQL data, default is `/opt/seafile-mysql/db` +- `SEAFILE_CADDY_VOLUME`: The volume directory of Caddy data used to store certificates obtained from Let's Encrypt's, default is `/opt/seafile-caddy` - `SEAFILE_MYSQL_ROOT_PASSWORD`: The user `root` password of MySQL - `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL - `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` diff --git a/manual/docker/docker-compose/ce/12.0/caddy.yml b/manual/docker/docker-compose/ce/12.0/caddy.yml index 608e5bdb4..3bf7e7314 100644 --- a/manual/docker/docker-compose/ce/12.0/caddy.yml +++ b/manual/docker/docker-compose/ce/12.0/caddy.yml @@ -11,7 +11,7 @@ services: - CADDY_INGRESS_NETWORKS=seafile-net volumes: - /var/run/docker.sock:/var/run/docker.sock - - ${SEAFILE_CADDY_VOLUMES:-/opt/seafile-caddy}:/data/caddy + - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy networks: - seafile-net healthcheck: diff --git a/manual/docker/docker-compose/ce/12.0/env b/manual/docker/docker-compose/ce/12.0/env index 3bfd8d441..9caf94880 100644 --- a/manual/docker/docker-compose/ce/12.0/env +++ b/manual/docker/docker-compose/ce/12.0/env @@ -7,9 +7,9 @@ SEAFILE_DB_IMAGE=mariadb:10.11 SEAFILE_MEMCACHED_IMAGE=memcached:1.6.29 SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.9 -SEAFILE_VOLUMES=/opt/seafile-data -SEAFILE_MYSQL_VOLUMES=/opt/seafile-mysql/db -SEAFILE_CADDY_VOLUMES=/opt/seafile-caddy +SEAFILE_VOLUME=/opt/seafile-data +SEAFILE_MYSQL_VOLUME=/opt/seafile-mysql/db +SEAFILE_CADDY_VOLUME=/opt/seafile-caddy SEAFILE_MYSQL_DB_HOST=db SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD @@ -28,7 +28,7 @@ SEAFILE_ADMIN_PASSWORD=asecret SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest -SEADOC_VOLUMES=/opt/seadoc-data +SEADOC_VOLUME=/opt/seadoc-data ENABLE_SEADOC=false SEADOC_SERVER_URL=http://example.seafile.com/sdoc-server diff --git a/manual/docker/docker-compose/ce/12.0/seadoc.yml b/manual/docker/docker-compose/ce/12.0/seadoc.yml index 240daa5e1..7bc2320ba 100644 --- a/manual/docker/docker-compose/ce/12.0/seadoc.yml +++ b/manual/docker/docker-compose/ce/12.0/seadoc.yml @@ -4,7 +4,7 @@ services: image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest} container_name: seadoc volumes: - - ${SEADOC_VOLUMES:-/opt/seadoc-data/}:/shared + - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared # ports: # - "80:80" environment: diff --git a/manual/docker/docker-compose/ce/12.0/seafile-server.yml b/manual/docker/docker-compose/ce/12.0/seafile-server.yml index ed027159b..6e3ffd100 100644 --- a/manual/docker/docker-compose/ce/12.0/seafile-server.yml +++ b/manual/docker/docker-compose/ce/12.0/seafile-server.yml @@ -7,7 +7,7 @@ services: - MYSQL_LOG_CONSOLE=true - MARIADB_AUTO_UPGRADE=1 volumes: - - "${SEAFILE_MYSQL_VOLUMES:-/opt/seafile-mysql/db}:/var/lib/mysql" + - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql" networks: - seafile-net @@ -24,7 +24,7 @@ services: # ports: # - "80:80" volumes: - - ${SEAFILE_VOLUMES:-/opt/seafile-data}:/shared + - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared environment: - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db} - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306} diff --git a/manual/docker/docker-compose/pro/12.0/caddy.yml b/manual/docker/docker-compose/pro/12.0/caddy.yml index 608e5bdb4..3bf7e7314 100644 --- a/manual/docker/docker-compose/pro/12.0/caddy.yml +++ b/manual/docker/docker-compose/pro/12.0/caddy.yml @@ -11,7 +11,7 @@ services: - CADDY_INGRESS_NETWORKS=seafile-net volumes: - /var/run/docker.sock:/var/run/docker.sock - - ${SEAFILE_CADDY_VOLUMES:-/opt/seafile-caddy}:/data/caddy + - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy networks: - seafile-net healthcheck: diff --git a/manual/docker/docker-compose/pro/12.0/env b/manual/docker/docker-compose/pro/12.0/env index 9ae2b92ff..dcbb23fd1 100644 --- a/manual/docker/docker-compose/pro/12.0/env +++ b/manual/docker/docker-compose/pro/12.0/env @@ -8,10 +8,10 @@ SEAFILE_MEMCACHED_IMAGE=memcached:1.6.29 SEAFILE_ELASTICSEARCH_IMAGE=elasticsearch:8.15.0 SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.9 -SEAFILE_VOLUMES=/opt/seafile-data -SEAFILE_MYSQL_VOLUMES=/opt/seafile-mysql/db -SEAFILE_ELASTICSEARCH_VOLUMES=/opt/seafile-elasticsearch/data -SEAFILE_CADDY_VOLUMES=/opt/seafile-caddy +SEAFILE_VOLUME=/opt/seafile-data +SEAFILE_MYSQL_VOLUME=/opt/seafile-mysql/db +SEAFILE_ELASTICSEARCH_VOLUME=/opt/seafile-elasticsearch/data +SEAFILE_CADDY_VOLUME=/opt/seafile-caddy SEAFILE_MYSQL_DB_HOST=db SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD @@ -30,7 +30,7 @@ SEAFILE_ADMIN_PASSWORD=asecret SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest -SEADOC_VOLUMES=/opt/seadoc-data +SEADOC_VOLUME=/opt/seadoc-data ENABLE_SEADOC=false SEADOC_SERVER_URL=http://example.seafile.com/sdoc-server diff --git a/manual/docker/docker-compose/pro/12.0/seadoc.yml b/manual/docker/docker-compose/pro/12.0/seadoc.yml index 240daa5e1..7bc2320ba 100644 --- a/manual/docker/docker-compose/pro/12.0/seadoc.yml +++ b/manual/docker/docker-compose/pro/12.0/seadoc.yml @@ -4,7 +4,7 @@ services: image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest} container_name: seadoc volumes: - - ${SEADOC_VOLUMES:-/opt/seadoc-data/}:/shared + - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared # ports: # - "80:80" environment: diff --git a/manual/docker/docker-compose/pro/12.0/seafile-server.yml b/manual/docker/docker-compose/pro/12.0/seafile-server.yml index d90bb5ce7..51fcf7028 100644 --- a/manual/docker/docker-compose/pro/12.0/seafile-server.yml +++ b/manual/docker/docker-compose/pro/12.0/seafile-server.yml @@ -7,7 +7,7 @@ services: - MYSQL_LOG_CONSOLE=true - MARIADB_AUTO_UPGRADE=1 volumes: - - "${SEAFILE_MYSQL_VOLUMES:-/opt/seafile-mysql/db}:/var/lib/mysql" + - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql" networks: - seafile-net @@ -32,7 +32,7 @@ services: hard: -1 mem_limit: 4g volumes: - - "${SEAFILE_MYSQL_VOLUMES:-/opt/seafile-elasticsearch/data}:/usr/share/elasticsearch/data" + - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-elasticsearch/data}:/usr/share/elasticsearch/data" networks: - seafile-net @@ -42,7 +42,7 @@ services: # ports: # - "80:80" volumes: - - ${SEAFILE_VOLUMES:-/opt/seafile-data}:/shared + - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared environment: - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db} - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306} diff --git a/manual/docker/docker-compose/seadoc/1.0/standalone/env b/manual/docker/docker-compose/seadoc/1.0/standalone/env index 42f4ae683..42eb9a2ce 100644 --- a/manual/docker/docker-compose/seadoc/1.0/standalone/env +++ b/manual/docker/docker-compose/seadoc/1.0/standalone/env @@ -4,7 +4,7 @@ COMPOSE_PATH_SEPARATOR=',' SEADOC_IMAGE=seafileltd/sdoc-server:1.0-latest -SEADOC_VOLUMES=/opt/seadoc-data +SEADOC_VOLUME=/opt/seadoc-data SEAFILE_MYSQL_DB_HOST=192.168.0.2 SEAFILE_MYSQL_DB_USER=seafile diff --git a/manual/docker/docker-compose/seadoc/1.0/standalone/seadoc.yml b/manual/docker/docker-compose/seadoc/1.0/standalone/seadoc.yml index e7f82ee55..c11b864ed 100644 --- a/manual/docker/docker-compose/seadoc/1.0/standalone/seadoc.yml +++ b/manual/docker/docker-compose/seadoc/1.0/standalone/seadoc.yml @@ -4,7 +4,7 @@ services: image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:1.0-latest} container_name: seadoc volumes: - - ${SEADOC_VOLUMES:-/opt/seadoc-data/}:/shared + - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared ports: - "80:80" environment: diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md index 3a6d621f8..2567e1803 100644 --- a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md +++ b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md @@ -66,10 +66,10 @@ nano .env The following fields merit particular attention: -- `SEAFILE_VOLUMES`: The volume directory of Seafile data -- `SEAFILE_MYSQL_VOLUMES`: The volume directory of MySQL data -- `SEAFILE_CADDY_VOLUMES`: The volume directory of Caddy data -- `SEAFILE_ELASTICSEARCH_VOLUMES`: The volume directory of Elasticsearch data +- `SEAFILE_VOLUME`: The volume directory of Seafile data, default is `/opt/seafile-data` +- `SEAFILE_MYSQL_VOLUME`: The volume directory of MySQL data, default is `/opt/seafile-mysql/db` +- `SEAFILE_CADDY_VOLUME`: The volume directory of Caddy data used to store certificates obtained from Let's Encrypt's, default is `/opt/seafile-caddy` +- `SEAFILE_ELASTICSEARCH_VOLUME`: The volume directory of Elasticsearch data - `SEAFILE_MYSQL_ROOT_PASSWORD`: The `root` password of MySQL - `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL - `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` diff --git a/manual/docker/seafile_docker_structures.md b/manual/docker/seafile_docker_overview.md similarity index 77% rename from manual/docker/seafile_docker_structures.md rename to manual/docker/seafile_docker_overview.md index 182b7d0b7..569963754 100644 --- a/manual/docker/seafile_docker_structures.md +++ b/manual/docker/seafile_docker_overview.md @@ -1,11 +1,11 @@ -# Seafile Docker Structures +# Seafile Docker overview -Seafile Docker consists of the following two components: +Seafile Docker consists of the following components: - Seafile server: Seafile core services, see [Seafile Components](../overview/components.md) for the details. - Sdoc server: SeaDoc server, provide a lightweight online collaborative document editor, see [SeaDoc](../extra_setup/setup_seadoc.md#architecture) for the details. - Database: Stores data related to Seafile and SeaDoc. - Memcached: Cache server. -- Caddy: Caddy server enables user to access the seafile service (i.e., Seafile server and Sdoc server) externally and handles `SSL` configuration +- Caddy: Caddy server enables user to access the Seafile service (i.e., Seafile server and Sdoc server) externally and handles `SSL` configuration ![Seafile Docker Structure](../images/seafile-12.0-docker-structure.png) diff --git a/manual/upgrade/upgrade_docker.md b/manual/upgrade/upgrade_docker.md index ef1c04cff..e0a5ae68d 100644 --- a/manual/upgrade/upgrade_docker.md +++ b/manual/upgrade/upgrade_docker.md @@ -119,10 +119,10 @@ wget https://manual.seafile.com/docker/docker-compose/pro/12.0/caddy.yml The following fields merit particular attention: -* The volume directory of Seafile data (SEAFILE_VOLUMES, same as the seafile volumes in the old docker-compose.yml) -* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUMES, same as the mysql volumes in the old docker-compose.yml) -* The volume directory of Elasticsearch data (SEAFILE_ELASTICSEARCH_VOLUMES, pro edition only, same as the elasticsearch volumes in the old docker-compose.yml) -* The volume directory of Caddy data (SEAFILE_CADDY_VOLUMES) +* The volume directory of Seafile data (SEAFILE_VOLUME, same as the seafile volumes in the old docker-compose.yml) +* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUME, same as the mysql volumes in the old docker-compose.yml) +* The volume directory of Elasticsearch data (SEAFILE_ELASTICSEARCH_VOLUME, pro edition only, same as the elasticsearch volumes in the old docker-compose.yml) +* The volume directory of Caddy data (SEAFILE_CADDY_VOLUME) * The user of MySQL (SEAFILE_MYSQL_DB_USER, `database` - `user` can be found in `conf/seafile.conf`) * The password of MySQL (SEAFILE_MYSQL_DB_PASSWORD, `database` - `password` can be found in `conf/seafile.conf`) * jwt (JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1`) @@ -199,7 +199,7 @@ wget https://manual.seafile.com/docker/docker-compose/pro/12.0/seadoc.yml ```env COMPOSE_FILE='seafile-server.yml,caddy.yml,seadoc.yml' -SEADOC_VOLUMES=/opt/seadoc-data +SEADOC_VOLUME=/opt/seadoc-data ENABLE_SEADOC=true SEADOC_SERVER_URL=http://example.seafile.com/sdoc-server ``` @@ -207,7 +207,7 @@ SEADOC_SERVER_URL=http://example.seafile.com/sdoc-server The following fields merit particular attention: * Add `seadoc.yml` to the `COMPOSE_FILE` field. -* The volume directory of SeaDoc data (SEADOC_VOLUMES) +* The volume directory of SeaDoc data (SEADOC_VOLUME) * Enable SeaDoc (ENABLE_SEADOC) * SeaDoc service url (SEADOC_SERVER_URL, hostname + `/sdoc-server`) diff --git a/manual/upgrade/upgrade_notes_for_12.0.x.md b/manual/upgrade/upgrade_notes_for_12.0.x.md index 6ef1ad1f2..83440c679 100644 --- a/manual/upgrade/upgrade_notes_for_12.0.x.md +++ b/manual/upgrade/upgrade_notes_for_12.0.x.md @@ -96,7 +96,7 @@ The following fields merit particular attention: * Seafile MySQL host (SEAFILE_MYSQL_DB_HOST) * Seafile MySQL user (SEAFILE_MYSQL_DB_USER) * Seafile MySQL password (SEAFILE_MYSQL_DB_PASSWD) -* The volume directory of SeaDoc data (SEADOC_VOLUMES) +* The volume directory of SeaDoc data (SEADOC_VOLUME) * SeaDoc service URL (SDOC_SERVER_HOSTNAME) * Seafile service URL (SEAHUB_SERVICE_URL) diff --git a/mkdocs.yml b/mkdocs.yml index b638b3137..80f229bed 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -77,7 +77,7 @@ nav: - Setup Seafile cluster with NFS: deploy_pro/setup_seafile_cluster_with_nfs.md - License: deploy_pro/seafile_professional_sdition_software_license_agreement.md - Seafile Setup with Docker: - - Seafile Docker Structures: docker/seafile_docker_structures.md + - Seafile Docker Overview: docker/seafile_docker_overview.md - Seafile Community Installation: docker/deploy_seafile_with_docker.md - Seafile Professional Installation: docker/pro-edition/deploy_seafile_pro_with_docker.md - Seafile Docker Cluster Deployment: docker/cluster/deploy_seafile_cluster_with_docker.md From e7f0e2c68adcf30fc28c6fc4ba3cb3d5c879be35 Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Sat, 12 Oct 2024 16:03:45 +0800 Subject: [PATCH 14/22] Update words for upgrade_notes_for_12.0.x --- manual/upgrade/upgrade_notes_for_12.0.x.md | 35 ++++++---------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/manual/upgrade/upgrade_notes_for_12.0.x.md b/manual/upgrade/upgrade_notes_for_12.0.x.md index 83440c679..1b9ad8838 100644 --- a/manual/upgrade/upgrade_notes_for_12.0.x.md +++ b/manual/upgrade/upgrade_notes_for_12.0.x.md @@ -47,7 +47,9 @@ For Ubuntu 22.04/24.04 sudo pip3 install future==1.0.* mysqlclient==2.2.* pillow==10.4.* sqlalchemy==2.0.* gevent==24.2.* captcha==0.6.* django_simple_captcha==0.6.* djangosaml2==1.9.* pysaml2==7.3.* pycryptodome==3.20.* cffi==1.17.0 python-ldap==3.4.* PyMuPDF==1.24.* ``` -## Upgrade to 12.0.x +## Upgrade to 12.0 (for binary installation) + +The following instruction is for binary package based installation. If you use Docker based installation, please see [](./upgrade_docker.md) ### 1) Stop Seafile-11.0.x server @@ -71,40 +73,21 @@ Note: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characte ## Upgrade SeaDoc from 0.8 to 1.0 -If you have deployed SeaDoc extension in version 11.0, please use the following steps to upgrade it to version 1.0. - -Deploying SeaDoc and Seafile binary package on the same server is no longer supported. You can: +If you have deployed SeaDoc v0.8 with Seafile v11.0, you can upgrade it to 1.0 use the following two steps: -* Deploy SeaDoc on a new server and integrate it with Seafile. -* Migrate Seafile to a docker based deployment method and then deploy SeaDoc in the same server. +1. Delete sdoc_db. +2. Re-deploy SeaDoc server. In other words, delete the old SeaDoc deployment and deploy a new SeaDoc server on a separate machine. -If you have deployed SeaDoc extension in version 11.0 on a standalone server, please use the following steps to upgrade it to version 1.0. +Note, deploying SeaDoc and **Seafile binary package** on the same server is no longer supported. If you really want to deploying SeaDoc and Seafile server on the same machine, you should deploy Seafile server with Docker. ### Delete sdoc_db -From version 1.0, SeaDoc is using seahub_db database to store its operation logs and no longer need an extra database sdoc_db. You can simply delete sdoc_db. - +From version 1.0, SeaDoc is using seahub_db database to store its operation logs and no longer need an extra database sdoc_db. The database tables in seahub_db are created automatically when you upgrade Seafile server from v11.0 to v12.0. You can simply delete sdoc_db. ### Deploy a new SeaDoc server -In version 1.0, we use env file to configure SeaDoc docker image, instead of modifying the docker-compose.yml file directly. +Please see the document [Setup SeaDoc](../extra_setup/setup_seadoc.md) to install SeaDoc on a separate machine and integrate with your binary packaged based Seafile server v12.0. -Download [.env](https://manual.seafile.com/docker/docker-compose/seadoc/1.0/standalone/env) and [docker-compose.yml](https://manual.seafile.com/docker/docker-compose/seadoc/1.0/standalone/docker-compose.yml), then modify .env file. - -The following fields merit particular attention: - -* Seafile MySQL host (SEAFILE_MYSQL_DB_HOST) -* Seafile MySQL user (SEAFILE_MYSQL_DB_USER) -* Seafile MySQL password (SEAFILE_MYSQL_DB_PASSWD) -* The volume directory of SeaDoc data (SEADOC_VOLUME) -* SeaDoc service URL (SDOC_SERVER_HOSTNAME) -* Seafile service URL (SEAHUB_SERVICE_URL) - -Start SeaDoc server with the following command - -```sh -docker compose up -d -``` ## FAQ From 1fd3684b2df31900541562c7edea1ff083205133 Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Sun, 13 Oct 2024 20:51:50 +0800 Subject: [PATCH 15/22] Remove deploy_seafile_behind_nat and deploy_seahub_at_non-root_domain --- manual/deploy/deploy_seafile_behind_nat.md | 103 --------------- .../deploy_seahub_at_non-root_domain.md | 120 ------------------ mkdocs.yml | 2 - 3 files changed, 225 deletions(-) delete mode 100644 manual/deploy/deploy_seafile_behind_nat.md delete mode 100644 manual/deploy/deploy_seahub_at_non-root_domain.md diff --git a/manual/deploy/deploy_seafile_behind_nat.md b/manual/deploy/deploy_seafile_behind_nat.md deleted file mode 100644 index 0f31c076f..000000000 --- a/manual/deploy/deploy_seafile_behind_nat.md +++ /dev/null @@ -1,103 +0,0 @@ -# Deploy Seafile behind NAT - -A lot of people want to deploy a seafile server in their LAN, and access it from the WAN. - -To achieve this, you need: - -- A router which supports port forwarding -- Use a dynamic DNS Service -- Modify your seafile server configuration - -### Table of Contents - -- [Setup the server](#setup-the-server) -- [Setup port forwarding in your router](#setup-port-forwarding-in-your-router) -- [Use a dynamic dns serivce](#use-a-dynamic-dns-serivce) -- [Modify your seafile configuration](#modify-your-seafile-configuration) - - -## Setup the server - -First, you should follow the guide on [Download and Setup Seafile Server](using_sqlite.md) to setup your Seafile server. - -Before you continue, make sure: - -- You can visit your seahub website -- You can download/sync a library through your seafile client - -## Setup Port Forwarding in Your Router - -### Ensure Your Router Supports Port Forwarding - -First, ensure your router supports port forwarding. - -- Login to the web adminstration page of your router. If you don't know how to do this, you should find the instructions on the manual of the router. If you have no maunal, just google **"XXX router administration page"** where `XXX` is your router's brand. - -- Navigate around in the adminstration page, and check if there is a tag which contains a word such as "forward", "advanced". If your router supports it, chances are that you can find the port forwarding related settings there. - -### Setup Port Forwarding Rules - -Seafile server is composed of several components. If you deployed Seafile behind Apache/Nginx you need to configure port forward for all the components listed below. - -component | default port | protocol --------------------|--------------|---------- -webserver (http) | 80 | TCP -webserver (https) | 443 | TCP - -* If you're not using the default ports, you should adjust the table according to your own customiztion. - -### How to test if your port forwarding is working - -After you have set the port forwarding rules on your router, you can check whether it works by: - -- Open a command line prompt -- Get your WAN IP. A convenient way to get your WAN ip is to visit `http://who.is`, which would show you your WAN IP. -- Try to connect your Seafile server - -```bash -telnet 80 -``` - -If your port forwarding is working, the command above should succeed. Otherwise, you may get a message saying something like *connection refused* or *connection timeout*. - -If your port forwarding is not working, the reasons may be: - -- You have configured a wrong port forwarding -- Your router may need a restart -- You network may be down - -### Set SERVICE_URL - -"SERVICE_URL" in `ccnet.conf` is used to generate the download/upload link for files when you browse files online. Set it using your WAN IP. - -```python -SERVICE_URL = https:// -``` - -Most routers support NAT loopback. When your access Seafile web from intranet, file download/upload still works even when external IP is used. - -## Use a Dynamic DNS Serivce - -### Why use a Dynamic DNS(DDNS) Service? - -Having done all the steps above, you should be able to visit your seahub server outside your LAN by your WAN IP. But for most people, the WAN IP address is likey to change regularly by their ISP(Internet Serice Provider), which makes this approach impratical. - -You can use a dynamic DNS(DDNS) Service to overcome this problem. By using a dynamic DNS service, you can visit your seahub by domain name (instead of by IP), and the domain name will always be mapped to your WAN IP address, even if it changes regularly. - -There are a dozen of dynamic DNS service providers on the internet. If you don't know what service to choose, we recommend using [www.noip.com](http://www.noip.com) since it performs well in our testing. - -The detailed process is beyond the scope of this wiki. But basically, you should: - -1. Choose a DDNS service provider -2. Register an account on the DDNS service provider's website -3. Download a client from your DDNS service provider to keep your domain name always mapped to your WAN IP - -## Modify your seafile configuration - -After you have setup your DDNS service, you need to modify the `ccnet.conf`: - -```python -SERVICE_URL = https:// -``` - -Restart your seafile server after this. diff --git a/manual/deploy/deploy_seahub_at_non-root_domain.md b/manual/deploy/deploy_seahub_at_non-root_domain.md deleted file mode 100644 index 7d7739a65..000000000 --- a/manual/deploy/deploy_seahub_at_non-root_domain.md +++ /dev/null @@ -1,120 +0,0 @@ -# Deploy Seahub at Non-root domain - -## Non-root Domain - -The following will talk about how to deploy Seafile Web using Apache/Nginx at Non-root directory of the website(e.g., www.example.com/seafile/). Please note that the file server path will still be e.g. www.example.com/seafhttp (rather than www.example.com/seafile/seafhttp) because this path is hardcoded in the clients. - -**Note:** We assume you have read [Deploy Seafile with nginx](deploy_with_nginx.md) or [Deploy Seafile with apache](deploy_with_apache.md). - -### Configure Seahub - -First, we need to overwrite some variables in seahub_settings.py: - -``` -MEDIA_URL = '/seafmedia/' -COMPRESS_URL = MEDIA_URL -STATIC_URL = MEDIA_URL + 'assets/' -SITE_ROOT = '/seafile/' -LOGIN_URL = '/seafile/accounts/login/' -FILE_SERVER_ROOT = 'http://www.myseafile.com/seafhttp' -SERVICE_URL = 'http://www.myseafile.com/seafile' -``` - -`MEDIA_URL` can be anything you like, just make sure a trailing slash is appended at the end. - -We deploy Seafile at `/seafile/` directory instead of root directory, so we set `SITE_ROOT` to `/seafile/`. - -**Note:** The file server path MUST be `/seafhttp` because this path is hardcoded in the clients. - -### Webserver configuration - -#### Deploy with Nginx - -Then, we need to configure the Nginx: - -``` -server { - listen 80; - server_name www.example.com; - - proxy_set_header X-Forwarded-For $remote_addr; - - location /seafile { - proxy_pass http://127.0.0.1:8000; - 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; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_read_timeout 1200s; - - # used for view/edit office file via Office Online Server - client_max_body_size 0; - - access_log /var/log/nginx/seahub.access.log; - error_log /var/log/nginx/seahub.error.log; - } - - location /seafhttp { - rewrite ^/seafhttp(.*)$ $1 break; - proxy_pass http://127.0.0.1:8082; - client_max_body_size 0; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_connect_timeout 36000s; - proxy_read_timeout 36000s; - } - - location /seafmedia { - rewrite ^/seafmedia(.*)$ /media$1 break; - root /home/user/haiwen/seafile-server-latest/seahub; - } -} -``` - -### Deploy with Apache - -Here is the sample configuration: - -``` - - ServerName www.example.com - DocumentRoot /var/www - Alias /seafmedia /home/user/haiwen/seafile-server-latest/seahub/media - - - ProxyPass ! - Require all granted - - - RewriteEngine On - - # - # seafile fileserver - # - ProxyPass /seafhttp http://127.0.0.1:8082 - ProxyPassReverse /seafhttp http://127.0.0.1:8082 - RewriteRule ^/seafhttp - [QSA,L] - - # - # seahub - # - SetEnvIf Request_URI . proxy-fcgi-pathinfo=unescape - SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 - ProxyPreserveHost On - ProxyPass /seafile http://127.0.0.1:8000/seafile - ProxyPassReverse /seafile http://127.0.0.1:8000/seafile - -``` - -We use Alias to let Apache serve static files, please change the second argument to your path. - -### Start Seafile and Seahub - -``` -./seafile.sh start -./seahub.sh start -``` - -### Using Seafile Client - -When logging in on the Seafile client, the server address should now be http://www.example.com/seafile, not http://www.example.com. diff --git a/mkdocs.yml b/mkdocs.yml index 80f229bed..a550e6593 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -126,8 +126,6 @@ nav: - Start Seafile at System Bootup: deploy/start_seafile_at_system_bootup.md - Logrotate: deploy/using_logrotate.md - Open Cloud Mesh: deploy/ocm.md - - Deploy Seafile behind NAT: deploy/deploy_seafile_behind_nat.md - - Deploy Seahub at Non-root domain or on custom port: deploy/deploy_seahub_at_non-root_domain.md - Config fail2ban: security/fail2ban.md - Real-time Backup Server: deploy_pro/real_time_backup.md - Configuration and Customization: From d88b4b0b3948db23d2133984aee6c9f8ea32c03c Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Mon, 14 Oct 2024 07:00:25 +0800 Subject: [PATCH 16/22] Remove realtime backup --- .../office-preview-yml/docker-compose.yml | 11 -- manual/deploy_pro/office_documents_preview.md | 177 ----------------- manual/deploy_pro/real_time_backup.md | 184 ------------------ mkdocs.yml | 1 - 4 files changed, 373 deletions(-) delete mode 100644 manual/deploy_pro/office-preview-yml/docker-compose.yml delete mode 100644 manual/deploy_pro/office_documents_preview.md delete mode 100644 manual/deploy_pro/real_time_backup.md diff --git a/manual/deploy_pro/office-preview-yml/docker-compose.yml b/manual/deploy_pro/office-preview-yml/docker-compose.yml deleted file mode 100644 index d9ee9a01b..000000000 --- a/manual/deploy_pro/office-preview-yml/docker-compose.yml +++ /dev/null @@ -1,11 +0,0 @@ -services: - office-preview: - image: seafileltd/office-preview:latest - container_name: seafile-office-preview - environment: - - IGNORE_JWT_CHECK=true - ports: - - "8089:8089" - command: bash start.sh - volumes: - - /opt/office-preview/shared:/shared # the host path can be customized diff --git a/manual/deploy_pro/office_documents_preview.md b/manual/deploy_pro/office_documents_preview.md deleted file mode 100644 index 3bc7f33cb..000000000 --- a/manual/deploy_pro/office_documents_preview.md +++ /dev/null @@ -1,177 +0,0 @@ -# Office Documents Preview with LibreOffice - -> This is a deprecated feature since version 11. Integrating with CollaboraOnline or OnlyOffice is recommended. - -Seafile Professional Server supports previewing office documents online by converting them to PDF. You can follow these steps to use the feature. If you'd like to edit office files online, you can integrate Seafile with Microsoft Office Online server, CollaboraOnline or OnlyOffice. - - -## Version 7.1.x - 8.0.x - -### Install Libreoffice/UNO - -Libreoffice 6.2+ and Python-uno library are required to enable office files online preview. - -On Ubuntu/Debian: - -```bash -sudo apt-get install libreoffice libreoffice-script-provider-python -``` - -> For older version of Ubuntu: `sudo apt-get install libreoffice python-uno` - -On Centos/RHEL, you need to first remove the default libreoffice in the distribution: - -``` -yum remove --setopt=clean_requirements_on_remove=0 libreoffice-* -``` - -Then install version 6.4 or newer ([Installation of LibreOffice on Linux](https://wiki.documentfoundation.org/Documentation/Install/Linux#Terminal-Based_Install)). - -Also, you may need to install fonts for your language, especially for Asians, otherwise the office document may not display correctly. - -### Enable Office Preview - -Open file `seafevents.conf`, in the `OFFICE CONVERTER` section: - -```conf -[OFFICE CONVERTER] -enabled = true -host = 127.0.0.1 -port = 6000 -``` - -After modifying and saving `seafevents.conf`, restart seafile server by `./seafile.sh restart` - -The office converter process will be started and listen on 127.0.0.1:6000 - -In `seahub_settings.py`, add the following config - -``` -OFFICE_CONVERTOR_ROOT = 'http://127.0.0.1:6000/' -``` - -Open a doc/ppt/xls file on Seahub, you should be about the previewing it in your browser. - -### Other Configurable Options - -Here are full list of options you can fine tune: - -```conf -[OFFICE CONVERTER] - -## must be "true" to enable office file online preview -enabled = true - -## How many libreoffice worker processes to run concurrenlty -workers = 1 - -## where to store the converted office/pdf files. Deafult is /tmp/. -outputdir = /tmp/ - -host = 127.0.0.1 -port = 6000 -``` - -## Version 9.0.x or above - -We use Docker to deploy LibreOffice as an example, so you need to install Docker on the server in advance (Docker installation is not introduced here). The office-preview service needs to be deployed on the same machine as the Seafile service. - -### Prepare `docker-compose.yml` - -Download and change [docker-compose.yml](./office-preview-yml/docker-compose.yml). - -``` -services: - office-preview: - image: seafileltd/office-preview:latest - container_name: seafile-office-preview - environment: - - IGNORE_JWT_CHECK=true # Usually, seafile and office-perview are deployed on the same machine and communicate through the intranet, so the jwt check can be ignored. - ports: - - "192.x.x.x:8089:8089" # 192.x.x.x is the IP address of the machine - command: bash start.sh - volumes: - - /opt/office-preview/shared:/shared # the host path can be customized -``` - -### Start `seafile-office-preview` container - -``` -docker compose up -d -``` - -Add `/opt/office-preview/shared/office_convertor_settings.py` manually. - -``` -# Make sure the SECRET_KEY is the same as value in seahub_settings.py -SECRET_KEY = "o@^yktib39k+oor2_busbcxqaach_$b5zq-)4l6l39v#8ky5ta" - -WORKERS = 10 # worker number -OUTPUT_DIR = '/shared/output' # output folder in container -PORT = 8089 # port in container -``` - -Restart `seafile-office-preview` container. -``` -docker restart seafile-office-preview -``` - -### Config seahub_settings.py - -Add the following configuration to `seahub_settings.py`. - -``` -OFFICE_CONVERTOR_ROOT = 'http://192.x.x.x:8089' # 192.x.x.x is the IP address of the machine -``` - -Restart seahub. -``` -./seahub.sh restart -``` - -## FAQ about Office document preview - -#### Document preview doesn't work, where to find more information? - -You can check the log at logs/seafevents.log - -#### My server is CentOS, and I see errors like "/usr/lib64/libreoffice/program/soffice.bin X11 error: Can't open display", how could I fix it? - -This error indicates you have not installed the `libreoffice-headless` package. Install it by `"sudo yum install libreoffice-headless"`. - -#### Document preview doesn't work on my Ubuntu/Debian server, what can I do? - -Current office online preview works with libreoffice 4.0-4.2. If the version of libreoffice installed by `apt-get` is too old or too new, you can solve this by: - -Remove the installed libreoffice: - -``` -sudo apt-get remove libreoffice* python-uno python3-uno -``` - -Download libreoffice packages from [libreoffice official site](https://downloadarchive.documentfoundation.org/libreoffice/old/) - -Install the downloaded pacakges: - -``` -tar xf LibreOffice_4.1.6_Linux_x86-64_deb.tar.gz -cd LibreOffice_4.1.6.2_Linux_x86-64_deb -cd DEBS -sudo dpkg -i *.deb -``` - -Restart your seafile server and try again. It should work now. - -``` -./seafile.sh restart -``` - -#### The browser displays "document conversion failed", and in the logs I see messages like `[WARNING] failed to convert xxx to ...`, what should I do? - -Sometimes the libreoffice process need to be restarted, especially if it's the first time seafile server is running on the server. - -Try to kill the libreoffice process with `pkill -f soffice.bin`. Then try re-opening the preview page in the brower again. If you are deploying seafile in cluster mode, make sure memcached is working on each server. - -#### The above solution does not solve my problem. - -Please check whether the user you run Seafile can correctly start the libreoffice process. There may be permission problems. For example, if you use www-data user to run Seafile, make sure www-data has a home directory and can write to the home directory. diff --git a/manual/deploy_pro/real_time_backup.md b/manual/deploy_pro/real_time_backup.md deleted file mode 100644 index bd5b5fb54..000000000 --- a/manual/deploy_pro/real_time_backup.md +++ /dev/null @@ -1,184 +0,0 @@ -# Seafile Real-Time Backup Server - -Note: This feature is deprecated and not recommended to use in production. If you're looking for backup solution: - -* If you're not using object storage, you can follow the instructions in [backup and recovery](../maintain/backup_recovery.md). -* If you're using object storage, you can use the [migration script](../deploy_pro/migrate.md) to backup the objects. - -Backup is the procedure that copies data from a primary server (which is running production service) to a backup server. - -The real-time backup server uses a syncing algorithm similar to the Seafile desktop client to retrieve data from the primary server. It works as follows: - -- Whenever a library is updated, the primary server notifies the backup server to retrieve the changed data. With a delta syncing algorithm, this procedure runs quickly and updates the backup server in nearly real-time. -- The backup server also checks all libraries on the primary server at a fixed period. Any new or updated libraries will be synced to the backup server. This will pick up any legged updates due to glitches in the above real-time sync procedure. -- The backup server always keep the database and data directory consistent. So no libraries on the backup server will be in corrupted state (unless they're already corrupted on the primary server). -- The full history of all libraries will be backed up. This is not like the desktop client, which only syncs the latest state of a library. - -There are two sets of data that need to be backed up: - -- The seafile-data directory and the core library metadata tables in the seafile database. This data is the core data structures of the libraries in Seafile. They're synced to the backup server with Seafile's syncing algorithm. In this procedure, the metadata tables are kept consistent with the seafile-data directory. -- All other tables in the database (including seafile, ccnet and seahub databases) are backed up with mysqldump. mysqldump can't back up the database in real time. You can setup a crontab for mysqldump at regular intervals. The latency of backup for these tables doesn't affect the integrity of library data. - -In the following discussion, we'll use "primary server" and "master server", "backup server" and "slave server" interchangeably. - -## Configure Real-Time Backup Server - -We assume you already have a primary server running, and now you want to set up a backup server. - -The steps to setup the backup server are: - -1. Install Seafile on the backup server -2. Configure Seafile syncing between the primary server and the backup server -3. Back up the tables in the database by `mysqldump` at regular intervals - -### Install Seafile on the Backup Server - -You should install Seafile Pro Edition on the backup server according to [this documentation](../deploy_pro/download_and_setup_seafile_professional_server.md). Since the real-time backup feature is only available for 5.1.0 or later, you also have to upgrade your primary server to version 5.1.0 or later. - -When installing Seafile on the backup server, you have to notice: - -- The database names (ccnet, seafile and seahub database) should be the same as the names on the primary server. -- You don't need to enable other Pro features, such as Office file preview, search indexing, file auditing etc. -- You can't start the seahub progress on backup server. It means that usually the Seafile backup server can't provide service. - -### Configure Real-time Backup in Seafile - -On the primary server, add following options to seafile.conf: - -``` -[backup] -backup_url = http://backup-server -sync_token = c7a78c0210c2470e14a20a8244562ab8ad509734 -``` - -On the backup server, add following options to seafile.conf: - -``` -[backup] -primary_url = http://primary-server -sync_token = c7a78c0210c2470e14a20a8244562ab8ad509734 -sync_poll_interval = 3 -``` - -- `backup_url`: the backup server's address in url format. You can use HTTP or HTTPS. -- `primary_url`: the primary server's address in url format. -- `sync_token`: a secret shared between the primary and backup server. It's a 40 character SHA1 token generated by the system admin. You can use `uuidgen | openssl sha1` command to generate a random token. -- `sync_poll_interval`: The backup server polls all libraries of the primary server periodically. You can set the poll interval in units of hours. The default interval is 1 hour, which means the backup server will poll the primary every hour. You should choose larger intervals if you have larger libraries. - -If you use HTTPS to sync between primary and backup servers, you must use the correct Seafile server package for your system. If you run CentOS, you should use the Seafile package named without the "Ubuntu" suffix; if you run Debian or Ubuntu, you should use the Seafile package named with "Ubuntu" suffix. Otherwise you may meet CA errors in HTTPS requests. - -After saving the configuration, restart the seafile service on the primary and backup servers. The backup server will automatically start backing up on restart. - -**Note**: Don't start the seahub progress on the Seafile backup server. - -### Back up the Databases - -Backup data from the databases on the primary server's MySQL with mysqldump: - -``` -mysqldump -u -p --databases \ ---ignore-table=.Repo \ ---ignore-table=.Branch \ ---ignore-table=.RepoHead \ - > dbdump.sql -``` - -You should replace ``, `` with your MySQL admin user and password. You should replace ``, `` and `` with your database names. - -The three ignored tables are core tables related to library data, and are synced by Seafile backup server in a real-time manner. They're kept in the seafile database of the backup server and are separated from the mysqldump process. - -**You should set up crontab to run the mysqldump at regular intervals.** - -If you want to back up the tables (except for the 3 tables synced by Seafile) in a more real-time manner, you can deploy the master-slave replication for the MySQL/MariaDB database from the primary node to another database server. **The database running on the backup server must not be used as the target of this replication.** Otherwise you'll end up with replication conflicts, since the db on backup server will also be updated by Seafile backup process too. - -### Checking Backup Status - -After the above setup, you should now have the below layout of your backup data: - -* Library data is backed up and managed by Seafile backup server. The data can be stored on external storage, object storage, or local disk, depending on your setup for the backup server. -* Database tables are split into two parts: - * 3 core library tables are backed up in real-time to the backup node's MySQL database. - * Other tables are regularly dumped to a file with mysqldump. The backup files are stored somewhere other than the primary server. - -`seaf-backup-cmd.sh` provides `status` command to view the backup status. The output is like: - -``` -# ./seaf-backup-cmd.sh status -Total number of libraries: xxx -Number of synchronized libraries: xxx -Number of libraries waiting for sync: xxx -Number of libraries syncing: xxx -Number of libraries failed to sync: xxx - -List of syncing libraries: -xxx -xxx - -List of libraries failed to sync: -xxx -xxx -``` - -There are a few reasons the backup of a library may fail: - -- Some data in the primary server is corrupted. The data may be in the latest state or in history. Since the backup procedure syncs the full history, corruption in history will fail the backup. -- The primary server has run seaf-fsck, which may restore a library back to an older state. - -## Restore from the Backup Server - -In the unfortunate situation where severe data corruption happens on the primary server, you can restore your service quickly directly on the backup server. The recovered service can be run directly on the backup server. - -There are tow steps to restore on the backup server: - -- Import the latest MySQL dump file into the Seafile backup server's MySQL database. -- Enable other Pro features on the Seafile backup server, and start seahub progress `./seahub.sh start`. - -#### Step1: Import MySQL dump file into backup server - -Importing the latest MySQL dump file into the backup server's database: - -``` -mysql -u -p < dbdump.sql -``` - -Replace `` and `` with your MySQL admin user name and password. - -#### Step2: Start the backup server's seahub - -Copy the seafile's configuration to the backup server, then start the seahub progress on the backup server. - -``` -./seahub.sh start -``` - -## Setup Backup Server for Seafile Cluster - -If your primary service runs as a Seafile cluster, you have two points to notice when setting up a backup server: - -1. You should only use one MySQL instance as the replication master, if you're using MariaDB cluster. -2. You have to change seafile.conf and set the `backup_url` and `sync_token` options on each Seafile node. The configuration on all primary Seafile node should be the same. They all point to the same backup server. - -Currently you cannot deploy the backup service **as** a cluster. That is, you can only use a single node as backup server. This support may be added in the future. - -## Managing the Real-time Backup Server - -`seaf-backup-cmd.sh` script is the tool for managing the backup server. The `seaf-backup-cmd.sh` script provides the following commands: - -### Manually Trigger Syncing a Library - -You can use the `sync` command to manually schedule backup of a library: - -``` -# ./seaf-backup-cmd.sh sync -``` - -The command will block until the backup is finished. - -### Handling Backup Errors - -The `--force` option of `sync` command can be used to force failing backup to complete. Permanent backup failures are usually caused by data corruption of a library in the primary server. The `--force` option asks the backup to skip corrupted objects and finish the backup. - -When you find a backup error, follow two steps: - -1. Run seaf-fsck on the primary server, for the failing libraries. Fsck fixes any corruption for the latest state of the libraries. -2. Run `seaf-backup-cmd.sh sync --force ` on the backup server. diff --git a/mkdocs.yml b/mkdocs.yml index a550e6593..5911d52c1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -127,7 +127,6 @@ nav: - Logrotate: deploy/using_logrotate.md - Open Cloud Mesh: deploy/ocm.md - Config fail2ban: security/fail2ban.md - - Real-time Backup Server: deploy_pro/real_time_backup.md - Configuration and Customization: - Outline: config/README.md - ccnet.conf: config/ccnet-conf.md From 44ced502dd80432f936a1e7ac7fdfb6a72f2e8c2 Mon Sep 17 00:00:00 2001 From: Junxiang Huang Date: Mon, 14 Oct 2024 10:32:31 +0800 Subject: [PATCH 17/22] opt: structures and sentences --- manual/docker/deploy_seafile_with_docker.md | 1 + .../deploy_seafile_pro_with_docker.md | 1 + manual/docker/seafile_docker_overview.md | 2 +- .../images/seafile-12.0-docker-structure.png | Bin 104053 -> 104606 bytes manual/upgrade/upgrade_docker.md | 22 +++++++++--------- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manual/docker/deploy_seafile_with_docker.md b/manual/docker/deploy_seafile_with_docker.md index bd7dabc85..3b2e76b7c 100644 --- a/manual/docker/deploy_seafile_with_docker.md +++ b/manual/docker/deploy_seafile_with_docker.md @@ -36,6 +36,7 @@ The following fields merit particular attention: - `SEAFILE_MYSQL_VOLUME`: The volume directory of MySQL data, default is `/opt/seafile-mysql/db` - `SEAFILE_CADDY_VOLUME`: The volume directory of Caddy data used to store certificates obtained from Let's Encrypt's, default is `/opt/seafile-caddy` - `SEAFILE_MYSQL_ROOT_PASSWORD`: The user `root` password of MySQL +- `SEAFILE_MYSQL_DB_USER`: The user of MySQL (`database` - `user` can be found in `conf/seafile.conf`) - `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL - `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` - `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain diff --git a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md index 2567e1803..36bcc4dc7 100644 --- a/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md +++ b/manual/docker/pro-edition/deploy_seafile_pro_with_docker.md @@ -71,6 +71,7 @@ The following fields merit particular attention: - `SEAFILE_CADDY_VOLUME`: The volume directory of Caddy data used to store certificates obtained from Let's Encrypt's, default is `/opt/seafile-caddy` - `SEAFILE_ELASTICSEARCH_VOLUME`: The volume directory of Elasticsearch data - `SEAFILE_MYSQL_ROOT_PASSWORD`: The `root` password of MySQL +- `SEAFILE_MYSQL_DB_USER`: The user of MySQL (`database` - `user` can be found in `conf/seafile.conf`) - `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL - `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` - `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain diff --git a/manual/docker/seafile_docker_overview.md b/manual/docker/seafile_docker_overview.md index 569963754..dedf1fcc4 100644 --- a/manual/docker/seafile_docker_overview.md +++ b/manual/docker/seafile_docker_overview.md @@ -1,6 +1,6 @@ # Seafile Docker overview -Seafile Docker consists of the following components: +Seafile docker based installation consist of the following components (docker images): - Seafile server: Seafile core services, see [Seafile Components](../overview/components.md) for the details. - Sdoc server: SeaDoc server, provide a lightweight online collaborative document editor, see [SeaDoc](../extra_setup/setup_seadoc.md#architecture) for the details. diff --git a/manual/images/seafile-12.0-docker-structure.png b/manual/images/seafile-12.0-docker-structure.png index 690a14cf4d23c45a9e9fd345fa0f848689a54585..8719a7479e3a093800dd7bdab8e191a8de190a95 100644 GIT binary patch literal 104606 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�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

=j+y!81)BbV`4U?@K4gKWTadC}+YY@+?jd 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 Q2mhqR<;32c(Y^Km06hcw2LJ#7 diff --git a/manual/upgrade/upgrade_docker.md b/manual/upgrade/upgrade_docker.md index e0a5ae68d..1d2ad3193 100644 --- a/manual/upgrade/upgrade_docker.md +++ b/manual/upgrade/upgrade_docker.md @@ -119,17 +119,17 @@ wget https://manual.seafile.com/docker/docker-compose/pro/12.0/caddy.yml The following fields merit particular attention: -* The volume directory of Seafile data (SEAFILE_VOLUME, same as the seafile volumes in the old docker-compose.yml) -* The volume directory of MySQL data (SEAFILE_MYSQL_VOLUME, same as the mysql volumes in the old docker-compose.yml) -* The volume directory of Elasticsearch data (SEAFILE_ELASTICSEARCH_VOLUME, pro edition only, same as the elasticsearch volumes in the old docker-compose.yml) -* The volume directory of Caddy data (SEAFILE_CADDY_VOLUME) -* The user of MySQL (SEAFILE_MYSQL_DB_USER, `database` - `user` can be found in `conf/seafile.conf`) -* The password of MySQL (SEAFILE_MYSQL_DB_PASSWORD, `database` - `password` can be found in `conf/seafile.conf`) -* jwt (JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1`) -* SEAFILE_SERVER_HOSTNAME (SEAFILE_SERVER_HOSTNAME, same as the SEAFILE_SERVER_HOSTNAME in the old docker-compose.yml) -* SEAFILE_SERVER_PROTOCOL (SEAFILE_SERVER_PROTOCOL, use http or https) - -SSL is now handled by the caddy server. If you have used SSL before, you will also need modify the seafile.nginx.conf. Change server listen 443 to 80. +- `SEAFILE_VOLUME`: The volume directory of Seafile data, default is `/opt/seafile-data` +- `SEAFILE_MYSQL_VOLUME`: The volume directory of MySQL data, default is `/opt/seafile-mysql/db` +- `SEAFILE_CADDY_VOLUME`: The volume directory of Caddy data used to store certificates obtained from Let's Encrypt's, default is `/opt/seafile-caddy` +- `SEAFILE_ELASTICSEARCH_VOLUME`: The volume directory of Elasticsearch data +- `SEAFILE_MYSQL_ROOT_PASSWORD`: The `root` password of MySQL +- `SEAFILE_MYSQL_DB_PASSWORD`: The user `seafile` password of MySQL +- `JWT`: JWT_PRIVATE_KEY, A random string with a length of no less than 32 characters, generate example: `pwgen -s 40 1` +- `SEAFILE_SERVER_HOSTNAME`: Seafile server hostname or domain +- `SEAFILE_SERVER_PROTOCOL`: Seafile server protocol (http or https) + +SSL is now handled by the [caddy server](../docker/deploy_seafile_with_docker.md#about-ssl-and-caddy). If you have used SSL before, you will also need modify the seafile.nginx.conf. Change server listen 443 to 80. Backup the original seafile.nginx.conf file: From 657b3d4b8185ba2ac24419e978a7485e88dcb4fd Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Mon, 14 Oct 2024 11:01:01 +0800 Subject: [PATCH 18/22] Delete outdated files --- manual/deploy_pro/adfs.md | 251 --------------- manual/deploy_pro/cas.md | 35 --- manual/upgrade/ce-7.0.md | 50 --- manual/upgrade/pro-7.0.md | 289 ------------------ .../upgrade_with_mysql_or_postgresql.md | 167 ---------- mkdocs.yml | 4 +- 6 files changed, 1 insertion(+), 795 deletions(-) delete mode 100644 manual/deploy_pro/adfs.md delete mode 100644 manual/deploy_pro/cas.md delete mode 100644 manual/upgrade/ce-7.0.md delete mode 100644 manual/upgrade/pro-7.0.md delete mode 100644 manual/upgrade/upgrade_with_mysql_or_postgresql.md diff --git a/manual/deploy_pro/adfs.md b/manual/deploy_pro/adfs.md deleted file mode 100644 index 08879367f..000000000 --- a/manual/deploy_pro/adfs.md +++ /dev/null @@ -1,251 +0,0 @@ -# AD Federation Service or SAML 2.0 Integration - -Note, this document is for Seafile version 9.0 or below. For version 10.0+, please follow the new document [SAML 2.0 in version 10.0+](./saml2_in_10.0.md). - -This documentation describes how to integrate to ADFS with SAML 2.0 protocol. The procedure can also be used to integrate with other SAML 2.0 compliant service with minimal change. - -## Requirements - -To use ADFS to log in to your Seafile, you need the following components: - -1. A Windows Server with [ADFS](https://technet.microsoft.com/en-us/library/hh831502.aspx) installed. For configuring and installing ADFS you can see [this article](https://msdn.microsoft.com/en-us/library/gg188612.aspx). -2. A valid SSL certificate for ADFS server, and here we use **adfs-server.adfs.com** as the domain name example. -3. A valid SSL certificate for Seafile server, and here we use **demo.seafile.com** as the domain name example. - -## Prepare Certs File - -1、x.509 certs for SP (Service Provider) - -You can generate them by: - -``` -openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout sp.key -out sp.crt - -``` - -These x.509 certs are used to sign and encrypt elements like NameID and Metadata for SAML. - -**Note: Do not use some special characters when generating a certificate** - -2、Then copy these two files to `/seahub-data/certs`. (if the certs folder not exists, create it.) - -1. x.509 cert from IdP (Identity Provider) -2. Log into the ADFS server and open the ADFS management. -3. Double click **Service** and choose **Certificates**. -4. Export the **Token-Signing** certificate: - 1. Right-click the certificate and select **View Certificate**. - 2. Select the **Details** tab. - 3. Click **Copy to File** (select **DER encoded binary X.509**). -5. Convert this certificate to PEM format, rename it to **idp.crt** -6. Then copy it to `/seahub-data/certs`. - -## Prepare IdP Metadata File - -1. Open -2. Save this xml file, rename it to **idp_federation_metadata.xml** -3. Copy it to `/seahub-data/certs`. - -## Install Requirements on Seafile Server - -* For Ubuntu 18.04/20.04 - -``` -sudo apt install libxmlsec1 xmlsec1 -``` - -* For Seafile 7.1.x - -``` -sudo pip install cryptography djangosaml2==0.18.1 pysaml2==4.6.0 -``` - -* For Seafile 8.0.x - -``` -sudo pip install cryptography djangosaml2==0.20.0 pysaml2==6.5.1 -``` - - -## Config Seafile - -Add the following lines to **seahub_settings.py** - -``` -from os import path -import saml2 -import saml2.saml - -CERTS_DIR = '/seahub-data/certs' -SP_SERVICE_URL = 'https://demo.seafile.com' -XMLSEC_BINARY = '/usr/bin/xmlsec1' - -# for 9.0 and later -ATTRIBUTE_MAP_DIR = '/seafile-server-latest/seahub/seahub/adfs_auth/attribute-maps' - -# for 8.0 and previous -ATTRIBUTE_MAP_DIR = '/seafile-server-latest/seahub-extra/seahub_extra/adfs_auth/attribute-maps' - -SAML_ATTRIBUTE_MAPPING = { - 'DisplayName': ('display_name', ), - 'ContactEmail': ('contact_email', ), - 'Department': ('department', ), - 'Telephone': ('telephone', ), -} - -ENABLE_ADFS_LOGIN = True -EXTRA_AUTHENTICATION_BACKENDS = ( - - # for 9.0 and later - 'seahub.adfs_auth.backends.Saml2Backend', - - # for 8.0 and previous - 'seahub_extra.adfs_auth.backends.Saml2Backend', -) -SAML_USE_NAME_ID_AS_USERNAME = True -LOGIN_REDIRECT_URL = '/saml2/complete/' -SAML_CONFIG = { - # full path to the xmlsec1 binary programm - 'xmlsec_binary': XMLSEC_BINARY, - - 'allow_unknown_attributes': True, - - # your entity id, usually your subdomain plus the url to the metadata view - 'entityid': SP_SERVICE_URL + '/saml2/metadata/', - - # directory with attribute mapping - 'attribute_map_dir': ATTRIBUTE_MAP_DIR, - - # this block states what services we provide - 'service': { - # we are just a lonely SP - 'sp' : { - "allow_unsolicited": True, - 'name': 'Federated Seafile Service', - 'name_id_format': saml2.saml.NAMEID_FORMAT_EMAILADDRESS, - 'endpoints': { - # url and binding to the assetion consumer service view - # do not change the binding or service name - 'assertion_consumer_service': [ - (SP_SERVICE_URL + '/saml2/acs/', - saml2.BINDING_HTTP_POST), - ], - # url and binding to the single logout service view - # do not change the binding or service name - 'single_logout_service': [ - (SP_SERVICE_URL + '/saml2/ls/', - saml2.BINDING_HTTP_REDIRECT), - (SP_SERVICE_URL + '/saml2/ls/post', - saml2.BINDING_HTTP_POST), - ], - }, - - # attributes that this project need to identify a user - 'required_attributes': ["uid"], - - # attributes that may be useful to have but not required - 'optional_attributes': ['eduPersonAffiliation', ], - - # in this section the list of IdPs we talk to are defined - 'idp': { - # we do not need a WAYF service since there is - # only an IdP defined here. This IdP should be - # present in our metadata - - # the keys of this dictionary are entity ids - 'https://adfs-server.adfs.com/federationmetadata/2007-06/federationmetadata.xml': { - 'single_sign_on_service': { - saml2.BINDING_HTTP_REDIRECT: 'https://adfs-server.adfs.com/adfs/ls/idpinitiatedsignon.aspx', - }, - 'single_logout_service': { - saml2.BINDING_HTTP_REDIRECT: 'https://adfs-server.adfs.com/adfs/ls/?wa=wsignout1.0', - }, - }, - }, - }, - }, - - # where the remote metadata is stored - 'metadata': { - 'local': [path.join(CERTS_DIR, 'idp_federation_metadata.xml')], - }, - - # set to 1 to output debugging information - 'debug': 1, - - # Signing - 'key_file': '', - 'cert_file': path.join(CERTS_DIR, 'idp.crt'), # from IdP - - # Encryption - 'encryption_keypairs': [{ - 'key_file': path.join(CERTS_DIR, 'sp.key'), # private part - 'cert_file': path.join(CERTS_DIR, 'sp.crt'), # public part - }], - - 'valid_for': 24, # how long is our metadata valid -} - -``` - -**Note: Users running the Seafile program should have permission to read all files under **`seahub-data/certs`**.** - -## **Role Map for ADFS** - -Since Pro 7.0.9, you are able to set user role with ADFS as with [Shibboleth](https://download.seafile.com/published/seafile-manual/deploy/shibboleth_config.md#user-content-Affiliation%20and%20user%20role). Details about user role, please refer to [role permissions](https://download.seafile.com/published/seafile-manual/deploy_pro/roles_permissions.md). - -To enable this, add the following configuration information to `seahub_settings.py` to define the role mapping: - -``` -SHIBBOLETH_AFFILIATION_ROLE_MAP = { - 'role@lian-adfs.local': 'can_generate_upload_link_false', - 'role1@lian-adfs.local': 'guest', - 'patterns': ( - ('*@lian-adfs.local', 'guest1'), - ('*@*.local', 'guest2'), - ('*', 'guest3'), - ), -} - -``` - -## Config ADFS Server - -1. Add **Relying Party Trust** - - Relying Party Trust is the connection between Seafile and ADFS. - -1. Log into the ADFS server and open the ADFS management. -2. Double click **Trust Relationships**, then right click **Relying Party Trusts**, select **Add Relying Party Trust…**. -3. Select **Import data about the relying party published online or one a local network**, input `https://demo.seafile.com/saml2/metadata/` in the **Federation metadata address**. -4. Then **Next** until **Finish**. -5. Add **Relying Party Claim Rules** - - Relying Party Claim Rules is used for attribute communication between Seafile and users in Windows Domain. - - **Important**: Users in Windows domain must have the **E-mail** value setted. - -1. Right-click on the relying party trust and select **Edit Claim Rules...** -2. On the Issuance Transform Rules tab select **Add Rules...** -3. Select **Send LDAP Attribute as Claims** as the claim rule template to use. -4. Give the claim a name such as LDAP Attributes. -5. Set the Attribute Store to **Active Directory**, the LDAP Attribute to **E-Mail-Addresses**, and the Outgoing Claim Type to **E-mail Address**. -6. Select **Finish**. -7. Click **Add Rule...** again. -8. Select **Transform an Incoming Claim**. -9. Give it a name such as **Email to Name ID**. -10. Incoming claim type should be **E-mail Address** (it must match the Outgoing Claim Type in rule #1). -11. The Outgoing claim type is **Name ID** (this is required in Seafile settings policy `'name_id_format': saml2.saml.NAMEID_FORMAT_EMAILADDRESS`). -12. the Outgoing name ID format is **Email**. -13. **Pass through all claim values** and click **Finish**. - -## Test - -After re-starting the services, you may open a web browser and type in `https://demo.seafile.com`, there should be a `ADFS` button in login dialog, click that button will redirect you to the ADFS server (adfs-server.adfs.com), if username and password are correct, you will be redirect back to Seafile home page. - -For descktop client, simply click "Shibboleth Login" in "Add a new account" window, type in `https://demo.seafile.com`, click OK button will open a new window display ADFS server login page, if username and password are correct, the window will be closed and show Seafile libraries panel. - -* -* -* - - diff --git a/manual/deploy_pro/cas.md b/manual/deploy_pro/cas.md deleted file mode 100644 index 328a10c1e..000000000 --- a/manual/deploy_pro/cas.md +++ /dev/null @@ -1,35 +0,0 @@ -# Log In By CAS (Deprecated) - -> New in 2019: CAS is not recommend way for SSO. The third party Python library is not well maintained. SAML2 is much better. - -Since Seafile-pro 6.3.0, Seafile supports CAS single-sign-on protocol. - -NOTE: The support for CAS protocol is deprecated due to low maintenance of third-party library. Please use OAuth or SAML protocol. - -## Requirements - -Supposed you have a usable CAS service, and the service can be accessed by the `https://:/cas/`. - -## configure seahub_settings.py - -* Add the following lines in `conf/seahub_settings.py` - - -``` -ENABLE_CAS = True -CAS_SERVER_URL = 'https://192.168.99.100:8443/cas/' -CAS_LOGOUT_COMPLETELY = True -# Uncomment following line if CAS server is using self-signed certificate -#CAS_SERVER_CERT_VERIFY = False - -``` - -* Restart the seahub - - -``` -./seahub.sh restart - -``` - -Now, you can login to Seafile web interface with CAS authentication. Please click the "Single Sign-on" on the Seafile's login page. diff --git a/manual/upgrade/ce-7.0.md b/manual/upgrade/ce-7.0.md deleted file mode 100644 index 1b0e4a6c6..000000000 --- a/manual/upgrade/ce-7.0.md +++ /dev/null @@ -1,50 +0,0 @@ -# ce-7.0 - -## Common Problems - -### Not able to open Markdown file - -If after upgrading to 7.0, you are not able to open Markdown file and if your seahub.log containing the following error, it is caused by you forgot to migrate file comment when you upgrade to 6.3 version. - -![](./image-1558745192334.png) - - - -You can delete the table base_filecomment and recreate the table. - -``` -CREATE TABLE `base_filecomment` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `author` varchar(255) NOT NULL, - `comment` longtext NOT NULL, - `created_at` datetime NOT NULL, - `updated_at` datetime NOT NULL, - `uuid_id` char(32) NOT NULL, - `detail` longtext NOT NULL, - `resolved` tinyint(1) NOT NULL, - - PRIMARY KEY (`id`), - KEY `base_filecomment_uuid_id_4f9a2ca2_fk_tags_fileuuidmap_uuid` (`uuid_id`), - KEY `base_filecomment_author_8a4d7e91` (`author`), - KEY `base_filecomment_resolved_e0717eca` (`resolved`), - CONSTRAINT `base_filecomment_uuid_id_4f9a2ca2_fk_tags_fileuuidmap_uuid` FOREIGN KEY (`uuid_id`) REFERENCES `tags_fileuuidmap` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -``` - -If you are using SQLite, the corresponding SQL is: - -``` -CREATE TABLE "base_filecomment" ( -"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, - "author" varchar(255) NOT NULL, - "comment" text NOT NULL, -"created_at" datetime NOT NULL, -"updated_at" datetime NOT NULL, -"uuid_id" char(32) NOT NULL REFERENCES "tags_fileuuidmap" ("uuid"), -"detail" text NOT NULL, -"resolved" bool NOT NULL); - -``` - - diff --git a/manual/upgrade/pro-7.0.md b/manual/upgrade/pro-7.0.md deleted file mode 100644 index 10d010beb..000000000 --- a/manual/upgrade/pro-7.0.md +++ /dev/null @@ -1,289 +0,0 @@ -# Upgrade to Pro 7.0 - -Since seafile-pro 7.0.0, we have upgraded Elasticsearch to 5.6. As Elasticsearch 5.6 relies on the Java 8 environment and can't run with root, you need to run Seafile with a non-root user and upgrade the Java version. - -## Upgrade the Java version - -In order to upgrade from 6.3.x to 7.0.x, you may need to upgrade the JDK version. - -Run the following command to view the current Java version information: - -``` -java -version - -``` - -If the current JDK version is 1.7.0, then you need to upgrade to 1.8.0. To upgrade to openjdk-1.8.0, refer to the following command: - -``` -# For CentOS -yum install java-1.8.0-openjdk - -``` - -``` -# For Ubuntu -apt-get install openjdk-8-jre - -``` - ---- - -**In addition, if you previously ran Seafile with root, you would need to run Seafile with a non-root user in order to use search functionality after upgrading to 7.0.x. If Seafile is already running with a non-root user, you can do the upgrade directly.** - -## Switch user if you are using root to run Seafile - -It is recommended that you run Seafile with the `seafile` user. For specific operations, please refer to the following process: - -**Assume that the Seafile installation directory is:** `/opt/seafile` - -**Assume that the Seafile data storage path is:** `/opt/seafile/seafile-data` - -### Stop Seafile Service - -You need to stop the currently running seafile process first. - -``` -cd /opt/seafile/seafile-server-latest -./seafile.sh stop -./seahub.sh stop - -``` - -### Create seafile user - -Create a system account to run the Seafile service. The suggested user name is seafile: - -``` -useradd --system --comment "seafile" seafile --create-home --home-dir /home/seafile - -``` - -### Modify directory permissions - -Modify the owner and group of the Seafile installation directory and the Seafile data storage directory to seafile: - -``` -chown -R seafile.seafile /opt/seafile -chown -R seafile.seafile /opt/seafile/seafile-data -chown -R seafile.seafile /tmp/seafile-office-output - -``` - -### Start the service - -``` -su - seafile -cd /opt/seafile/seafile-server-latest -./seafile.sh start -./seahub.sh start - -``` - -### Modify the startup scripts - -**If you used the systemd manager to implement boot-up:** - -* You need to modify `/etc/systemd/system/seafile.service`: - - -``` -[Unit] -Description=Seafile Server -After=network.target mariadb.service - -[Service] -ExecStart=/opt/seafile/seafile-server-latest/seafile.sh start -ExecStop=/opt/seafile/seafile-server-latest/seafile.sh stop -User=seafile -Group=seafile -Type=oneshot -RemainAfterExit=yes - -[Install] -WantedBy=multi-user.target - -``` - -And `/etc/systemd/system/seahub.service`: - -``` -[Unit] -Description=Seafile Seahub -After=network.target seafile.service - -[Service] -ExecStart=/opt/seafile/seafile-server-latest/seahub.sh start -ExecStop=/opt/seafile/seafile-server-latest/seahub.sh stop -User=seafile -Group=seafile -Type=oneshot -RemainAfterExit=yes - -[Install] -WantedBy=multi-user.target - -``` - -Reload the systemd manager configuration: - -``` -systemctl daemon-reload - -``` - -**If you used the init script to implement boot-up:** - -You need to modify `/etc/init.d/seafile-server`: - -``` -#!/bin/bash -### BEGIN INIT INFO -# Provides: seafile-server -# Required-Start: $remote_fs $syslog mysql -# Required-Stop: $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Seafile server -# Description: Start Seafile server -### END INIT INFO - -# Author: Alexander Jackson - -# Change the value of "seafile_dir" to your path of seafile installation -user=seafile -seafile_dir=/opt/seafile -script_path=${seafile_dir}/seafile-server-latest -seafile_init_log=${seafile_dir}/logs/seafile.init.log -seahub_init_log=${seafile_dir}/logs/seahub.init.log - -case "$1" in - start) - sudo -u ${user} ${script_path}/seafile.sh $1 >> ${seafile_init_log} - sudo -u ${user} ${script_path}/seahub.sh $1 >> ${seahub_init_log} - ;; - restart) - sudo -u ${user} ${script_path}/seafile.sh $1 >> ${seafile_init_log} - sudo -u ${user} ${script_path}/seahub.sh $1 >> ${seahub_init_log} - ;; - stop) - sudo -u ${user} ${script_path}/seafile.sh $1 >> ${seafile_init_log} - sudo -u ${user} ${script_path}/seahub.sh $1 >> ${seahub_init_log} - ;; - *) - echo "Usage: /etc/init.d/seafile-server {start|stop|restart}" - exit 1 - ;; -esac - -``` - -### Upgrade Seafile - -Stop running the current seafile service: - -``` -su - seafile -cd /opt/seafile/seafile-server-latest -./seafile.sh stop -./seahub.sh stop - -``` - -Download the seafile-pro 7.0.x package and extract it to the Seafile installation directory `/opt/seafile`; then execute the upgrade script: - -``` -cd /opt/seafile/seafile-pro-server-7.0.x/upgrade/ -./upgrade_6.3_7.0.sh - -``` - -After the upgrade script is successfully executed, start the Seafile service: - -``` -cd /opt/seafile/seafile-server-latest -./seafile.sh start -./seahub.sh start - -``` - -## Features Modification - -### Encrypted libraries - -Note, to enable using new encrypted libraries with different salt for different libraries, you need to add the following configuration to seahub_setting.py - -``` -ENCRYPTED_LIBRARY_VERSION = 3 - -``` - -Currently the mobile clients and desktop clients does not supported new version of encrypted library yet. After we upgrade the clients, we will make the setting as default. - -### File history - -Recording file history to database for fast access is enabled by default for 'Markdown, .txt, ppt, pptx, doc, docx, xls, xlsx'. To disable the feature or to modified the file list, you can add the following settings to seafevents.conf - -``` -[FILE HISTORY] -enabled = false -suffix = md,txt,... - -``` - -After enable the feature, the old histories version for markdown, doc, docx files will not be list in the history page. (Only new histories that stored in database will be listed) But the users can still access the old versions in the library snapshots. - -For file types not listed in the `suffix` , histories version will be scanned from the library history as before. - -### File activities - -The file activities feature are redesigned. We use a new database table to record file activities. The old activities will not be displayed. - -### Wikis - -In version 6.3, users can create public or private Wikis. In version 7.0, private Wikis is replaced by column mode view. Every library has a column mode view. So users don't need to explicitly create private Wikis. - -Public Wikis are now renamed to published libraries. - -There are two role permissions that control whether a user can create public Wikis, share link permission and publish library permission. A user must have both the permissions to be able to use public Wikis. - -## Common Problems - -### Not able to open Markdown file - -If after upgrading to 7.0, you are not able to open Markdown file and if your seahub.log containing the following error, it is caused by you forgot to migrate file comment when you upgrade to 6.3 version. - -![](./image-1558745192334.png) - - - -You can delete the table base_filecomment and recreate the table. - -``` -CREATE TABLE `base_filecomment` ( - - `id` int(11) NOT NULL AUTO_INCREMENT, - `author` varchar(255) NOT NULL, - - `comment` longtext NOT NULL, - `created_at` datetime NOT NULL, - - `updated_at` datetime NOT NULL, - `uuid_id` char(32) NOT NULL, - - `detail` longtext NOT NULL, - `resolved` tinyint(1) NOT NULL, - - PRIMARY KEY (`id`), - KEY `base_filecomment_uuid_id_4f9a2ca2_fk_tags_fileuuidmap_uuid` (`uuid_id`), - - KEY `base_filecomment_author_8a4d7e91` (`author`), - - KEY `base_filecomment_resolved_e0717eca` (`resolved`), - - CONSTRAINT `base_filecomment_uuid_id_4f9a2ca2_fk_tags_fileuuidmap_uuid` FOREIGN KEY (`uuid_id`) REFERENCES `tags_fileuuidmap` (`uuid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -``` - - diff --git a/manual/upgrade/upgrade_with_mysql_or_postgresql.md b/manual/upgrade/upgrade_with_mysql_or_postgresql.md deleted file mode 100644 index 6be912d71..000000000 --- a/manual/upgrade/upgrade_with_mysql_or_postgresql.md +++ /dev/null @@ -1,167 +0,0 @@ -#Seafile -## Upgrade with MySQL or PostgreSQL - -First, download the new version, for example seafile-server_1.6.0_x86-64.tar.gz, and extract it to the directory where you put all Seafile related staff. You should have a directory layout similar to this: - -``` -haiwen - -- seafile-server-1.5.0 - -- seafile-server-1.6.0 - -- ccnet - -- seafile-data -``` - -## Major Continuous Upgrade (like from 1.5 to 1.6) - -Major continuous upgrade including upgrading from 1.5.0 to 1.6.0 or upgrading from 1.5.0 to 1.6.1. It involves four steps: - -1. Stop Seafile/Seahub -2. Update avatars folder and database tables -3. Update Nginx/Apache configs -4. Restart Seafile/Seahub - -### 2. Update avatars folder and database tables (After Seafile Server 2.1.1 for MySQL) - -Since seafile server 2.1.1, You can upgrade the the avatars folder and the databases using the upgrade scripts. The script's name is like `upgrade_X.X_Y.Y.sh`. For example, assume you are upgrading from seafile server 2.0.0 to seafile server 2.1.1, the you should run the `upgrade_2.0_2.1.sh` script. - -```sh -cd seafile-server-2.1.1/ -./upgrade/upgrade_2.0_2.1.sh -``` - -The script would update the avatars folder and the database tables for you. - -### 2. Update avatars folder and database tables (For PostgreSQL and before Seafile Server 2.1.1) - -Before Seafile Server 2.1.1 or if you are using PostgreSQL, you have to manually: - -- update the avatars folder symbolic link -- update and the database tables - -#### Update avatars symbolic link - -Assume your top level directory is `/data/haiwen/`, and you are upgrading to seafile server version 1.6.0: - -``` -cd /data/haiwen -cp -a seafile-server-1.6.0/seahub/media/avatars/* seahub-data/avatars/ -rm -rf seafile-server-1.6.0/seahub/media/avatars -#the new server avatars' folder will be linked to the updated avatars folder -ln -s -t seafile-server-1.6.0/seahub/media/ ../../../seahub-data/avatars/ -``` - -#### Update database tables - -When a new version of seafile server is released, there may be changes to the database of seafile/seahub/ccnet. We provide the sql statements to update the databases: - -- `upgrade/sql//mysql/seahub.sql`, for changes to seahub database -- `upgrade/sql//mysql/seafile.sql`, for changes to seafile database -- `upgrade/sql//mysql/ccnet.sql`, for changes to ccnet database - -To apply the changes, just execute the sqls in the correspondent database. If any of the sql files above do not exist, it means the new version does not bring changes to the correspondent database. - -```sh -seafile-server-1.6.0 -├── seafile -├── seahub -├── upgrade - ├── sql - ├── 1.6.0 - ├── mysql - ├── seahub.mysql - ├── seafile.mysql - ├── ccnet.mysql -``` - - -### 3. Update Nginx/Apache Config - -For Nginx: - -``` - location /media { - root /data/haiwen/seafile-server-1.6.0/seahub; - } -``` - -For Apache: - -``` -Alias /media /data/haiwen/seafile-server-1.6.0/seahub/media -``` - -**Tip:** -You can create a symbolic link `seafile-server-latest`, and make it point to your current seafile server folder (Since seafile server 2.1.0, the `setup-seafile.sh` script will do this for your). Then, each time you run a upgrade script, it would update the `seafile-server-latest` symbolic link to keep it always point to the latest version seafile server folder. - -In this case, you can write: - -``` - location /media { - root /data/haiwen/seafile-server-latest/seahub; - } -``` - -or For Apache: - -``` -Alias /media /data/haiwen/seafile-server-latest/seahub/media -``` - -This way, you no longer need to update the nginx/apache config file each time you upgrade your seafile server. - - -### 4. Restart Seafile/Seahub/Nginx/Apache - -After done above updating, now restart Seafile/Seahub/Nginx/Apache to see the new version at work! - -## Noncontinuous Upgrade (like from 1.1 to 1.3) - -You may also upgrade a few versions at once, e.g. from 1.1.0 to 1.3.0. -The procedure is: - -1. upgrade from 1.1.0 to 1.2.0; -2. upgrade from 1.2.0 to 1.3.0. - - -## Minor upgrade (like from 1.5.0 to 1.5.1) - -Minor upgrade is like an upgrade from 1.5.0 to 1.5.1. - -Here is our dir strutcutre - -``` -haiwen - -- seafile-server-1.5.0 - -- seafile-server-1.5.1 - -- ccnet - -- seafile-data -``` - -### Update the avatar link - -We provide a script for you, just run it: - -```sh -cd seafile-server-1.5.1 -upgrade/minor-upgrade.sh -``` - -### Update Nginx/Apache Config - -For Nginx: - -``` - location /media { - root /data/haiwen/seafile-server-1.5.1/seahub; - } -``` - -For Apache: - -``` -Alias /media /data/haiwen/seafile-server-1.5.1/seahub/media -``` - -### Restart Seafile/Seahub/Nginx/Apache - -After done above updating, now restart Seafile/Seahub/Nginx/Apache to see the new version at work! diff --git a/mkdocs.yml b/mkdocs.yml index 5911d52c1..7bb446119 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -99,9 +99,7 @@ nav: - Remote User Authentication: deploy/remote_user.md - Shibboleth Authentication: deploy/shibboleth_authentication.md - Auto Login to SeaDrive on Windows: deploy/auto_login_seadrive.md - - SAML 2.0 in version 10.0+ (Pro): deploy_pro/saml2_in_10.0.md - - SAML 2.0 (old) (Pro): deploy_pro/adfs.md - - CAS Authentication (Pro): deploy_pro/cas.md + - SAML 2.0 (Pro): deploy_pro/saml2_in_10.0.md - Switch authentication: deploy/auth_switch.md - Online Office: - LibreOffice Online Integration: deploy/libreoffice_online.md From 46f1a5d7abc683ca15fa709b19e3a6a2a9e59654 Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Mon, 14 Oct 2024 11:04:30 +0800 Subject: [PATCH 19/22] Delete outdated files --- .../common_problems_for_setting_up_server.md | 40 --- manual/deploy/using_sqlite.md | 248 ------------------ mkdocs.yml | 2 +- 3 files changed, 1 insertion(+), 289 deletions(-) delete mode 100644 manual/deploy/common_problems_for_setting_up_server.md delete mode 100644 manual/deploy/using_sqlite.md diff --git a/manual/deploy/common_problems_for_setting_up_server.md b/manual/deploy/common_problems_for_setting_up_server.md deleted file mode 100644 index 8582efcab..000000000 --- a/manual/deploy/common_problems_for_setting_up_server.md +++ /dev/null @@ -1,40 +0,0 @@ -# Common Problems for Setting up Server - - -#### Seafile fails to start: "failed to run "seaf-server -t" (Ubuntu 20.04) - -![image-20210713171856512](C:\Users\RDB\AppData\Roaming\Typora\typora-user-images\image-20210713171856512.png) - -The MySQL user seafile uses the mysql_native_password plugin to authenticate. The error message means that the user could not connect to the database. - -Connect to the database with the MySQL root user: - -``` -#mysql -u root -p -``` - -Then change the authentication plugin for the user seafile to mysql_native_password: - -```mysql -mysql> ALTER USER 'seafile'@'127.0.0.1' identified with mysql_native_password by 'PASSWORD'; -``` - -PASSWORD is the password of the MySQL user seafile. You can find this password in the log file seafile.conf in /opt/seafile/conf. - - -#### Failed to upload/download file online - -* Check your SERVICE_URL setting in ccnet.conf and FILE_SERVER_ROOT setting in seahub_settings.py -* Make sure you firewall for seafile fileserver is opened. -* Using chrome/firefox debug mode to find which link is given when click download button and what's wrong with this link - - -#### Seafile with Apache / HTTPS has text only (no CSS formatting / images) - -The media folder (Alias location identified in /etc/apache2/sites-enabled/000-default (Ubuntu) has inappropriate permissions - -Solutions: - -1. Run installation script as non-root user -2. Copy /media folder to var/www/ and edit the Alias location in /etc/apache2/sites-enabled/000-default - diff --git a/manual/deploy/using_sqlite.md b/manual/deploy/using_sqlite.md deleted file mode 100644 index c598e3504..000000000 --- a/manual/deploy/using_sqlite.md +++ /dev/null @@ -1,248 +0,0 @@ -# Deploying Seafile with SQLite - -> Deploying Seafile with SQLite is no longer supported since version 11.0 - -## Download binary package - -Visit our [download page](http://www.seafile.com/en/download/#server), download the latest server package. - -Choose one of: -- Generic Linux -- Server for Raspberry Pi - -Click the tarball link and save it. - -## Deploying and Directory Layout - -NOTE: If you place the Seafile data directory in external storage, such as NFS, CIFS mount, you should not use SQLite as the database, but use MySQL instead. - -Supposed you've downloaded seafile-server_8.0.* into your home directory. We suggest you to use the following layout for your deployment: -```sh -mkdir /opt/seafile -mv seafile-server_8.0.* /opt/seafile -cd /opt/seafile -tar -xzf seafile-server_8.0.* -``` - -Now you should have the following directory layout -```sh -root@5575983a9804:/opt/seafile# tree . -L 2 -. -|-- seafile-server-8.0.* -| |-- check_init_admin.py -| |-- reset-admin.sh -| |-- runtime -| |-- seaf-fsck.sh -| |-- seaf-fuse.sh -| |-- seaf-gc.sh -| |-- seafile -| |-- seafile.sh -| |-- seahub -| |-- seahub.sh -| |-- setup-seafile-mysql.py -| |-- setup-seafile-mysql.sh -| |-- setup-seafile.sh -| |-- sql -| `-- upgrade -`-- seafile-server_8.0.*_x86-64.tar.gz -``` - -Benefits of this layout are - - - We can place all the config files for Seafile server inside "/opt/seafile/conf" directory, making it easier to manage. - - When you upgrade to a new version of Seafile, you can simply untar the latest package into "/opt/seafile" directory. In this way you can reuse the existing config files in "/opt/seafile/conf" directory and don't need to configure again. - -## Setting Up Seafile Server - -#### Prerequisites - -The Seafile server package requires the following packages have been installed in your system - -``` -# on Ubuntu 20.04 server - -apt-get install -y python3 python3-setuptools python3-pip memcached libmemcached-dev pwgen sqlite3 - -pip3 install --timeout=3600 django==2.2.* future Pillow pylibmc captcha jinja2 psd-tools django-pylibmc django-simple-captcha pycryptodome==3.12.0 cffi==1.14.0 -``` - -``` -# on CentOS 8 server -yum install epel-release -y - -yum install python3 python3-setuptools python3-pip memcached libmemcached libffi-devel pwgen curl python3-devel gcc gcc-c++ sqlite -y - -pip3 install --timeout=3600 django==2.2.* future Pillow pylibmc jinja2 psd-tools django-pylibmc django-simple-captcha captcha pycryptodome==3.12.0 cffi==1.14.0 lxml -``` - -#### Setup - -```sh -cd /opt/seafile/seafile-server-8.0.* -./setup-seafile.sh #run the setup script & answer prompted questions -``` - -If some of the prerequisites are not installed, the Seafile initialization script will ask you to install them. - -The script will guide you through the settings of various configuration options. - -**Seafile configuration options** - -| Option | Description | Note | -| -- | -- | ---- | -| server name | Name of this Seafile server | 3-15 characters, only English letters, digits and underscore ('_') are allowed | -| server ip or domain | The IP address or domain name used by this server | Seafile client program will access the server with this address | -| Seafile data dir | Seafile stores your data in this directory. By default it'll be placed in the current directory. | The size of this directory will increase as you put more and more data into Seafile. Please select a disk partition with enough free space. | -| fileserver port | The TCP port used by Seafile fileserver | Default is 8082. If it's been used by other service, you can set it to another port. | - - -Now you should have the following directory layout: - -```sh -root@5575983a9804:/opt/seafile# tree . -L 2 -. -|-- ccnet -| |-- GroupMgr -| |-- OrgMgr -| |-- PeerMgr -| `-- misc -|-- conf -| |-- __pycache__ -| |-- ccnet.conf -| |-- gunicorn.conf.py -| |-- seafdav.conf -| |-- seafile.conf -| `-- seahub_settings.py -|-- logs -| |-- controller.log -| |-- seafile.log -| `-- seahub.log -|-- pids -| |-- seaf-server.pid -| `-- seahub.pid -|-- seafile-data -| |-- httptemp -| |-- library-template -| |-- seafile.db -| |-- storage -| `-- tmpfiles -|-- seafile-server-8.0.5 -| |-- check_init_admin.py -| |-- reset-admin.sh -| |-- runtime -| |-- seaf-fsck.sh -| |-- seaf-fuse.sh -| |-- seaf-gc.sh -| |-- seafile -| |-- seafile.sh -| |-- seahub -| |-- seahub.sh -| |-- setup-seafile-mysql.py -| |-- setup-seafile-mysql.sh -| |-- setup-seafile.sh -| |-- sql -| `-- upgrade -|-- seafile-server-latest -> seafile-server-8.0.5 -|-- seafile-server_8.0.5_x86-64.tar.gz -|-- seahub-data -| `-- avatars -`-- seahub.db -``` - -The folder seafile-server-latest is a symbolic link to the current Seafile server folder. When later you upgrade to a new version, the upgrade scripts would update this link to keep it always point to the latest Seafile server folder. - -## Running Seafile Server - -#### Before Running - -Since Seafile uses persistent connections between client and server, you should increase Linux file descriptors by ulimit if you have a large number of clients before start Seafile, like: - -``ulimit -n 30000`` - -#### Starting Seafile Server and Seahub Website - -- Start Seafile: -``` -./seafile.sh start # Start Seafile service -``` - -- Start Seahub: -``` -./seahub.sh start # Start Seahub website, port defaults to 8000 -``` - -**Note**: The first time you start Seahub, the script is going to prompt you to create an admin account for your Seafile server. - -After starting the services, you may open a web browser and type in - -``http://192.168.1.111:8000`` - -you will be redirected to the Login page. Just enter the admin username and password. - -**Congratulations!** Now you have successfully setup your private Seafile server. - -#### Run Seahub on another port - -You can assign the port of Seahub by setting the `conf/gunicorn.conf`. - -- stop the Seafile server -``` -./seahub.sh stop -./seafile.sh stop -``` - -- modify the value of SERVICE_URL in the file ccnet.conf (or seahub_settings.py if you use 9.0.0+ version), like this: (assume your ip or domain is 192.168.1.100). You can also modify SERVICE_URL via web UI in "System Admin->Settings". (**Warning**: if you set the value both via Web UI and ccnet.conf, the setting via Web UI will take precedence.) - -``` -SERVICE_URL = http://192.168.1.100:8001 -``` - -- **modify the conf/gunicorn.conf** - -``` -# default localhost:8000 -bind = "0.0.0.0:8001" -``` - -- restart Seafile server -``` -./seafile.sh start -./seahub.sh start -``` - -See Seafile [Server Configuration Manual](../config/ccnet-conf.md) for more details about ``ccnet.conf``. - -## Manage Seafile and Seahub -#### Stopping -``` -./seahub.sh stop # stop seahub website -./seafile.sh stop # stop seafile processes -``` -#### Restarting -``` -./seafile.sh restart -./seahub.sh restart -``` -#### When the Scripts Fail - -Most of the time, `seafile.sh` and `seahub.sh` work fine. But if they fail, you might want to - -- Use pgrep command to check if Seafile/Seahub processes are still running -``` -pgrep -f seafile-controller # check Seafile processes -pgrep -f "seahub" # check Seahub process -``` - -- Use pkill to kill the processes -``` -pkill -f seafile-controller -pkill -f "seahub" -``` - - -## That's it! - -For a production server we highly recommend to setup with Nginx/Apache and enable SSL/TLS. - -That's it! Now you might want read more about Seafile. -- [Administration](../maintain/README.md) diff --git a/mkdocs.yml b/mkdocs.yml index 7bb446119..d7021ee3c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -7,7 +7,7 @@ repo_name: haiwen/seafile-admin-docs repo_url: https://github.com/haiwen/seafile-admin-docs/ edit_uri: blob/master/manual -copyright: Copyright © 2023 Seafile Ltd. +copyright: Copyright © 2024 Seafile Ltd. theme: name: material From c3844c097410645e6459a0059423382c10c249cd Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Mon, 14 Oct 2024 11:12:35 +0800 Subject: [PATCH 20/22] Remove outdated files --- manual/deploy/using_ldap.md | 137 ---------- manual/deploy_pro/ldap_group_sync.md | 158 ------------ manual/deploy_pro/ldap_role_sync.md | 47 ---- manual/deploy_pro/using_ldap_pro.md | 368 --------------------------- mkdocs.yml | 8 +- 5 files changed, 2 insertions(+), 716 deletions(-) delete mode 100644 manual/deploy/using_ldap.md delete mode 100644 manual/deploy_pro/ldap_group_sync.md delete mode 100644 manual/deploy_pro/ldap_role_sync.md delete mode 100644 manual/deploy_pro/using_ldap_pro.md diff --git a/manual/deploy/using_ldap.md b/manual/deploy/using_ldap.md deleted file mode 100644 index df5934954..000000000 --- a/manual/deploy/using_ldap.md +++ /dev/null @@ -1,137 +0,0 @@ -# Configure Seafile to use LDAP - -Note: This documentation is for the Community Edition. If you're using Pro Edition, please refer to [the Seafile Pro documentation](../deploy_pro/using_ldap_pro.md). - - For version 11.0, please follow the new document [LDAP in version 11.0](./ldap_in_11.0.md). - -## How does LDAP User Management work in Seafile - -When Seafile is integrated with LDAP/AD, users in the system can be divided into two tiers: - -- Users within Seafile's internal user database. Some attributes are attached to these users, such as whether it's a system admin user, whether it's activated. This tier includes two types of users: - * Native users: these users are created by the admin on Seafile's system admin interface. These users are stored in the `EmailUser` table of the `ccnet` database. - * Users imported from LDAP/AD server: When a user in LDAP/AD logs into Seafile, its information will be imported from LDAP/AD server into Seafile's database. These users are stored in the `LDAPUsers` table of the `ccnet` database. -- Users in LDAP/AD server. These are all the intended users of Seafile inside the LDAP server. Seafile doesn't manipulate these users directly. It has to import them into its internal database before setting attributes on them. - -When Seafile counts the number of users in the system, it only counts the **activated** users in its internal database. - -When Seafile is integrated with LDAP/AD, it'll look up users from both the internal database and LDAP server. As long as the user exists in one of these two sources, they can log into the system. - -## Basic LDAP/AD Integration - -The only requirement for Seafile to use LDAP/AD for authentication is that there must be a unique identifier for each user in the LDAP/AD server. Seafile can only use email-address-format user identifiers. So there are usually only two options for this unique identifier: - -- Email address: this is the most common choice. Most organizations assign unique email address for each member. -- UserPrincipalName: this is a user attribute only available in Active Directory. It's format is `user-login-name@domain-name`, e.g. `john@example.com`. It's not a real email address, but it works fine as the unique identifier. - -### Connecting to Active Directory - -To use AD to authenticate user, please add the following lines to ccnet.conf. - -If you choose email address as unique identifier: - - [LDAP] - HOST = ldap://192.168.1.123/ - BASE = cn=users,dc=example,dc=com - USER_DN = administrator@example.local - PASSWORD = secret - LOGIN_ATTR = mail - -If you choose UserPrincipalName as unique identifier: - - [LDAP] - HOST = ldap://192.168.1.123/ - BASE = cn=users,dc=example,dc=com - USER_DN = administrator@example.local - PASSWORD = secret - LOGIN_ATTR = userPrincipalName - -Meaning of each config options: - -* HOST: LDAP URL for the host. ldap://, ldaps:// and ldapi:// are supported. You can also include a port number in the URL, like ldap://ldap.example.com:389. To use TLS, you should configure the LDAP server to listen on LDAPS port and specify ldaps:// here. More details about TLS will be covered below. -* BASE: The root distinguished name (DN) to use when running queries against the directory server. **You cannot use the root DN (e.g. dc=example,dc=com) as BASE**. -* USER_DN: The distinguished name of the user that Seafile will use when connecting to the directory server. This user should have sufficient privilege to access all the nodes under BASE. It's recommended to use a user in the administrator group. -* PASSWORD: Password of the above user. -* LOGIN_ATTR: The attribute used for user's unique identifier. Use `mail` or `userPrincipalName`. - -Tips for choosing BASE and USER_DN: - -* To determine the BASE, you first have to navigate your organization hierachy on the domain controller GUI. - * If you want to allow all users to use Seafile, you can use 'cn=users,dc=yourdomain,dc=com' as BASE (with proper adjustment for your own needs). - * If you want to limit users to a certain OU (Organization Unit), you run `dsquery` command on the domain controller to find out the DN for this OU. For example, if the OU is 'staffs', you can run 'dsquery ou -name staff'. More information can be found [here](https://technet.microsoft.com/en-us/library/cc770509.aspx). -* AD supports 'user@domain.name' format for the USER_DN option. For example you can use administrator@example.com for USER_DN. Sometime the domain controller doesn't recognize this format. You can still use `dsquery` command to find out user's DN. For example, if the user name is 'seafileuser', run `dsquery user -name seafileuser`. More information [here](https://technet.microsoft.com/en-us/library/cc725702.aspx). - -### Connecting to other LDAP servers - -Please add the following options to ccnet.conf: - - [LDAP] - HOST = ldap://192.168.1.123/ - BASE = ou=users,dc=example,dc=com - USER_DN = cn=admin,dc=example,dc=com - PASSWORD = secret - LOGIN_ATTR = mail - -The meaning of the options are the same as described in the previous section. With other LDAP servers, you can only use `mail` attribute as user's unique identifier. - -## Advanced LDAP/AD Integration Options - -### Multiple BASE - -Multiple base DN is useful when your company has more than one OUs to use Seafile. You can specify a list of base DN in the "BASE" config. The DNs are separated by ";", e.g. `ou=developers,dc=example,dc=com;ou=marketing,dc=example,dc=com` - -### Additional Search Filter - -Search filter is very useful when you have a large organization but only a portion of people want to use Seafile. The filter can be given by setting "FILTER" config. The value of this option follows standard LDAP search filter syntax (https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx). - -The final filter used for searching for users is `(&($LOGIN_ATTR=*)($FILTER))`. `$LOGIN_ATTR` and `$FILTER` will be replaced by your option values. - -For example, add the following line to LDAP config: - -``` -FILTER = memberOf=CN=group,CN=developers,DC=example,DC=com -``` - -The final search filter would be `(&(mail=*)(memberOf=CN=group,CN=developers,DC=example,DC=com))` - -Note that the case of attribute names in the above example is significant. The `memberOf` attribute is only available in Active Directory. - -### Limiting Seafile Users to a Group in Active Directory - -You can use the FILTER option to limit user scope to a certain AD group. - -1. First, you should find out the DN for the group. Again, we'll use the `dsquery` command on the domain controller. For example, if group name is 'seafilegroup', run `dsquery group -name seafilegroup`. -2. Add the following line to LDAP config: - -``` -FILTER = memberOf={output of dsquery command} -``` - -### Using TLS connection to LDAP/AD server - -To use a TLS connection to the directory server, you should install a valid SSL certificate on the directory server. - -The current version of Seafile Linux server package is compiled on CentOS. We include the ldap client library in the package to maintain compatibility with older Linux distributions. But since different Linux distributions have different path or configuration for OpenSSL library, sometimes Seafile is unable to connect to the directory server with TLS. - -The ldap library (libldap) bundled in the Seafile package is of version 2.4. If your Linux distribution is new enough (like CentOS 6, Debian 7 or Ubuntu 12.04 or above), you can use system's libldap instead. - -On Ubuntu 14.04 and Debian 7/8, moving the bundled ldap related libraries out of the library path should make TLS connection work. - -``` -cd ${SEAFILE_INSTALLATION_DIR}/seafile-server-latest/seafile/lib -mkdir disabled_libs_use_local_ones_instead -mv liblber-2.4.so.2 libldap-2.4.so.2 libsasl2.so.2 libldap_r-2.4.so.2 disabled_libs_use_local_ones_instead/ -``` - -On CentOS 6, you have to move the libnssutil library: - -``` -cd ${SEAFILE_INSTALLATION_DIR}/seafile-server-latest/seafile/lib -mkdir disabled_libs_use_local_ones_instead -mv libnssutil3.so disabled_libs_use_local_ones_instead/ -``` - -This effectively removes the bundled libraries from the library search path. -When the server starts, it'll instead find and use the system libraries (if they are installed). -This change has to be repeated after each update of the Seafile installation. - diff --git a/manual/deploy_pro/ldap_group_sync.md b/manual/deploy_pro/ldap_group_sync.md deleted file mode 100644 index 39166347e..000000000 --- a/manual/deploy_pro/ldap_group_sync.md +++ /dev/null @@ -1,158 +0,0 @@ -# Importing Groups from LDAP/AD - -Since version 4.1.0, the Pro Edition supports importing (syncing) groups from LDAP or Active Directory. - -For version 11.0, please follow the new document [LDAP in version 11.0](./ldap_in_11.0.md#setting-up-ldap-group-sync-optional). - -## How It Works - -The importing or syncing process maps groups from LDAP directory server to groups in Seafile's internal database. This process is one-way. - -* Any changes to groups in the database won't propagate back to LDAP; -* Any changes to groups in the database, except for "setting a member as group admin", will be overwritten in the next LDAP sync operation. If you want to add or delete members, you can only do that on LDAP server. -* The creator of imported groups will be set to the system admin. - -There are two modes of operation: - -* Periodical: the syncing process will be executed in a fixed interval -* Manual: there is a script you can run to trigger the syncing once - -## Prerequisite - -You have to install python-ldap library in your system. - -For Debian or Ubuntu - -``` -sudo apt-get install python-ldap - -``` - -For CentOS or RedHat - -``` -sudo yum install python-ldap - -``` - -## Syncing Groups - -### Configuration - -Before enabling LDAP group sync, you should have configured LDAP authentication. See [Configure Seafile to use LDAP](using_ldap_pro.md) for details. - -The following are LDAP group sync related options. They're in the "\[ldap_sync]" section of [ccnet.conf](../config/ccnet-conf.md). - -Below are summary of options for syncing groups: - -* **ENABLE_GROUP_SYNC**: set to "true" if you want to enable ldap group syncing -* **GROUP_OBJECT_CLASS**: This is the name of the class used to search for group objects. In Active Directory, it's usually "group"; in OpenLDAP or others, you may use "groupOfNames","groupOfUniqueNames" or "posixGroup", depends on your LDAP server. The default value is "group". -* **SYNC_INTERVAL**: The interval to sync. Unit is minutes. You can set it to 60, which means that data is synchronized from the LDAP/AD server every 60 minutes. -* **GROUP_FILTER**: An additional filter to use when searching group objects. If it's set, the final filter used to run search is "(&(objectClass=GROUP_OBJECT_CLASS)(GROUP_FILTER))"; otherwise the final filter would be "(objectClass=GROUP_OBJECT_CLASS)". -* **GROUP_MEMBER_ATTR**: The attribute field to use when loading the group's members. For most directory servers, the attributes is "member", which is the default value.For "posixGroup", it should be set to "memberUid". -* **USER_ATTR_IN_MEMBERUID**: The user attribute set in 'memberUid' option, which is used in "posixGroup".The default value is "uid". -* **DEL_GROUP_IF_NOT_FOUND**: set to "true", will deleted the groups if not found it in LDAP/AD server; need Seafile-pro-6.3.0 and above version -* **SYNC_GROUP_AS_DEPARTMENT**: In 6.3.8 version, a new option SYNC_GROUP_AS_DEPARTMENT is added. If this option is set to "true", the groups will be synced as top-level departments in Seafile, instead of simple groups. Learn more about departments in Seafile [here](https://help.seafile.com/sharing_collaboration/departments/). -* **CREATE_DEPARTMENT_LIBRARY**: If you decide to sync the group as a department, you can set this option to "true". In this way, when the group is synchronized for the first time, a library is automatically created for the department, and the library's name is the department's name. -* **DEFAULT_DEPARTMENT_QUOTA**: If you decide to sync the group as a department, you can set a default space quota for each department when you synchronize a group for the first time. The quota is set to unlimited if this option is not set. Unit is MB. -* **DEPT_NAME_ATTR**: Get the department name. You can set this configuration item to an AD field that represents the "department" name, such as "description". The name of the department created by Seafile will be the department name set in the AD field instead of the OU name. Requires Seafile-pro-7.0.11 and above. -* **DEPT_REPO_PERM**: Set the permissions of the department repo. The default permission is 'rw'. Set permissions for the department repo created during AD synchronization. Requires Seafile-pro-7.0.11 and above. -* **USE_GROUP_MEMBER_RANGE_QUERY**: When a group contains too many members, AD will only return part of them. Set this option to TRUE to make LDAP sync work with large groups. -* **GROUP_UUID_ATTR**: Since Seafile pro 8.0, UUID is used to identify groups in LDAP/AD servers. Before that, group DN is used. So when a group changes name, the old group will be deleted and a new group will be created. This is not a desirable behavior. With the new mechanism, the rename can be detected and the groups in Seafile remains intact. The default attribute is "ObjectGUID", which is available in AD. For other LDAP servers, please refer to https://ldapwiki.com/wiki/Universally%20Unique%20Identifier . - -The search base for groups is the "BASE_DN" set in "\[ldap]" section of ccnet.conf. - -Some LDAP server, such as Active Directory, allows a group to be a member of another group. This is called "group nesting". If we find a nested group B in group A, we should recursively add all the members from group B into group A. And group B should still be imported a separate group. That is, all members of group B are also members in group A. - -In some LDAP server, such as OpenLDAP, it's common practice to use Posix groups to store group membership. To import Posix groups as Seafile groups, set GROUP_OBJECT_CLASS option to posixGroup . A posixGroup object in LDAP usually contains a multi-value attribute for the list of member UIDs. The name of this attribute can be set with the GROUP_MEMBER_ATTR option. It's MemberUid by default. The value of the MemberUid attribute is an ID that can be used to identify a user, which corresponds to an attribute in the user object. The name of this ID attribute is usually uid , but can be set via the USER_ATTR_IN_MEMBERUID option. Note that posixGroup doesn't support nested groups. - -### Example Configurations - -Here is an example configuration for syncing nested groups in Active Directory: - -``` -[LDAP] -HOST = ldap://192.168.1.123/ -BASE = cn=users,dc=example,dc=com -USER_DN = administrator@example.local -PASSWORD = secret -LOGIN_ATTR = mail - -[LDAP_SYNC] -ENABLE_GROUP_SYNC = true -SYNC_INTERVAL = 60 - -``` - -For AD, you usually don't need to configure other options except for "ENABLE_GROUP_SYNC". That's because the default values for other options are the usual values for AD. If you have special settings in your LDAP server, just set the corresponding options. - -Here is an example configuration for syncing nested groups (but not PosixGroups) in OpenLDAP: - -``` -[LDAP] -HOST = ldap://192.168.1.123/ -BASE = ou=users,dc=example,dc=com -USER_DN = cn=admin,dc=example,dc=com -PASSWORD = secret -LOGIN_ATTR = mail - -[LDAP_SYNC] -ENABLE_GROUP_SYNC = true -SYNC_INTERVAL = 60 -GROUP_OBJECT_CLASS = groupOfNames - -``` - -## Sync OU as Departments - -A department in Seafile is a special group. In addition to what you can do with a group, there are two key new features for departments: - -* Department supports hierarchy. A department can have any levels of sub-departments. -* Department can have storage quota. - -Seafile supports syncing OU (Organizational Units) from AD/LDAP to departments. The sync process keeps the hierarchical structure of the OUs. - -Options for syncing departments from OU: - -* **SYNC_DEPARTMENT_FROM_OU**: set to "true" to enable syncing departments from OU. -* **SYNC_INTERVAL**: The interval to sync. Unit is minutes. You can set it to 60, which means that data is synchronized from the LDAP/AD server every 60 minutes. -* **DEL_DEPARTMENT_IF_NOT_FOUND**: If set to "true", sync process will delete a department if the corresponding OU is not found in AD/LDAP server. -* **CREATE_DEPARTMENT_LIBRARY**: set to "true", if you want to automatically create a department library with the OU name. -* **DEFAULT_DEPARTMENT_QUOTA**: default quota for the imported departments in MB. The quota is set to unlimited if this option is not set. -* **DEPT_NAME_ATTR**: Get the department name. You can set this configuration item to an AD field that represents the "department" name, such as "description". The name of the department created by Seafile will be the department name set in the AD field instead of the OU name. Requires Seafile-pro-7.0.11 and above. -* **DEPT_REPO_PERM**: Set the permissions of the department repo. The default permission is 'rw'. Set permissions for the department repo created during AD synchronization. Requires Seafile-pro-7.0.11 and above. -* **GROUP_UUID_ATTR**: Since Seafile pro 8.0, UUID is used to identify groups in LDAP/AD servers. Before that, OU DN is used. So when an OU changes name, the old group will be deleted and a new group will be created. This is not a desirable behavior. With the new mechanism, the rename can be detected and the groups in Seafile remains intact. The default attribute is "ObjectGUID", which is available in AD. For other LDAP servers, please refer to https://ldapwiki.com/wiki/Universally%20Unique%20Identifier . - -**NOTE**: Before 6.3.8, an old configuration syntax is used for syncing OU as departments. That syntax is no long supported. The old syntax cannot support syncing both groups and OU from AD/LDAP at the same time. However this is necessary for many situations. With the new syntax, you can sync both. - -## Periodical and Manual Sync - -Periodical sync won't happen immediately after you restart seafile server. It gets scheduled after the first sync interval. For example if you set sync interval to 30 minutes, the first auto sync will happen after 30 minutes you restarts. To sync immediately, you need to manually trigger it. - -After the sync is run, you should see log messages like the following in logs/seafevents.log. And you should be able to see the groups in system admin page. - -``` -[2015-03-30 18:15:05,109] [DEBUG] create group 1, and add dn pair CN=DnsUpdateProxy,CN=Users,DC=Seafile,DC=local<->1 success. -[2015-03-30 18:15:05,145] [DEBUG] create group 2, and add dn pair CN=Domain Computers,CN=Users,DC=Seafile,DC=local<->2 success. -[2015-03-30 18:15:05,154] [DEBUG] create group 3, and add dn pair CN=Domain Users,CN=Users,DC=Seafile,DC=local<->3 success. -[2015-03-30 18:15:05,164] [DEBUG] create group 4, and add dn pair CN=Domain Admins,CN=Users,DC=Seafile,DC=local<->4 success. -[2015-03-30 18:15:05,176] [DEBUG] create group 5, and add dn pair CN=RAS and IAS Servers,CN=Users,DC=Seafile,DC=local<->5 success. -[2015-03-30 18:15:05,186] [DEBUG] create group 6, and add dn pair CN=Enterprise Admins,CN=Users,DC=Seafile,DC=local<->6 success. -[2015-03-30 18:15:05,197] [DEBUG] create group 7, and add dn pair CN=dev,CN=Users,DC=Seafile,DC=local<->7 success. - -``` - -To trigger LDAP sync manually, - -```sh -cd seafile-server-latest -./pro/pro.py ldapsync - -``` - -For Seafile Docker - -```sh -docker exec -it seafile /opt/seafile/seafile-server-latest/pro/pro.py ldapsync - -``` diff --git a/manual/deploy_pro/ldap_role_sync.md b/manual/deploy_pro/ldap_role_sync.md deleted file mode 100644 index 6f33fe63e..000000000 --- a/manual/deploy_pro/ldap_role_sync.md +++ /dev/null @@ -1,47 +0,0 @@ -# Importing Roles from LDAP/AD - -For version 11.0, please follow the new document [LDAP in version 11.0](./ldap_in_11.0.md#importing-roles-from-ldap). - -Since version 6.1.5, the Pro Edition supports syncing roles from LDAP or Active Directory. - -To enable this feature, add config option `ROLE_NAME_ATTR` to ccnet.conf - -``` -[LDAP_SYNC] -ROLE_NAME_ATTR = title - -``` - -`ROLE_NAME_ATTR` is the attribute field to configure roles in LDAP . -We provide a user-defined function to map the role:Create `custom_functions.py` under conf/ and edit it like: - -``` -#coding=utf-8 -import sys -reload(sys) -sys.setdefaultencoding('utf8') - -def ldap_role_mapping(role): - if 'staff' in role: - return 'Staff' - if 'guest' in role: - return 'Guest' - if 'manager' in role: - return 'Manager' - -``` - -you can rewrite this function (in python) to make your own mapping rules. If the file or function doesn't exist, all roles in `ROLE_NAME_ATTR` will be synced. - -** NOTE: **Make sure that ccnet-server keeps running while doing LDAP role sync. - -Note: If you are using 7.1 version or later, and with Python 3, you should remove the following code from \`custom_functions.py\`: - -``` -import sys -reload(sys) -sys.setdefaultencoding('utf8') - -``` - - diff --git a/manual/deploy_pro/using_ldap_pro.md b/manual/deploy_pro/using_ldap_pro.md deleted file mode 100644 index a3d2c9f60..000000000 --- a/manual/deploy_pro/using_ldap_pro.md +++ /dev/null @@ -1,368 +0,0 @@ -# Configure Seafile Pro Edition to use LDAP - -For version 11.0, please follow the new document [LDAP in version 11.0](./ldap_in_11.0.md). - -## How does LDAP User Management works with Seafile - -When Seafile is integrated with LDAP/AD, users in the system can be divided into two tiers: - -* Users within Seafile's internal user database. Some attributes are attached to these users, such as whether it's a system admin user, whether it's activated. This tier includes two types of users: - * Native users: these users are created by the admin on Seafile's system admin interface and are stored in the `EmailUser` table of the `ccnet` database. - * Users imported from LDAP/AD server: When a user in LDAP/AD logs into Seafile, its information will be imported from LDAP/AD server into Seafile's database. These users are stored in the `LDAPUsers` table of the `ccnet` database. -* Users in LDAP/AD server. These are all the intended users of Seafile inside the LDAP server. Seafile doesn't manipulate these users directly. It has to import them into its internal database before setting attributes on them. - -When Seafile counts the user number in the system, it only counts the **activated** users in its internal database. - -When Seafile is integrated with LDAP/AD, it'll look up users from both the internal database and LDAP server. As long as the user exists in one of these two sources, he/she can log into the system. - -## Basic LDAP/AD Integration - -The only requirement for Seafile to use LDAP/AD for authentication is that there must be a unique identifier for each user in the LDAP/AD server. Seafile can only use email-address-format user identifiers. So there are usually only two options for this unique identifier: - -* Email address: this is the most common choice. Most organizations assign a unique email address for each member. -* UserPrincipalName: this is a user attribute only available in Active Directory. It's format is `user-login-name@domain-name`, e.g. `john@example.com`. It's not a real email address, but it works fine as the unique identifier. - -### Connecting to Active Directory - -To use AD to authenticate a user, please add the following lines to ccnet.conf. - -If you choose email address as unique identifier: - -``` -[LDAP] -HOST = ldap://192.168.1.123/ -BASE = cn=users,dc=example,dc=com -USER_DN = administrator@example.local -PASSWORD = secret -LOGIN_ATTR = mail - -``` - -If you choose UserPrincipalName as unique identifier: - -``` -[LDAP] -HOST = ldap://192.168.1.123/ -BASE = cn=users,dc=example,dc=com -USER_DN = administrator@example.local -PASSWORD = secret -LOGIN_ATTR = userPrincipalName - -``` - -Meaning of each config options: - -* HOST: LDAP URL for the host. ldap://, ldaps:// and ldapi:// are supported. You can also include port number in the URL, like ldap://ldap.example.com:389. To use TLS, you should configure the LDAP server to listen on LDAPS port and specify ldaps:// here. More details about TLS are covered below. -* BASE: The distinguished name (DN) of the search base when running queries against the directory server. If you want to use the root DN as search base (e.g. dc=example,dc=com), you need to add `FOLLOW_REFERRALS = false` to the configuration. The meaning of this option will be explained in following sections. -* USER_DN: The distinguished name of the user that Seafile will use when connecting to the directory server. This user should have sufficient privileges to access all the nodes under BASE. It's recommended to use a user in the administrator group. -* PASSWORD: Password of the above user. -* LOGIN_ATTR: The attribute used for user's unique identifier. Use `mail` or `userPrincipalName`. - -Tips for choosing BASE and USER_DN: - -* To determine the BASE, you first have to navigate your organization hierachy on the domain controller GUI. - * If you want to allow all users to use Seafile, you can use 'cn=users,dc=yourdomain,dc=com' as BASE (with proper adjustment for your own needs). - * If you want to limit users to a certain OU (Organization Unit), you run `dsquery` command on the domain controller to find out the DN for this OU. For example, if the OU is 'staffs', you can run 'dsquery ou -name staff'. More information can be found [here](https://technet.microsoft.com/en-us/library/cc770509.aspx). -* AD supports 'user@domain.name' format for the USER_DN option. For example you can use administrator@example.com for USER_DN. Sometimes the domain controller doesn't recognize this format. You can still use `dsquery` command to find out user's DN. For example, if the user name is 'seafileuser', run `dsquery user -name seafileuser`. More information [here](https://technet.microsoft.com/en-us/library/cc725702.aspx). - -### Connecting to other LDAP servers - -Please add the following options to ccnet.conf: - -``` -[LDAP] -HOST = ldap://192.168.1.123/ -BASE = ou=users,dc=example,dc=com -USER_DN = cn=admin,dc=example,dc=com -PASSWORD = secret -LOGIN_ATTR = mail - -``` - -The meaning of these options is the same as described in the previous section. With other LDAP servers, you can only use `mail` attribute as user's unique identifier. - -### Testing your LDAP Configuration - -Since 5.0.0 Pro Edition, we provide a command line tool for checking your LDAP configuration. - -To use this tool, make sure you have `python-ldap` package installed on your system. - -``` -sudo apt-get install python-ldap - -``` - -Then you can run the test: - -``` -cd seafile-server-latest -./pro/pro.py ldapsync --test - -``` - -The test script checks your LDAP settings under the `[LDAP]` section of ccnet.conf. If everything works, it'll print the first ten users of the search results. Otherwise, it'll print out possible errors in your config. - -## Setting Up LDAP/AD User Sync (optional) - -In Seafile Pro, except for importing users into internal database when they log in, you can also configure Seafile to periodically sync user information from LDAP/AD server into the internal database. - -* User's full name, department and contact email address can be synced to internal database. Users can use this information to more easily search for a specific user. -* User's Windows or Unix login id can be synced to the internal database. This allows the user to log in with its familiar login id. -* When a user is removed from LDAP/AD, the corresponding user in Seafile will be deactivated. Otherwise, he could still sync files with Seafile client or access the web interface. - -After synchronization is complete, you can see the user's full name, department and contact email on its profile page. - -### Active Directory - -If you're using Active Directory, add the following options to ccnet.conf: - -``` -[LDAP] -...... - -[LDAP_SYNC] -ENABLE_USER_SYNC = true -DEACTIVE_USER_IF_NOTFOUND = true -SYNC_INTERVAL = 60 -USER_OBJECT_CLASS = person -ENABLE_EXTRA_USER_INFO_SYNC = true -FIRST_NAME_ATTR = givenName -LAST_NAME_ATTR = sn -UID_ATTR = sAMAccountName - -``` - -Meaning of each options: - -* **ENABLE_USER_SYNC**: set to "true" if you want to enable ldap user synchronization -* **DEACTIVE_USER_IF_NOTFOUND**: set to "true" if you want to deactivate a user when he/she was deleted in AD server. -* **SYNC_INTERVAL**: The interval to sync. Unit is minutes. Defaults to 60 minutes. -* **USER_OBJECT_CLASS**: This is the name of the class used to search for user objects. In Active Directory, it's usually "person". The default value is "person". -* **ENABLE_EXTRA_USER_INFO_SYNC**: Enable synchronization of additional user information, including user's full name, department, and Windows login name, etc. -* **FIRST_NAME_ATTR**: Attribute for user's first name. It's "givenName" by default. -* **LAST_NAME_ATTR**: Attribute for user's last name. It's "sn" by default. -* **USER_NAME_REVERSE**: In some languages, such as Chinese, the display order of the first and last name is reversed. Set this option if you need it. -* **UID_ATTR**: Attribute for Windows login name. If this is synchronized, users can also log in with their Windows login name. In AD, the attribute `sAMAccountName` can be used as `UID_ATTR`. - -If you choose `userPrincipalName` as the unique identifier for user, Seafile cannot use it as real email address to send notification emails to user. If the users in AD also have an email address attribute, you can sync these email addresses into Seafile's internal database. Seafile can then use them to send emails. The configuration option is: - -* **CONTACT_EMAIL_ATTR**: usually you can set it to the `mail` attribute. - -### Other LDAP servers - -Add the following options to ccnet.conf: - -``` -[LDAP] -...... - -[LDAP_SYNC] -ENABLE_USER_SYNC = true -DEACTIVE_USER_IF_NOTFOUND = true -SYNC_INTERVAL = 60 -USER_OBJECT_CLASS = userOfNames -ENABLE_EXTRA_USER_INFO_SYNC = true -FIRST_NAME_ATTR = givenName -LAST_NAME_ATTR = sn -UID_ATTR = uid - -``` - -Meaning of each option: - -* **ENABLE_USER_SYNC**: set to "true" if you want to enable ldap user synchronization -* **DEACTIVE_USER_IF_NOTFOUND**: set to "true" if you want to deactivate a user when he/she was deleted in LDAP server. -* **SYNC_INTERVAL**: The synchronization interval. Unit is minutes. Defaults to 60 minutes. -* **USER_OBJECT_CLASS**: This is the name of the class used to search for user objects. In OpenLDAP, you can use "userOfNames". The default value is "person". -* **ENABLE_EXTRA_USER_INFO_SYNC**: Enable synchronization of additional user information, including user's full name, department, and Windows/Unix login name, etc. -* **FIRST_NAME_ATTR**: Attribute for user's first name. It's "givenName" by default. -* **LAST_NAME_ATTR**: Attribute for user's last name. It's "sn" by default. -* **USER_NAME_REVERSE**: In some languages, such as Chinese, the display order of the first and last name is reversed. Set this option if you need it. -* **UID_ATTR**: Attribute for Windows/Unix login name. If this is synchronized, users can also log in with their Windows/Unix login name. In OpenLDAP, the attribute `uid` or something similar can be used. - -### Importing Users without Activating Them - -The users imported with the above configuration will be activated by default. For some organizations with large number of users, they may want to import user information (such as user full name) without activating the imported users. Activating all imported users will require licenses for all users in AD/LDAP, which may not be affordable. - -Seafile provides a combination of options for such use case. First, you have to add below option to \[ldap_sync] section of ccnet.conf: - -``` -ACTIVATE_USER_WHEN_IMPORT = false - -``` - -This prevents Seafile from activating imported users. Second, add below option to `seahub_settings.py`: - -``` -ACTIVATE_AFTER_FIRST_LOGIN = True - -``` - -This option will automatically activate users when they login to Seafile for the first time. - - -### Reactivating Users - -When you set the \`**DEACTIVE_USER_IF_NOTFOUND**\` option, a user will be deactivated when it's not found in LDAP server. By default, even after this user reappears in the LDAP server, it won't be reactivated automatically. This is to prevent auto reactivating a user that was manually deactivated by the system admin. - -However, sometimes it's desirable to auto reactivate such users. So in version 7.1.8 we added a new option to provide this behavior. - -``` -AUTO_REACTIVATE_USERS = True - -``` - -### Manually Trigger Synchronization - -To test your LDAP sync configuration, you can run the sync command manually. - -To trigger LDAP sync manually, - -```sh -cd seafile-server-latest -./pro/pro.py ldapsync - -``` - -For Seafile Docker - -```sh -docker exec -it seafile /opt/seafile/seafile-server-latest/pro/pro.py ldapsync - -``` - -## Advanced LDAP/AD Integration Options - -### Multiple BASE - -Multiple base DN is useful when your company has more than one OUs to use Seafile. You can specify a list of base DN in the "BASE" config. The DNs are separated by ";", e.g. `ou=developers,dc=example,dc=com;ou=marketing,dc=example,dc=com` - -### Additional Search Filter - -Search filter is very useful when you have a large organization but only a portion of people want to use Seafile. The filter can be given by setting "FILTER" config. The value of this option follows standard LDAP search filter syntax (). - -The final filter used for searching for users is `(&($LOGIN_ATTR=*)($FILTER))`. `$LOGIN_ATTR` and `$FILTER` will be replaced by your option values. - -For example, add the following line to LDAP config: - -``` -FILTER = memberOf=CN=group,CN=developers,DC=example,DC=com - -``` - -The final search filter would be `(&(mail=*)(memberOf=CN=group,CN=developers,DC=example,DC=com))` - -Note that the cases in the above example is significant. The `memberOf` attribute is only available in Active Directory. - -### Limiting Seafile Users to a Group in Active Directory - -You can use the FILTER option to limit user scope to a certain AD group. - -1. First, you should find out the DN for the group. Again, we'll use `dsquery` command on the domain controller. For example, if group name is 'seafilegroup', run `dsquery group -name seafilegroup`. -2. Add following line to LDAP config: - - -``` -FILTER = memberOf={output of dsquery command} - -``` - -### Using TLS connection to LDAP/AD server - -To use TLS connection to the directory server, you should install a valid SSL certificate on the directory server. - -To make sure Seafile server successfully connect to the directory server with TLS, you have to choose the right version of Seafile Pro servers. - -* If you're using Seafile 9.0 or newer, you should use Docker to run Seafile. There should be no problem connecting with TLS as long as SSL certificate on the directory server is valid. -* If you're using older version of Seafile, you should choose Seafile package based on your OS. For CentOS/RHEL, choose the package for CentOS; for Ubuntu/Debian, choose the package for Ubuntu. - -The Seafile server package bundles the version of libldap from the OS where it's built. So libldap will try to locate OpenSSL library in the same path as the buidling OS. Since different Linux distributions have different path or configuration for OpenSSL library, sometimes Seafile is unable to connect to the directory server with TLS. - -When Seafile fails to connect with TLS, you may try to install ldap client libraries on your OS and ask Seafile to use them instead. - -On Ubuntu and Debian, moving the bundled ldap related libraries out of the library path should make TLS connection work. - -``` -cd ${SEAFILE_INSTALLATION_DIR}/seafile-server-latest/seafile/lib -mkdir disabled_libs_use_local_ones_instead -mv liblber-2.4.so.2 libldap-2.4.so.2 libsasl2.so.2 libldap_r-2.4.so.2 disabled_libs_use_local_ones_instead/ - -``` - -On some CentOS systems, you may have to move the libnssutil library as well: - -``` -cd ${SEAFILE_INSTALLATION_DIR}/seafile-server-latest/seafile/lib -mkdir disabled_libs_use_local_ones_instead -mv libnssutil3.so disabled_libs_use_local_ones_instead/ - -``` - -This effectively removes the bundled libraries from the library search path. -When the server starts, it'll instead find and use the system libraries (if they are installed). -This change has to be repeated after each update of the Seafile installation. - -### Use paged results extension - -LDAP protocol version 3 supports "paged results" (PR) extension. When you have large number of users, this option can greatly improve the performance of listing users. Most directory server nowadays support this extension. - -In Seafile Pro Edition, add this option to LDAP section of ccnet.conf to enable PR: - -``` -USE_PAGED_RESULT = true - -``` - -### Follow referrals - -Starting from Pro Edition 4.0.4, Seafile supports auto following referrals in LDAP search. This is useful for partitioned LDAP or AD servers, where users may be spreaded on multiple directory servers. For more information about referrals, you can refer to [this article](https://technet.microsoft.com/en-us/library/cc978014.aspx). - -To configure, add following option to ccnet.conf in the \[ldap] section: - -``` -FOLLOW_REFERRALS = true - -``` - -### Configure Multi-ldap Servers - -Since seafile 5.1.4 pro edition, we support multi-ldap servers, that is besides base ldap server info in \[ldap] section, you can set other ldap servers info in \[ldap_multi_1], \[ldap_multi_2] ... \[ldap_multi_9] sections, so you can configure ten ldap servers to work with seafile. Multi-ldap servers mean that, when get or search ldap user, it will iterate all configured ldap servers until a match is found; When listing all ldap users, it will iterate all ldap servers to get all users; For Ldap sync it will sync all user/group info in all configured ldap servers to seafile. - -For example I have configured base ldap server in `ccnet.conf` as follow: - -``` -[LDAP] -HOST = ldap://192.168.1.123/ -BASE = ou=users,dc=example,dc=com -USER_DN = cn=admin,dc=example,dc=com -PASSWORD = secret -LOGIN_ATTR = mail - -``` - -Then I can configure another ldap server in `ccnet.conf` as follow: - -``` -[LDAP_MULTI_1] -HOST = ldap://192.168.1.124/ -BASE = ou=users,dc=example,dc=com -USER_DN = cn=admin,dc=example,dc=com -PASSWORD = secret - -``` - -Before 6.3.8, all ldap servers share LOGIN_ATTR, USE_PAGED_RESULT, FOLLOW_REFERRALS attributes in \[ldap] section; For ldap user/group sync, all ldap servers share all ldap sync related attributes in \[ldap_sync] section. - -Since seafile 6.3.8 pro, we support more independent config sections for each ldap server. The LOGIN_ATTR, USE_PAGED_RESULT, FOLLOW_REFERRALS options can be set independently in each \[ldap_multi_x] section. Furthermore, independent \[ldap_sync_multi_x] sections can be set for each LDAP server. That is, each LDAP server can use different LDAP sync options. - -There are still some shared config options that can only be set in \[ldap_sync] section, which is used for all LDAP servers. - -* SYNC_INTERVAL -* DEACTIVE_USER_IF_NOTFOUND -* ACTIVATE_USER_WHEN_IMPORT -* IMPORT_NEW_USER -* DEL_GROUP_IF_NOT_FOUND - -These options are used to control synchronization behaviors, so they're shared for all LDAP servers. - -NOTE: It is recommended to have a \[ldap_sync_multi_x] section for each \[ldap_multi_x] section. Otherwise the LDAP sync process will use the options in \[ldap_sync] section for that LDAP server. diff --git a/mkdocs.yml b/mkdocs.yml index d7021ee3c..9bcd596a6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -87,12 +87,8 @@ nav: - Seafile Docker autostart: docker/seafile_docker_autostart.md - Advanced Setup Options: - LDAP/AD Integration: - - LDAP Integration: deploy/using_ldap.md - - LDAP Configuration for Seafile Pro: deploy_pro/using_ldap_pro.md - - Importing Groups from LDAP (Pro): deploy_pro/ldap_group_sync.md - - Importing Roles from LDAP (Pro): deploy_pro/ldap_role_sync.md - - LDAP in version 11.0: deploy/ldap_in_11.0.md - - LDAP in version 11.0 (Pro): deploy_pro/ldap_in_11.0.md + - LDAP Integration: deploy/ldap_in_11.0.md + - LDAP Integration (Pro): deploy_pro/ldap_in_11.0.md - Single Sign On: - Outline: deploy/single_sign_on.md - OAuth Authentication: deploy/oauth.md From 99e044a1522376c26ce4a64296e4a9c834901bb0 Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Mon, 14 Oct 2024 13:47:44 +0800 Subject: [PATCH 21/22] Remove seaf_import --- manual/deploy_pro/seaf_import.md | 30 ------------------------------ mkdocs.yml | 1 - 2 files changed, 31 deletions(-) delete mode 100644 manual/deploy_pro/seaf_import.md diff --git a/manual/deploy_pro/seaf_import.md b/manual/deploy_pro/seaf_import.md deleted file mode 100644 index 4f0b09d75..000000000 --- a/manual/deploy_pro/seaf_import.md +++ /dev/null @@ -1,30 +0,0 @@ -# Import Directory To Seafile - -Since seafile 5.1.3 pro edition, we support importing a local directory on the server to seafile. It's a handy tool for the system admin to import files from existing file servers (NFS, Samba etc.). - -To import a directory, use the `seaf-import.sh` script in seafile-server-latest directory. - -``` -usage : -seaf-import.sh - -p - -n - -u -``` - -The specified directory will be imported into Seafile as a library. You can set the name and owner of the imported library. - -Run `./seaf-import.sh -p

-n -u `, - -``` -Starting seaf-import, please wait ... -[04/26/16 03:36:23] seaf-import.c(79): Import file ./runtime/seahub.pid successfully. -[04/26/16 03:36:23] seaf-import.c(79): Import file ./runtime/error.log successfully. -[04/26/16 03:36:23] seaf-import.c(79): Import file ./runtime/seahub.conf successfully. -[04/26/16 03:36:23] seaf-import.c(79): Import file ./runtime/access.log successfully. -[04/26/16 03:36:23] seaf-import.c(183): Import dir ./runtime/ to repo 5ffb1f43 successfully. - run done -Done. -``` - -Login to seafile server with the specified library owner, you will find a new library with the specified name. diff --git a/mkdocs.yml b/mkdocs.yml index 9bcd596a6..41dfee1ec 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -141,7 +141,6 @@ nav: - Seafile FSCK: maintain/seafile_fsck.md - Seafile GC: maintain/seafile_gc.md - Clean database: maintain/clean_database.md - - Import Directory To Seafile (Pro): deploy_pro/seaf_import.md - Upgrade Seafile Server: - Outline: upgrade/upgrade.md - Upgrade Seafile Docker: upgrade/upgrade_docker.md From 02993cb9a1950ab82a247fab48e47ec5d46595ff Mon Sep 17 00:00:00 2001 From: Daniel Pan Date: Thu, 17 Oct 2024 21:25:57 +0800 Subject: [PATCH 22/22] Update changelog-for-seafile-professional-server.md --- .../changelog-for-seafile-professional-server.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/manual/changelog/changelog-for-seafile-professional-server.md b/manual/changelog/changelog-for-seafile-professional-server.md index 800d06a3e..4973af940 100644 --- a/manual/changelog/changelog-for-seafile-professional-server.md +++ b/manual/changelog/changelog-for-seafile-professional-server.md @@ -8,6 +8,15 @@ Please check our document for how to upgrade to 11.0: +### 11.0.15 (2024-10-17) + +* [fix] Check the length of email in login form, preventing too long input +* [fix] Use user name instead of user ID in email content +* [fix] auth-token API also prevent brute force attack +* [fix] Fix invite people in multi-tenancy mode +* [fix] Add option SSO_LDAP_USE_SAME_UID + + ### 11.0.14 (2024-08-22) * [fix] Fix a bug that system admin can not share a library in admin panel