diff --git a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml index 1e8a935f8f74..0026b362caf0 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2111.section.xml @@ -373,6 +373,14 @@ services.multipath. + + + seafile, + an open source file syncing & sharing software. Available + as + services.seafile. + +
diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index 0ddbfc5ab813..e02fbb9ea314 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -114,6 +114,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [multipath](https://github.com/opensvc/multipath-tools), the device mapper multipath (DM-MP) daemon. Available as [services.multipath](#opt-services.multipath.enable). +- [seafile](https://www.seafile.com/en/home/), an open source file syncing & sharing software. Available as [services.seafile](options.html#opt-services.seafile.enable). + ## Backward Incompatibilities {#sec-release-21.11-incompatibilities} - The `services.wakeonlan` option was removed, and replaced with `networking.interfaces..wakeOnLan`. diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 41a7db17c328..9343f2dbc847 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -838,6 +838,7 @@ ./services/networking/rpcbind.nix ./services/networking/rxe.nix ./services/networking/sabnzbd.nix + ./services/networking/seafile.nix ./services/networking/searx.nix ./services/networking/skydns.nix ./services/networking/shadowsocks.nix diff --git a/nixos/modules/services/networking/seafile.nix b/nixos/modules/services/networking/seafile.nix new file mode 100644 index 000000000000..856797b6b020 --- /dev/null +++ b/nixos/modules/services/networking/seafile.nix @@ -0,0 +1,290 @@ +{ config, lib, pkgs, ... }: +with lib; +let + python = pkgs.python3Packages.python; + cfg = config.services.seafile; + settingsFormat = pkgs.formats.ini { }; + + ccnetConf = settingsFormat.generate "ccnet.conf" cfg.ccnetSettings; + + seafileConf = settingsFormat.generate "seafile.conf" cfg.seafileSettings; + + seahubSettings = pkgs.writeText "seahub_settings.py" '' + FILE_SERVER_ROOT = '${cfg.ccnetSettings.General.SERVICE_URL}/seafhttp' + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': '${seahubDir}/seahub.db', + } + } + MEDIA_ROOT = '${seahubDir}/media/' + THUMBNAIL_ROOT = '${seahubDir}/thumbnail/' + + with open('${seafRoot}/.seahubSecret') as f: + SECRET_KEY = f.readline().rstrip() + + ${cfg.seahubExtraConf} + ''; + + seafRoot = "/var/lib/seafile"; # hardcode it due to dynamicuser + ccnetDir = "${seafRoot}/ccnet"; + dataDir = "${seafRoot}/data"; + seahubDir = "${seafRoot}/seahub"; + +in { + + ###### Interface + + options.services.seafile = { + enable = mkEnableOption "Seafile server"; + + ccnetSettings = mkOption { + type = types.submodule { + freeformType = settingsFormat.type; + + options = { + General = { + SERVICE_URL = mkOption { + type = types.str; + example = "https://www.example.com"; + description = '' + Seahub public URL. + ''; + }; + }; + }; + }; + default = { }; + description = '' + Configuration for ccnet, see + + 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.str; + default = "127.0.0.1"; + example = "0.0.0.0"; + description = '' + The binding address used by seafile fileserver. + ''; + }; + }; + }; + }; + default = { }; + description = '' + Configuration for seafile-server, see + + for supported values. + ''; + }; + + 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.str; + description = '' + Seafile Seahub Admin Account Email. + ''; + }; + + initialAdminPassword = mkOption { + example = "someStrongPass"; + type = types.str; + description = '' + Seafile Seahub Admin Account initial password. + Should be change via Seahub web front-end. + ''; + }; + + seafilePackage = mkOption { + type = types.package; + description = "Which package to use for the seafile server."; + default = pkgs.seafile-server; + }; + + seahubExtraConf = mkOption { + default = ""; + type = types.lines; + description = '' + Extra config to append to `seahub_settings.py` file. + Refer to + for all available options. + ''; + }; + }; + + ###### Implementation + + config = mkIf cfg.enable { + + environment.etc."seafile/ccnet.conf".source = ccnetConf; + environment.etc."seafile/seafile.conf".source = seafileConf; + environment.etc."seafile/seahub_settings.py".source = seahubSettings; + + systemd.targets.seafile = { + wantedBy = [ "multi-user.target" ]; + description = "Seafile components"; + }; + + systemd.services = let + securityOptions = { + ProtectHome = true; + PrivateUsers = true; + PrivateDevices = true; + ProtectClock = true; + ProtectHostname = true; + ProtectProc = "invisible"; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictNamespaces = true; + LockPersonality = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + MemoryDenyWriteExecute = true; + SystemCallArchitectures = "native"; + RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" ]; + }; + in { + seaf-server = { + description = "Seafile server"; + partOf = [ "seafile.target" ]; + after = [ "network.target" ]; + wantedBy = [ "seafile.target" ]; + restartTriggers = [ ccnetConf seafileConf ]; + serviceConfig = securityOptions // { + User = "seafile"; + Group = "seafile"; + DynamicUser = true; + StateDirectory = "seafile"; + RuntimeDirectory = "seafile"; + LogsDirectory = "seafile"; + ConfigurationDirectory = "seafile"; + ExecStart = '' + ${cfg.seafilePackage}/bin/seaf-server \ + --foreground \ + -F /etc/seafile \ + -c ${ccnetDir} \ + -d ${dataDir} \ + -l /var/log/seafile/server.log \ + -P /run/seafile/server.pid \ + -p /run/seafile + ''; + }; + preStart = '' + if [ ! -f "${seafRoot}/server-setup" ]; then + mkdir -p ${dataDir}/library-template + mkdir -p ${ccnetDir}/{GroupMgr,misc,OrgMgr,PeerMgr} + ${pkgs.sqlite}/bin/sqlite3 ${ccnetDir}/GroupMgr/groupmgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/groupmgr.sql" + ${pkgs.sqlite}/bin/sqlite3 ${ccnetDir}/misc/config.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/config.sql" + ${pkgs.sqlite}/bin/sqlite3 ${ccnetDir}/OrgMgr/orgmgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/org.sql" + ${pkgs.sqlite}/bin/sqlite3 ${ccnetDir}/PeerMgr/usermgr.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/user.sql" + ${pkgs.sqlite}/bin/sqlite3 ${dataDir}/seafile.db ".read ${cfg.seafilePackage}/share/seafile/sql/sqlite/seafile.sql" + echo "${cfg.seafilePackage.version}-sqlite" > "${seafRoot}"/server-setup + fi + # checking for upgrades and handling them + # WARNING: needs to be extended to actually handle major version migrations + 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.seafilePackage.version}" | cut -d"." -f1) + pkgMinor=$(echo "${cfg.seafilePackage.version}" | cut -d"." -f2) + if [ $installedMajor != $pkgMajor ] || [ $installedMinor != $pkgMinor ]; then + echo "Unsupported upgrade" >&2 + exit 1 + fi + ''; + }; + + seahub = let + penv = (pkgs.python3.withPackages (ps: with ps; [ gunicorn seahub ])); + in { + description = "Seafile Server Web Frontend"; + wantedBy = [ "seafile.target" ]; + partOf = [ "seafile.target" ]; + after = [ "network.target" "seaf-server.service" ]; + requires = [ "seaf-server.service" ]; + restartTriggers = [ seahubSettings ]; + environment = { + PYTHONPATH = + "${pkgs.python3Packages.seahub}/thirdpart:${pkgs.python3Packages.seahub}:${penv}/${python.sitePackages}"; + DJANGO_SETTINGS_MODULE = "seahub.settings"; + CCNET_CONF_DIR = ccnetDir; + SEAFILE_CONF_DIR = dataDir; + SEAFILE_CENTRAL_CONF_DIR = "/etc/seafile"; + SEAFILE_RPC_PIPE_PATH = "/run/seafile"; + SEAHUB_LOG_DIR = "/var/log/seafile"; + }; + serviceConfig = securityOptions // { + User = "seafile"; + Group = "seafile"; + DynamicUser = true; + RuntimeDirectory = "seahub"; + StateDirectory = "seafile"; + LogsDirectory = "seafile"; + ConfigurationDirectory = "seafile"; + ExecStart = '' + ${penv}/bin/gunicorn seahub.wsgi:application \ + --name seahub \ + --workers ${toString cfg.workers} \ + --log-level=info \ + --preload \ + --timeout=1200 \ + --limit-request-line=8190 \ + --bind unix:/run/seahub/gunicorn.sock + ''; + }; + preStart = '' + mkdir -p ${seahubDir}/media + # Link all media except avatars + for m in `find ${pkgs.python3Packages.seahub}/media/ -maxdepth 1 -not -name "avatars"`; do + ln -sf $m ${seahubDir}/media/ + done + if [ ! -e "${seafRoot}/.seahubSecret" ]; then + ${penv}/bin/python ${pkgs.python3Packages.seahub}/tools/secret_key_generator.py > ${seafRoot}/.seahubSecret + chmod 400 ${seafRoot}/.seahubSecret + fi + if [ ! -f "${seafRoot}/seahub-setup" ]; then + # avatars directory should be writable + install -D -t ${seahubDir}/media/avatars/ ${pkgs.python3Packages.seahub}/media/avatars/default.png + install -D -t ${seahubDir}/media/avatars/groups ${pkgs.python3Packages.seahub}/media/avatars/groups/default.png + # init database + ${pkgs.python3Packages.seahub}/manage.py migrate + # create admin account + ${pkgs.expect}/bin/expect -c 'spawn ${pkgs.python3Packages.seahub}/manage.py createsuperuser --email=${cfg.adminEmail}; expect "Password: "; send "${cfg.initialAdminPassword}\r"; expect "Password (again): "; send "${cfg.initialAdminPassword}\r"; expect "Superuser created successfully."' + echo "${pkgs.python3Packages.seahub.version}-sqlite" > "${seafRoot}/seahub-setup" + fi + if [ $(cat "${seafRoot}/seahub-setup" | cut -d"-" -f1) != "${pkgs.python3Packages.seahub.version}" ]; then + # update database + ${pkgs.python3Packages.seahub}/manage.py migrate + echo "${pkgs.python3Packages.seahub.version}-sqlite" > "${seafRoot}/seahub-setup" + fi + ''; + }; + }; + }; +} diff --git a/nixos/tests/seafile.nix b/nixos/tests/seafile.nix new file mode 100644 index 000000000000..17862cff189e --- /dev/null +++ b/nixos/tests/seafile.nix @@ -0,0 +1,123 @@ +import ./make-test-python.nix ({ pkgs, ... }: + let + client = { config, pkgs, ... }: { + virtualisation.memorySize = 256; + environment.systemPackages = [ pkgs.seafile-shared pkgs.curl ]; + }; + in { + name = "seafile"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ kampfschlaefer schmittlauch ]; + }; + + nodes = { + server = { config, pkgs, ... }: { + virtualisation.memorySize = 512; + services.seafile = { + enable = true; + ccnetSettings.General.SERVICE_URL = "http://server"; + 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://127.0.0.1:8082"; + 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.sleep(3) + + client1.succeed("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.sleep(2) + + client1.succeed("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.sleep(3) + + client2.succeed("seaf-cli status |grep synchronized >&2") + + client2.succeed("ls -la test01 >&2") + + client2.succeed('[ `cat test01/first_file` = "bla" ]') + ''; + }) diff --git a/pkgs/development/libraries/oniguruma/default.nix b/pkgs/development/libraries/oniguruma/default.nix index 1968e76274bf..e50750d58ec0 100644 --- a/pkgs/development/libraries/oniguruma/default.nix +++ b/pkgs/development/libraries/oniguruma/default.nix @@ -12,6 +12,7 @@ stdenv.mkDerivation rec { }; nativeBuildInputs = [ autoreconfHook ]; + configureFlags = [ "--enable-posix-api=yes" ]; meta = with lib; { homepage = "https://github.com/kkos/oniguruma"; diff --git a/pkgs/development/python-modules/django-formtools/default.nix b/pkgs/development/python-modules/django-formtools/default.nix new file mode 100644 index 000000000000..faca36c2a98b --- /dev/null +++ b/pkgs/development/python-modules/django-formtools/default.nix @@ -0,0 +1,23 @@ +{ stdenv, lib, buildPythonPackage, fetchPypi, django, python }: + +buildPythonPackage rec { + pname = "django-formtools"; + version = "2.2"; + + src = fetchPypi { + inherit pname version; + sha256 = "1chkbl188yj6hvhh1wgjpfgql553k6hrfwxzb8vv4lfdq41jq9y5"; + }; + + propagatedBuildInputs = [ django ]; + checkPhase = '' + ${python.interpreter} -m django test --settings=tests.settings + ''; + + meta = with lib; { + description = "A set of high-level abstractions for Django forms"; + homepage = "https://github.com/jazzband/django-formtools"; + license = licenses.bsd3; + maintainers = with maintainers; [ greizgh schmittlauch ]; + }; +} diff --git a/pkgs/development/python-modules/django-statici18n/default.nix b/pkgs/development/python-modules/django-statici18n/default.nix new file mode 100644 index 000000000000..88c63319a89d --- /dev/null +++ b/pkgs/development/python-modules/django-statici18n/default.nix @@ -0,0 +1,24 @@ +{ stdenv, lib, buildPythonPackage, fetchPypi, django, django_appconf }: + +buildPythonPackage rec { + pname = "django-statici18n"; + version = "2.0.1"; + + src = fetchPypi { + inherit pname version; + sha256 = "0cqwfirzjbanibq3mfz9lcwqnc8655zpysf9hk9g3lbwj2m478sp"; + }; + + propagatedBuildInputs = [ django django_appconf ]; + + # pypi package does not contains test harness + # source tarball requires setting up a config + doCheck = false; + + meta = with lib; { + description = "Helper for generating Javascript catalog to static files"; + homepage = "https://github.com/zyegfryed/django-statici18n"; + license = licenses.bsd3; + maintainers = with maintainers; [ greizgh schmittlauch ]; + }; +} diff --git a/pkgs/development/python-modules/seahub/default.nix b/pkgs/development/python-modules/seahub/default.nix new file mode 100644 index 000000000000..3ed0d9acfedc --- /dev/null +++ b/pkgs/development/python-modules/seahub/default.nix @@ -0,0 +1,56 @@ +{ stdenv, lib, fetchFromGitHub, python3Packages, makeWrapper }: + +python3Packages.buildPythonPackage rec { + pname = "seahub"; + version = "8.0.7"; + + src = fetchFromGitHub { + owner = "haiwen"; + repo = "seahub"; + rev = "4f7bb3f617dd847cf0a6b33c0bfb567b44c06059"; # using a fixed revision because upstream may re-tag releases :/ + sha256 = "09d05sxly1bljxxzm77limhwsbg8c4b54fzv3kmaih59pjnjyr03"; + }; + + dontBuild = true; + doCheck = false; # disabled because it requires a ccnet environment + + nativeBuildInputs = [ makeWrapper ]; + + propagatedBuildInputs = with python3Packages; [ + django + future + django-statici18n + django-webpack-loader + django-simple-captcha + django-picklefield + django-formtools + mysqlclient + pillow + python-dateutil + django_compressor + djangorestframework + openpyxl + requests + requests_oauthlib + pyjwt + pycryptodome + qrcode + pysearpc + seaserv + ]; + + installPhase = '' + cp -dr --no-preserve='ownership' . $out/ + wrapProgram $out/manage.py \ + --prefix PYTHONPATH : "$PYTHONPATH:$out/thirdpart:" \ + --prefix PATH : "${python3Packages.python}/bin" + ''; + + meta = with lib; { + homepage = "https://github.com/haiwen/seahub"; + description = "The web end of seafile server"; + license = licenses.asl20; + platforms = platforms.linux; + maintainers = with maintainers; [ greizgh schmittlauch ]; + }; +} diff --git a/pkgs/misc/seafile-shared/default.nix b/pkgs/misc/seafile-shared/default.nix index cc6d0ced6d1b..6db3ab932db9 100644 --- a/pkgs/misc/seafile-shared/default.nix +++ b/pkgs/misc/seafile-shared/default.nix @@ -18,8 +18,8 @@ stdenv.mkDerivation rec { src = fetchFromGitHub { owner = "haiwen"; repo = "seafile"; - rev = "v${version}"; - sha256 = "QflLh3fj+jOq/8etr9aG8LGrvtIlB/htVkWbdO+GIbM="; + rev = "0fdc14d5175979919b7c741f6bb97bfaaacbbfbe"; + sha256 = "1cr1hvpp96s5arnzh1r5sazapcghhvbazbf7zym37yp3fy3lpya1"; }; nativeBuildInputs = [ @@ -40,12 +40,12 @@ stdenv.mkDerivation rec { configureFlags = [ "--disable-server" - "--disable-console" "--with-python3" ]; pythonPath = with python3.pkgs; [ - libsearpc + future + pysearpc ]; postFixup = '' @@ -55,8 +55,8 @@ stdenv.mkDerivation rec { meta = with lib; { homepage = "https://github.com/haiwen/seafile"; description = "Shared components of Seafile: seafile-daemon, libseafile, libseafile python bindings, manuals, and icons"; - license = licenses.gpl3; + license = licenses.gpl2Plus; platforms = platforms.linux; - maintainers = [ ]; + maintainers = with maintainers; [ greizgh schmittlauch ]; }; } diff --git a/pkgs/servers/seafile-server/default.nix b/pkgs/servers/seafile-server/default.nix new file mode 100644 index 000000000000..d60dd7809913 --- /dev/null +++ b/pkgs/servers/seafile-server/default.nix @@ -0,0 +1,52 @@ +{ stdenv, lib, fetchFromGitHub, pkg-config, python3Packages, autoreconfHook +, libuuid, sqlite, glib, libevent, libsearpc, openssl, fuse, libarchive, which +, vala, cmake, oniguruma }: + +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 rec { + pname = "seafile-server"; + version = "8.0.7"; + + src = fetchFromGitHub { + owner = "haiwen"; + repo = "seafile-server"; + rev = "27dac89bb3a81c5acc3f764ce92134eb357ea64b"; + sha256 = "1h2hxvv0l5m9nbkdyjpznb7ddk8hb8hhwj8b2lx6aqbvp8gll9q7"; + }; + + nativeBuildInputs = [ autoreconfHook pkg-config ]; + + buildInputs = [ + libuuid + sqlite + openssl + glib + libsearpc + libevent + python3Packages.python + fuse + libarchive + which + vala + libevhtp + oniguruma + ]; + + postInstall = '' + mkdir -p $out/share/seafile/sql + cp -r scripts/sql $out/share/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; [ greizgh schmittlauch ]; + }; +} diff --git a/pkgs/servers/seafile-server/libevhtp.nix b/pkgs/servers/seafile-server/libevhtp.nix new file mode 100644 index 000000000000..97cdc0804faa --- /dev/null +++ b/pkgs/servers/seafile-server/libevhtp.nix @@ -0,0 +1,29 @@ +{ stdenv, lib, fetchFromGitHub, cmake, libevent }: + +stdenv.mkDerivation rec { + 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; [ greizgh schmittlauch ]; + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 29b44acfc8a0..f111f9dbd7d4 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -32676,6 +32676,8 @@ with pkgs; thrift = thrift-0_10; }; + seafile-server = callPackage ../servers/seafile-server { }; + seafile-shared = callPackage ../misc/seafile-shared { }; ser2net = callPackage ../servers/ser2net {}; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 7b303aa4b307..f355534dc77e 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -2110,6 +2110,8 @@ in { django-filter = callPackage ../development/python-modules/django-filter { }; + django-formtools = callPackage ../development/python-modules/django-formtools { }; + django-gravatar2 = callPackage ../development/python-modules/django-gravatar2 { }; django_guardian = callPackage ../development/python-modules/django_guardian { }; @@ -2179,6 +2181,8 @@ in { django-sr = callPackage ../development/python-modules/django-sr { }; + django-statici18n = callPackage ../development/python-modules/django-statici18n { }; + django-storages = callPackage ../development/python-modules/django-storages { }; django_tagging = callPackage ../development/python-modules/django_tagging { }; @@ -6956,6 +6960,8 @@ in { pysdl2 = callPackage ../development/python-modules/pysdl2 { }; + pysearpc = toPythonModule pkgs.libsearpc; + pysendfile = callPackage ../development/python-modules/pysendfile { }; pysensors = callPackage ../development/python-modules/pysensors { }; @@ -8319,6 +8325,10 @@ in { seabreeze = callPackage ../development/python-modules/seabreeze { }; + seahub = callPackage ../development/python-modules/seahub { }; + + seaserv = toPythonModule pkgs.seafile-server; + seccomp = callPackage ../development/python-modules/seccomp { }; secp256k1 = callPackage ../development/python-modules/secp256k1 {