-
-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
All configuration lives under /etc/seafile/, mode 0500 owned by seafile:seafile (only the service user and root can read it):
-
seafile.env- secrets, database connection, cache, hostname, feature toggles. Loaded as environment variables by every seafile systemd service. -
seafile.conf-seaf-server/file server tuning (upload limits, quotas, history retention, library trash expiry). -
seahub_settings.py- Seahub (Django) settings: email, self-registration, session policy, thumbnails, and more. -
gunicorn.conf.py- the gunicorn server running Seahub.
These are managed with ucf, so local edits survive package upgrades (a three-way merge, same as dpkg's own conffile handling).
Seafile needs three MySQL/MariaDB databases: ccnet_db, seafile_db, seahub_db. The server refuses to start until these and the connection details in seafile.env are configured.
Create a dedicated user, then either let the package create the databases for you, or create them yourself:
Option A - grant CREATE, let the package set up the databases:
CREATE USER 'seafile'@'127.0.0.1' IDENTIFIED BY 'choose-a-strong-password';
GRANT ALL PRIVILEGES ON `ccnet_db`.* TO 'seafile'@'127.0.0.1';
GRANT ALL PRIVILEGES ON `seafile_db`.* TO 'seafile'@'127.0.0.1';
GRANT ALL PRIVILEGES ON `seahub_db`.* TO 'seafile'@'127.0.0.1';
FLUSH PRIVILEGES;A database-scoped GRANT ALL PRIVILEGES works even before the database exists - MySQL/MariaDB records it, and the grantee can then CREATE DATABASE that specific name. The first start of seafile.service creates the databases and loads the schema automatically.
Option B - create the databases yourself (if you'd rather not grant CREATE to the application user):
CREATE DATABASE ccnet_db CHARACTER SET utf8mb4;
CREATE DATABASE seafile_db CHARACTER SET utf8mb4;
CREATE DATABASE seahub_db CHARACTER SET utf8mb4;
CREATE USER 'seafile'@'127.0.0.1' IDENTIFIED BY 'choose-a-strong-password';
GRANT ALL PRIVILEGES ON ccnet_db.* TO 'seafile'@'127.0.0.1';
GRANT ALL PRIVILEGES ON seafile_db.* TO 'seafile'@'127.0.0.1';
GRANT ALL PRIVILEGES ON seahub_db.* TO 'seafile'@'127.0.0.1';
FLUSH PRIVILEGES;Either way, set the connection details in seafile.env:
sudo -e /etc/seafile/seafile.envSEAFILE_MYSQL_DB_HOST=127.0.0.1
SEAFILE_MYSQL_DB_PORT=3306
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=<the password you chose above>The SEAFILE_MYSQL_DB_CCNET_DB_NAME/SEAFILE_MYSQL_DB_SEAFILE_DB_NAME/SEAFILE_MYSQL_DB_SEAHUB_DB_NAME variables only need changing if you used different database names than the defaults shown above.
Two secrets must be set before Seahub will start, both 32+ byte random hex strings:
openssl rand -hex 32-
JWT_PRIVATE_KEYinseafile.env- signs the tokens exchanged betweenseaf-server, the file server, the notification server and Seahub. Changing it later invalidates all running sessions between components. -
SECRET_KEYinseahub_settings.py- Django's secret key.
sudo systemctl restart seafile seafile-fileserver seafile-notification seahubseafile-migrate.service runs automatically before seafile/seahub start - it creates the database schema on first start (or applies schema upgrades after a package upgrade) and is safe to re-run on every start; it's a no-op once the data is already at the installed version.
Create the first admin account once the services are up - see Admin Tools.
Every service binds to 127.0.0.1 only - a reverse proxy is required for clients to reach the server. Route:
| Path | Backend | Notes |
|---|---|---|
/ |
127.0.0.1:8000 |
Seahub (gunicorn) |
/seafhttp |
127.0.0.1:8082 |
File server (upload/download) |
/notification |
127.0.0.1:8083 |
Notification server - needs WebSocket (Upgrade/Connection headers) proxying |
A minimal nginx starting point (adjust for your domain/TLS setup, and see the official manual's nginx guide for the complete reference configuration):
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /seafhttp {
proxy_pass http://127.0.0.1:8082;
client_max_body_size 0;
}
location /notification {
proxy_pass http://127.0.0.1:8083;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}NOTIFICATION_SERVER_URL in seafile.env must be set to the public URL clients reach /notification through (e.g. wss://your.domain/notification) - client notifications stay inactive while it's unset.
| Unit | Purpose |
|---|---|
seafile.service |
seaf-server - the core storage/sync daemon |
seafile-fileserver.service |
Go file server (upload/download); only runs while ENABLE_GO_FILESERVER=true in seafile.env
|
seafile-notification.service |
Real-time notification server; only runs while ENABLE_NOTIFICATION_SERVER=true
|
seahub.service |
The web frontend |
seafile-migrate.service |
Database schema init/upgrade one-shot; not meant to be managed directly |
seafile-fuse.service |
Optional read-only FUSE mount (seafile-fuse package only), disabled by default |
For a headless server, disable seahub:
sudo systemctl disable --now seahubSee Admin Tools for seaf-gc (garbage collection), seaf-fsck (integrity check/repair), and seahub-reset-admin (create/reset an admin account).
Don't edit the shipped unit files directly - use systemctl edit <unit> to add a drop-in override instead, so your changes survive package upgrades. Every unit's own comments document the sandboxing options and what each StateDirectory/ConfigurationDirectory entry is for.
See Upgrading for what happens automatically on a package upgrade, and Admin Tools for day-to-day maintenance commands.
seafile-migrate checks SEAFILE_MYSQL_DB_PASSWORD, JWT_PRIVATE_KEY and SECRET_KEY before doing anything. Check journalctl -u seafile-migrate for exactly which one is still missing.
If you used Option A above but the grant didn't take effect, double check you ran FLUSH PRIVILEGES and that the grant's host part ('seafile'@'127.0.0.1') matches SEAFILE_MYSQL_DB_HOST exactly - a mismatch (e.g. localhost vs 127.0.0.1) is treated as a different user by MySQL/MariaDB.