Compare commits
	
		
			No commits in common. "mainline" and "python3" have entirely different histories.
		
	
	
		
	
		
					 4 changed files with 96 additions and 234 deletions
				
			
		|  | @ -2,40 +2,6 @@ | |||
| with lib; | ||||
| let | ||||
|   cfg = config.services.seafile-server; | ||||
|   seafileConfigFile = pkgs.writeText "seafile.conf" | ||||
|     (generators.toINI {} cfg.seafileSettings); | ||||
|   ccnetConfigFile = pkgs.writeText "ccnet.conf" | ||||
|     (generators.toINI {} cfg.ccnetSettings); | ||||
|   gunicornConfigFile = pkgs.writeText "gunicorn.conf.py" | ||||
|     '' | ||||
|       import os | ||||
|       daemon = True | ||||
|       workers = 5 | ||||
|       # default localhost:8000 | ||||
|       bind = "127.0.0.1:8000" | ||||
|       # Pid | ||||
|       pids_dir = '${cfg.storagePath}/pids' | ||||
|       pidfile = os.path.join(pids_dir, 'seahub.pid') | ||||
|       # for file upload, we need a longer timeout value (default is only 30s, too short) | ||||
|       timeout = 1200 | ||||
|       limit_request_line = 8190 | ||||
|     ''; | ||||
|   seahubConfigFile = pkgs.writeText "seahub_settings.py" | ||||
|     '' | ||||
|       SECRET_KEY = #seckey# | ||||
| 
 | ||||
|       DATABASES = { | ||||
|           'default': { | ||||
|               'ENGINE': 'django.db.backends.${if cfg.db.type == "mysql" then | ||||
|                 "mysql" else abort "invalid db type"}', | ||||
|               'NAME': '${cfg.db.dbnameSeahub}', | ||||
|               'USER': '${cfg.db.user}', | ||||
|               'PASSWORD': '#dbpass#', | ||||
|               'HOST': '${cfg.db.host}', | ||||
|               'PORT': '${toString cfg.db.port}' | ||||
|           } | ||||
|       } | ||||
|     ''; | ||||
|   # fix permissions at start | ||||
| in | ||||
|   { | ||||
|  | @ -46,20 +12,6 @@ in | |||
|         default = "/srv/seafile"; | ||||
|         description = "where to store uploaded file data"; | ||||
|       }; | ||||
|       ccnetSettings = mkOption { | ||||
|         type = with types; attrsOf (attrsOf (oneOf [ bool int str ])); | ||||
|         default = {}; | ||||
|         description = '' | ||||
|           all possible ccnet.conf settings | ||||
|           ''; | ||||
|         }; | ||||
|       seafileSettings = mkOption { | ||||
|         type = with types; attrsOf (attrsOf (oneOf [ bool int str ])); | ||||
|         default = {}; | ||||
|         description = '' | ||||
|           all possible seafile.conf settings | ||||
|           ''; | ||||
|         }; | ||||
|       autorun = mkOption { | ||||
|         type = types.bool; | ||||
|         default = true; | ||||
|  | @ -76,40 +28,38 @@ in | |||
|           default = "seafile"; | ||||
|           description = "Database user name. Not required for sqlite."; | ||||
|         }; | ||||
|         dbnameSeafile = mkOption { | ||||
|         dbname = mkOption { | ||||
|           type = types.nullOr types.str; | ||||
|           default = "seafile"; | ||||
|           description = "Database name for Seafile server. Not required for sqlite."; | ||||
|           description = "Database name. Not required for sqlite."; | ||||
|         }; | ||||
|         dbnameCcnet = mkOption { | ||||
|           type = types.nullOr types.str; | ||||
|           default = "seafile"; | ||||
|           description = "Database name for Ccnet server. Not required for sqlite."; | ||||
|         }; | ||||
|         dbnameSeahub = mkOption { | ||||
|           type = types.nullOr types.str; | ||||
|           default = "seafile"; | ||||
|           description = "Database name for Seahub web interface. Not required for sqlite."; | ||||
|         }; | ||||
|         passwordFile = mkOption { | ||||
|         password = mkOption { | ||||
|           type = types.nullOr types.str; | ||||
|           default = null; | ||||
|           description = '' | ||||
|             The full path to a file that contains the database password. | ||||
|             Not required for sqlite. | ||||
|           ''; | ||||
|             Database password. Use <literal>passwordFile</literal> to avoid this | ||||
|             being world-readable in the <literal>/nix/store</literal>. | ||||
| 
 | ||||
|             Not required for sqlite.''; | ||||
|           }; | ||||
|           passwordFile = mkOption { | ||||
|             type = types.nullOr types.str; | ||||
|             default = null; | ||||
|             description = '' | ||||
|               The full path to a file that contains the database password. | ||||
|             ''; | ||||
|           }; | ||||
|           host = mkOption { | ||||
|             type = types.nullOr types.str; | ||||
|             default = "localhost"; | ||||
|             description = "Database host."; | ||||
|           }; | ||||
|           dbport = mkOption { | ||||
|             type = with types; nullOr (either int str); | ||||
|             default = 3306; | ||||
|             description = "Database port. Not required for sqlite."; | ||||
|           }; | ||||
|         }; | ||||
|         host = mkOption { | ||||
|           type = types.nullOr types.str; | ||||
|           default = "localhost"; | ||||
|           description = "Database host."; | ||||
|         }; | ||||
|         port = mkOption { | ||||
|           type = with types; nullOr (either int str); | ||||
|           default = 3306; | ||||
|           description = "Database port. Not required for sqlite."; | ||||
|         }; | ||||
|       }; | ||||
| 
 | ||||
