nixos/seafile: drop (#435059)
This commit is contained in:
@@ -126,6 +126,10 @@
|
||||
|
||||
- The Pocket ID module ([`services.pocket-id`][#opt-services.pocket-id.enable]) and package (`pocket-id`) has been updated to 1.0.0. Some environment variables have been changed or removed, see the [migration guide](https://pocket-id.org/docs/setup/migrate-to-v1/).
|
||||
|
||||
- `services.seafile` has been removed, as it is unmaintained and outdated.
|
||||
See [the manual](https://manual.seafile.com/13.0/upgrade/upgrade_notes_for_13.0.x/#important-release-changes)
|
||||
for details and next steps.
|
||||
|
||||
- The `zigbee2mqtt` package was updated to version 2.x, which contains breaking changes. See the [discussion](https://github.com/Koenkk/zigbee2mqtt/discussions/24198) for further information.
|
||||
|
||||
- []{#sec-release-25.11-incompatibilities-sourcehut-removed} The `services.sourcehut` module and corresponding `sourcehut` packages were removed due to being broken and unmaintained.
|
||||
|
||||
@@ -1325,7 +1325,6 @@
|
||||
./services/networking/scion/scion-ip-gateway.nix
|
||||
./services/networking/scion/scion-router.nix
|
||||
./services/networking/scion/scion.nix
|
||||
./services/networking/seafile.nix
|
||||
./services/networking/searx.nix
|
||||
./services/networking/shadowsocks.nix
|
||||
./services/networking/shairport-sync.nix
|
||||
|
||||
@@ -1,547 +0,0 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.seafile;
|
||||
settingsFormat = pkgs.formats.ini { };
|
||||
|
||||
ccnetConf = settingsFormat.generate "ccnet.conf" (
|
||||
lib.attrsets.recursiveUpdate {
|
||||
Database = {
|
||||
ENGINE = "mysql";
|
||||
UNIX_SOCKET = "/var/run/mysqld/mysqld.sock";
|
||||
DB = "ccnet_db";
|
||||
CONNECTION_CHARSET = "utf8";
|
||||
};
|
||||
} cfg.ccnetSettings
|
||||
);
|
||||
|
||||
seafileConf = settingsFormat.generate "seafile.conf" (
|
||||
lib.attrsets.recursiveUpdate {
|
||||
database = {
|
||||
type = "mysql";
|
||||
unix_socket = "/var/run/mysqld/mysqld.sock";
|
||||
db_name = "seafile_db";
|
||||
connection_charset = "utf8";
|
||||
};
|
||||
} cfg.seafileSettings
|
||||
);
|
||||
|
||||
seahubSettings = pkgs.writeText "seahub_settings.py" ''
|
||||
FILE_SERVER_ROOT = '${cfg.ccnetSettings.General.SERVICE_URL}/seafhttp'
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME' : 'seahub_db',
|
||||
'HOST' : '/var/run/mysqld/mysqld.sock',
|
||||
}
|
||||
}
|
||||
MEDIA_ROOT = '${seahubDir}/media/'
|
||||
THUMBNAIL_ROOT = '${seahubDir}/thumbnail/'
|
||||
|
||||
SERVICE_URL = '${cfg.ccnetSettings.General.SERVICE_URL}'
|
||||
|
||||
CSRF_TRUSTED_ORIGINS = ["${cfg.ccnetSettings.General.SERVICE_URL}"]
|
||||
|
||||
with open('${seafRoot}/.seahubSecret') as f:
|
||||
SECRET_KEY = f.readline().rstrip()
|
||||
|
||||
${cfg.seahubExtraConf}
|
||||
'';
|
||||
|
||||
seafRoot = "/var/lib/seafile";
|
||||
ccnetDir = "${seafRoot}/ccnet";
|
||||
seahubDir = "${seafRoot}/seahub";
|
||||
defaultUser = "seafile";
|
||||
|
||||
in
|
||||
{
|
||||
|
||||
###### Interface
|
||||
|
||||
options.services.seafile = with lib; {
|
||||
enable = mkEnableOption "Seafile server";
|
||||
|
||||
ccnetSettings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options = {
|
||||
General = {
|
||||
SERVICE_URL = mkOption {
|
||||
type = types.singleLineStr;
|
||||
example = "https://www.example.com";
|
||||
description = ''
|
||||
Seahub public URL.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for ccnet, see
|
||||
<https://manual.seafile.com/11.0/config/ccnet-conf/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
|
||||
seafileSettings = mkOption {
|
||||
type = types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options = {
|
||||
fileserver = {
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8082;
|
||||
description = ''
|
||||
The tcp port used by seafile fileserver.
|
||||
'';
|
||||
};
|
||||
host = mkOption {
|
||||
type = types.singleLineStr;
|
||||
default = "ipv4:127.0.0.1";
|
||||
example = "unix:/run/seafile/server.sock";
|
||||
description = ''
|
||||
The bind address used by seafile fileserver.
|
||||
|
||||
The addr can be defined as one of the following:
|
||||
- ipv6:<ipv6addr> for binding to an IPv6 address.
|
||||
- unix:<named pipe> for binding to a unix named socket
|
||||
- ipv4:<ipv4addr> for binding to an ipv4 address
|
||||
Otherwise the addr is assumed to be ipv4.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
description = ''
|
||||
Configuration for seafile-server, see
|
||||
<https://manual.seafile.com/11.0/config/seafile-conf/>
|
||||
for supported values.
|
||||
'';
|
||||
};
|
||||
|
||||
seahubAddress = mkOption {
|
||||
type = types.singleLineStr;
|
||||
default = "unix:/run/seahub/gunicorn.sock";
|
||||
example = "[::1]:8083";
|
||||
description = ''
|
||||
Which address to bind the seahub server to, of the form:
|
||||
- HOST
|
||||
- HOST:PORT
|
||||
- unix:PATH.
|
||||
IPv6 HOSTs must be wrapped in brackets.
|
||||
'';
|
||||
};
|
||||
|
||||
workers = mkOption {
|
||||
type = types.int;
|
||||
default = 4;
|
||||
example = 10;
|
||||
description = ''
|
||||
The number of gunicorn worker processes for handling requests.
|
||||
'';
|
||||
};
|
||||
|
||||
adminEmail = mkOption {
|
||||
example = "john@example.com";
|
||||
type = types.singleLineStr;
|
||||
description = ''
|
||||
Seafile Seahub Admin Account Email.
|
||||
'';
|
||||
};
|
||||
|
||||
initialAdminPassword = mkOption {
|
||||
example = "someStrongPass";
|
||||
type = types.singleLineStr;
|
||||
description = ''
|
||||
Seafile Seahub Admin Account initial password.
|
||||
Should be changed via Seahub web front-end.
|
||||
'';
|
||||
};
|
||||
|
||||
seahubPackage = mkPackageOption pkgs "seahub" { };
|
||||
|
||||
user = mkOption {
|
||||
type = types.singleLineStr;
|
||||
default = defaultUser;
|
||||
description = "User account under which seafile runs.";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.singleLineStr;
|
||||
default = defaultUser;
|
||||
description = "Group under which seafile runs.";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.path;
|
||||
default = "${seafRoot}/data";
|
||||
description = "Path in which to store user data";
|
||||
};
|
||||
|
||||
gc = {
|
||||
enable = mkEnableOption "automatic garbage collection on stored data blocks";
|
||||
|
||||
dates = mkOption {
|
||||
type = types.listOf types.singleLineStr;
|
||||
default = [ "Sun 03:00:00" ];
|
||||
description = ''
|
||||
When to run garbage collection on stored data blocks.
|
||||
The time format is described in {manpage}`systemd.time(7)`.
|
||||
'';
|
||||
};
|
||||
|
||||
randomizedDelaySec = mkOption {
|
||||
default = "0";
|
||||
type = types.singleLineStr;
|
||||
example = "45min";
|
||||
description = ''
|
||||
Add a randomized delay before each garbage collection.
|
||||
The delay will be chosen between zero and this value.
|
||||
This value must be a time span in the format specified by
|
||||
{manpage}`systemd.time(7)`
|
||||
'';
|
||||
};
|
||||
|
||||
persistent = mkOption {
|
||||
default = true;
|
||||
type = types.bool;
|
||||
example = false;
|
||||
description = ''
|
||||
Takes a boolean argument. If true, the time when the service
|
||||
unit was last triggered is stored on disk. When the timer is
|
||||
activated, the service unit is triggered immediately if it
|
||||
would have been triggered at least once during the time when
|
||||
the timer was inactive. Such triggering is nonetheless
|
||||
subject to the delay imposed by RandomizedDelaySec=. This is
|
||||
useful to catch up on missed runs of the service when the
|
||||
system was powered down.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
seahubExtraConf = mkOption {
|
||||
default = "";
|
||||
example = ''
|
||||
CSRF_TRUSTED_ORIGINS = ["https://example.com"]
|
||||
'';
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Extra config to append to `seahub_settings.py` file.
|
||||
Refer to <https://manual.seafile.com/11.0/config/seahub_settings_py/>
|
||||
for all available options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
###### Implementation
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
package = lib.mkDefault pkgs.mariadb;
|
||||
ensureDatabases = [
|
||||
"ccnet_db"
|
||||
"seafile_db"
|
||||
"seahub_db"
|
||||
];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = cfg.user;
|
||||
ensurePermissions = {
|
||||
"ccnet_db.*" = "ALL PRIVILEGES";
|
||||
"seafile_db.*" = "ALL PRIVILEGES";
|
||||
"seahub_db.*" = "ALL PRIVILEGES";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
environment.etc."seafile/ccnet.conf".source = ccnetConf;
|
||||
environment.etc."seafile/seafile.conf".source = seafileConf;
|
||||
environment.etc."seafile/seahub_settings.py".source = seahubSettings;
|
||||
|
||||
users.users = lib.optionalAttrs (cfg.user == defaultUser) {
|
||||
"${defaultUser}" = {
|
||||
group = cfg.group;
|
||||
isSystemUser = true;
|
||||
};
|
||||
};
|
||||
|
||||
users.groups = lib.optionalAttrs (cfg.group == defaultUser) { "${defaultUser}" = { }; };
|
||||
|
||||
systemd.targets.seafile = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
description = "Seafile components";
|
||||
};
|
||||
|
||||
systemd.services =
|
||||
let
|
||||
serviceOptions = {
|
||||
ProtectHome = true;
|
||||
PrivateUsers = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "strict";
|
||||
ProtectClock = true;
|
||||
ProtectHostname = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectControlGroups = true;
|
||||
RestrictNamespaces = true;
|
||||
RemoveIPC = true;
|
||||
LockPersonality = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
NoNewPrivileges = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
SystemCallArchitectures = "native";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_UNIX"
|
||||
"AF_INET"
|
||||
];
|
||||
|
||||
User = cfg.user;
|
||||
Group = cfg.group;
|
||||
StateDirectory = "seafile";
|
||||
RuntimeDirectory = "seafile";
|
||||
LogsDirectory = "seafile";
|
||||
ConfigurationDirectory = "seafile";
|
||||
ReadWritePaths = lib.lists.optional (cfg.dataDir != "${seafRoot}/data") cfg.dataDir;
|
||||
};
|
||||
in
|
||||
{
|
||||
seaf-server = {
|
||||
description = "Seafile server";
|
||||
partOf = [ "seafile.target" ];
|
||||
unitConfig.RequiresMountsFor = lib.lists.optional (cfg.dataDir != "${seafRoot}/data") cfg.dataDir;
|
||||
requires = [ "mysql.service" ];
|
||||
after = [
|
||||
"network.target"
|
||||
"mysql.service"
|
||||
];
|
||||
wantedBy = [ "seafile.target" ];
|
||||
restartTriggers = [
|
||||
ccnetConf
|
||||
seafileConf
|
||||
];
|
||||
serviceConfig = serviceOptions // {
|
||||
ExecStart = ''
|
||||
${lib.getExe cfg.seahubPackage.seafile-server} \
|
||||
--foreground \
|
||||
-F /etc/seafile \
|
||||
-c ${ccnetDir} \
|
||||
-d ${cfg.dataDir} \
|
||||
-l /var/log/seafile/server.log \
|
||||
-P /run/seafile/server.pid \
|
||||
-p /run/seafile
|
||||
'';
|
||||
};
|
||||
preStart = ''
|
||||
if [ ! -f "${seafRoot}/server-setup" ]; then
|
||||
mkdir -p ${cfg.dataDir}/library-template
|
||||
# Load schema on first install
|
||||
${pkgs.mariadb.client}/bin/mysql --database=ccnet_db < ${cfg.seahubPackage.seafile-server}/share/seafile/sql/mysql/ccnet.sql
|
||||
${pkgs.mariadb.client}/bin/mysql --database=seafile_db < ${cfg.seahubPackage.seafile-server}/share/seafile/sql/mysql/seafile.sql
|
||||
echo "${cfg.seahubPackage.seafile-server.version}-mysql" > "${seafRoot}"/server-setup
|
||||
echo Loaded MySQL schemas for first install
|
||||
fi
|
||||
# checking for upgrades and handling them
|
||||
installedMajor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f1)
|
||||
installedMinor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f2)
|
||||
pkgMajor=$(echo "${cfg.seahubPackage.seafile-server.version}" | cut -d"." -f1)
|
||||
pkgMinor=$(echo "${cfg.seahubPackage.seafile-server.version}" | cut -d"." -f2)
|
||||
|
||||
if [[ $installedMajor == $pkgMajor && $installedMinor == $pkgMinor ]]; then
|
||||
:
|
||||
elif [[ $installedMajor == 10 && $installedMinor == 0 && $pkgMajor == 11 && $pkgMinor == 0 ]]; then
|
||||
# Upgrade from 10.0 to 11.0: migrate to mysql
|
||||
echo Migrating from version 10 to 11
|
||||
|
||||
# From https://github.com/haiwen/seahub/blob/e12f941bfef7191795d8c72a7d339c01062964b2/scripts/sqlite2mysql.sh
|
||||
|
||||
echo Migrating ccnet database to MySQL
|
||||
${lib.getExe pkgs.sqlite} ${ccnetDir}/PeerMgr/usermgr.db ".dump" | \
|
||||
${lib.getExe cfg.seahubPackage.python3} ${cfg.seahubPackage}/scripts/sqlite2mysql.py > ${ccnetDir}/ccnet.sql
|
||||
${lib.getExe pkgs.sqlite} ${ccnetDir}/GroupMgr/groupmgr.db ".dump" | \
|
||||
${lib.getExe cfg.seahubPackage.python3} ${cfg.seahubPackage}/scripts/sqlite2mysql.py >> ${ccnetDir}/ccnet.sql
|
||||
sed 's/ctime INTEGER/ctime BIGINT/g' -i ${ccnetDir}/ccnet.sql
|
||||
sed 's/email TEXT, role TEXT/email VARCHAR(255), role TEXT/g' -i ${ccnetDir}/ccnet.sql
|
||||
${pkgs.mariadb.client}/bin/mysql --database=ccnet_db < ${ccnetDir}/ccnet.sql
|
||||
|
||||
echo Migrating seafile database to MySQL
|
||||
${lib.getExe pkgs.sqlite} ${cfg.dataDir}/seafile.db ".dump" | \
|
||||
${lib.getExe cfg.seahubPackage.python3} ${cfg.seahubPackage}/scripts/sqlite2mysql.py > ${cfg.dataDir}/seafile.sql
|
||||
sed 's/owner_id TEXT/owner_id VARCHAR(255)/g' -i ${cfg.dataDir}/seafile.sql
|
||||
sed 's/user_name TEXT/user_name VARCHAR(255)/g' -i ${cfg.dataDir}/seafile.sql
|
||||
${pkgs.mariadb.client}/bin/mysql --database=seafile_db < ${cfg.dataDir}/seafile.sql
|
||||
|
||||
echo Migrating seahub database to MySQL
|
||||
echo 'SET FOREIGN_KEY_CHECKS=0;' > ${seahubDir}/seahub.sql
|
||||
${lib.getExe pkgs.sqlite} ${seahubDir}/seahub.db ".dump" | \
|
||||
${lib.getExe cfg.seahubPackage.python3} ${cfg.seahubPackage}/scripts/sqlite2mysql.py >> ${seahubDir}/seahub.sql
|
||||
sed 's/`permission` , `reporter` text NOT NULL/`permission` longtext NOT NULL/g' -i ${seahubDir}/seahub.sql
|
||||
sed 's/varchar(256) NOT NULL UNIQUE/varchar(255) NOT NULL UNIQUE/g' -i ${seahubDir}/seahub.sql
|
||||
sed 's/, UNIQUE (`user_email`, `contact_email`)//g' -i ${seahubDir}/seahub.sql
|
||||
sed '/INSERT INTO `base_dirfileslastmodifiedinfo`/d' -i ${seahubDir}/seahub.sql
|
||||
sed '/INSERT INTO `notifications_usernotification`/d' -i ${seahubDir}/seahub.sql
|
||||
sed 's/DEFERRABLE INITIALLY DEFERRED//g' -i ${seahubDir}/seahub.sql
|
||||
${pkgs.mariadb.client}/bin/mysql --database=seahub_db < ${seahubDir}/seahub.sql
|
||||
|
||||
echo "${cfg.seahubPackage.seafile-server.version}-mysql" > "${seafRoot}"/server-setup
|
||||
echo Migration complete
|
||||
else
|
||||
echo "Unsupported upgrade: $installedMajor.$installedMinor to $pkgMajor.$pkgMinor" >&2
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
|
||||
# Fix unix socket permissions
|
||||
postStart = (
|
||||
lib.strings.optionalString (lib.strings.hasPrefix "unix:" cfg.seafileSettings.fileserver.host) ''
|
||||
while [[ ! -S "${lib.strings.removePrefix "unix:" cfg.seafileSettings.fileserver.host}" ]]; do
|
||||
sleep 1
|
||||
done
|
||||
chmod 666 "${lib.strings.removePrefix "unix:" cfg.seafileSettings.fileserver.host}"
|
||||
''
|
||||
);
|
||||
};
|
||||
|
||||
seahub = {
|
||||
description = "Seafile Server Web Frontend";
|
||||
wantedBy = [ "seafile.target" ];
|
||||
partOf = [ "seafile.target" ];
|
||||
unitConfig.RequiresMountsFor = lib.lists.optional (cfg.dataDir != "${seafRoot}/data") cfg.dataDir;
|
||||
requires = [
|
||||
"mysql.service"
|
||||
"seaf-server.service"
|
||||
];
|
||||
after = [
|
||||
"network.target"
|
||||
"mysql.service"
|
||||
"seaf-server.service"
|
||||
];
|
||||
restartTriggers = [ seahubSettings ];
|
||||
environment = {
|
||||
PYTHONPATH = "${cfg.seahubPackage.pythonPath}:${cfg.seahubPackage}/thirdpart:${cfg.seahubPackage}";
|
||||
DJANGO_SETTINGS_MODULE = "seahub.settings";
|
||||
CCNET_CONF_DIR = ccnetDir;
|
||||
SEAFILE_CONF_DIR = cfg.dataDir;
|
||||
SEAFILE_CENTRAL_CONF_DIR = "/etc/seafile";
|
||||
SEAFILE_RPC_PIPE_PATH = "/run/seafile";
|
||||
SEAHUB_LOG_DIR = "/var/log/seafile";
|
||||
};
|
||||
serviceConfig = serviceOptions // {
|
||||
RuntimeDirectory = "seahub";
|
||||
ExecStart = ''
|
||||
${lib.getExe cfg.seahubPackage.python3.pkgs.gunicorn} seahub.wsgi:application \
|
||||
--name seahub \
|
||||
--workers ${toString cfg.workers} \
|
||||
--log-level=info \
|
||||
--preload \
|
||||
--timeout=1200 \
|
||||
--limit-request-line=8190 \
|
||||
--bind ${cfg.seahubAddress}
|
||||
'';
|
||||
};
|
||||
preStart = ''
|
||||
mkdir -p ${seahubDir}/media
|
||||
# Link all media except avatars
|
||||
for m in `find ${cfg.seahubPackage}/media/ -maxdepth 1 -not -name "avatars"`; do
|
||||
ln -sf $m ${seahubDir}/media/
|
||||
done
|
||||
if [ ! -e "${seafRoot}/.seahubSecret" ]; then
|
||||
(
|
||||
umask 377 &&
|
||||
${lib.getExe cfg.seahubPackage.python3} ${cfg.seahubPackage}/tools/secret_key_generator.py > ${seafRoot}/.seahubSecret
|
||||
)
|
||||
fi
|
||||
if [ ! -f "${seafRoot}/seahub-setup" ]; then
|
||||
# avatars directory should be writable
|
||||
install -D -t ${seahubDir}/media/avatars/ ${cfg.seahubPackage}/media/avatars/default.png
|
||||
install -D -t ${seahubDir}/media/avatars/groups ${cfg.seahubPackage}/media/avatars/groups/default.png
|
||||
# init database
|
||||
${cfg.seahubPackage}/manage.py migrate
|
||||
# create admin account
|
||||
${lib.getExe pkgs.expect} -c 'spawn ${cfg.seahubPackage}/manage.py createsuperuser --email=${cfg.adminEmail}; expect "Password: "; send "${cfg.initialAdminPassword}\r"; expect "Password (again): "; send "${cfg.initialAdminPassword}\r"; expect "Superuser created successfully."'
|
||||
echo "${cfg.seahubPackage.version}-mysql" > "${seafRoot}/seahub-setup"
|
||||
fi
|
||||
if [ $(cat "${seafRoot}/seahub-setup" | cut -d"-" -f1) != "${pkgs.seahub.version}" ]; then
|
||||
# run django migrations
|
||||
${cfg.seahubPackage}/manage.py migrate
|
||||
echo "${cfg.seahubPackage.version}-mysql" > "${seafRoot}/seahub-setup"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
seaf-gc = {
|
||||
description = "Seafile storage garbage collection";
|
||||
conflicts = [
|
||||
"seaf-server.service"
|
||||
"seahub.service"
|
||||
];
|
||||
after = [
|
||||
"seaf-server.service"
|
||||
"seahub.service"
|
||||
];
|
||||
unitConfig.RequiresMountsFor = lib.lists.optional (cfg.dataDir != "${seafRoot}/data") cfg.dataDir;
|
||||
onSuccess = [
|
||||
"seaf-server.service"
|
||||
"seahub.service"
|
||||
];
|
||||
onFailure = [
|
||||
"seaf-server.service"
|
||||
"seahub.service"
|
||||
];
|
||||
startAt = lib.lists.optionals cfg.gc.enable cfg.gc.dates;
|
||||
serviceConfig = serviceOptions // {
|
||||
Type = "oneshot";
|
||||
};
|
||||
script = ''
|
||||
if [ ! -f "${seafRoot}/server-setup" ]; then
|
||||
echo "Server not setup yet, GC not needed" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
# checking for pending upgrades
|
||||
installedMajor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f1)
|
||||
installedMinor=$(cat "${seafRoot}/server-setup" | cut -d"-" -f1 | cut -d"." -f2)
|
||||
pkgMajor=$(echo "${cfg.seahubPackage.seafile-server.version}" | cut -d"." -f1)
|
||||
pkgMinor=$(echo "${cfg.seahubPackage.seafile-server.version}" | cut -d"." -f2)
|
||||
|
||||
if [[ $installedMajor != $pkgMajor || $installedMinor != $pkgMinor ]]; then
|
||||
echo "Server not upgraded yet" >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
# Clean up user-deleted blocks and libraries
|
||||
${cfg.seahubPackage.seafile-server}/bin/seafserv-gc \
|
||||
-F /etc/seafile \
|
||||
-c ${ccnetDir} \
|
||||
-d ${cfg.dataDir} \
|
||||
--rm-fs
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd.timers.seaf-gc = lib.mkIf cfg.gc.enable {
|
||||
timerConfig = {
|
||||
RandomizedDelaySec = cfg.gc.randomizedDelaySec;
|
||||
Persistent = cfg.gc.persistent;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
schmittlauch
|
||||
];
|
||||
}
|
||||
@@ -1330,7 +1330,6 @@ in
|
||||
scx = runTest ./scx/default.nix;
|
||||
sddm = import ./sddm.nix { inherit runTest; };
|
||||
sdl3 = runTest ./sdl3.nix;
|
||||
seafile = runTest ./seafile.nix;
|
||||
searx = runTest ./searx.nix;
|
||||
seatd = runTest ./seatd.nix;
|
||||
send = runTest ./send.nix;
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
let
|
||||
client =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
environment.systemPackages = [
|
||||
pkgs.seafile-shared
|
||||
pkgs.curl
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "seafile";
|
||||
meta = with pkgs.lib.maintainers; {
|
||||
maintainers = [
|
||||
kampfschlaefer
|
||||
];
|
||||
};
|
||||
|
||||
nodes = {
|
||||
server =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
services.seafile = {
|
||||
enable = true;
|
||||
ccnetSettings.General.SERVICE_URL = "http://server";
|
||||
seafileSettings.fileserver.host = "unix:/run/seafile/server.sock";
|
||||
adminEmail = "admin@example.com";
|
||||
initialAdminPassword = "seafile_password";
|
||||
};
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
virtualHosts."server" = {
|
||||
locations."/".proxyPass = "http://unix:/run/seahub/gunicorn.sock";
|
||||
locations."/seafhttp" = {
|
||||
proxyPass = "http://unix:/run/seafile/server.sock";
|
||||
extraConfig = ''
|
||||
rewrite ^/seafhttp(.*)$ $1 break;
|
||||
client_max_body_size 0;
|
||||
proxy_connect_timeout 36000s;
|
||||
proxy_read_timeout 36000s;
|
||||
proxy_send_timeout 36000s;
|
||||
send_timeout 36000s;
|
||||
proxy_http_version 1.1;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 80 ];
|
||||
};
|
||||
};
|
||||
client1 = client pkgs;
|
||||
client2 = client pkgs;
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
with subtest("start seaf-server"):
|
||||
server.wait_for_unit("seaf-server.service")
|
||||
server.wait_for_file("/run/seafile/seafile.sock")
|
||||
|
||||
with subtest("start seahub"):
|
||||
server.wait_for_unit("seahub.service")
|
||||
server.wait_for_unit("nginx.service")
|
||||
server.wait_for_file("/run/seahub/gunicorn.sock")
|
||||
|
||||
with subtest("client1 fetch seahub page"):
|
||||
client1.succeed("curl -L http://server | grep 'Log In' >&2")
|
||||
|
||||
with subtest("client1 connect"):
|
||||
client1.wait_for_unit("default.target")
|
||||
client1.succeed("seaf-cli init -d . >&2")
|
||||
client1.succeed("seaf-cli start >&2")
|
||||
client1.succeed(
|
||||
"seaf-cli list-remote -s http://server -u admin\@example.com -p seafile_password >&2"
|
||||
)
|
||||
|
||||
libid = client1.succeed(
|
||||
'seaf-cli create -s http://server -n test01 -u admin\@example.com -p seafile_password -t "first test library"'
|
||||
).strip()
|
||||
|
||||
client1.succeed(
|
||||
"seaf-cli list-remote -s http://server -u admin\@example.com -p seafile_password |grep test01"
|
||||
)
|
||||
client1.fail(
|
||||
"seaf-cli list-remote -s http://server -u admin\@example.com -p seafile_password |grep test02"
|
||||
)
|
||||
|
||||
client1.succeed(
|
||||
f"seaf-cli download -l {libid} -s http://server -u admin\@example.com -p seafile_password -d . >&2"
|
||||
)
|
||||
|
||||
client1.wait_until_succeeds("seaf-cli status |grep synchronized >&2")
|
||||
|
||||
client1.succeed("ls -la >&2")
|
||||
client1.succeed("ls -la test01 >&2")
|
||||
|
||||
client1.execute("echo bla > test01/first_file")
|
||||
|
||||
client1.wait_until_succeeds("seaf-cli status |grep synchronized >&2")
|
||||
|
||||
with subtest("client2 sync"):
|
||||
client2.wait_for_unit("default.target")
|
||||
|
||||
client2.succeed("seaf-cli init -d . >&2")
|
||||
client2.succeed("seaf-cli start >&2")
|
||||
|
||||
client2.succeed(
|
||||
"seaf-cli list-remote -s http://server -u admin\@example.com -p seafile_password >&2"
|
||||
)
|
||||
|
||||
libid = client2.succeed(
|
||||
"seaf-cli list-remote -s http://server -u admin\@example.com -p seafile_password |grep test01 |cut -d' ' -f 2"
|
||||
).strip()
|
||||
|
||||
client2.succeed(
|
||||
f"seaf-cli download -l {libid} -s http://server -u admin\@example.com -p seafile_password -d . >&2"
|
||||
)
|
||||
|
||||
client2.wait_until_succeeds("seaf-cli status |grep synchronized >&2")
|
||||
|
||||
client2.succeed("ls -la test01 >&2")
|
||||
|
||||
client2.succeed('[ `cat test01/first_file` = "bla" ]')
|
||||
'';
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
cmake,
|
||||
libevent,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
pname = "libevhtp";
|
||||
version = "unstable-2021-04-28";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "haiwen";
|
||||
repo = "libevhtp";
|
||||
rev = "18c649203f009ef1d77d6f8301eba09af3777adf";
|
||||
sha256 = "1rf0jcy2lf8jbzpkhfgv289hc8zdy5zs6sn36k4vlqvilginxiid";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ cmake ];
|
||||
|
||||
buildInputs = [ libevent ];
|
||||
|
||||
cmakeFlags = [
|
||||
"-DEVHTP_DISABLE_SSL=ON"
|
||||
"-DEVHTP_BUILD_SHARED=ON"
|
||||
];
|
||||
|
||||
meta = with lib; {
|
||||
description = "Create extremely-fast and secure embedded HTTP servers with ease";
|
||||
homepage = "https://github.com/criticalstack/libevhtp";
|
||||
license = licenses.bsd3;
|
||||
maintainers = with maintainers; [
|
||||
schmittlauch
|
||||
melvyn2
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
fetchpatch,
|
||||
pkg-config,
|
||||
python3,
|
||||
autoreconfHook,
|
||||
libuuid,
|
||||
libmysqlclient,
|
||||
sqlite,
|
||||
glib,
|
||||
libevent,
|
||||
libsearpc,
|
||||
openssl,
|
||||
fuse,
|
||||
libarchive,
|
||||
libjwt,
|
||||
curl,
|
||||
which,
|
||||
vala,
|
||||
cmake,
|
||||
oniguruma,
|
||||
nixosTests,
|
||||
}:
|
||||
|
||||
let
|
||||
# seafile-server relies on a specific version of libevhtp.
|
||||
# It contains non upstreamed patches and is forked off an outdated version.
|
||||
libevhtp = import ./libevhtp.nix {
|
||||
inherit
|
||||
stdenv
|
||||
lib
|
||||
fetchFromGitHub
|
||||
cmake
|
||||
libevent
|
||||
;
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "seafile-server";
|
||||
version = "11.0.12"; # Doc links match Seafile 11.0 in seafile.nix – update if version changes.
|
||||
src = fetchFromGitHub {
|
||||
owner = "haiwen";
|
||||
repo = "seafile-server";
|
||||
rev = "5e6c0974e6abe5d92b8ba1db41c6ddbc1029f2d5"; # using a fixed revision because upstream may re-tag releases :/
|
||||
hash = "sha256-BVa4QZiHPkqRB5FvDlCSbEVxdnyxVy2KuCDb2orRMuI=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
autoreconfHook
|
||||
pkg-config
|
||||
python3
|
||||
libsearpc # searpc-codegen.py
|
||||
vala # valac
|
||||
which
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
libuuid
|
||||
libmysqlclient
|
||||
sqlite
|
||||
glib
|
||||
libsearpc
|
||||
libevent
|
||||
python3
|
||||
fuse
|
||||
libarchive
|
||||
libjwt
|
||||
libevhtp
|
||||
oniguruma
|
||||
];
|
||||
|
||||
patches = [
|
||||
# https://github.com/haiwen/seafile-server/pull/658
|
||||
(fetchpatch {
|
||||
url = "https://github.com/haiwen/seafile-server/commit/8029a11a731bfe142af43f230f47b93811ebaaaa.patch";
|
||||
hash = "sha256-AWNDXIyrKXgqgq3p0m8+s3YH8dKxWnf7uEMYzSsjmX4=";
|
||||
})
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/share/seafile/sql
|
||||
cp -r scripts/sql $out/share/seafile
|
||||
'';
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) seafile;
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "File syncing and sharing software with file encryption and group sharing, emphasis on reliability and high performance";
|
||||
homepage = "https://github.com/haiwen/seafile-server";
|
||||
license = licenses.agpl3Plus;
|
||||
platforms = platforms.linux;
|
||||
maintainers = with maintainers; [
|
||||
melvyn2
|
||||
];
|
||||
mainProgram = "seaf-server";
|
||||
};
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
{
|
||||
lib,
|
||||
fetchFromGitHub,
|
||||
python3,
|
||||
makeWrapper,
|
||||
nixosTests,
|
||||
seafile-server,
|
||||
}:
|
||||
python3.pkgs.buildPythonApplication rec {
|
||||
pname = "seahub";
|
||||
version = "11.0.12";
|
||||
pyproject = false;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "haiwen";
|
||||
repo = "seahub";
|
||||
rev = "d998361dd890cac3f6d6ebec3af47a589e0332bc"; # using a fixed revision because upstream may re-tag releases :/
|
||||
hash = "sha256-n56sRZ9TVb37JA0+12ZoF2Mt7dADjaYk7V0PmdBY0EU=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
doCheck = false; # disabled because it requires a ccnet environment
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
|
||||
propagatedBuildInputs = with python3.pkgs; [
|
||||
django
|
||||
django-compressor
|
||||
django-statici18n
|
||||
django-webpack-loader
|
||||
django-simple-captcha
|
||||
django-picklefield
|
||||
django-formtools
|
||||
djangosaml2
|
||||
mysqlclient
|
||||
pillow
|
||||
python-dateutil
|
||||
djangorestframework
|
||||
openpyxl
|
||||
requests
|
||||
requests-oauthlib
|
||||
chardet
|
||||
pyjwt
|
||||
pycryptodome
|
||||
pyopenssl
|
||||
python-ldap
|
||||
qrcode
|
||||
pysearpc
|
||||
gunicorn
|
||||
markdown
|
||||
bleach
|
||||
|
||||
(python3.pkgs.toPythonModule (seafile-server.override { inherit python3; }))
|
||||
];
|
||||
|
||||
postPatch = ''
|
||||
substituteInPlace seahub/settings.py --replace-fail "SEAFILE_VERSION = '6.3.3'" "SEAFILE_VERSION = '${version}'"
|
||||
substituteInPlace thirdpart/constance/management/commands/constance.py --replace-fail \
|
||||
"from __future__ import unicode_literals" ""
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
cp -dr --no-preserve='ownership' . $out/
|
||||
wrapProgram $out/manage.py \
|
||||
--prefix PYTHONPATH : "$PYTHONPATH:$out/thirdpart:"
|
||||
'';
|
||||
|
||||
passthru = {
|
||||
inherit python3;
|
||||
pythonPath = python3.pkgs.makePythonPath propagatedBuildInputs;
|
||||
tests = {
|
||||
inherit (nixosTests) seafile;
|
||||
};
|
||||
inherit seafile-server;
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Web end of seafile server";
|
||||
homepage = "https://github.com/haiwen/seahub";
|
||||
license = lib.licenses.asl20;
|
||||
maintainers = with lib.maintainers; [
|
||||
melvyn2
|
||||
];
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
||||
@@ -2105,6 +2105,8 @@ mapAliases {
|
||||
scitoken-cpp = scitokens-cpp; # Added 2024-02-12
|
||||
scry = throw "'scry' has been removed as it was archived upstream. Use 'crystalline' instead"; # Added 2025-02-12
|
||||
scudcloud = throw "'scudcloud' has been removed as it was archived by upstream"; # Added 2025-07-24
|
||||
seafile-server = throw "'seafile-server' has been removed as it is unmaintained"; # Added 2025-08-21
|
||||
seahub = throw "'seahub' has been removed as it is unmaintained"; # Added 2025-08-21
|
||||
semeru-bin-16 = throw "Semeru 16 has been removed as it has reached its end of life"; # Added 2024-08-01
|
||||
semeru-jre-bin-16 = throw "Semeru 16 has been removed as it has reached its end of life"; # Added 2024-08-01
|
||||
sensu = throw "sensu has been removed as the upstream project is deprecated. Consider using `sensu-go`"; # Added 2024-10-28
|
||||
|
||||
@@ -743,6 +743,7 @@ mapAliases ({
|
||||
scikitlearn = scikit-learn; # added 2021-07-21
|
||||
scikit-optimize = throw "scikit-optimize has been removed because it is abandoned"; # added 2024-09-30
|
||||
scikits-samplerate = throw "scikits-samplerate has been removed, it was unsed and unmaintained since 2015"; # added 2024-05-23
|
||||
seaserv = throw "seaserv has been removed as it is unmaintained"; # Added 2025-08-21
|
||||
selectors2 = throw "selectors2 has been removed: archived by upstream."; # added 2024-07-27
|
||||
selectors34 = throw "selectors34 has been removed: functionality provided by Python itself; archived by upstream."; # added 2021-06-10
|
||||
sentry-sdk_2 = sentry-sdk; # added 2025-04-20
|
||||
|
||||
@@ -16401,8 +16401,6 @@ self: super: with self; {
|
||||
|
||||
seabreeze = callPackage ../development/python-modules/seabreeze { };
|
||||
|
||||
seaserv = toPythonModule (pkgs.seafile-server.override { python3 = self.python; });
|
||||
|
||||
seasonal = callPackage ../development/python-modules/seasonal { };
|
||||
|
||||
seatconnect = callPackage ../development/python-modules/seatconnect { };
|
||||
|
||||
Reference in New Issue
Block a user