|         user = mkOption { | ||||
|           type = types.str; | ||||
|  | @ -123,11 +73,11 @@ in | |||
|           description = "Group account under which the Seafile server runs."; | ||||
|         }; | ||||
| 
 | ||||
|         name = mkOption { | ||||
|           type = types.str; | ||||
|           default = "Seafile"; | ||||
|           description = "name of the Seafile instance, will show up in client and web interface"; | ||||
|         }; | ||||
| #        name = mkOption { | ||||
| #          type = types.str; | ||||
| #          default = "Seafile"; | ||||
| #          description = "name of the Seafile instance, will show up in client and web interface"; | ||||
| #        }; | ||||
| 
 | ||||
|         domainName = mkOption { | ||||
|           type = types.str; | ||||
|  | @ -222,68 +172,16 @@ in | |||
|         directoriesToManage = [ cfg.storagePath ]; | ||||
|       in | ||||
|       mkIf cfg.enable { | ||||
|         services.seafile-server.ccnetSettings = { | ||||
|           # TODO: ID and NAME might be required | ||||
|           General.SERVICE_URL="http${if cfg.enableTLS then "s" else ""}://${cfg.domainName}:${toString cfg.externalPort}/"; | ||||
|           Database = mkMerge [ | ||||
|             { | ||||
|               ENGINE = cfg.db.type; | ||||
|             } | ||||
|             (mkIf (cfg.db.type == "mysql") { | ||||
|               HOST = cfg.db.host; | ||||
|               PORT = cfg.db.port; | ||||
|               USER = cfg.db.user; | ||||
|               CONNECTION_CHARSET = "utf8"; | ||||
|               DB = cfg.db.dbnameCcnet; | ||||
|               password = "#dbpass#"; | ||||
|             }) | ||||
|           ]; | ||||
| 
 | ||||
|         }; | ||||
| 
 | ||||
|         services.seafile-server.seafileSettings = { | ||||
|           library_trash.expire_days = cfg.trashExpirationTime; | ||||
|           fileserver = { | ||||
|             host = cfg.fileserverBindAddress; | ||||
|             port = cfg.fileserverPort; | ||||
|             worker_threads = cfg.fileserverWorkers; | ||||
|             max_indexing_threads = cfg.fileserverIndexers; | ||||
|             fixed_block_size = cfg.fileserverBlockSize; | ||||
|           }; | ||||
|           quota = mkIf (! isNull cfg.defaultQuota) { | ||||
|             default = cfg.defaultQuota; | ||||
|           }; | ||||
|           history = mkIf (! isNull cfg.fileRevisionHistoryDays) { | ||||
|             keep_days = cfg.fileRevisionHistoryDays; | ||||
|           }; | ||||
|           database = mkMerge [ | ||||
|             { | ||||
|               type = cfg.db.type; | ||||
|             } | ||||
|             # while just using the cfg.db set directly might be possible and | ||||
|             # save lines of code, I prefer hand-picking options | ||||
|             (mkIf (cfg.db.type == "mysql") { | ||||
|               host = cfg.db.host; | ||||
|               port = cfg.db.port; | ||||
|               user = cfg.db.user; | ||||
|               connection_charset = "utf8"; | ||||
|               db_name = cfg.db.dbnameSeafile; | ||||
|               max_connections = 100; | ||||
|               password = "#dbpass#"; | ||||
|             }) | ||||
|           ]; | ||||
|         }; | ||||
| 
 | ||||
|         systemd = { | ||||
|           # state directory permissions managed by systemd | ||||
|           tmpfiles.rules = [ | ||||
|             "d ${cfg.storagePath} 0750 ${cfg.user} ${cfg.group} -" | ||||
|             "d ${cfg.storagePath}/conf 0700 ${cfg.user} ${cfg.group} -" | ||||
|             "d ${cfg.storagePath}/pids 0710 ${cfg.user} ${cfg.group} -" | ||||
|             "d ${cfg.storagePath}/conf 0750 ${cfg.user} ${cfg.group} -" | ||||
|             "d ${cfg.storagePath}/home 0710 ${cfg.user} ${cfg.group} -" | ||||
|           ]; | ||||
|           services.seafile-server = { | ||||
| 
 | ||||
|           path = with pkgs; [ seafile-server.seafile-server-core ]; | ||||
|           path = with pkgs; [ seafile-server.ccnet-server seafile-server.seafile-server-core ]; | ||||
|           script = '' | ||||
|             ./seafile-server/seafile-server-latest/bin/seafile-admin start | ||||
|             ''; | ||||
|  | @ -295,46 +193,66 @@ in | |||
|               ''}") | ||||
|               ("${pkgs.writeShellScript "seafile-server-preStart-unprivileged" '' | ||||
|                 # stuff run as seafile user | ||||
|                 set -ex | ||||
| 
 | ||||
|                 # ccnet-init must only be run once per installation, as it also generates stateful key and ID | ||||
|                 # solution: invoke it once, use result as template | ||||
|                 if [ ! -e ./ccnet/mykey.peer ]; then | ||||
|                   ${pkgs.seafile-server.ccnet-server}/bin/ccnet-init -c ./ccnet -H 'TEMPLATEHOST' | ||||
|                   mv ./ccnet/ccnet.conf{,.template} | ||||
|                 fi | ||||
| 
 | ||||
|                 # generate actual ccnet config file | ||||
|                 echo "[General]" > ./conf/ccnet.conf | ||||
|                 grep "^ID =" ./ccnet/ccnet.conf.template >> ./conf/ccnet.conf | ||||
|                 # outside URL | ||||
|                 SERVICE_URL = http${if cfg.enableTLS then "s" else ""}://${cfg.domainName}:${toString cfg.externalPort} | ||||
| 
 | ||||
|                 # seafile.conf generation | ||||
| 
 | ||||
|                 # move config templates from nix store | ||||
|                 ${pkgs.coreutils}/bin/install ${ccnetConfigFile} ./conf/ccnet.conf | ||||
|                 ${pkgs.coreutils}/bin/install ${seafileConfigFile} ./conf/seafile.conf | ||||
|                 ${pkgs.coreutils}/bin/install ${gunicornConfigFile} ./conf/gunicorn.conf.py | ||||
|                 ${pkgs.coreutils}/bin/install ${seahubConfigFile} ./conf/seahub_settings.py | ||||
|                 echo '[library_trash] | ||||
|                 expire_days ${toString cfg.trashExpirationTime} | ||||
| 
 | ||||
|                 # seahub secret key | ||||
|                 if [ ! -e .seahubSecret ]; then | ||||
|                     ${pkgs.seafile-server.pythonEnv}/bin/python ${pkgs.seafile-server}/seahub/tools/secret_key_generator.py > .seahubSecret | ||||
|                     chmod 400 .seahubSecret | ||||
|                 fi | ||||
|                 SEAHUB_SECRET="$(head -n1 .seahubSecret)" | ||||
|                 # TODO: check for special characters needing to be escaped | ||||
|                 sed -e "s,#seckey#,$SEAHUB_SECRET,g" -i ./conf/seahub_settings.py | ||||
|                 [fileserver] | ||||
|                 host = ${cfg.fileserverBindAddress} | ||||
|                 port = ${toString cfg.fileserverPort} | ||||
|                 worker_threads = ${toString cfg.fileserverWorkers} | ||||
|                 max_indexing_threads = ${toString cfg.fileserverIndexers} | ||||
|                 fixed_block_size = ${toString cfg.fileserverIndexers}' > ./conf/seafile.conf | ||||
| 
 | ||||
|                 # replace placeholder secrets with real secret read from file | ||||
|                 #TODO: unset -x to prevent DBPASS from being leaked in journal | ||||
|                 ${if !(isNull cfg.db.passwordFile) then '' | ||||
|                   DBPASS="$(head -n1 ${toString cfg.db.passwordFile})" | ||||
|                   sed -e "s,#dbpass#,$DBPASS,g" -i ./conf/seafile.conf ./conf/ccnet.conf ./conf/seahub_settings.py | ||||
|                   '' | ||||
|                   else "" | ||||
|                 } | ||||
| 
 | ||||
|                  | ||||
|                 # initialise db and other things needed at first run | ||||
|                 if [ -e .initialised ]; then | ||||
|                     #TODO: db initialisation | ||||
| 
 | ||||
|                     touch .initialised | ||||
|                 if [ ${toString (! isNull cfg.defaultQuota)} ]; then | ||||
|                   echo '[quota]' >> ./conf/seafile.conf | ||||
|                   echo 'default = ${toString cfg.defaultQuota}' >> ./conf/seafile.conf | ||||
|                 fi | ||||
| 
 | ||||
|                 ln -nsf ${pkgs.seafile-server} seafile-server | ||||
|                 if [ ${toString (! isNull cfg.fileRevisionHistoryDays)} ]; then | ||||
|                   echo '[history]' >> ./conf/seafile.conf | ||||
|                   echo 'keep_days = ${toString cfg.defaultQuota}' >> ./conf/seafile.conf | ||||
|                 fi | ||||
| 
 | ||||
|                 # for determining update version mismatches | ||||
|                 ${pkgs.coreutils}/bin/install ${pkgs.seafile-server}/installed_version . | ||||
|                 # seafile database settings | ||||
| 
 | ||||
|                 if [ ${cfg.db.type} = "mysql" ]; then | ||||
|                 echo '[database] | ||||
|                 type = mysql | ||||
|                 host = ${cfg.db.host} | ||||
|                 port = ${toString cfg.db.dbport} | ||||
|                 user = ${cfg.db.user} | ||||
|                 connection_charset = utf8 | ||||
|                 db_name = ${cfg.db.dbname} | ||||
|                 max_connections = 100' >> ./conf/seafile.conf | ||||
| 
 | ||||
|                 if [ ${toString (! isNull cfg.db.password)}; then | ||||
|                 echo 'password = ${toString cfg.db.password}' >> ./conf/seafile.conf | ||||
|                 else | ||||
|                 echo "password = $(cat ${toString cfg.db.passwordFile})" >> ./conf/seafile.conf | ||||
|                 fi | ||||
|                 else | ||||
|                 echo '[database] | ||||
|                 type = sqlite' >> ./conf/seafile.conf | ||||
|                 fi | ||||
| 
 | ||||
|                 ln -s ${pkgs.seafile-server} seafile-server | ||||
|                 ./seafile-server/seafile-server-latest/bin/seafile-admin setup | ||||
|               ''}") | ||||
|             ]; | ||||
|             User = cfg.user; | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ import (<nixos-unstable/nixos/tests/make-test-python.nix>) { | |||
|             (import ./default.nix) | ||||
|           ]; | ||||
| 
 | ||||
|           console.keyMap = "de"; | ||||
|           i18n.consoleKeyMap = "de"; | ||||
|           users.mutableUsers = false; | ||||
|           users.users.test = { | ||||
|             isNormalUser = true; | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ | |||
| , python3Packages | ||||
| }: | ||||
| let | ||||
|   version = "8.0.3"; | ||||
|   version = "8.0.0"; | ||||
|   python = python3; | ||||
|   pythonPackages = python3Packages; | ||||
|   django = pythonPackages.django; | ||||
|  | @ -49,8 +49,6 @@ let | |||
|     pycryptodome | ||||
|   ] | ||||
|   ++ map (p: p.override { inherit django; }) djangoModules; # build django modules with required version | ||||
|   # defining them here to be able to expose them in a python environment as well | ||||
|   pythonEnvDeps = seahubPythonDependencies ++ [ libsearpc ]; | ||||
|   seafile-server-core = stdenv.mkDerivation rec { | ||||
|     name = "seafile-server-core"; | ||||
|     inherit version; | ||||
|  | @ -58,7 +56,7 @@ let | |||
|       owner = "haiwen"; | ||||
|       repo = "seafile-server"; | ||||
|       rev = "v${version}-server"; | ||||
|       sha256 = "1wmbx4smf342b5pars1zm9af2i0yaq7kjj7ry0gr337gdpa4qn3b"; | ||||
|       sha256 = "0pd1zjsw6lkpxd54ln0dz5r9zx9585nib10kvpl1vgzp61g4d223"; | ||||
|     }; | ||||
|     # patch to work with latest, non-vulnerable libevhtp | ||||
|     patches = [ | ||||
|  | @ -68,14 +66,7 @@ let | |||
|     # `which` is called directly from python during buildPhase, so we need the binary | ||||
|     nativeBuildInputs = [ autoconf automake libtool pkgconfig vala autoreconfHook which pythonPackages.wrapPython ]; | ||||
|     buildInputs = [ sqlite glib python libuuid openssl oniguruma fuse libarchive libevent libevhtp ]; | ||||
|     propagatedBuildInputs = pythonEnvDeps; | ||||
|     # copy manual to required location | ||||
|     postInstall = '' | ||||
|       mkdir $out/doc | ||||
|       cp ${src}/doc/*.doc $out/doc/ | ||||
|       ''; | ||||
|     # prevent doc directory from being moved to share in fixupPhase | ||||
|     forceShare = [ "man" "info" ]; | ||||
|     propagatedBuildInputs = [ libsearpc ] ++ seahubPythonDependencies; | ||||
|     postFixup = '' | ||||
|       buildPythonPath $propagatedBuildInputs | ||||
|       wrapPythonProgramsIn "$out/bin" "$out $pythonPath" | ||||
|  | @ -94,7 +85,7 @@ let | |||
|       owner = "haiwen"; | ||||
|       repo = "seahub"; | ||||
|       rev = "v${version}-server"; | ||||
|       sha256 = "0vfkiavsmpjm6wjr5rcnmnpnb3rxr3svwk8fsh5c76zg87ckdz4d"; | ||||
|       sha256 = "0j7g43j7w1zb00pg4aaacdv5ycva3qf561hj9pbwh4709mbiykip"; | ||||
|     }; | ||||
|     phases = [ "unpackPhase" "installPhase" "fixupPhase" "distPhase" ]; | ||||
|     buildInputs = [ python pythonPackages.wrapPython ]; | ||||
|  | @ -129,40 +120,19 @@ stdenv.mkDerivation { | |||
|   name = "seafile-server"; | ||||
|   inherit version; | ||||
| 
 | ||||
|   nativeBuildInputs = [ python3Packages.wrapPython  ]; | ||||
|   buildInputs = [ seahub seafile-server-core libsearpc ] | ||||
|     ++ lib.optional withMysql libmysqlclient; | ||||
|   phases = [ "installPhase" "fixupPhase" "distPhase" ]; | ||||
|   # create required directory structure | ||||
|   # Which files need to be copied is specified in the function `copy_scripts_and_libs` | ||||
|   # of  ${seafile-server-core.src}/scripts/build/build-server.py | ||||
|   # The install script below has been hand crafted from that list of files and needs to be updated on new releases. | ||||
|   # todo: create data directory in /srv in activation script | ||||
|   installPhase = '' | ||||
|     mkdir "$out" | ||||
|     cd "$out" | ||||
|     ln -s ${seahub} seahub | ||||
|     ln -s ${seafile-server-core} seafile-server | ||||
|     # copy general scripts | ||||
|     cp ${seafile-server-core.src}/scripts/{setup-seafile.sh,setup-seafile-mysql.sh,setup-seafile-mysql.py,seafile.sh,seahub.sh,reset-admin.sh,seaf-fuse.sh,check_init_admin.py,seaf-gc.sh,seaf-fsck.sh} . | ||||
|     # copy update scripts (and their sql) | ||||
|     cp -r ${seafile-server-core.src}/scripts/upgrade . | ||||
|     cp -r ${seafile-server-core.src}/scripts/sql . | ||||
|     # copy_user_manual is already done in the postInstall hook of seafile-server-core | ||||
|     # python admin scripts need to be made executable and patched with python path | ||||
|     chmod ugo+x *.py | ||||
|     buildPythonPath $propagatedBuildInputs | ||||
|     wrapPythonProgramsIn "$out/*.py" "$out $pythonPath" | ||||
| 
 | ||||
|     echo -n "${version}" > installed_version | ||||
|     ln -s ${seafile-server-core} seafile-server-latest | ||||
|   ''; | ||||
|   meta = with lib; { | ||||
|     maintainers = with maintainers; [ schmittlauch ]; | ||||
|     license = licenses.free; # components with different free software licenses are combined | ||||
|   }; | ||||
|   inherit seafile-server-core seahub;# for using the path in the NixOS module | ||||
|    | ||||
|   pythonEnv = python3.buildEnv.override { | ||||
|     extraLibs = pythonEnvDeps; | ||||
|     ignoreCollisions = true; | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -10,13 +10,13 @@ | |||
|     (import ./default.nix) | ||||
|     ]; | ||||
| 
 | ||||
|   console.keyMap = "de"; | ||||
|   i18n.consoleKeyMap = "de"; | ||||
|   users.mutableUsers = false; | ||||
|   users.users.test = { | ||||
|     isNormalUser = true; | ||||
|     extraGroups = [ "wheel" ]; | ||||
|     #hashedPassword = "$6$SZCzE/xB$Hr9sfsJ7xAcBCoptG39cxxQk8RZfldDjjGpSngOvn9Ufex5dHBEbdncXRZnfrGATsGcYPvLi7m4wIu.f8tY9B."; | ||||
|     password = "test"; | ||||
|     password = ""; | ||||
|     home = "/home/test"; | ||||
|     createHome = true; | ||||
|   }; | ||||
|  | @ -25,33 +25,7 @@ | |||
|   services.seafile-server = { | ||||
|     enable = true; | ||||
|     #autorun = false; | ||||
|     domainName = "seaf.local"; | ||||
|     db = { | ||||
|       type = "mysql"; | ||||
|       passwordFile = toString (pkgs.writeText "testPW" "test"); | ||||
|     }; | ||||
|     domainName = "localhost"; | ||||
|   }; | ||||
| 
 | ||||
|   # db backend | ||||
|   services.mysql = | ||||
|     { | ||||
|       enable = true; | ||||
|       package = pkgs.mariadb; | ||||
|       ensureDatabases = [ "ccnet" "seafile" "seahub" ]; | ||||
|       ensureUsers = [ | ||||
|         rec { | ||||
|           name = config.services.seafile-server.db.user; | ||||
|           ensurePermissions = { | ||||
|             "ccnet.*" = "ALL PRIVILEGES"; | ||||
|             "seafile.*" = "ALL PRIVILEGES"; | ||||
|             "seahub.*" = "ALL PRIVILEGES"; | ||||
|           }; | ||||
|         } | ||||
|       ]; | ||||
|       # set a password for the seafile user | ||||
|       initialScript = pkgs.writeText "mariadb-init.sql" '' | ||||
|         CREATE USER ${config.services.seafile-server.db.user}@localhost IDENTIFIED VIA mysql_native_password USING PASSWORD("test"); | ||||
|       ''; | ||||
|     }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue